1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgk@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * ulimit [-HSacdfmnstuv] [limit]
23 *
24 * David Korn
25 * AT&T Labs
26 *
27 */
28
29 #include <ast.h>
30 #include <sfio.h>
31 #include <error.h>
32 #include "defs.h"
33 #include "builtins.h"
34 #include "name.h"
35 #include "ulimit.h"
36 #ifndef SH_DICT
37 # define SH_DICT "libshell"
38 #endif
39
40 #ifdef _no_ulimit
b_ulimit(int argc,char * argv[],Shbltin_t * context)41 int b_ulimit(int argc,char *argv[],Shbltin_t *context)
42 {
43 NOT_USED(argc);
44 NOT_USED(argv);
45 NOT_USED(context);
46 errormsg(SH_DICT,ERROR_exit(2),e_nosupport);
47 return(0);
48 }
49 #else
50
infof(Opt_t * op,Sfio_t * sp,const char * s,Optdisc_t * dp)51 static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
52 {
53 register const Limit_t* tp;
54
55 for (tp = shtab_limits; tp->option; tp++)
56 {
57 sfprintf(sp, "[%c=%d:%s?The %s", tp->option, tp - shtab_limits + 1, tp->name, tp->description);
58 if(tp->type != LIM_COUNT)
59 sfprintf(sp, " in %ss", e_units[tp->type]);
60 sfprintf(sp, ".]");
61 }
62 return(1);
63 }
64
65 #define HARD 2
66 #define SOFT 4
67
b_ulimit(int argc,char * argv[],Shbltin_t * context)68 int b_ulimit(int argc,char *argv[],Shbltin_t *context)
69 {
70 register char *limit;
71 register int mode=0, n;
72 register unsigned long hit = 0;
73 Shell_t *shp = context->shp;
74 #ifdef _lib_getrlimit
75 struct rlimit rlp;
76 #endif /* _lib_getrlimit */
77 const Limit_t* tp;
78 char* conf;
79 int label, unit, nosupport;
80 rlim_t i;
81 char tmp[32];
82 Optdisc_t disc;
83 memset(&disc, 0, sizeof(disc));
84 disc.version = OPT_VERSION;
85 disc.infof = infof;
86 opt_info.disc = &disc;
87 while((n = optget(argv,sh_optulimit))) switch(n)
88 {
89 case 'H':
90 mode |= HARD;
91 continue;
92 case 'S':
93 mode |= SOFT;
94 continue;
95 case 'a':
96 hit = ~0;
97 break;
98 default:
99 if(n < 0)
100 hit |= (1L<<(-(n+1)));
101 else
102 errormsg(SH_DICT,2, e_notimp, opt_info.name);
103 break;
104 case ':':
105 errormsg(SH_DICT,2, "%s", opt_info.arg);
106 break;
107 case '?':
108 errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
109 break;
110 }
111 opt_info.disc = 0;
112 /* default to -f */
113 limit = argv[opt_info.index];
114 if(hit==0)
115 for(n=0; shtab_limits[n].option; n++)
116 if(shtab_limits[n].index == RLIMIT_FSIZE)
117 {
118 hit |= (1L<<n);
119 break;
120 }
121 /* only one option at a time for setting */
122 label = (hit&(hit-1));
123 if(error_info.errors || (limit && label) || argc>opt_info.index+1)
124 errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
125 if(mode==0)
126 mode = (HARD|SOFT);
127 for(tp = shtab_limits; tp->option && hit; tp++,hit>>=1)
128 {
129 if(!(hit&1))
130 continue;
131 nosupport = (n = tp->index) == RLIMIT_UNKNOWN;
132 unit = shtab_units[tp->type];
133 if(limit)
134 {
135 if(shp->subshell && !shp->subshare)
136 sh_subfork();
137 if(strcmp(limit,e_unlimited)==0)
138 i = INFINITY;
139 else
140 {
141 char *last;
142 /* an explicit suffix unit overrides the default */
143 if((i=strtol(limit,&last,0))!=INFINITY && !*last)
144 i *= unit;
145 else if((i=strton(limit,&last,NiL,0))==INFINITY || *last)
146 {
147 if((i=sh_strnum(limit,&last,2))==INFINITY || *last)
148 errormsg(SH_DICT,ERROR_system(1),e_number,limit);
149 i *= unit;
150 }
151 }
152 if(nosupport)
153 errormsg(SH_DICT,ERROR_system(1),e_readonly,tp->name);
154 else
155 {
156 #ifdef _lib_getrlimit
157 if(getrlimit(n,&rlp) <0)
158 errormsg(SH_DICT,ERROR_system(1),e_number,limit);
159 if(mode&HARD)
160 rlp.rlim_max = i;
161 if(mode&SOFT)
162 rlp.rlim_cur = i;
163 if(setrlimit(n,&rlp) <0)
164 errormsg(SH_DICT,ERROR_system(1),e_overlimit,limit);
165 #else
166 if((i=vlimit(n,i)) < 0)
167 errormsg(SH_DICT,ERROR_system(1),e_number,limit);
168 #endif /* _lib_getrlimit */
169 }
170 }
171 else
172 {
173 if(!nosupport)
174 {
175 #ifdef _lib_getrlimit
176 if(getrlimit(n,&rlp) <0)
177 errormsg(SH_DICT,ERROR_system(1),e_number,limit);
178 if(mode&HARD)
179 i = rlp.rlim_max;
180 if(mode&SOFT)
181 i = rlp.rlim_cur;
182 #else
183 # ifdef _lib_ulimit
184 n--;
185 # endif /* _lib_ulimit */
186 i = -1;
187 if((i=vlimit(n,i)) < 0)
188 errormsg(SH_DICT,ERROR_system(1),e_number,limit);
189 #endif /* _lib_getrlimit */
190 }
191 if(label)
192 {
193 if(tp->type != LIM_COUNT)
194 sfsprintf(tmp,sizeof(tmp),"%s (%ss)", tp->description, e_units[tp->type]);
195 else
196 sfsprintf(tmp,sizeof(tmp),"%s", tp->name);
197 sfprintf(sfstdout,"%-30s (-%c) ",tmp,tp->option);
198 }
199 if(nosupport)
200 {
201 if(!tp->conf || !*(conf = astconf(tp->conf, NiL, NiL)))
202 conf = (char*)e_nosupport;
203 sfputr(sfstdout,conf,'\n');
204 }
205 else if(i!=INFINITY)
206 {
207 i += (unit-1);
208 sfprintf(sfstdout,"%I*d\n",sizeof(i),i/unit);
209 }
210 else
211 sfputr(sfstdout,e_unlimited,'\n');
212 }
213 }
214 return(0);
215 }
216 #endif /* _no_ulimit */
217