]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/ulimit.def
f3d0c8e563be6d120185093cd4e0e7cff886a93b
[thirdparty/bash.git] / builtins / ulimit.def
1 This file is ulimit.def, from which is created ulimit.c.
2 It implements the builtin "ulimit" in Bash.
3
4 Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 $PRODUCES ulimit.c
23
24 $BUILTIN ulimit
25 $FUNCTION ulimit_builtin
26 $DEPENDS_ON !_MINIX
27 $SHORT_DOC ulimit [-SHacdflmnpstuv] [limit]
28 Ulimit provides control over the resources available to processes
29 started by the shell, on systems that allow such control. If an
30 option is given, it is interpreted as follows:
31
32 -S use the `soft' resource limit
33 -H use the `hard' resource limit
34 -a all current limits are reported
35 -c the maximum size of core files created
36 -d the maximum size of a process's data segment
37 -f the maximum size of files created by the shell
38 -l the maximum size a process may lock into memory
39 -m the maximum resident set size
40 -n the maximum number of open file descriptors
41 -p the pipe buffer size
42 -s the maximum stack size
43 -t the maximum amount of cpu time in seconds
44 -u the maximum number of user processes
45 -v the size of virtual memory
46
47 If LIMIT is given, it is the new value of the specified resource.
48 Otherwise, the current value of the specified resource is printed.
49 If no option is given, then -f is assumed. Values are in 1024-byte
50 increments, except for -t, which is in seconds, -p, which is in
51 increments of 512 bytes, and -u, which is an unscaled number of
52 processes.
53 $END
54
55 #if !defined (_MINIX)
56
57 #include <config.h>
58
59 #include "../bashtypes.h"
60 #ifndef _MINIX
61 # include <sys/param.h>
62 #endif
63
64 #if defined (HAVE_UNISTD_H)
65 # include <unistd.h>
66 #endif
67
68 #include <stdio.h>
69 #include <errno.h>
70
71 #include "../shell.h"
72 #include "common.h"
73 #include "bashgetopt.h"
74 #include "pipesize.h"
75
76 #if !defined (errno)
77 extern int errno;
78 #endif
79
80 /* For some reason, HPUX chose to make these definitions visible only if
81 _KERNEL is defined, so we define _KERNEL before including <sys/resource.h>
82 and #undef it afterward. */
83 #if defined (HAVE_RESOURCE)
84 # include <sys/time.h>
85 # if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
86 # define _KERNEL
87 # endif
88 # include <sys/resource.h>
89 # if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
90 # undef _KERNEL
91 # endif
92 #else
93 # include <sys/times.h>
94 #endif
95
96 #if defined (HAVE_LIMITS_H)
97 # include <limits.h>
98 #endif
99
100 /* Check for the most basic symbols. If they aren't present, this
101 system's <sys/resource.h> isn't very useful to us. */
102 #if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
103 # undef HAVE_RESOURCE
104 #endif
105
106 #if !defined (RLIMTYPE)
107 # define RLIMTYPE long
108 # define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
109 # define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
110 #endif
111
112 #define DESCFMT "%-28s"
113
114 /* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
115 #if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
116 # define RLIMIT_NOFILE RLIMIT_OFILE
117 #endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
118
119 /* Some systems have these, some do not. */
120 #ifdef RLIMIT_FSIZE
121 # define RLIMIT_FILESIZE RLIMIT_FSIZE
122 #else
123 # define RLIMIT_FILESIZE 256
124 #endif
125
126 #define RLIMIT_PIPESIZE 257
127
128 #ifdef RLIMIT_NOFILE
129 # define RLIMIT_OPENFILES RLIMIT_NOFILE
130 #else
131 # define RLIMIT_OPENFILES 258
132 #endif
133
134 #ifdef RLIMIT_VMEM
135 # define RLIMIT_VIRTMEM RLIMIT_VMEM
136 # define RLIMIT_VMBLKSZ 1024
137 #else
138 # ifdef RLIMIT_AS
139 # define RLIMIT_VIRTMEM RLIMIT_AS
140 # define RLIMIT_VMBLKSZ 1024
141 # else
142 # define RLIMIT_VIRTMEM 259
143 # define RLIMIT_VMBLKSZ 1
144 # endif
145 #endif
146
147 #ifdef RLIMIT_NPROC
148 # define RLIMIT_MAXUPROC RLIMIT_NPROC
149 #else
150 # define RLIMIT_MAXUPROC 260
151 #endif
152
153 #if !defined (RLIM_INFINITY)
154 # define RLIM_INFINITY 0x7fffffff
155 #endif
156
157 #define LIMIT_HARD 0x01
158 #define LIMIT_SOFT 0x02
159
160 static int ulimit_internal __P((int, char *, int, int));
161 static void printone __P((int, RLIMTYPE, int));
162 static void print_all_limits __P((int));
163
164 static int get_limit __P((int, int, RLIMTYPE *));
165 static int set_limit __P((int, RLIMTYPE, int));
166
167 static int filesize __P((RLIMTYPE *));
168 static int pipesize __P((RLIMTYPE *));
169 static int getmaxuprc __P((int, RLIMTYPE *));
170 static int getmaxvm __P((int, RLIMTYPE *));
171
172 typedef struct {
173 int option; /* The ulimit option for this limit. */
174 int parameter; /* Parameter to pass to get_limit (). */
175 int block_factor; /* Blocking factor for specific limit. */
176 char *description; /* Descriptive string to output. */
177 } RESOURCE_LIMITS;
178
179 static RESOURCE_LIMITS limits[] = {
180 #ifdef RLIMIT_CORE
181 { 'c', RLIMIT_CORE, 1024, "core file size (blocks)" },
182 #endif
183 #ifdef RLIMIT_DATA
184 { 'd', RLIMIT_DATA, 1024, "data seg size (kbytes)" },
185 #endif
186 { 'f', RLIMIT_FILESIZE, 1024, "file size (blocks)" },
187 #ifdef RLIMIT_MEMLOCK
188 { 'l', RLIMIT_MEMLOCK, 1024, "max locked memory (kbytes)" },
189 #endif
190 #ifdef RLIMIT_RSS
191 { 'm', RLIMIT_RSS, 1024, "max memory size (kbytes)" },
192 #endif /* RLIMIT_RSS */
193 { 'n', RLIMIT_OPENFILES, 1, "open files" },
194 { 'p', RLIMIT_PIPESIZE, 512, "pipe size (512 bytes)" },
195 #ifdef RLIMIT_STACK
196 { 's', RLIMIT_STACK, 1024, "stack size (kbytes)" },
197 #endif
198 #ifdef RLIMIT_CPU
199 { 't', RLIMIT_CPU, 1, "cpu time (seconds)" },
200 #endif /* RLIMIT_CPU */
201 { 'u', RLIMIT_MAXUPROC, 1, "max user processes" },
202 #if defined (HAVE_RESOURCE)
203 { 'v', RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory (kbytes)" },
204 #endif
205 { -1, -1, -1, (char *)NULL }
206 };
207 #define NCMDS (sizeof(limits) / sizeof(limits[0]))
208
209 typedef struct _cmd {
210 int cmd;
211 char *arg;
212 } ULCMD;
213
214 static ULCMD *cmdlist;
215 static int ncmd;
216 static int cmdlistsz;
217
218 #if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
219 long
220 ulimit (cmd, newlim)
221 int cmd;
222 long newlim;
223 {
224 errno = EINVAL;
225 return -1;
226 }
227 #endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
228
229 static int
230 _findlim (opt)
231 int opt;
232 {
233 register int i;
234
235 for (i = 0; limits[i].option > 0; i++)
236 if (limits[i].option == opt)
237 return i;
238 return -1;
239 }
240
241 static char optstring[4 + 2 * NCMDS];
242
243 /* Report or set limits associated with certain per-process resources.
244 See the help documentation in builtins.c for a full description. */
245 int
246 ulimit_builtin (list)
247 register WORD_LIST *list;
248 {
249 register char *s;
250 int c, limind, mode, opt, all_limits;
251
252 mode = 0;
253
254 all_limits = 0;
255
256 /* Idea stolen from pdksh -- build option string the first time called. */
257 if (optstring[0] == 0)
258 {
259 s = optstring;
260 *s++ = 'a'; *s++ = 'S'; *s++ = 'H';
261 for (c = 0; limits[c].option > 0; c++)
262 {
263 *s++ = limits[c].option;
264 *s++ = ';';
265 }
266 *s = '\0';
267 }
268
269 /* Initialize the command list. */
270 if (cmdlistsz == 0)
271 cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD));
272 ncmd = 0;
273
274 reset_internal_getopt ();
275 while ((opt = internal_getopt (list, optstring)) != -1)
276 {
277 switch (opt)
278 {
279 case 'a':
280 all_limits++;
281 break;
282
283 /* -S and -H are modifiers, not real options. */
284 case 'S':
285 mode |= LIMIT_SOFT;
286 break;
287
288 case 'H':
289 mode |= LIMIT_HARD;
290 break;
291
292 case '?':
293 builtin_usage ();
294 return (EX_USAGE);
295
296 default:
297 if (ncmd >= cmdlistsz)
298 cmdlist = (ULCMD *)xrealloc (cmdlist, (cmdlistsz *= 2) * sizeof (ULCMD));
299 cmdlist[ncmd].cmd = opt;
300 cmdlist[ncmd++].arg = list_optarg;
301 break;
302 }
303 }
304 list = loptend;
305
306 if (all_limits)
307 {
308 print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
309 return (EXECUTION_SUCCESS);
310 }
311
312 /* default is `ulimit -f' */
313 if (ncmd == 0)
314 {
315 cmdlist[ncmd].cmd = 'f';
316 /* `ulimit something' is same as `ulimit -f something' */
317 cmdlist[ncmd++].arg = list ? list->word->word : (char *)NULL;
318 if (list)
319 list = list->next;
320 }
321
322 /* verify each command in the list. */
323 for (c = 0; c < ncmd; c++)
324 {
325 limind = _findlim (cmdlist[c].cmd);
326 if (limind == -1)
327 {
328 builtin_error ("bad command: `%c'", cmdlist[c].cmd);
329 return (EX_USAGE);
330 }
331 }
332
333 for (c = 0; c < ncmd; c++)
334 if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
335 return (EXECUTION_FAILURE);
336
337 return (EXECUTION_SUCCESS);
338 }
339
340 static int
341 ulimit_internal (cmd, cmdarg, mode, multiple)
342 int cmd;
343 char *cmdarg;
344 int mode, multiple;
345 {
346 int opt, limind, setting;
347 long block_factor;
348 RLIMTYPE current_limit, real_limit, limit;
349
350 setting = cmdarg != 0;
351 limind = _findlim (cmd);
352 if (mode == 0)
353 mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
354 opt = get_limit (limind, mode, &current_limit);
355 if (opt < 0)
356 {
357 builtin_error ("cannot get limit: %s", strerror (errno));
358 return (EXECUTION_FAILURE);
359 }
360
361 if (setting == 0) /* print the value of the specified limit */
362 {
363 printone (limind, current_limit, multiple);
364 return (EXECUTION_SUCCESS);
365 }
366
367 /* Setting the limit. */
368 if (STREQ (cmdarg, "unlimited"))
369 limit = RLIM_INFINITY;
370 else if (all_digits (cmdarg))
371 limit = string_to_rlimtype (cmdarg);
372 else
373 {
374 builtin_error ("bad non-numeric arg `%s'", cmdarg);
375 return (EXECUTION_FAILURE);
376 }
377
378 block_factor = (limit == RLIM_INFINITY) ? 1 : limits[limind].block_factor;
379 real_limit = limit * block_factor;
380
381 if (real_limit < 0 || (real_limit == 0 && limit != 0))
382 {
383 builtin_error ("limit out of range: %d", limit);
384 return (EXECUTION_FAILURE);
385 }
386
387 if (set_limit (limind, real_limit, mode) < 0)
388 {
389 builtin_error ("cannot modify limit: %s", strerror (errno));
390 return (EXECUTION_FAILURE);
391 }
392 return (EXECUTION_SUCCESS);
393 }
394
395 static int
396 get_limit (ind, mode, limptr)
397 int ind, mode;
398 RLIMTYPE *limptr;
399 {
400 RLIMTYPE value;
401 #if defined (HAVE_RESOURCE)
402 struct rlimit limit;
403 #endif
404
405 if (limits[ind].parameter >= 256)
406 {
407 switch (limits[ind].parameter)
408 {
409 case RLIMIT_FILESIZE:
410 if (filesize (&value) < 0)
411 return -1;
412 break;
413 case RLIMIT_PIPESIZE:
414 if (pipesize (&value) < 0)
415 return -1;
416 break;
417 case RLIMIT_OPENFILES:
418 value = (RLIMTYPE)getdtablesize ();
419 break;
420 case RLIMIT_VIRTMEM:
421 if (getmaxvm (mode, &value) < 0)
422 return -1;
423 break;
424 case RLIMIT_MAXUPROC:
425 if (getmaxuprc (mode, &value) < 0)
426 return -1;
427 break;
428 default:
429 errno = EINVAL;
430 return -1;
431 }
432 *limptr = value;
433 return (0);
434 }
435 else
436 {
437 #if defined (HAVE_RESOURCE)
438 if (getrlimit (limits[ind].parameter, &limit) < 0)
439 return -1;
440 value = (mode & LIMIT_SOFT) ? limit.rlim_cur : limit.rlim_max;
441 # if defined (HPUX9)
442 if (limits[ind].parameter == RLIMIT_FILESIZE)
443 *limptr = value * 512; /* Ugh. */
444 else
445 # endif /* HPUX9 */
446 *limptr = value;
447 return 0;
448 #else
449 errno = EINVAL;
450 return -1;
451 #endif
452 }
453 }
454
455 static int
456 set_limit (ind, newlim, mode)
457 int ind;
458 RLIMTYPE newlim;
459 int mode;
460 {
461 #if defined (HAVE_RESOURCE)
462 struct rlimit limit;
463 RLIMTYPE val;
464 #endif
465
466 if (limits[ind].parameter >= 256)
467 switch (limits[ind].parameter)
468 {
469 case RLIMIT_FILESIZE:
470 #if !defined (HAVE_RESOURCE)
471 return (ulimit (2, newlim / 512L));
472 #else
473 errno = EINVAL;
474 return -1;
475 #endif
476
477 case RLIMIT_OPENFILES:
478 #if defined (HAVE_SETDTABLESIZE)
479 return (setdtablesize (newlim));
480 #endif
481 case RLIMIT_PIPESIZE:
482 case RLIMIT_VIRTMEM:
483 case RLIMIT_MAXUPROC:
484 default:
485 errno = EINVAL;
486 return -1;
487 }
488 else
489 {
490 #if defined (HAVE_RESOURCE)
491 if (getrlimit (limits[ind].parameter, &limit) < 0)
492 return -1;
493 # if defined (HPUX9)
494 if (limits[ind].parameter == RLIMIT_FILESIZE)
495 newlim /= 512; /* Ugh. */
496 # endif /* HPUX9 */
497 val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
498 (limit.rlim_cur <= limit.rlim_max))
499 ? limit.rlim_max : newlim;
500 if (mode & LIMIT_SOFT)
501 limit.rlim_cur = val;
502 if (mode & LIMIT_HARD)
503 limit.rlim_max = val;
504
505 return (setrlimit (limits[ind].parameter, &limit));
506 #else
507 errno = EINVAL;
508 return -1;
509 #endif
510 }
511 }
512
513 static int
514 getmaxvm (mode, valuep)
515 int mode;
516 RLIMTYPE *valuep;
517 {
518 #if defined (HAVE_RESOURCE)
519 struct rlimit rl;
520 RLIMTYPE maxdata, maxstack;
521
522 if (getrlimit (RLIMIT_DATA, &rl) < 0)
523 return -1;
524 else
525 maxdata = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
526
527 if (getrlimit (RLIMIT_STACK, &rl) < 0)
528 return -1;
529 else
530 maxstack = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
531
532 /* Protect against overflow. */
533 *valuep = (maxdata / 1024L) + (maxstack / 1024L);
534 return 0;
535 #else
536 errno = EINVAL;
537 return -1;
538 #endif /* HAVE_RESOURCE */
539 }
540
541 static int
542 filesize(valuep)
543 RLIMTYPE *valuep;
544 {
545 #if !defined (HAVE_RESOURCE)
546 long result;
547 if ((result = ulimit (1, 0L)) < 0)
548 return -1;
549 else
550 *valuep = (RLIMTYPE) result;
551 return 0;
552 #else
553 errno = EINVAL;
554 return -1;
555 #endif
556 }
557
558 static int
559 pipesize (valuep)
560 RLIMTYPE *valuep;
561 {
562 #if defined (PIPE_BUF)
563 /* This is defined on Posix systems. */
564 *valuep = (RLIMTYPE) PIPE_BUF;
565 return 0;
566 #else
567 # if defined (PIPESIZE)
568 /* This is defined by running a program from the Makefile. */
569 *valuep = (RLIMTYPE) PIPESIZE;
570 return 0;
571 # else
572 errno = EINVAL;
573 return -1;
574 # endif /* PIPESIZE */
575 #endif /* PIPE_BUF */
576 }
577
578 static int
579 getmaxuprc (mode, valuep)
580 int mode;
581 RLIMTYPE *valuep;
582 {
583 # if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
584 long maxchild;
585 maxchild = sysconf (_SC_CHILD_MAX);
586 if (maxchild < 0)
587 return -1;
588 else
589 *valuep = (RLIMTYPE) maxchild;
590 return 0;
591 # else /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
592 # if defined (MAXUPRC)
593 *valuep = (RLIMTYPE) MAXUPRC;
594 return 0;
595 # else /* MAXUPRC */
596 errno = EINVAL;
597 return -1;
598 # endif /* !MAXUPRC */
599 # endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
600 }
601
602 static void
603 print_all_limits (mode)
604 int mode;
605 {
606 register int i;
607 RLIMTYPE value;
608
609 if (mode == 0)
610 mode |= LIMIT_SOFT;
611
612 for (i = 0; limits[i].option > 0; i++)
613 {
614 if (get_limit (i, mode, &value) < 0)
615 {
616 fprintf (stderr, DESCFMT, limits[i].description);
617 builtin_error ("cannot get limit: %s", strerror (errno));
618 }
619 else
620 printone (i, value, 1);
621 }
622 }
623
624 static void
625 printone (limind, curlim, pdesc)
626 int limind;
627 RLIMTYPE curlim;
628 int pdesc;
629 {
630 if (pdesc)
631 printf (DESCFMT, limits[limind].description);
632 if (curlim == RLIM_INFINITY)
633 puts ("unlimited");
634 else
635 print_rlimtype ((curlim / limits[limind].block_factor), 1);
636 }
637 #endif /* !_MINIX */