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