c_ulimit.c revision 1.1 1 /*
2 ulimit -- handle "ulimit" builtin
3
4 Reworked to use getrusage() and ulimit() at once (as needed on
5 some schizophenic systems, eg, HP-UX 9.01), made argument parsing
6 conform to at&t ksh, added autoconf support. Michael Rendell, May, '94
7
8 Eric Gisin, September 1988
9 Adapted to PD KornShell. Removed AT&T code.
10
11 last edit: 06-Jun-1987 D A Gwyn
12
13 This started out as the BRL UNIX System V system call emulation
14 for 4.nBSD, and was later extended by Doug Kingston to handle
15 the extended 4.nBSD resource limits. It now includes the code
16 that was originally under case SYSULIMIT in source file "xec.c".
17 */
18
19 #include "sh.h"
20 #include "ksh_time.h"
21 #ifdef HAVE_SYS_RESOURCE_H
22 # include <sys/resource.h>
23 #endif /* HAVE_SYS_RESOURCE_H */
24 #ifdef HAVE_ULIMIT_H
25 # include <ulimit.h>
26 #else /* HAVE_ULIMIT_H */
27 # ifdef HAVE_ULIMIT
28 extern long ulimit();
29 # endif /* HAVE_ULIMIT */
30 #endif /* HAVE_ULIMIT_H */
31
32 #define SOFT 0x1
33 #define HARD 0x2
34
35 int
36 c_ulimit(wp)
37 char **wp;
38 {
39 static const struct limits {
40 const char *name;
41 enum { RLIMIT, ULIMIT } which;
42 int gcmd; /* get command */
43 int scmd; /* set command (or -1, if no set command) */
44 int factor; /* multiply by to get rlim_{cur,max} values */
45 char option;
46 } limits[] = {
47 /* Do not use options -H, -S or -a */
48 #ifdef RLIMIT_CPU
49 { "time(cpu-seconds)", RLIMIT, RLIMIT_CPU, RLIMIT_CPU, 1, 't' },
50 #endif
51 #ifdef RLIMIT_FSIZE
52 { "file(blocks)", RLIMIT, RLIMIT_FSIZE, RLIMIT_FSIZE, 512, 'f' },
53 #else /* RLIMIT_FSIZE */
54 # ifdef UL_GETFSIZE /* x/open */
55 { "file(blocks)", ULIMIT, UL_GETFSIZE, UL_SETFSIZE, 1, 'f' },
56 # else /* UL_GETFSIZE */
57 # ifdef UL_GFILLIM /* svr4/xenix */
58 { "file(blocks)", ULIMIT, UL_GFILLIM, UL_SFILLIM, 1, 'f' },
59 # else /* UL_GFILLIM */
60 { "file(blocks)", ULIMIT, 1, 2, 1, 'f' },
61 # endif /* UL_GFILLIM */
62 # endif /* UL_GETFSIZE */
63 #endif /* RLIMIT_FSIZE */
64 #ifdef RLIMIT_CORE
65 { "coredump(blocks)", RLIMIT, RLIMIT_CORE, RLIMIT_CORE, 512, 'c' },
66 #endif
67 #ifdef RLIMIT_DATA
68 { "data(kbytes)", RLIMIT, RLIMIT_DATA, RLIMIT_DATA, 1024, 'd' },
69 #endif
70 #ifdef RLIMIT_STACK
71 { "stack(kbytes)", RLIMIT, RLIMIT_STACK, RLIMIT_STACK, 1024, 's' },
72 #endif
73 #ifdef RLIMIT_MEMLOCK
74 { "lockedmem(kbytes)", RLIMIT, RLIMIT_MEMLOCK, RLIMIT_MEMLOCK, 1024, 'l' },
75 #endif
76 #ifdef RLIMIT_RSS
77 { "memory(kbytes)", RLIMIT, RLIMIT_RSS, RLIMIT_RSS, 1024, 'm' },
78 #endif
79 #ifdef RLIMIT_NOFILE
80 { "nofiles(descriptors)", RLIMIT, RLIMIT_NOFILE, RLIMIT_NOFILE, 1, 'n' },
81 #else /* RLIMIT_NOFILE */
82 # ifdef UL_GDESLIM /* svr4/xenix */
83 { "nofiles(descriptors)", ULIMIT, UL_GDESLIM, -1, 1, 'n' },
84 # endif /* UL_GDESLIM */
85 #endif /* RLIMIT_NOFILE */
86 #ifdef RLIMIT_NPROC
87 { "processes", RLIMIT, RLIMIT_NPROC, RLIMIT_NPROC, 1, 'p' },
88 #endif
89 #ifdef RLIMIT_VMEM
90 { "vmemory(kbytes)", RLIMIT, RLIMIT_VMEM, RLIMIT_VMEM, 1024, 'v' },
91 #else /* RLIMIT_VMEM */
92 /* These are not quite right - really should subtract etext or something */
93 # ifdef UL_GMEMLIM /* svr4/xenix */
94 { "vmemory(maxaddr)", ULIMIT, UL_GMEMLIM, -1, 1, 'v' },
95 # else /* UL_GMEMLIM */
96 # ifdef UL_GETBREAK /* osf/1 */
97 { "vmemory(maxaddr)", ULIMIT, UL_GETBREAK, -1, 1, 'v' },
98 # else /* UL_GETBREAK */
99 # ifdef UL_GETMAXBRK /* hpux */
100 { "vmemory(maxaddr)", ULIMIT, UL_GETMAXBRK, -1, 1, 'v' },
101 # endif /* UL_GETMAXBRK */
102 # endif /* UL_GETBREAK */
103 # endif /* UL_GMEMLIM */
104 #endif /* RLIMIT_VMEM */
105 #ifdef RLIMIT_SWAP
106 { "swap(kbytes)", RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' },
107 #endif
108 { (char *) 0 }
109 };
110 static char options[3 + NELEM(limits)];
111 rlim_t UNINITIALIZED(val);
112 int how = SOFT | HARD;
113 const struct limits *l;
114 int set, all = 0;
115 int optc, what;
116 #ifdef HAVE_SETRLIMIT
117 struct rlimit limit;
118 #endif /* HAVE_SETRLIMIT */
119
120 if (!options[0]) {
121 /* build options string on first call - yuck */
122 char *p = options;
123
124 *p++ = 'H'; *p++ = 'S'; *p++ = 'a';
125 for (l = limits; l->name; l++)
126 *p++ = l->option;
127 *p = '\0';
128 }
129 what = 'f';
130 while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
131 switch (optc) {
132 case 'H':
133 how = HARD;
134 break;
135 case 'S':
136 how = SOFT;
137 break;
138 case 'a':
139 all = 1;
140 break;
141 case '?':
142 return 1;
143 default:
144 what = optc;
145 }
146
147 for (l = limits; l->name && l->option != what; l++)
148 ;
149 if (!l->name) {
150 internal_errorf(0, "ulimit: %c", what);
151 return 1;
152 }
153
154 wp += builtin_opt.optind;
155 set = *wp ? 1 : 0;
156 if (set) {
157 char *p = *wp;
158
159 if (all || wp[1]) {
160 bi_errorf("too many arguments");
161 return 1;
162 }
163 #ifdef RLIM_INFINITY
164 if (strcmp(p, "unlimited") == 0)
165 val = RLIM_INFINITY;
166 else
167 #endif /* RLIM_INFINITY */
168 {
169 long rval;
170
171 if (!evaluate(p, &rval, TRUE))
172 return 1;
173 val = rval * l->factor;
174 }
175 }
176 if (all) {
177 for (l = limits; l->name; l++) {
178 #ifdef HAVE_SETRLIMIT
179 if (l->which == RLIMIT) {
180 getrlimit(l->gcmd, &limit);
181 if (how & SOFT)
182 val = limit.rlim_cur;
183 else if (how & HARD)
184 val = limit.rlim_max;
185 } else
186 #endif /* HAVE_SETRLIMIT */
187 #ifdef HAVE_ULIMIT
188 {
189 val = ulimit(l->gcmd, (rlim_t) 0);
190 }
191 #else /* HAVE_ULIMIT */
192 ;
193 #endif /* HAVE_ULIMIT */
194 shprintf("%-20s ", l->name);
195 #ifdef RLIM_INFINITY
196 if (val == RLIM_INFINITY)
197 shprintf("unlimited\n");
198 else
199 #endif /* RLIM_INFINITY */
200 {
201 val /= l->factor;
202 shprintf("%ld\n", (long) val);
203 }
204 }
205 return 0;
206 }
207 #ifdef HAVE_SETRLIMIT
208 if (l->which == RLIMIT) {
209 getrlimit(l->gcmd, &limit);
210 if (set) {
211 if (how & SOFT)
212 limit.rlim_cur = val;
213 if (how & HARD)
214 limit.rlim_max = val;
215 if (setrlimit(l->scmd, &limit) < 0) {
216 bi_errorf("bad limit: %s", strerror(errno));
217 return 1;
218 }
219 } else {
220 if (how & SOFT)
221 val = limit.rlim_cur;
222 else if (how & HARD)
223 val = limit.rlim_max;
224 }
225 } else
226 #endif /* HAVE_SETRLIMIT */
227 #ifdef HAVE_ULIMIT
228 {
229 if (set) {
230 if (l->scmd == -1) {
231 bi_errorf("can't change limit");
232 return 1;
233 } else if (ulimit(l->scmd, val) < 0) {
234 bi_errorf("bad limit: %s", strerror(errno));
235 return 1;
236 }
237 } else
238 val = ulimit(l->gcmd, (rlim_t) 0);
239 }
240 #else /* HAVE_ULIMIT */
241 ;
242 #endif /* HAVE_ULIMIT */
243 if (!set) {
244 #ifdef RLIM_INFINITY
245 if (val == RLIM_INFINITY)
246 shprintf("unlimited\n");
247 else
248 #endif /* RLIM_INFINITY */
249 {
250 val /= l->factor;
251 shprintf("%ld\n", (long) val);
252 }
253 }
254 return 0;
255 }
256