]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is ulimit.def, from which is created ulimit.c. |
2 | It implements the builtin "ulimit" in Bash. | |
3 | ||
495aee44 | 4 | Copyright (C) 1987-2010 Free Software Foundation, Inc. |
726f6388 JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
8 | Bash is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation, either version 3 of the License, or | |
11 | (at your option) any later version. | |
726f6388 | 12 | |
3185942a JA |
13 | Bash is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
726f6388 | 17 | |
3185942a JA |
18 | You should have received a copy of the GNU General Public License |
19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
726f6388 JA |
20 | |
21 | $PRODUCES ulimit.c | |
22 | ||
23 | $BUILTIN ulimit | |
24 | $FUNCTION ulimit_builtin | |
cce855bc | 25 | $DEPENDS_ON !_MINIX |
ac50fbac | 26 | $SHORT_DOC ulimit [-SHabcdefilmnpqrstuvxT] [limit] |
3185942a JA |
27 | Modify shell resource limits. |
28 | ||
29 | Provides control over the resources available to the shell and processes | |
30 | it creates, on systems that allow such control. | |
31 | ||
32 | Options: | |
33 | -S use the `soft' resource limit | |
34 | -H use the `hard' resource limit | |
35 | -a all current limits are reported | |
36 | -b the socket buffer size | |
37 | -c the maximum size of core files created | |
38 | -d the maximum size of a process's data segment | |
39 | -e the maximum scheduling priority (`nice') | |
40 | -f the maximum size of files written by the shell and its children | |
41 | -i the maximum number of pending signals | |
42 | -l the maximum size a process may lock into memory | |
43 | -m the maximum resident set size | |
44 | -n the maximum number of open file descriptors | |
45 | -p the pipe buffer size | |
46 | -q the maximum number of bytes in POSIX message queues | |
47 | -r the maximum real-time scheduling priority | |
48 | -s the maximum stack size | |
49 | -t the maximum amount of cpu time in seconds | |
50 | -u the maximum number of user processes | |
51 | -v the size of virtual memory | |
52 | -x the maximum number of file locks | |
ac50fbac CR |
53 | -T the maximum number of threads |
54 | ||
55 | Not all options are available on all platforms. | |
3185942a JA |
56 | |
57 | If LIMIT is given, it is the new value of the specified resource; the | |
58 | special LIMIT values `soft', `hard', and `unlimited' stand for the | |
59 | current soft limit, the current hard limit, and no limit, respectively. | |
60 | Otherwise, the current value of the specified resource is printed. If | |
61 | no option is given, then -f is assumed. | |
62 | ||
63 | Values are in 1024-byte increments, except for -t, which is in seconds, | |
64 | -p, which is in increments of 512 bytes, and -u, which is an unscaled | |
65 | number of processes. | |
66 | ||
67 | Exit Status: | |
68 | Returns success unless an invalid option is supplied or an error occurs. | |
726f6388 JA |
69 | $END |
70 | ||
cce855bc JA |
71 | #if !defined (_MINIX) |
72 | ||
ccc6cda3 JA |
73 | #include <config.h> |
74 | ||
75 | #include "../bashtypes.h" | |
ac50fbac | 76 | #if defined (HAVE_SYS_PARAM_H) |
cce855bc JA |
77 | # include <sys/param.h> |
78 | #endif | |
ccc6cda3 JA |
79 | |
80 | #if defined (HAVE_UNISTD_H) | |
81 | # include <unistd.h> | |
82 | #endif | |
83 | ||
84 | #include <stdio.h> | |
726f6388 | 85 | #include <errno.h> |
ccc6cda3 | 86 | |
b80f6443 JA |
87 | #include "../bashintl.h" |
88 | ||
726f6388 | 89 | #include "../shell.h" |
ccc6cda3 JA |
90 | #include "common.h" |
91 | #include "bashgetopt.h" | |
726f6388 JA |
92 | #include "pipesize.h" |
93 | ||
94 | #if !defined (errno) | |
95 | extern int errno; | |
96 | #endif | |
97 | ||
ccc6cda3 JA |
98 | /* For some reason, HPUX chose to make these definitions visible only if |
99 | _KERNEL is defined, so we define _KERNEL before including <sys/resource.h> | |
100 | and #undef it afterward. */ | |
726f6388 JA |
101 | #if defined (HAVE_RESOURCE) |
102 | # include <sys/time.h> | |
ccc6cda3 JA |
103 | # if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL) |
104 | # define _KERNEL | |
105 | # endif | |
726f6388 | 106 | # include <sys/resource.h> |
ccc6cda3 JA |
107 | # if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL) |
108 | # undef _KERNEL | |
109 | # endif | |
3185942a | 110 | #elif defined (HAVE_SYS_TIMES_H) |
726f6388 JA |
111 | # include <sys/times.h> |
112 | #endif | |
113 | ||
726f6388 JA |
114 | #if defined (HAVE_LIMITS_H) |
115 | # include <limits.h> | |
116 | #endif | |
117 | ||
118 | /* Check for the most basic symbols. If they aren't present, this | |
119 | system's <sys/resource.h> isn't very useful to us. */ | |
ccc6cda3 | 120 | #if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT) |
726f6388 JA |
121 | # undef HAVE_RESOURCE |
122 | #endif | |
123 | ||
495aee44 CR |
124 | #if !defined (HAVE_RESOURCE) && defined (HAVE_ULIMIT_H) |
125 | # include <ulimit.h> | |
126 | #endif | |
127 | ||
726f6388 JA |
128 | #if !defined (RLIMTYPE) |
129 | # define RLIMTYPE long | |
cce855bc | 130 | # define string_to_rlimtype(s) strtol(s, (char **)NULL, 10) |
726f6388 JA |
131 | # define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "") |
132 | #endif | |
133 | ||
ccc6cda3 JA |
134 | /* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */ |
135 | #if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE) | |
136 | # define RLIMIT_NOFILE RLIMIT_OFILE | |
137 | #endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */ | |
726f6388 | 138 | |
ccc6cda3 JA |
139 | /* Some systems have these, some do not. */ |
140 | #ifdef RLIMIT_FSIZE | |
141 | # define RLIMIT_FILESIZE RLIMIT_FSIZE | |
142 | #else | |
143 | # define RLIMIT_FILESIZE 256 | |
144 | #endif | |
145 | ||
146 | #define RLIMIT_PIPESIZE 257 | |
726f6388 | 147 | |
ccc6cda3 JA |
148 | #ifdef RLIMIT_NOFILE |
149 | # define RLIMIT_OPENFILES RLIMIT_NOFILE | |
150 | #else | |
151 | # define RLIMIT_OPENFILES 258 | |
152 | #endif | |
726f6388 | 153 | |
ccc6cda3 JA |
154 | #ifdef RLIMIT_VMEM |
155 | # define RLIMIT_VIRTMEM RLIMIT_VMEM | |
156 | # define RLIMIT_VMBLKSZ 1024 | |
157 | #else | |
158 | # ifdef RLIMIT_AS | |
159 | # define RLIMIT_VIRTMEM RLIMIT_AS | |
160 | # define RLIMIT_VMBLKSZ 1024 | |
161 | # else | |
162 | # define RLIMIT_VIRTMEM 259 | |
163 | # define RLIMIT_VMBLKSZ 1 | |
164 | # endif | |
165 | #endif | |
166 | ||
167 | #ifdef RLIMIT_NPROC | |
168 | # define RLIMIT_MAXUPROC RLIMIT_NPROC | |
169 | #else | |
170 | # define RLIMIT_MAXUPROC 260 | |
171 | #endif | |
726f6388 | 172 | |
ac50fbac CR |
173 | #if !defined (RLIMIT_PTHREAD) && defined (RLIMIT_NTHR) |
174 | # define RLIMIT_PTHREAD RLIMIT_NTHR | |
175 | #endif | |
176 | ||
726f6388 | 177 | #if !defined (RLIM_INFINITY) |
ccc6cda3 | 178 | # define RLIM_INFINITY 0x7fffffff |
726f6388 JA |
179 | #endif |
180 | ||
f73dda09 JA |
181 | #if !defined (RLIM_SAVED_CUR) |
182 | # define RLIM_SAVED_CUR RLIM_INFINITY | |
183 | #endif | |
184 | ||
185 | #if !defined (RLIM_SAVED_MAX) | |
186 | # define RLIM_SAVED_MAX RLIM_INFINITY | |
187 | #endif | |
188 | ||
726f6388 JA |
189 | #define LIMIT_HARD 0x01 |
190 | #define LIMIT_SOFT 0x02 | |
191 | ||
3185942a JA |
192 | /* "Blocks" are defined as 512 bytes when in Posix mode and 1024 bytes |
193 | otherwise. */ | |
194 | #define POSIXBLK -2 | |
195 | ||
196 | #define BLOCKSIZE(x) (((x) == POSIXBLK) ? (posixly_correct ? 512 : 1024) : (x)) | |
197 | ||
198 | extern int posixly_correct; | |
199 | ||
f73dda09 JA |
200 | static int _findlim __P((int)); |
201 | ||
b72432fd | 202 | static int ulimit_internal __P((int, char *, int, int)); |
f73dda09 JA |
203 | |
204 | static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *)); | |
205 | static int set_limit __P((int, RLIMTYPE, int)); | |
206 | ||
b72432fd JA |
207 | static void printone __P((int, RLIMTYPE, int)); |
208 | static void print_all_limits __P((int)); | |
ccc6cda3 | 209 | |
f73dda09 | 210 | static int set_all_limits __P((int, RLIMTYPE)); |
ccc6cda3 | 211 | |
b72432fd JA |
212 | static int filesize __P((RLIMTYPE *)); |
213 | static int pipesize __P((RLIMTYPE *)); | |
f73dda09 JA |
214 | static int getmaxuprc __P((RLIMTYPE *)); |
215 | static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *)); | |
ccc6cda3 JA |
216 | |
217 | typedef struct { | |
218 | int option; /* The ulimit option for this limit. */ | |
219 | int parameter; /* Parameter to pass to get_limit (). */ | |
220 | int block_factor; /* Blocking factor for specific limit. */ | |
3185942a JA |
221 | const char * const description; /* Descriptive string to output. */ |
222 | const char * const units; /* scale */ | |
ccc6cda3 | 223 | } RESOURCE_LIMITS; |
726f6388 | 224 | |
ccc6cda3 | 225 | static RESOURCE_LIMITS limits[] = { |
3185942a JA |
226 | #ifdef RLIMIT_PTHREAD |
227 | { 'T', RLIMIT_PTHREAD, 1, "number of threads", (char *)NULL }, | |
228 | #endif | |
229 | #ifdef RLIMIT_SBSIZE | |
230 | { 'b', RLIMIT_SBSIZE, 1, "socket buffer size", "bytes" }, | |
231 | #endif | |
ccc6cda3 | 232 | #ifdef RLIMIT_CORE |
3185942a | 233 | { 'c', RLIMIT_CORE, POSIXBLK, "core file size", "blocks" }, |
ccc6cda3 JA |
234 | #endif |
235 | #ifdef RLIMIT_DATA | |
f73dda09 | 236 | { 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" }, |
0628567a JA |
237 | #endif |
238 | #ifdef RLIMIT_NICE | |
239 | { 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL }, | |
ccc6cda3 | 240 | #endif |
3185942a | 241 | { 'f', RLIMIT_FILESIZE, POSIXBLK, "file size", "blocks" }, |
95732b49 JA |
242 | #ifdef RLIMIT_SIGPENDING |
243 | { 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL }, | |
244 | #endif | |
ccc6cda3 | 245 | #ifdef RLIMIT_MEMLOCK |
f73dda09 | 246 | { 'l', RLIMIT_MEMLOCK, 1024, "max locked memory", "kbytes" }, |
ccc6cda3 JA |
247 | #endif |
248 | #ifdef RLIMIT_RSS | |
f73dda09 | 249 | { 'm', RLIMIT_RSS, 1024, "max memory size", "kbytes" }, |
ccc6cda3 | 250 | #endif /* RLIMIT_RSS */ |
f73dda09 JA |
251 | { 'n', RLIMIT_OPENFILES, 1, "open files", (char *)NULL}, |
252 | { 'p', RLIMIT_PIPESIZE, 512, "pipe size", "512 bytes" }, | |
95732b49 JA |
253 | #ifdef RLIMIT_MSGQUEUE |
254 | { 'q', RLIMIT_MSGQUEUE, 1, "POSIX message queues", "bytes" }, | |
255 | #endif | |
0628567a JA |
256 | #ifdef RLIMIT_RTPRIO |
257 | { 'r', RLIMIT_RTPRIO, 1, "real-time priority", (char *)NULL }, | |
258 | #endif | |
ccc6cda3 | 259 | #ifdef RLIMIT_STACK |
f73dda09 | 260 | { 's', RLIMIT_STACK, 1024, "stack size", "kbytes" }, |
ccc6cda3 JA |
261 | #endif |
262 | #ifdef RLIMIT_CPU | |
f73dda09 | 263 | { 't', RLIMIT_CPU, 1, "cpu time", "seconds" }, |
ccc6cda3 | 264 | #endif /* RLIMIT_CPU */ |
f73dda09 | 265 | { 'u', RLIMIT_MAXUPROC, 1, "max user processes", (char *)NULL }, |
726f6388 | 266 | #if defined (HAVE_RESOURCE) |
f73dda09 | 267 | { 'v', RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" }, |
28ef6c31 JA |
268 | #endif |
269 | #ifdef RLIMIT_SWAP | |
f73dda09 | 270 | { 'w', RLIMIT_SWAP, 1024, "swap size", "kbytes" }, |
95732b49 JA |
271 | #endif |
272 | #ifdef RLIMIT_LOCKS | |
273 | { 'x', RLIMIT_LOCKS, 1, "file locks", (char *)NULL }, | |
ccc6cda3 | 274 | #endif |
f73dda09 | 275 | { -1, -1, -1, (char *)NULL, (char *)NULL } |
ccc6cda3 JA |
276 | }; |
277 | #define NCMDS (sizeof(limits) / sizeof(limits[0])) | |
726f6388 | 278 | |
ccc6cda3 JA |
279 | typedef struct _cmd { |
280 | int cmd; | |
281 | char *arg; | |
282 | } ULCMD; | |
726f6388 | 283 | |
ccc6cda3 JA |
284 | static ULCMD *cmdlist; |
285 | static int ncmd; | |
286 | static int cmdlistsz; | |
726f6388 | 287 | |
d166f048 JA |
288 | #if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT) |
289 | long | |
290 | ulimit (cmd, newlim) | |
291 | int cmd; | |
292 | long newlim; | |
293 | { | |
294 | errno = EINVAL; | |
295 | return -1; | |
296 | } | |
297 | #endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */ | |
298 | ||
726f6388 | 299 | static int |
ccc6cda3 JA |
300 | _findlim (opt) |
301 | int opt; | |
726f6388 | 302 | { |
ccc6cda3 | 303 | register int i; |
726f6388 | 304 | |
ccc6cda3 JA |
305 | for (i = 0; limits[i].option > 0; i++) |
306 | if (limits[i].option == opt) | |
307 | return i; | |
308 | return -1; | |
726f6388 | 309 | } |
726f6388 | 310 | |
ccc6cda3 | 311 | static char optstring[4 + 2 * NCMDS]; |
726f6388 | 312 | |
ccc6cda3 JA |
313 | /* Report or set limits associated with certain per-process resources. |
314 | See the help documentation in builtins.c for a full description. */ | |
726f6388 JA |
315 | int |
316 | ulimit_builtin (list) | |
317 | register WORD_LIST *list; | |
318 | { | |
319 | register char *s; | |
ccc6cda3 | 320 | int c, limind, mode, opt, all_limits; |
726f6388 | 321 | |
ccc6cda3 | 322 | mode = 0; |
726f6388 | 323 | |
ccc6cda3 | 324 | all_limits = 0; |
726f6388 | 325 | |
ccc6cda3 JA |
326 | /* Idea stolen from pdksh -- build option string the first time called. */ |
327 | if (optstring[0] == 0) | |
328 | { | |
329 | s = optstring; | |
330 | *s++ = 'a'; *s++ = 'S'; *s++ = 'H'; | |
331 | for (c = 0; limits[c].option > 0; c++) | |
726f6388 | 332 | { |
ccc6cda3 JA |
333 | *s++ = limits[c].option; |
334 | *s++ = ';'; | |
726f6388 | 335 | } |
ccc6cda3 JA |
336 | *s = '\0'; |
337 | } | |
726f6388 | 338 | |
ccc6cda3 JA |
339 | /* Initialize the command list. */ |
340 | if (cmdlistsz == 0) | |
341 | cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD)); | |
342 | ncmd = 0; | |
343 | ||
344 | reset_internal_getopt (); | |
345 | while ((opt = internal_getopt (list, optstring)) != -1) | |
346 | { | |
347 | switch (opt) | |
726f6388 | 348 | { |
ccc6cda3 JA |
349 | case 'a': |
350 | all_limits++; | |
351 | break; | |
352 | ||
353 | /* -S and -H are modifiers, not real options. */ | |
354 | case 'S': | |
355 | mode |= LIMIT_SOFT; | |
356 | break; | |
357 | ||
358 | case 'H': | |
359 | mode |= LIMIT_HARD; | |
360 | break; | |
361 | ||
362 | case '?': | |
363 | builtin_usage (); | |
364 | return (EX_USAGE); | |
365 | ||
366 | default: | |
367 | if (ncmd >= cmdlistsz) | |
368 | cmdlist = (ULCMD *)xrealloc (cmdlist, (cmdlistsz *= 2) * sizeof (ULCMD)); | |
369 | cmdlist[ncmd].cmd = opt; | |
370 | cmdlist[ncmd++].arg = list_optarg; | |
371 | break; | |
726f6388 | 372 | } |
ccc6cda3 JA |
373 | } |
374 | list = loptend; | |
726f6388 | 375 | |
ccc6cda3 JA |
376 | if (all_limits) |
377 | { | |
f73dda09 JA |
378 | #ifdef NOTYET |
379 | if (list) /* setting */ | |
380 | { | |
381 | if (STREQ (list->word->word, "unlimited") == 0) | |
382 | { | |
b80f6443 | 383 | builtin_error (_("%s: invalid limit argument"), list->word->word); |
f73dda09 JA |
384 | return (EXECUTION_FAILURE); |
385 | } | |
386 | return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY)); | |
387 | } | |
388 | #endif | |
ccc6cda3 | 389 | print_all_limits (mode == 0 ? LIMIT_SOFT : mode); |
3185942a | 390 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 | 391 | } |
726f6388 | 392 | |
ccc6cda3 JA |
393 | /* default is `ulimit -f' */ |
394 | if (ncmd == 0) | |
395 | { | |
396 | cmdlist[ncmd].cmd = 'f'; | |
397 | /* `ulimit something' is same as `ulimit -f something' */ | |
398 | cmdlist[ncmd++].arg = list ? list->word->word : (char *)NULL; | |
399 | if (list) | |
400 | list = list->next; | |
401 | } | |
402 | ||
403 | /* verify each command in the list. */ | |
404 | for (c = 0; c < ncmd; c++) | |
405 | { | |
406 | limind = _findlim (cmdlist[c].cmd); | |
407 | if (limind == -1) | |
726f6388 | 408 | { |
b80f6443 | 409 | builtin_error (_("`%c': bad command"), cmdlist[c].cmd); |
ccc6cda3 | 410 | return (EX_USAGE); |
726f6388 JA |
411 | } |
412 | } | |
ccc6cda3 JA |
413 | |
414 | for (c = 0; c < ncmd; c++) | |
415 | if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE) | |
416 | return (EXECUTION_FAILURE); | |
726f6388 JA |
417 | |
418 | return (EXECUTION_SUCCESS); | |
419 | } | |
420 | ||
ccc6cda3 JA |
421 | static int |
422 | ulimit_internal (cmd, cmdarg, mode, multiple) | |
423 | int cmd; | |
424 | char *cmdarg; | |
425 | int mode, multiple; | |
426 | { | |
427 | int opt, limind, setting; | |
f73dda09 JA |
428 | int block_factor; |
429 | RLIMTYPE soft_limit, hard_limit, real_limit, limit; | |
726f6388 | 430 | |
ccc6cda3 JA |
431 | setting = cmdarg != 0; |
432 | limind = _findlim (cmd); | |
433 | if (mode == 0) | |
434 | mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT; | |
f73dda09 | 435 | opt = get_limit (limind, &soft_limit, &hard_limit); |
ccc6cda3 JA |
436 | if (opt < 0) |
437 | { | |
b80f6443 | 438 | builtin_error (_("%s: cannot get limit: %s"), limits[limind].description, |
7117c2d2 | 439 | strerror (errno)); |
ccc6cda3 JA |
440 | return (EXECUTION_FAILURE); |
441 | } | |
726f6388 | 442 | |
ccc6cda3 JA |
443 | if (setting == 0) /* print the value of the specified limit */ |
444 | { | |
f73dda09 | 445 | printone (limind, (mode & LIMIT_SOFT) ? soft_limit : hard_limit, multiple); |
ccc6cda3 JA |
446 | return (EXECUTION_SUCCESS); |
447 | } | |
448 | ||
449 | /* Setting the limit. */ | |
f73dda09 JA |
450 | if (STREQ (cmdarg, "hard")) |
451 | real_limit = hard_limit; | |
452 | else if (STREQ (cmdarg, "soft")) | |
453 | real_limit = soft_limit; | |
454 | else if (STREQ (cmdarg, "unlimited")) | |
455 | real_limit = RLIM_INFINITY; | |
ccc6cda3 | 456 | else if (all_digits (cmdarg)) |
ccc6cda3 | 457 | { |
f73dda09 | 458 | limit = string_to_rlimtype (cmdarg); |
3185942a | 459 | block_factor = BLOCKSIZE(limits[limind].block_factor); |
f73dda09 | 460 | real_limit = limit * block_factor; |
ccc6cda3 | 461 | |
f73dda09 JA |
462 | if ((real_limit / block_factor) != limit) |
463 | { | |
3185942a | 464 | sh_erange (cmdarg, _("limit")); |
f73dda09 JA |
465 | return (EXECUTION_FAILURE); |
466 | } | |
467 | } | |
468 | else | |
d166f048 | 469 | { |
7117c2d2 | 470 | sh_invalidnum (cmdarg); |
d166f048 JA |
471 | return (EXECUTION_FAILURE); |
472 | } | |
473 | ||
ccc6cda3 JA |
474 | if (set_limit (limind, real_limit, mode) < 0) |
475 | { | |
b80f6443 | 476 | builtin_error (_("%s: cannot modify limit: %s"), limits[limind].description, |
7117c2d2 | 477 | strerror (errno)); |
ccc6cda3 JA |
478 | return (EXECUTION_FAILURE); |
479 | } | |
f73dda09 | 480 | |
ccc6cda3 JA |
481 | return (EXECUTION_SUCCESS); |
482 | } | |
483 | ||
484 | static int | |
f73dda09 JA |
485 | get_limit (ind, softlim, hardlim) |
486 | int ind; | |
487 | RLIMTYPE *softlim, *hardlim; | |
726f6388 | 488 | { |
ccc6cda3 | 489 | RLIMTYPE value; |
726f6388 JA |
490 | #if defined (HAVE_RESOURCE) |
491 | struct rlimit limit; | |
726f6388 JA |
492 | #endif |
493 | ||
ccc6cda3 | 494 | if (limits[ind].parameter >= 256) |
726f6388 | 495 | { |
ccc6cda3 | 496 | switch (limits[ind].parameter) |
726f6388 | 497 | { |
ccc6cda3 | 498 | case RLIMIT_FILESIZE: |
b72432fd JA |
499 | if (filesize (&value) < 0) |
500 | return -1; | |
ccc6cda3 JA |
501 | break; |
502 | case RLIMIT_PIPESIZE: | |
b72432fd JA |
503 | if (pipesize (&value) < 0) |
504 | return -1; | |
ccc6cda3 JA |
505 | break; |
506 | case RLIMIT_OPENFILES: | |
507 | value = (RLIMTYPE)getdtablesize (); | |
508 | break; | |
509 | case RLIMIT_VIRTMEM: | |
f73dda09 | 510 | return (getmaxvm (softlim, hardlim)); |
ccc6cda3 | 511 | case RLIMIT_MAXUPROC: |
f73dda09 | 512 | if (getmaxuprc (&value) < 0) |
b72432fd | 513 | return -1; |
ccc6cda3 JA |
514 | break; |
515 | default: | |
516 | errno = EINVAL; | |
517 | return -1; | |
726f6388 | 518 | } |
f73dda09 | 519 | *softlim = *hardlim = value; |
b72432fd | 520 | return (0); |
ccc6cda3 JA |
521 | } |
522 | else | |
523 | { | |
524 | #if defined (HAVE_RESOURCE) | |
525 | if (getrlimit (limits[ind].parameter, &limit) < 0) | |
526 | return -1; | |
f73dda09 JA |
527 | *softlim = limit.rlim_cur; |
528 | *hardlim = limit.rlim_max; | |
b72432fd JA |
529 | # if defined (HPUX9) |
530 | if (limits[ind].parameter == RLIMIT_FILESIZE) | |
f73dda09 JA |
531 | { |
532 | *softlim *= 512; | |
533 | *hardlim *= 512; /* Ugh. */ | |
534 | } | |
b72432fd JA |
535 | else |
536 | # endif /* HPUX9 */ | |
ccc6cda3 | 537 | return 0; |
726f6388 JA |
538 | #else |
539 | errno = EINVAL; | |
ccc6cda3 JA |
540 | return -1; |
541 | #endif | |
542 | } | |
543 | } | |
726f6388 | 544 | |
ccc6cda3 JA |
545 | static int |
546 | set_limit (ind, newlim, mode) | |
547 | int ind; | |
548 | RLIMTYPE newlim; | |
549 | int mode; | |
550 | { | |
551 | #if defined (HAVE_RESOURCE) | |
552 | struct rlimit limit; | |
553 | RLIMTYPE val; | |
554 | #endif | |
726f6388 | 555 | |
ccc6cda3 JA |
556 | if (limits[ind].parameter >= 256) |
557 | switch (limits[ind].parameter) | |
558 | { | |
559 | case RLIMIT_FILESIZE: | |
560 | #if !defined (HAVE_RESOURCE) | |
561 | return (ulimit (2, newlim / 512L)); | |
d166f048 JA |
562 | #else |
563 | errno = EINVAL; | |
564 | return -1; | |
ccc6cda3 | 565 | #endif |
726f6388 | 566 | |
ccc6cda3 JA |
567 | case RLIMIT_OPENFILES: |
568 | #if defined (HAVE_SETDTABLESIZE) | |
28ef6c31 JA |
569 | # if defined (__CYGWIN__) |
570 | /* Grrr... Cygwin declares setdtablesize as void. */ | |
571 | setdtablesize (newlim); | |
572 | return 0; | |
573 | # else | |
ccc6cda3 | 574 | return (setdtablesize (newlim)); |
28ef6c31 | 575 | # endif |
ccc6cda3 JA |
576 | #endif |
577 | case RLIMIT_PIPESIZE: | |
578 | case RLIMIT_VIRTMEM: | |
579 | case RLIMIT_MAXUPROC: | |
580 | default: | |
581 | errno = EINVAL; | |
582 | return -1; | |
583 | } | |
584 | else | |
585 | { | |
726f6388 | 586 | #if defined (HAVE_RESOURCE) |
ccc6cda3 JA |
587 | if (getrlimit (limits[ind].parameter, &limit) < 0) |
588 | return -1; | |
b72432fd JA |
589 | # if defined (HPUX9) |
590 | if (limits[ind].parameter == RLIMIT_FILESIZE) | |
591 | newlim /= 512; /* Ugh. */ | |
592 | # endif /* HPUX9 */ | |
d166f048 | 593 | val = (current_user.euid != 0 && newlim == RLIM_INFINITY && |
28ef6c31 | 594 | (mode & LIMIT_HARD) == 0 && /* XXX -- test */ |
d166f048 JA |
595 | (limit.rlim_cur <= limit.rlim_max)) |
596 | ? limit.rlim_max : newlim; | |
ccc6cda3 JA |
597 | if (mode & LIMIT_SOFT) |
598 | limit.rlim_cur = val; | |
599 | if (mode & LIMIT_HARD) | |
600 | limit.rlim_max = val; | |
601 | ||
602 | return (setrlimit (limits[ind].parameter, &limit)); | |
603 | #else | |
726f6388 | 604 | errno = EINVAL; |
ccc6cda3 JA |
605 | return -1; |
606 | #endif | |
726f6388 JA |
607 | } |
608 | } | |
609 | ||
b72432fd | 610 | static int |
f73dda09 JA |
611 | getmaxvm (softlim, hardlim) |
612 | RLIMTYPE *softlim, *hardlim; | |
726f6388 | 613 | { |
ccc6cda3 | 614 | #if defined (HAVE_RESOURCE) |
f73dda09 | 615 | struct rlimit datalim, stacklim; |
726f6388 | 616 | |
f73dda09 | 617 | if (getrlimit (RLIMIT_DATA, &datalim) < 0) |
b72432fd | 618 | return -1; |
726f6388 | 619 | |
f73dda09 | 620 | if (getrlimit (RLIMIT_STACK, &stacklim) < 0) |
b72432fd | 621 | return -1; |
726f6388 JA |
622 | |
623 | /* Protect against overflow. */ | |
f73dda09 JA |
624 | *softlim = (datalim.rlim_cur / 1024L) + (stacklim.rlim_cur / 1024L); |
625 | *hardlim = (datalim.rlim_max / 1024L) + (stacklim.rlim_max / 1024L); | |
b72432fd | 626 | return 0; |
ccc6cda3 JA |
627 | #else |
628 | errno = EINVAL; | |
b72432fd | 629 | return -1; |
726f6388 | 630 | #endif /* HAVE_RESOURCE */ |
ccc6cda3 | 631 | } |
726f6388 | 632 | |
b72432fd JA |
633 | static int |
634 | filesize(valuep) | |
635 | RLIMTYPE *valuep; | |
726f6388 | 636 | { |
ccc6cda3 | 637 | #if !defined (HAVE_RESOURCE) |
b72432fd JA |
638 | long result; |
639 | if ((result = ulimit (1, 0L)) < 0) | |
640 | return -1; | |
641 | else | |
f73dda09 | 642 | *valuep = (RLIMTYPE) result * 512; |
b72432fd | 643 | return 0; |
726f6388 | 644 | #else |
ccc6cda3 | 645 | errno = EINVAL; |
b72432fd | 646 | return -1; |
726f6388 JA |
647 | #endif |
648 | } | |
649 | ||
b72432fd JA |
650 | static int |
651 | pipesize (valuep) | |
652 | RLIMTYPE *valuep; | |
726f6388 JA |
653 | { |
654 | #if defined (PIPE_BUF) | |
655 | /* This is defined on Posix systems. */ | |
b72432fd JA |
656 | *valuep = (RLIMTYPE) PIPE_BUF; |
657 | return 0; | |
726f6388 | 658 | #else |
95732b49 JA |
659 | # if defined (_POSIX_PIPE_BUF) |
660 | *valuep = (RLIMTYPE) _POSIX_PIPE_BUF; | |
661 | return 0; | |
662 | # else | |
663 | # if defined (PIPESIZE) | |
726f6388 | 664 | /* This is defined by running a program from the Makefile. */ |
b72432fd JA |
665 | *valuep = (RLIMTYPE) PIPESIZE; |
666 | return 0; | |
95732b49 | 667 | # else |
726f6388 | 668 | errno = EINVAL; |
b72432fd | 669 | return -1; |
95732b49 JA |
670 | # endif /* PIPESIZE */ |
671 | # endif /* _POSIX_PIPE_BUF */ | |
726f6388 JA |
672 | #endif /* PIPE_BUF */ |
673 | } | |
674 | ||
b72432fd | 675 | static int |
f73dda09 | 676 | getmaxuprc (valuep) |
b72432fd | 677 | RLIMTYPE *valuep; |
726f6388 | 678 | { |
b72432fd | 679 | long maxchild; |
7117c2d2 JA |
680 | |
681 | maxchild = getmaxchild (); | |
b72432fd | 682 | if (maxchild < 0) |
7117c2d2 JA |
683 | { |
684 | errno = EINVAL; | |
685 | return -1; | |
686 | } | |
b72432fd | 687 | else |
7117c2d2 JA |
688 | { |
689 | *valuep = (RLIMTYPE) maxchild; | |
690 | return 0; | |
691 | } | |
726f6388 JA |
692 | } |
693 | ||
694 | static void | |
ccc6cda3 JA |
695 | print_all_limits (mode) |
696 | int mode; | |
726f6388 JA |
697 | { |
698 | register int i; | |
f73dda09 | 699 | RLIMTYPE softlim, hardlim; |
726f6388 | 700 | |
726f6388 | 701 | if (mode == 0) |
ccc6cda3 | 702 | mode |= LIMIT_SOFT; |
726f6388 | 703 | |
ccc6cda3 | 704 | for (i = 0; limits[i].option > 0; i++) |
726f6388 | 705 | { |
95732b49 JA |
706 | if (get_limit (i, &softlim, &hardlim) == 0) |
707 | printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1); | |
708 | else if (errno != EINVAL) | |
7117c2d2 JA |
709 | builtin_error ("%s: cannot get limit: %s", limits[i].description, |
710 | strerror (errno)); | |
726f6388 | 711 | } |
726f6388 JA |
712 | } |
713 | ||
714 | static void | |
ccc6cda3 JA |
715 | printone (limind, curlim, pdesc) |
716 | int limind; | |
717 | RLIMTYPE curlim; | |
718 | int pdesc; | |
726f6388 | 719 | { |
f73dda09 | 720 | char unitstr[64]; |
3185942a | 721 | int factor; |
f73dda09 | 722 | |
3185942a | 723 | factor = BLOCKSIZE(limits[limind].block_factor); |
ccc6cda3 | 724 | if (pdesc) |
f73dda09 JA |
725 | { |
726 | if (limits[limind].units) | |
727 | sprintf (unitstr, "(%s, -%c) ", limits[limind].units, limits[limind].option); | |
728 | else | |
729 | sprintf (unitstr, "(-%c) ", limits[limind].option); | |
730 | ||
95732b49 | 731 | printf ("%-20s %16s", limits[limind].description, unitstr); |
f73dda09 | 732 | } |
ccc6cda3 JA |
733 | if (curlim == RLIM_INFINITY) |
734 | puts ("unlimited"); | |
f73dda09 JA |
735 | else if (curlim == RLIM_SAVED_MAX) |
736 | puts ("hard"); | |
737 | else if (curlim == RLIM_SAVED_CUR) | |
738 | puts ("soft"); | |
ccc6cda3 | 739 | else |
3185942a | 740 | print_rlimtype ((curlim / factor), 1); |
726f6388 | 741 | } |
f73dda09 JA |
742 | |
743 | /* Set all limits to NEWLIM. NEWLIM currently must be RLIM_INFINITY, which | |
744 | causes all limits to be set as high as possible depending on mode (like | |
745 | csh `unlimit'). Returns -1 if NEWLIM is invalid, 0 if all limits | |
746 | were set successfully, and 1 if at least one limit could not be set. | |
747 | ||
748 | To raise all soft limits to their corresponding hard limits, use | |
749 | ulimit -S -a unlimited | |
750 | To attempt to raise all hard limits to infinity (superuser-only), use | |
751 | ulimit -H -a unlimited | |
752 | To attempt to raise all soft and hard limits to infinity, use | |
753 | ulimit -a unlimited | |
754 | */ | |
755 | ||
756 | static int | |
757 | set_all_limits (mode, newlim) | |
758 | int mode; | |
759 | RLIMTYPE newlim; | |
760 | { | |
761 | register int i; | |
762 | int retval = 0; | |
763 | ||
764 | if (newlim != RLIM_INFINITY) | |
765 | { | |
766 | errno = EINVAL; | |
767 | return -1; | |
768 | } | |
769 | ||
770 | if (mode == 0) | |
771 | mode = LIMIT_SOFT|LIMIT_HARD; | |
772 | ||
773 | for (retval = i = 0; limits[i].option > 0; i++) | |
774 | if (set_limit (i, newlim, mode) < 0) | |
775 | { | |
3185942a | 776 | builtin_error (_("%s: cannot modify limit: %s"), limits[i].description, |
7117c2d2 | 777 | strerror (errno)); |
f73dda09 JA |
778 | retval = 1; |
779 | } | |
780 | return retval; | |
781 | } | |
782 | ||
cce855bc | 783 | #endif /* !_MINIX */ |