Imported from ../bash-1.14.7.tar.gz.
[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 [-SHacdfmstpnuv [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     -m  the maximum resident set size
38     -s  the maximum stack size
39     -t  the maximum amount of cpu time in seconds
40     -f  the maximum size of files created by the shell
41     -p  the pipe buffer size
42     -n  the maximum number of open file descriptors
43     -u  the maximum number of user processes
44     -v  the size of virtual memory 
45
46 If LIMIT is given, it is the new value of the specified resource.
47 Otherwise, the current value of the specified resource is printed.
48 If no option is given, then -f is assumed.  Values are in 1k
49 increments, except for -t, which is in seconds, -p, which is in
50 increments of 512 bytes, and -u, which is an unscaled number of
51 processes.
52 $END
53
54 #include <stdio.h>
55 #include <sys/types.h>
56 #include <sys/param.h>
57 #include <errno.h>
58 #include "../shell.h"
59 #include "pipesize.h"
60
61 #if !defined (errno)
62 extern int errno;
63 #endif
64
65 #if defined (HAVE_RESOURCE)
66 #  include <sys/time.h>
67 #  include <sys/resource.h>
68 #else
69 #  include <sys/times.h>
70 #endif
71
72 #if defined (HAVE_UNISTD_H)
73 #  include <unistd.h>
74 #endif
75
76 #if defined (HAVE_LIMITS_H)
77 #  include <limits.h>
78 #endif
79
80 /* Check for the most basic symbols.  If they aren't present, this
81    system's <sys/resource.h> isn't very useful to us. */
82 #if !defined (RLIMIT_FSIZE) || defined (GETRLIMIT_MISSING)
83 #  undef HAVE_RESOURCE
84 #endif
85
86 #if !defined (RLIMTYPE)
87 #  define RLIMTYPE long
88 #  define string_to_rlimtype string_to_long
89 #  define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
90 #endif
91
92 static void print_long ();
93
94 /* **************************************************************** */
95 /*                                                                  */
96 /*                      Ulimit builtin and Hacks.                   */
97 /*                                                                  */
98 /* **************************************************************** */
99
100 /* Block size for ulimit operations. */
101 #define ULIMIT_BLOCK_SIZE ((long)1024)
102
103 #define u_FILE_SIZE             0x001
104 #define u_MAX_BREAK_VAL         0x002
105 #define u_PIPE_SIZE             0x004
106 #define u_CORE_FILE_SIZE        0x008
107 #define u_DATA_SEG_SIZE         0x010
108 #define u_PHYS_MEM_SIZE         0x020
109 #define u_CPU_TIME_LIMIT        0x040
110 #define u_STACK_SIZE            0x080
111 #define u_NUM_OPEN_FILES        0x100
112 #define u_MAX_VIRTUAL_MEM       0x200
113 #define u_MAX_USER_PROCS        0x400
114
115 #define u_ALL_LIMITS            0x7ff
116
117 #if !defined (RLIM_INFINITY)
118 #  define RLIM_INFINITY  0x7fffffff
119 #endif
120
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 */
125
126 #define LIMIT_HARD 0x01
127 #define LIMIT_SOFT 0x02
128
129 static RLIMTYPE shell_ulimit ();
130 static RLIMTYPE pipesize ();
131 static RLIMTYPE open_files ();
132
133 #if defined (HAVE_RESOURCE)
134 static RLIMTYPE getmaxvm ();
135 #endif /* HAVE_RESOURCE */
136
137 static void print_specific_limits ();
138 static void print_all_limits ();
139
140 static char t[2];
141
142 /* Return 1 if the limit associated with CMD can be raised from CURRENT
143    to NEW.  This is for USG systems without HAVE_RESOURCE, most of which
144    do not allow any user other than root to raise limits.  There are,
145    however, exceptions. */
146 #if !defined (HAVE_RESOURCE)
147 static int
148 canraise (cmd, current, new)
149      int cmd;
150      RLIMTYPE current, new;
151 {
152 #  if defined (HAVE_SETDTABLESIZE)
153   if (cmd == u_NUM_OPEN_FILES)
154     return (1);
155 #  endif /* HAVE_SETDTABLSIZE */
156
157   return ((current > new) || (current_user.uid == 0));
158 }
159 #endif /* !HAVE_RESOURCE */
160
161 /* Report or set limits associated with certain per-process resources.
162    See the help documentation in builtins.c for a full description.
163
164    Rewritten by Chet Ramey 6/30/91. */
165 int
166 ulimit_builtin (list)
167      register WORD_LIST *list;
168 {
169   register char *s;
170   int c, setting, cmd, mode, verbose_print, opt_eof;
171   int all_limits, specific_limits;
172   long block_factor;
173   RLIMTYPE current_limit, real_limit, limit;
174
175   c = mode = verbose_print = opt_eof = 0;
176   limit = (RLIMTYPE)-1;
177
178   do
179     {
180       cmd = setting = all_limits = specific_limits = 0;
181       block_factor = ULIMIT_BLOCK_SIZE;
182
183       /* read_options: */
184       if (list && !opt_eof && *list->word->word == '-')
185         {
186           s = &(list->word->word[1]);
187           list = list->next;
188
189           while (*s && (c = *s++))
190             {
191               switch (c)
192                 {
193 #define ADD_CMD(x) { if (cmd) specific_limits++; cmd |= (x); }
194
195                 case '-':       /* ulimit -- */
196                   opt_eof++;
197                   break;
198                   
199                 case 'a':
200                   all_limits++;
201                   break;
202
203                 case 'f':
204                   ADD_CMD (u_FILE_SIZE);
205                   break;
206
207 #if defined (HAVE_RESOURCE)
208                 /* -S and -H are modifiers, not real options.  */
209                 case 'S':
210                   mode |= LIMIT_SOFT;
211                   break;
212
213                 case 'H':
214                   mode |= LIMIT_HARD;
215                   break;
216
217                 case 'c':
218                   ADD_CMD (u_CORE_FILE_SIZE);
219                   break;
220
221                 case 'd':
222                   ADD_CMD (u_DATA_SEG_SIZE);
223                   break;
224
225 #if !defined (USGr4)
226                 case 'm':
227                   ADD_CMD (u_PHYS_MEM_SIZE);
228                   break;
229 #endif /* USGr4 */
230
231                 case 't':
232                   ADD_CMD (u_CPU_TIME_LIMIT);
233                   block_factor = 1;     /* seconds */
234                   break;
235
236                 case 's':
237                   ADD_CMD (u_STACK_SIZE);
238                   break;
239
240                 case 'v':
241                   ADD_CMD (u_MAX_VIRTUAL_MEM);
242                   block_factor = 1;
243                   break;
244
245                 case 'u':
246                   ADD_CMD (u_MAX_USER_PROCS);
247                   block_factor = 1;
248                   break;
249
250 #endif /* HAVE_RESOURCE */
251
252                 case 'p':
253                   ADD_CMD (u_PIPE_SIZE);
254                   block_factor = 512;
255                   break;
256
257                 case 'n':
258                   ADD_CMD (u_NUM_OPEN_FILES);
259                   block_factor = 1;
260                   break;
261
262                 default:                /* error_case: */
263                   t[0] = c;
264                   t[1] = '\0';
265                   bad_option (t);
266 #if !defined (HAVE_RESOURCE)
267                   builtin_error("usage: ulimit [-afnp] [new limit]");
268 #else
269                   builtin_error("usage: ulimit [-SHacmdstfnpuv] [new limit]");
270 #endif
271                   return (EX_USAGE);
272                 }
273             }
274         }
275
276         if (all_limits)
277           {
278             print_all_limits (mode);
279             return (EXECUTION_SUCCESS);
280           }
281
282         if (specific_limits)
283           {
284             print_specific_limits (cmd, mode);
285             if (list)
286               verbose_print++;
287             continue;
288           }
289
290         if (cmd == 0)
291           cmd = u_FILE_SIZE;
292
293         /* If an argument was supplied for the command, then we want to
294            set the limit.  Note that `ulimit something' means a command
295            of -f with argument `something'. */
296         if (list)
297           {
298             if (opt_eof || (*list->word->word != '-'))
299               {
300                 s = list->word->word;
301                 list = list->next;
302
303                 if (STREQ (s, "unlimited"))
304                   limit = RLIM_INFINITY;
305                 else if (all_digits (s))
306                   limit = string_to_rlimtype (s);
307                 else
308                   {
309                     builtin_error ("bad non-numeric arg `%s'", s);
310                     return (EXECUTION_FAILURE);
311                   }
312                 setting++;
313               }
314             else if (!opt_eof)
315               verbose_print++;
316           }
317
318       if (limit == RLIM_INFINITY)
319         block_factor = 1;
320
321       real_limit = limit * block_factor;
322
323       /* If more than one option is given, list each in a verbose format,
324          the same that is used for -a. */
325       if (!setting && verbose_print)
326         {
327           print_specific_limits (cmd, mode);
328           continue;
329         }
330
331       current_limit = shell_ulimit (cmd, real_limit, 0, mode);
332
333       if (setting)
334         {
335 #if !defined (HAVE_RESOURCE)
336           /* Most USG systems do not most allow limits to be raised by any
337              user other than root.  There are, however, exceptions. */
338           if (canraise (cmd, current_limit, real_limit) == 0)
339             {
340               builtin_error ("cannot raise limit: %s", strerror (EPERM));
341               return (EXECUTION_FAILURE);
342             }
343 #endif /* !HAVE_RESOURCE */
344
345           if (shell_ulimit (cmd, real_limit, 1, mode) == (RLIMTYPE)-1)
346             {
347               builtin_error ("cannot raise limit: %s", strerror (errno));
348               return (EXECUTION_FAILURE);
349             }
350
351           continue;
352         }
353       else
354         {
355           if (current_limit < 0)
356             builtin_error ("cannot get limit: %s", strerror (errno));
357           else if (current_limit != RLIM_INFINITY)
358             print_rlimtype ((current_limit / block_factor), 1);
359           else
360             printf ("unlimited\n");
361         }
362     }
363   while (list);
364
365   return (EXECUTION_SUCCESS);
366 }
367
368 /* The ulimit that we call from within Bash.
369
370    WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
371    contains the desired new limit.  Otherwise, the existing limit is
372    returned.  If mode & LIMIT_HARD, the hard limit is used; if
373    mode & LIMIT_SOFT, the soft limit.  Both may be set by specifying
374    -H and -S; if both are specified, or if neither is specified, the
375    soft limit will be returned.
376
377    Systems without BSD resource limits can specify only u_FILE_SIZE.
378    This includes most USG systems.
379
380    Chet Ramey supplied the BSD resource limit code. */
381 static RLIMTYPE
382 shell_ulimit (which, newlim, setting, mode)
383      int which, setting, mode;
384      RLIMTYPE newlim;
385 {
386 #if defined (HAVE_RESOURCE)
387   struct rlimit limit;
388   int cmd;
389
390   if (mode == 0)
391     mode |= LIMIT_SOFT;
392 #endif
393
394   switch (which)
395     {
396 #if !defined (HAVE_RESOURCE)
397
398     case u_FILE_SIZE:
399       if (!setting)
400         {
401           /* ulimit () returns a number that is in 512 byte blocks, thus we
402              must multiply it by 512 to get back to bytes.  This is false
403              only under HP/UX 6.x. */
404           RLIMTYPE result;
405
406           result = ulimit (1, 0L);
407
408 #  if defined (hpux) && !defined (_POSIX_VERSION)
409           return (result);
410 #  else
411           return (result * 512);
412 #  endif /* hpux 6.x */
413         }
414       else
415         return (ulimit (2, newlim / 512L));
416
417       break;
418
419 #else /* defined (HAVE_RESOURCE) */
420
421     case u_FILE_SIZE:
422       cmd = RLIMIT_FSIZE;
423       goto do_ulimit;
424
425     case u_CORE_FILE_SIZE:
426       cmd = RLIMIT_CORE;
427       goto do_ulimit;
428
429     case u_DATA_SEG_SIZE:
430       cmd = RLIMIT_DATA;
431       goto do_ulimit;
432
433 #if !defined (USGr4)
434     case u_PHYS_MEM_SIZE:
435 #  if defined (RLIMIT_RSS)
436       cmd = RLIMIT_RSS;
437 #  else /* !RLIMIT_RSS */
438       errno = EINVAL;
439       return ((RLIMTYPE)-1);
440 #  endif /* !RLIMIT_RSS */
441
442       goto do_ulimit;
443 #endif /* USGr4 */
444
445     case u_CPU_TIME_LIMIT:
446 #if defined (RLIMIT_CPU)
447       cmd = RLIMIT_CPU;
448       goto do_ulimit;
449 #else
450       errno = EINVAL;
451       return ((RLIMTYPE)-1);
452 #  endif /* !RLIMIT_CPU */
453
454
455     case u_STACK_SIZE:
456       cmd = RLIMIT_STACK;
457
458     do_ulimit:
459
460       if (getrlimit (cmd, &limit) != 0)
461         return ((RLIMTYPE)-1);
462
463       if (!setting)
464         {
465           if (mode & LIMIT_SOFT)
466             return (limit.rlim_cur);
467           else
468             return (limit.rlim_max);
469         }
470       else
471         {
472           if (mode & LIMIT_SOFT)
473             {
474               /* Non-root users are only allowed to raise a limit up to the
475                  hard limit, not to infinity. */
476               if (current_user.euid != 0 && newlim == RLIM_INFINITY)
477                 limit.rlim_cur = limit.rlim_max;
478               else
479                 limit.rlim_cur = newlim;
480             }
481           if (mode & LIMIT_HARD)
482             limit.rlim_max = newlim;
483
484           return (setrlimit (cmd, &limit));
485         }
486
487       break;
488
489 #endif /* HAVE_RESOURCE */
490
491       /* You can't get or set the pipe size with getrlimit, so we have to
492          cheat.  */
493     case u_PIPE_SIZE:
494       if (setting)
495         {
496           errno = EINVAL;
497           return ((RLIMTYPE)-1);
498         }
499       return (pipesize ());
500
501     case u_NUM_OPEN_FILES:
502       if (setting)
503         {
504 #if defined (HAVE_RESOURCE) && defined (RLIMIT_NOFILE)
505           cmd = RLIMIT_NOFILE;
506           goto do_ulimit;
507 #else
508 #  if defined (HAVE_SETDTABLESIZE)
509           return (setdtablesize (newlim));
510 #  else
511           errno = EINVAL;
512           return ((RLIMTYPE)-1);
513 #  endif /* HAVE_SETDTABLESIZE */
514 #endif /* !HAVE_RESOURCE || !RLIMIT_NOFILE */
515         }
516       else
517         return (open_files (mode));
518
519     case u_MAX_VIRTUAL_MEM:
520       if (setting)
521         {
522           errno = EINVAL;
523           return ((RLIMTYPE)-1);
524         }
525       else
526         {
527 #if defined (HAVE_RESOURCE)
528           return (getmaxvm (mode));
529 #else /* !HAVE_RESOURCE */
530           errno = EINVAL;
531           return ((RLIMTYPE)-1);
532 #endif /* !HAVE_RESOURCE */
533         }
534
535     case u_MAX_USER_PROCS:
536 #if defined (HAVE_RESOURCE) && defined (RLIMIT_NPROC)
537       cmd = RLIMIT_NPROC;
538       goto do_ulimit;
539 #else /* !HAVE_RESOURCE || !RLIMIT_NPROC */
540       errno = EINVAL;
541       return ((RLIMTYPE)-1);
542 #endif /* !HAVE_RESOURCE || !RLIMIT_NPROC */
543       
544     default:
545       errno = EINVAL;
546       return ((RLIMTYPE)-1);
547     }
548 }
549
550 #if defined (HAVE_RESOURCE)
551 static RLIMTYPE
552 getmaxvm (mode)
553      int mode;
554 {
555   struct rlimit rl;
556
557 #if defined (RLIMIT_VMEM)
558   if (getrlimit (RLIMIT_VMEM, &rl) < 0)
559     return ((RLIMTYPE)-1);
560   else
561     return (((mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max) / 1024L);
562 #else /* !RLIMIT_VMEM */
563   RLIMTYPE maxdata, maxstack;
564
565   if (getrlimit (RLIMIT_DATA, &rl) < 0)
566     return ((RLIMTYPE)-1);
567   else
568     maxdata = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
569
570   if (getrlimit (RLIMIT_STACK, &rl) < 0)
571     return ((RLIMTYPE)-1);
572   else
573     maxstack = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
574
575   /* Protect against overflow. */
576   return ((maxdata / 1024L) + (maxstack / 1024L));
577 #endif /* !RLIMIT_VMEM */
578 }
579 #endif /* HAVE_RESOURCE */
580
581 static RLIMTYPE
582 open_files (mode)
583      int mode;
584 {
585 #if !defined (RLIMIT_NOFILE)
586   return ((RLIMTYPE)getdtablesize ());
587 #else
588   struct rlimit rl;
589
590   getrlimit (RLIMIT_NOFILE, &rl);
591   if (mode & LIMIT_SOFT)
592     return (rl.rlim_cur);
593   else
594     return (rl.rlim_max);
595 #endif
596 }
597
598 static RLIMTYPE
599 pipesize ()
600 {
601 #if defined (PIPE_BUF)
602   /* This is defined on Posix systems. */
603   return ((RLIMTYPE) PIPE_BUF);
604 #else
605 #  if defined (PIPESIZE)
606   /* This is defined by running a program from the Makefile. */
607   return ((RLIMTYPE) PIPESIZE);
608 #  else
609   errno = EINVAL;
610   return ((RLIMTYPE)-1);
611 #  endif /* PIPESIZE */
612 #endif /* PIPE_BUF */
613 }
614
615 /* ulimit(2) returns information about file size limits in terms of 512-byte
616    blocks.  This is the factor by which to divide to turn it into information
617    in terms of 1024-byte blocks.  Except for hpux 6.x, which returns it in
618    terms of bytes. */
619 #if !defined (hpux) || defined (_POSIX_VERSION)
620 #  define ULIMIT_DIVISOR 2
621 #else
622 #  define ULIMIT_DIVISOR 1024
623 #endif
624
625 #if defined (HAVE_RESOURCE)
626
627 typedef struct {
628   int  option_cmd;              /* The ulimit command for this limit. */
629   int  parameter;               /* Parameter to pass to getrlimit (). */
630   int  block_factor;            /* Blocking factor for specific limit. */
631   char *description;            /* Descriptive string to output. */
632 } BSD_RESOURCE_LIMITS;
633
634 static BSD_RESOURCE_LIMITS limits[] = {
635   { u_CORE_FILE_SIZE, RLIMIT_CORE,  1024, "core file size (blocks)" },
636   { u_DATA_SEG_SIZE,  RLIMIT_DATA,  1024, "data seg size (kbytes)" },
637   { u_FILE_SIZE,      RLIMIT_FSIZE, 1024, "file size (blocks)" },
638 #if !defined (USGr4) && defined (RLIMIT_RSS)
639   { u_PHYS_MEM_SIZE,  RLIMIT_RSS,   1024, "max memory size (kbytes)" },
640 #endif /* USGr4 && RLIMIT_RSS */
641   { u_STACK_SIZE,     RLIMIT_STACK, 1024, "stack size (kbytes)" },
642 #if defined (RLIMIT_CPU)
643   { u_CPU_TIME_LIMIT, RLIMIT_CPU,      1, "cpu time (seconds)" },
644 #endif /* RLIMIT_CPU */
645 #if defined (RLIMIT_NPROC)
646   { u_MAX_USER_PROCS, RLIMIT_NPROC,    1, "max user processes" },
647 #endif /* RLIMIT_NPROC */
648   { 0, 0, 0, (char *)NULL }
649 };
650
651 static void
652 print_bsd_limit (i, mode)
653      int i, mode;
654 {
655   struct rlimit rl;
656   RLIMTYPE limit;
657
658   getrlimit (limits[i].parameter, &rl);
659   if (mode & LIMIT_HARD)
660     limit = rl.rlim_max;
661   else
662     limit = rl.rlim_cur;
663   printf ("%-25s", limits[i].description);
664   if (limit == RLIM_INFINITY)
665     printf ("unlimited\n");
666   else
667     print_rlimtype ((limit / limits[i].block_factor), 1);
668 }
669
670 static void
671 print_specific_bsd_limits (cmd, mode)
672      int cmd, mode;
673 {
674   register int i;
675
676   for (i = 0; limits[i].option_cmd; i++)
677     if (cmd & limits[i].option_cmd)
678       print_bsd_limit (i, mode);
679 }
680 #endif /* HAVE_RESOURCE */
681
682 /* Print the limits corresponding to a specific set of resources.  This is
683    called when an option string contains more than one character (e.g. -at),
684    because limits may not be specified with that kind of argument. */
685 static void
686 print_specific_limits (cmd, mode)
687      int cmd, mode;
688 {
689   if (mode == 0)
690     mode = LIMIT_SOFT;
691
692 #if defined (HAVE_RESOURCE)
693   print_specific_bsd_limits (cmd, mode);
694 #else /* !HAVE_RESOURCE */
695   if (cmd & u_FILE_SIZE)
696     {
697       printf ("%-25s", "file size (blocks)");
698       print_rlimtype ((ulimit (1, 0L) / ULIMIT_DIVISOR), 1);
699     }
700 #endif /* !HAVE_RESOURCE */
701
702   if (cmd & u_PIPE_SIZE)
703     {
704       printf ("%-25s", "pipe size (512 bytes)");
705       print_rlimtype ((pipesize () / 512), 1);
706     }
707
708   if (cmd & u_NUM_OPEN_FILES)
709     {
710       printf ("%-25s", "open files");
711       print_rlimtype (open_files (mode), 1);
712     }
713
714 #if defined (HAVE_RESOURCE)
715   if (cmd & u_MAX_VIRTUAL_MEM)
716     {
717       printf ("%-25s", "virtual memory (kbytes)");
718       print_rlimtype (getmaxvm (mode), 1);
719     }
720 #endif /* HAVE_RESOURCE */
721 }
722
723 static void
724 print_all_limits (mode)
725      int mode;
726 {
727   if (mode == 0)
728     mode |= LIMIT_SOFT;
729
730   print_specific_limits (u_ALL_LIMITS, mode);
731 }