f3d0c8e563be6d120185093cd4e0e7cff886a93b
[platform/upstream/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 */