03cbe8a0bcf469eb3158bd012faaf03afaabbf14
[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-2010 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
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.
12
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.
17
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/>.
20
21 $PRODUCES ulimit.c
22
23 $BUILTIN ulimit
24 $FUNCTION ulimit_builtin
25 $DEPENDS_ON !_MINIX
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.
66 $END
67
68 #if !defined (_MINIX)
69
70 #include <config.h>
71
72 #include "../bashtypes.h"
73 #ifndef _MINIX
74 #  include <sys/param.h>
75 #endif
76
77 #if defined (HAVE_UNISTD_H)
78 #  include <unistd.h>
79 #endif
80
81 #include <stdio.h>
82 #include <errno.h>
83
84 #include "../bashintl.h"
85
86 #include "../shell.h"
87 #include "common.h"
88 #include "bashgetopt.h"
89 #include "pipesize.h"
90
91 #if !defined (errno)
92 extern int errno;
93 #endif
94
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. */
98 #if defined (HAVE_RESOURCE)
99 #  include <sys/time.h>
100 #  if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
101 #    define _KERNEL
102 #  endif
103 #  include <sys/resource.h>
104 #  if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
105 #    undef _KERNEL
106 #  endif
107 #elif defined (HAVE_SYS_TIMES_H)
108 #  include <sys/times.h>
109 #endif
110
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. */
117 #if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
118 #  undef HAVE_RESOURCE
119 #endif
120
121 #if !defined (HAVE_RESOURCE) && defined (HAVE_ULIMIT_H)
122 #  include <ulimit.h>
123 #endif
124
125 #if !defined (RLIMTYPE)
126 #  define RLIMTYPE long
127 #  define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
128 #  define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
129 #endif
130
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 */
135
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
144
145 #ifdef RLIMIT_NOFILE
146 #  define RLIMIT_OPENFILES      RLIMIT_NOFILE
147 #else
148 #  define RLIMIT_OPENFILES      258
149 #endif
150
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
169
170 #if !defined (RLIM_INFINITY)
171 #  define RLIM_INFINITY 0x7fffffff
172 #endif
173
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
182 #define LIMIT_HARD 0x01
183 #define LIMIT_SOFT 0x02
184
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
193 static int _findlim __P((int));
194
195 static int ulimit_internal __P((int, char *, int, int));
196
197 static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *));
198 static int set_limit __P((int, RLIMTYPE, int));
199
200 static void printone __P((int, RLIMTYPE, int));
201 static void print_all_limits __P((int));
202
203 static int set_all_limits __P((int, RLIMTYPE));
204
205 static int filesize __P((RLIMTYPE *));
206 static int pipesize __P((RLIMTYPE *));
207 static int getmaxuprc __P((RLIMTYPE *));
208 static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *));
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. */
214   const char * const description;       /* Descriptive string to output. */
215   const char * const units;     /* scale */
216 } RESOURCE_LIMITS;
217
218 static RESOURCE_LIMITS limits[] = {
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
225 #ifdef RLIMIT_CORE
226   { 'c',        RLIMIT_CORE,  POSIXBLK, "core file size",       "blocks" },
227 #endif
228 #ifdef RLIMIT_DATA
229   { 'd',        RLIMIT_DATA,  1024,     "data seg size",        "kbytes" },
230 #endif
231 #ifdef RLIMIT_NICE
232   { 'e',        RLIMIT_NICE,  1,        "scheduling priority",  (char *)NULL },
233 #endif
234   { 'f',        RLIMIT_FILESIZE, POSIXBLK,      "file size",            "blocks" },
235 #ifdef RLIMIT_SIGPENDING
236   { 'i',        RLIMIT_SIGPENDING, 1,   "pending signals",      (char *)NULL },
237 #endif
238 #ifdef RLIMIT_MEMLOCK
239   { 'l',        RLIMIT_MEMLOCK, 1024,   "max locked memory",    "kbytes" },
240 #endif
241 #ifdef RLIMIT_RSS
242   { 'm',        RLIMIT_RSS,   1024,     "max memory size",      "kbytes" },
243 #endif /* RLIMIT_RSS */
244   { 'n',        RLIMIT_OPENFILES, 1,    "open files",           (char *)NULL},
245   { 'p',        RLIMIT_PIPESIZE, 512,   "pipe size",            "512 bytes" },
246 #ifdef RLIMIT_MSGQUEUE
247   { 'q',        RLIMIT_MSGQUEUE, 1,     "POSIX message queues", "bytes" },
248 #endif
249 #ifdef RLIMIT_RTPRIO
250   { 'r',        RLIMIT_RTPRIO,  1,      "real-time priority",   (char *)NULL },
251 #endif
252 #ifdef RLIMIT_STACK
253   { 's',        RLIMIT_STACK, 1024,     "stack size",           "kbytes" },
254 #endif
255 #ifdef RLIMIT_CPU
256   { 't',        RLIMIT_CPU,      1,     "cpu time",             "seconds" },
257 #endif /* RLIMIT_CPU */
258   { 'u',        RLIMIT_MAXUPROC, 1,     "max user processes",   (char *)NULL },
259 #if defined (HAVE_RESOURCE)
260   { 'v',        RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" },
261 #endif
262 #ifdef RLIMIT_SWAP
263   { 'w',        RLIMIT_SWAP,    1024,   "swap size",            "kbytes" },
264 #endif
265 #ifdef RLIMIT_LOCKS
266   { 'x',        RLIMIT_LOCKS,   1,      "file locks",           (char *)NULL },
267 #endif
268   { -1, -1, -1, (char *)NULL, (char *)NULL }
269 };
270 #define NCMDS   (sizeof(limits) / sizeof(limits[0]))
271
272 typedef struct _cmd {
273   int cmd;
274   char *arg;
275 } ULCMD;
276
277 static ULCMD *cmdlist;
278 static int ncmd;
279 static int cmdlistsz;
280
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
292 static int
293 _findlim (opt)
294      int opt;
295 {
296   register int i;
297
298   for (i = 0; limits[i].option > 0; i++)
299     if (limits[i].option == opt)
300       return i;
301   return -1;
302 }
303
304 static char optstring[4 + 2 * NCMDS];
305
306 /* Report or set limits associated with certain per-process resources.
307    See the help documentation in builtins.c for a full description. */
308 int
309 ulimit_builtin (list)
310      register WORD_LIST *list;
311 {
312   register char *s;
313   int c, limind, mode, opt, all_limits;
314
315   mode = 0;
316
317   all_limits = 0;
318
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++)
325         {
326           *s++ = limits[c].option;
327           *s++ = ';';
328         }
329       *s = '\0';
330     }
331
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)
341         {
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;
365         }
366     }
367   list = loptend;
368
369   if (all_limits)
370     {
371 #ifdef NOTYET
372       if (list)         /* setting */
373         {
374           if (STREQ (list->word->word, "unlimited") == 0)
375             {
376               builtin_error (_("%s: invalid limit argument"), list->word->word);
377               return (EXECUTION_FAILURE);
378             }
379           return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY));
380         }
381 #endif
382       print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
383       return (sh_chkwrite (EXECUTION_SUCCESS));
384     }
385
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)
401         {
402           builtin_error (_("`%c': bad command"), cmdlist[c].cmd);
403           return (EX_USAGE);
404         }
405     }
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);
410
411   return (EXECUTION_SUCCESS);
412 }
413
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;
421   int block_factor;
422   RLIMTYPE soft_limit, hard_limit, real_limit, limit;
423
424   setting = cmdarg != 0;
425   limind = _findlim (cmd);
426   if (mode == 0)
427     mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
428   opt = get_limit (limind, &soft_limit, &hard_limit);
429   if (opt < 0)
430     {
431       builtin_error (_("%s: cannot get limit: %s"), limits[limind].description,
432                                                  strerror (errno));
433       return (EXECUTION_FAILURE);
434     }
435
436   if (setting == 0)     /* print the value of the specified limit */
437     {
438       printone (limind, (mode & LIMIT_SOFT) ? soft_limit : hard_limit, multiple);
439       return (EXECUTION_SUCCESS);
440     }
441  
442   /* Setting the limit. */
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;
449   else if (all_digits (cmdarg))
450     {
451       limit = string_to_rlimtype (cmdarg);
452       block_factor = BLOCKSIZE(limits[limind].block_factor);
453       real_limit = limit * block_factor;
454
455       if ((real_limit / block_factor) != limit)
456         {
457           sh_erange (cmdarg, _("limit"));
458           return (EXECUTION_FAILURE);
459         }
460     }
461   else
462     {
463       sh_invalidnum (cmdarg);
464       return (EXECUTION_FAILURE);
465     }
466
467   if (set_limit (limind, real_limit, mode) < 0)
468     {
469       builtin_error (_("%s: cannot modify limit: %s"), limits[limind].description,
470                                                     strerror (errno));
471       return (EXECUTION_FAILURE);
472     }
473
474   return (EXECUTION_SUCCESS);
475 }
476
477 static int
478 get_limit (ind, softlim, hardlim)
479      int ind;
480      RLIMTYPE *softlim, *hardlim;
481 {
482   RLIMTYPE value;
483 #if defined (HAVE_RESOURCE)
484   struct rlimit limit;
485 #endif
486
487   if (limits[ind].parameter >= 256)
488     {
489       switch (limits[ind].parameter)
490         {
491         case RLIMIT_FILESIZE:
492           if (filesize (&value) < 0)
493             return -1;
494           break;
495         case RLIMIT_PIPESIZE:
496           if (pipesize (&value) < 0)
497             return -1;
498           break;
499         case RLIMIT_OPENFILES:
500           value = (RLIMTYPE)getdtablesize ();
501           break;
502         case RLIMIT_VIRTMEM:
503           return (getmaxvm (softlim, hardlim));
504         case RLIMIT_MAXUPROC:
505           if (getmaxuprc (&value) < 0)
506             return -1;
507           break;
508         default:
509           errno = EINVAL;
510           return -1;
511         }
512       *softlim = *hardlim = value;
513       return (0);
514     }
515   else
516     {
517 #if defined (HAVE_RESOURCE)
518       if (getrlimit (limits[ind].parameter, &limit) < 0)
519         return -1;
520       *softlim = limit.rlim_cur;
521       *hardlim = limit.rlim_max;
522 #  if defined (HPUX9)
523       if (limits[ind].parameter == RLIMIT_FILESIZE)
524         {
525           *softlim *= 512;
526           *hardlim *= 512;                      /* Ugh. */
527         }
528       else
529 #  endif /* HPUX9 */
530       return 0;
531 #else
532       errno = EINVAL;
533       return -1;
534 #endif
535     }
536 }
537
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
548
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));
555 #else
556         errno = EINVAL;
557         return -1;
558 #endif
559
560       case RLIMIT_OPENFILES:
561 #if defined (HAVE_SETDTABLESIZE)
562 #  if defined (__CYGWIN__)
563         /* Grrr... Cygwin declares setdtablesize as void. */
564         setdtablesize (newlim);
565         return 0;
566 #  else
567         return (setdtablesize (newlim));
568 #  endif
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     {
579 #if defined (HAVE_RESOURCE)
580       if (getrlimit (limits[ind].parameter, &limit) < 0)
581         return -1;
582 #  if defined (HPUX9)
583       if (limits[ind].parameter == RLIMIT_FILESIZE)
584         newlim /= 512;                          /* Ugh. */
585 #  endif /* HPUX9 */
586       val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
587                (mode & LIMIT_HARD) == 0 &&              /* XXX -- test */
588                (limit.rlim_cur <= limit.rlim_max))
589                  ? limit.rlim_max : newlim;
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
597       errno = EINVAL;
598       return -1;
599 #endif
600     }
601 }
602
603 static int
604 getmaxvm (softlim, hardlim)
605      RLIMTYPE *softlim, *hardlim;
606 {
607 #if defined (HAVE_RESOURCE)
608   struct rlimit datalim, stacklim;
609
610   if (getrlimit (RLIMIT_DATA, &datalim) < 0)
611     return -1;
612
613   if (getrlimit (RLIMIT_STACK, &stacklim) < 0)
614     return -1;
615
616   /* Protect against overflow. */
617   *softlim = (datalim.rlim_cur / 1024L) + (stacklim.rlim_cur / 1024L);
618   *hardlim = (datalim.rlim_max / 1024L) + (stacklim.rlim_max / 1024L);
619   return 0;
620 #else
621   errno = EINVAL;
622   return -1;
623 #endif /* HAVE_RESOURCE */
624 }
625
626 static int
627 filesize(valuep)
628      RLIMTYPE *valuep;
629 {
630 #if !defined (HAVE_RESOURCE)
631   long result;
632   if ((result = ulimit (1, 0L)) < 0)
633     return -1;
634   else
635     *valuep = (RLIMTYPE) result * 512;
636   return 0;
637 #else
638   errno = EINVAL;
639   return -1;
640 #endif
641 }
642
643 static int
644 pipesize (valuep)
645      RLIMTYPE *valuep;
646 {
647 #if defined (PIPE_BUF)
648   /* This is defined on Posix systems. */
649   *valuep = (RLIMTYPE) PIPE_BUF;
650   return 0;
651 #else
652 #  if defined (_POSIX_PIPE_BUF)
653   *valuep = (RLIMTYPE) _POSIX_PIPE_BUF;
654   return 0;
655 #  else
656 #    if defined (PIPESIZE)
657   /* This is defined by running a program from the Makefile. */
658   *valuep = (RLIMTYPE) PIPESIZE;
659   return 0;
660 #    else
661   errno = EINVAL;
662   return -1;  
663 #    endif /* PIPESIZE */
664 #  endif /* _POSIX_PIPE_BUF */
665 #endif /* PIPE_BUF */
666 }
667
668 static int
669 getmaxuprc (valuep)
670      RLIMTYPE *valuep;
671 {
672   long maxchild;
673
674   maxchild = getmaxchild ();
675   if (maxchild < 0)
676     {
677       errno = EINVAL;
678       return -1;
679     }
680   else
681     {
682       *valuep = (RLIMTYPE) maxchild;
683       return 0;
684     }
685 }
686
687 static void
688 print_all_limits (mode)
689      int mode;
690 {
691   register int i;
692   RLIMTYPE softlim, hardlim;
693
694   if (mode == 0)
695     mode |= LIMIT_SOFT;
696
697   for (i = 0; limits[i].option > 0; i++)
698     {
699       if (get_limit (i, &softlim, &hardlim) == 0)
700         printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
701       else if (errno != EINVAL)
702         builtin_error ("%s: cannot get limit: %s", limits[i].description,
703                                                    strerror (errno));
704     }
705 }
706
707 static void
708 printone (limind, curlim, pdesc)
709      int limind;
710      RLIMTYPE curlim;
711      int pdesc;
712 {
713   char unitstr[64];
714   int factor;
715
716   factor = BLOCKSIZE(limits[limind].block_factor);
717   if (pdesc)
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
724       printf ("%-20s %16s", limits[limind].description, unitstr);
725     }
726   if (curlim == RLIM_INFINITY)
727     puts ("unlimited");
728   else if (curlim == RLIM_SAVED_MAX)
729     puts ("hard");
730   else if (curlim == RLIM_SAVED_CUR)
731     puts ("soft");
732   else
733     print_rlimtype ((curlim / factor), 1);
734 }
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       {
769         builtin_error (_("%s: cannot modify limit: %s"), limits[i].description,
770                                                       strerror (errno));
771         retval = 1;
772       }
773   return retval;
774 }
775
776 #endif /* !_MINIX */