1 This file is ulimit.def, from which is created ulimit.c.
2 It implements the builtin "ulimit" in Bash.
4 Copyright (C) 1987-2005 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
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 2, or (at your option) any later
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
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, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
25 $FUNCTION ulimit_builtin
27 $SHORT_DOC ulimit [-SHacdfilmnpqstuvx] [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:
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 -e the maximum scheduling priority (`nice')
38 -f the maximum size of files written by the shell and its children
39 -i the maximum number of pending signals
40 -l the maximum size a process may lock into memory
41 -m the maximum resident set size
42 -n the maximum number of open file descriptors
43 -p the pipe buffer size
44 -q the maximum number of bytes in POSIX message queues
45 -r the maximum real-time scheduling priority
46 -s the maximum stack size
47 -t the maximum amount of cpu time in seconds
48 -u the maximum number of user processes
49 -v the size of virtual memory
50 -x the maximum number of file locks
52 If LIMIT is given, it is the new value of the specified resource;
53 the special LIMIT values `soft', `hard', and `unlimited' stand for
54 the current soft limit, the current hard limit, and no limit, respectively.
55 Otherwise, the current value of the specified resource is printed.
56 If no option is given, then -f is assumed. Values are in 1024-byte
57 increments, except for -t, which is in seconds, -p, which is in
58 increments of 512 bytes, and -u, which is an unscaled number of
66 #include "../bashtypes.h"
68 # include <sys/param.h>
71 #if defined (HAVE_UNISTD_H)
78 #include "../bashintl.h"
82 #include "bashgetopt.h"
89 /* For some reason, HPUX chose to make these definitions visible only if
90 _KERNEL is defined, so we define _KERNEL before including <sys/resource.h>
91 and #undef it afterward. */
92 #if defined (HAVE_RESOURCE)
93 # include <sys/time.h>
94 # if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
97 # include <sys/resource.h>
98 # if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
102 # include <sys/times.h>
105 #if defined (HAVE_LIMITS_H)
109 /* Check for the most basic symbols. If they aren't present, this
110 system's <sys/resource.h> isn't very useful to us. */
111 #if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
112 # undef HAVE_RESOURCE
115 #if !defined (RLIMTYPE)
116 # define RLIMTYPE long
117 # define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
118 # define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
121 /* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
122 #if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
123 # define RLIMIT_NOFILE RLIMIT_OFILE
124 #endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
126 /* Some systems have these, some do not. */
128 # define RLIMIT_FILESIZE RLIMIT_FSIZE
130 # define RLIMIT_FILESIZE 256
133 #define RLIMIT_PIPESIZE 257
136 # define RLIMIT_OPENFILES RLIMIT_NOFILE
138 # define RLIMIT_OPENFILES 258
142 # define RLIMIT_VIRTMEM RLIMIT_VMEM
143 # define RLIMIT_VMBLKSZ 1024
146 # define RLIMIT_VIRTMEM RLIMIT_AS
147 # define RLIMIT_VMBLKSZ 1024
149 # define RLIMIT_VIRTMEM 259
150 # define RLIMIT_VMBLKSZ 1
155 # define RLIMIT_MAXUPROC RLIMIT_NPROC
157 # define RLIMIT_MAXUPROC 260
160 #if !defined (RLIM_INFINITY)
161 # define RLIM_INFINITY 0x7fffffff
164 #if !defined (RLIM_SAVED_CUR)
165 # define RLIM_SAVED_CUR RLIM_INFINITY
168 #if !defined (RLIM_SAVED_MAX)
169 # define RLIM_SAVED_MAX RLIM_INFINITY
172 #define LIMIT_HARD 0x01
173 #define LIMIT_SOFT 0x02
175 static int _findlim __P((int));
177 static int ulimit_internal __P((int, char *, int, int));
179 static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *));
180 static int set_limit __P((int, RLIMTYPE, int));
182 static void printone __P((int, RLIMTYPE, int));
183 static void print_all_limits __P((int));
185 static int set_all_limits __P((int, RLIMTYPE));
187 static int filesize __P((RLIMTYPE *));
188 static int pipesize __P((RLIMTYPE *));
189 static int getmaxuprc __P((RLIMTYPE *));
190 static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *));
193 int option; /* The ulimit option for this limit. */
194 int parameter; /* Parameter to pass to get_limit (). */
195 int block_factor; /* Blocking factor for specific limit. */
196 char *description; /* Descriptive string to output. */
197 char *units; /* scale */
200 static RESOURCE_LIMITS limits[] = {
202 { 'c', RLIMIT_CORE, 1024, "core file size", "blocks" },
205 { 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
208 { 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL },
210 { 'f', RLIMIT_FILESIZE, 1024, "file size", "blocks" },
211 #ifdef RLIMIT_SIGPENDING
212 { 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
214 #ifdef RLIMIT_MEMLOCK
215 { 'l', RLIMIT_MEMLOCK, 1024, "max locked memory", "kbytes" },
218 { 'm', RLIMIT_RSS, 1024, "max memory size", "kbytes" },
219 #endif /* RLIMIT_RSS */
220 { 'n', RLIMIT_OPENFILES, 1, "open files", (char *)NULL},
221 { 'p', RLIMIT_PIPESIZE, 512, "pipe size", "512 bytes" },
222 #ifdef RLIMIT_MSGQUEUE
223 { 'q', RLIMIT_MSGQUEUE, 1, "POSIX message queues", "bytes" },
226 { 'r', RLIMIT_RTPRIO, 1, "real-time priority", (char *)NULL },
229 { 's', RLIMIT_STACK, 1024, "stack size", "kbytes" },
232 { 't', RLIMIT_CPU, 1, "cpu time", "seconds" },
233 #endif /* RLIMIT_CPU */
234 { 'u', RLIMIT_MAXUPROC, 1, "max user processes", (char *)NULL },
235 #if defined (HAVE_RESOURCE)
236 { 'v', RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" },
239 { 'w', RLIMIT_SWAP, 1024, "swap size", "kbytes" },
242 { 'x', RLIMIT_LOCKS, 1, "file locks", (char *)NULL },
244 { -1, -1, -1, (char *)NULL, (char *)NULL }
246 #define NCMDS (sizeof(limits) / sizeof(limits[0]))
248 typedef struct _cmd {
253 static ULCMD *cmdlist;
255 static int cmdlistsz;
257 #if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
266 #endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
274 for (i = 0; limits[i].option > 0; i++)
275 if (limits[i].option == opt)
280 static char optstring[4 + 2 * NCMDS];
282 /* Report or set limits associated with certain per-process resources.
283 See the help documentation in builtins.c for a full description. */
285 ulimit_builtin (list)
286 register WORD_LIST *list;
289 int c, limind, mode, opt, all_limits;
295 /* Idea stolen from pdksh -- build option string the first time called. */
296 if (optstring[0] == 0)
299 *s++ = 'a'; *s++ = 'S'; *s++ = 'H';
300 for (c = 0; limits[c].option > 0; c++)
302 *s++ = limits[c].option;
308 /* Initialize the command list. */
310 cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD));
313 reset_internal_getopt ();
314 while ((opt = internal_getopt (list, optstring)) != -1)
322 /* -S and -H are modifiers, not real options. */
336 if (ncmd >= cmdlistsz)
337 cmdlist = (ULCMD *)xrealloc (cmdlist, (cmdlistsz *= 2) * sizeof (ULCMD));
338 cmdlist[ncmd].cmd = opt;
339 cmdlist[ncmd++].arg = list_optarg;
348 if (list) /* setting */
350 if (STREQ (list->word->word, "unlimited") == 0)
352 builtin_error (_("%s: invalid limit argument"), list->word->word);
353 return (EXECUTION_FAILURE);
355 return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY));
358 print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
359 return (EXECUTION_SUCCESS);
362 /* default is `ulimit -f' */
365 cmdlist[ncmd].cmd = 'f';
366 /* `ulimit something' is same as `ulimit -f something' */
367 cmdlist[ncmd++].arg = list ? list->word->word : (char *)NULL;
372 /* verify each command in the list. */
373 for (c = 0; c < ncmd; c++)
375 limind = _findlim (cmdlist[c].cmd);
378 builtin_error (_("`%c': bad command"), cmdlist[c].cmd);
383 for (c = 0; c < ncmd; c++)
384 if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
385 return (EXECUTION_FAILURE);
387 return (EXECUTION_SUCCESS);
391 ulimit_internal (cmd, cmdarg, mode, multiple)
396 int opt, limind, setting;
398 RLIMTYPE soft_limit, hard_limit, real_limit, limit;
400 setting = cmdarg != 0;
401 limind = _findlim (cmd);
403 mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
404 opt = get_limit (limind, &soft_limit, &hard_limit);
407 builtin_error (_("%s: cannot get limit: %s"), limits[limind].description,
409 return (EXECUTION_FAILURE);
412 if (setting == 0) /* print the value of the specified limit */
414 printone (limind, (mode & LIMIT_SOFT) ? soft_limit : hard_limit, multiple);
415 return (EXECUTION_SUCCESS);
418 /* Setting the limit. */
419 if (STREQ (cmdarg, "hard"))
420 real_limit = hard_limit;
421 else if (STREQ (cmdarg, "soft"))
422 real_limit = soft_limit;
423 else if (STREQ (cmdarg, "unlimited"))
424 real_limit = RLIM_INFINITY;
425 else if (all_digits (cmdarg))
427 limit = string_to_rlimtype (cmdarg);
428 block_factor = limits[limind].block_factor;
429 real_limit = limit * block_factor;
431 if ((real_limit / block_factor) != limit)
433 sh_erange (cmdarg, "limit");
434 return (EXECUTION_FAILURE);
439 sh_invalidnum (cmdarg);
440 return (EXECUTION_FAILURE);
443 if (set_limit (limind, real_limit, mode) < 0)
445 builtin_error (_("%s: cannot modify limit: %s"), limits[limind].description,
447 return (EXECUTION_FAILURE);
450 return (EXECUTION_SUCCESS);
454 get_limit (ind, softlim, hardlim)
456 RLIMTYPE *softlim, *hardlim;
459 #if defined (HAVE_RESOURCE)
463 if (limits[ind].parameter >= 256)
465 switch (limits[ind].parameter)
467 case RLIMIT_FILESIZE:
468 if (filesize (&value) < 0)
471 case RLIMIT_PIPESIZE:
472 if (pipesize (&value) < 0)
475 case RLIMIT_OPENFILES:
476 value = (RLIMTYPE)getdtablesize ();
479 return (getmaxvm (softlim, hardlim));
480 case RLIMIT_MAXUPROC:
481 if (getmaxuprc (&value) < 0)
488 *softlim = *hardlim = value;
493 #if defined (HAVE_RESOURCE)
494 if (getrlimit (limits[ind].parameter, &limit) < 0)
496 *softlim = limit.rlim_cur;
497 *hardlim = limit.rlim_max;
499 if (limits[ind].parameter == RLIMIT_FILESIZE)
502 *hardlim *= 512; /* Ugh. */
515 set_limit (ind, newlim, mode)
520 #if defined (HAVE_RESOURCE)
525 if (limits[ind].parameter >= 256)
526 switch (limits[ind].parameter)
528 case RLIMIT_FILESIZE:
529 #if !defined (HAVE_RESOURCE)
530 return (ulimit (2, newlim / 512L));
536 case RLIMIT_OPENFILES:
537 #if defined (HAVE_SETDTABLESIZE)
538 # if defined (__CYGWIN__)
539 /* Grrr... Cygwin declares setdtablesize as void. */
540 setdtablesize (newlim);
543 return (setdtablesize (newlim));
546 case RLIMIT_PIPESIZE:
548 case RLIMIT_MAXUPROC:
555 #if defined (HAVE_RESOURCE)
556 if (getrlimit (limits[ind].parameter, &limit) < 0)
559 if (limits[ind].parameter == RLIMIT_FILESIZE)
560 newlim /= 512; /* Ugh. */
562 val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
563 (mode & LIMIT_HARD) == 0 && /* XXX -- test */
564 (limit.rlim_cur <= limit.rlim_max))
565 ? limit.rlim_max : newlim;
566 if (mode & LIMIT_SOFT)
567 limit.rlim_cur = val;
568 if (mode & LIMIT_HARD)
569 limit.rlim_max = val;
571 return (setrlimit (limits[ind].parameter, &limit));
580 getmaxvm (softlim, hardlim)
581 RLIMTYPE *softlim, *hardlim;
583 #if defined (HAVE_RESOURCE)
584 struct rlimit datalim, stacklim;
586 if (getrlimit (RLIMIT_DATA, &datalim) < 0)
589 if (getrlimit (RLIMIT_STACK, &stacklim) < 0)
592 /* Protect against overflow. */
593 *softlim = (datalim.rlim_cur / 1024L) + (stacklim.rlim_cur / 1024L);
594 *hardlim = (datalim.rlim_max / 1024L) + (stacklim.rlim_max / 1024L);
599 #endif /* HAVE_RESOURCE */
606 #if !defined (HAVE_RESOURCE)
608 if ((result = ulimit (1, 0L)) < 0)
611 *valuep = (RLIMTYPE) result * 512;
623 #if defined (PIPE_BUF)
624 /* This is defined on Posix systems. */
625 *valuep = (RLIMTYPE) PIPE_BUF;
628 # if defined (_POSIX_PIPE_BUF)
629 *valuep = (RLIMTYPE) _POSIX_PIPE_BUF;
632 # if defined (PIPESIZE)
633 /* This is defined by running a program from the Makefile. */
634 *valuep = (RLIMTYPE) PIPESIZE;
639 # endif /* PIPESIZE */
640 # endif /* _POSIX_PIPE_BUF */
641 #endif /* PIPE_BUF */
650 maxchild = getmaxchild ();
658 *valuep = (RLIMTYPE) maxchild;
664 print_all_limits (mode)
668 RLIMTYPE softlim, hardlim;
673 for (i = 0; limits[i].option > 0; i++)
675 if (get_limit (i, &softlim, &hardlim) == 0)
676 printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
677 else if (errno != EINVAL)
678 builtin_error ("%s: cannot get limit: %s", limits[i].description,
684 printone (limind, curlim, pdesc)
693 if (limits[limind].units)
694 sprintf (unitstr, "(%s, -%c) ", limits[limind].units, limits[limind].option);
696 sprintf (unitstr, "(-%c) ", limits[limind].option);
698 printf ("%-20s %16s", limits[limind].description, unitstr);
700 if (curlim == RLIM_INFINITY)
702 else if (curlim == RLIM_SAVED_MAX)
704 else if (curlim == RLIM_SAVED_CUR)
707 print_rlimtype ((curlim / limits[limind].block_factor), 1);
710 /* Set all limits to NEWLIM. NEWLIM currently must be RLIM_INFINITY, which
711 causes all limits to be set as high as possible depending on mode (like
712 csh `unlimit'). Returns -1 if NEWLIM is invalid, 0 if all limits
713 were set successfully, and 1 if at least one limit could not be set.
715 To raise all soft limits to their corresponding hard limits, use
716 ulimit -S -a unlimited
717 To attempt to raise all hard limits to infinity (superuser-only), use
718 ulimit -H -a unlimited
719 To attempt to raise all soft and hard limits to infinity, use
724 set_all_limits (mode, newlim)
731 if (newlim != RLIM_INFINITY)
738 mode = LIMIT_SOFT|LIMIT_HARD;
740 for (retval = i = 0; limits[i].option > 0; i++)
741 if (set_limit (i, newlim, mode) < 0)
743 builtin_error ("%s: cannot modify limit: %s", limits[i].description,