Bash-4.3 distribution sources and documentation
[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 [-SHabcdefilmnpqrstuvxT] [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   -T    the maximum number of threads
54
55 Not all options are available on all platforms.
56
57 If LIMIT is given, it is the new value of the specified resource; the
58 special LIMIT values `soft', `hard', and `unlimited' stand for the
59 current soft limit, the current hard limit, and no limit, respectively.
60 Otherwise, the current value of the specified resource is printed.  If
61 no option is given, then -f is assumed.
62
63 Values are in 1024-byte increments, except for -t, which is in seconds,
64 -p, which is in increments of 512 bytes, and -u, which is an unscaled
65 number of processes.
66
67 Exit Status:
68 Returns success unless an invalid option is supplied or an error occurs.
69 $END
70
71 #if !defined (_MINIX)
72
73 #include <config.h>
74
75 #include "../bashtypes.h"
76 #if defined (HAVE_SYS_PARAM_H)
77 #  include <sys/param.h>
78 #endif
79
80 #if defined (HAVE_UNISTD_H)
81 #  include <unistd.h>
82 #endif
83
84 #include <stdio.h>
85 #include <errno.h>
86
87 #include "../bashintl.h"
88
89 #include "../shell.h"
90 #include "common.h"
91 #include "bashgetopt.h"
92 #include "pipesize.h"
93
94 #if !defined (errno)
95 extern int errno;
96 #endif
97
98 /* For some reason, HPUX chose to make these definitions visible only if
99    _KERNEL is defined, so we define _KERNEL before including <sys/resource.h>
100    and #undef it afterward. */
101 #if defined (HAVE_RESOURCE)
102 #  include <sys/time.h>
103 #  if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
104 #    define _KERNEL
105 #  endif
106 #  include <sys/resource.h>
107 #  if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
108 #    undef _KERNEL
109 #  endif
110 #elif defined (HAVE_SYS_TIMES_H)
111 #  include <sys/times.h>
112 #endif
113
114 #if defined (HAVE_LIMITS_H)
115 #  include <limits.h>
116 #endif
117
118 /* Check for the most basic symbols.  If they aren't present, this
119    system's <sys/resource.h> isn't very useful to us. */
120 #if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
121 #  undef HAVE_RESOURCE
122 #endif
123
124 #if !defined (HAVE_RESOURCE) && defined (HAVE_ULIMIT_H)
125 #  include <ulimit.h>
126 #endif
127
128 #if !defined (RLIMTYPE)
129 #  define RLIMTYPE long
130 #  define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
131 #  define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
132 #endif
133
134 /* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
135 #if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
136 #  define RLIMIT_NOFILE RLIMIT_OFILE
137 #endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
138
139 /* Some systems have these, some do not. */
140 #ifdef RLIMIT_FSIZE
141 #  define RLIMIT_FILESIZE       RLIMIT_FSIZE
142 #else
143 #  define RLIMIT_FILESIZE       256
144 #endif
145
146 #define RLIMIT_PIPESIZE 257
147
148 #ifdef RLIMIT_NOFILE
149 #  define RLIMIT_OPENFILES      RLIMIT_NOFILE
150 #else
151 #  define RLIMIT_OPENFILES      258
152 #endif
153
154 #ifdef RLIMIT_VMEM
155 #  define RLIMIT_VIRTMEM        RLIMIT_VMEM
156 #  define RLIMIT_VMBLKSZ        1024
157 #else
158 #  ifdef RLIMIT_AS
159 #    define RLIMIT_VIRTMEM      RLIMIT_AS
160 #    define RLIMIT_VMBLKSZ      1024
161 #  else
162 #    define RLIMIT_VIRTMEM      259
163 #    define RLIMIT_VMBLKSZ      1
164 #  endif
165 #endif
166
167 #ifdef RLIMIT_NPROC
168 #  define RLIMIT_MAXUPROC       RLIMIT_NPROC
169 #else
170 #  define RLIMIT_MAXUPROC       260
171 #endif
172
173 #if !defined (RLIMIT_PTHREAD) && defined (RLIMIT_NTHR)
174 #  define RLIMIT_PTHREAD RLIMIT_NTHR
175 #endif
176
177 #if !defined (RLIM_INFINITY)
178 #  define RLIM_INFINITY 0x7fffffff
179 #endif
180
181 #if !defined (RLIM_SAVED_CUR)
182 #  define RLIM_SAVED_CUR RLIM_INFINITY
183 #endif
184
185 #if !defined (RLIM_SAVED_MAX)
186 #  define RLIM_SAVED_MAX RLIM_INFINITY
187 #endif
188
189 #define LIMIT_HARD 0x01
190 #define LIMIT_SOFT 0x02
191
192 /* "Blocks" are defined as 512 bytes when in Posix mode and 1024 bytes
193    otherwise. */
194 #define POSIXBLK        -2
195
196 #define BLOCKSIZE(x)    (((x) == POSIXBLK) ? (posixly_correct ? 512 : 1024) : (x))
197
198 extern int posixly_correct;
199
200 static int _findlim __P((int));
201
202 static int ulimit_internal __P((int, char *, int, int));
203
204 static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *));
205 static int set_limit __P((int, RLIMTYPE, int));
206
207 static void printone __P((int, RLIMTYPE, int));
208 static void print_all_limits __P((int));
209
210 static int set_all_limits __P((int, RLIMTYPE));
211
212 static int filesize __P((RLIMTYPE *));
213 static int pipesize __P((RLIMTYPE *));
214 static int getmaxuprc __P((RLIMTYPE *));
215 static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *));
216
217 typedef struct {
218   int  option;                  /* The ulimit option for this limit. */
219   int  parameter;               /* Parameter to pass to get_limit (). */
220   int  block_factor;            /* Blocking factor for specific limit. */
221   const char * const description;       /* Descriptive string to output. */
222   const char * const units;     /* scale */
223 } RESOURCE_LIMITS;
224
225 static RESOURCE_LIMITS limits[] = {
226 #ifdef RLIMIT_PTHREAD
227   { 'T',        RLIMIT_PTHREAD,  1,     "number of threads",    (char *)NULL },
228 #endif
229 #ifdef RLIMIT_SBSIZE
230   { 'b',        RLIMIT_SBSIZE,  1,      "socket buffer size",   "bytes" },
231 #endif
232 #ifdef RLIMIT_CORE
233   { 'c',        RLIMIT_CORE,  POSIXBLK, "core file size",       "blocks" },
234 #endif
235 #ifdef RLIMIT_DATA
236   { 'd',        RLIMIT_DATA,  1024,     "data seg size",        "kbytes" },
237 #endif
238 #ifdef RLIMIT_NICE
239   { 'e',        RLIMIT_NICE,  1,        "scheduling priority",  (char *)NULL },
240 #endif
241   { 'f',        RLIMIT_FILESIZE, POSIXBLK,      "file size",            "blocks" },
242 #ifdef RLIMIT_SIGPENDING
243   { 'i',        RLIMIT_SIGPENDING, 1,   "pending signals",      (char *)NULL },
244 #endif
245 #ifdef RLIMIT_MEMLOCK
246   { 'l',        RLIMIT_MEMLOCK, 1024,   "max locked memory",    "kbytes" },
247 #endif
248 #ifdef RLIMIT_RSS
249   { 'm',        RLIMIT_RSS,   1024,     "max memory size",      "kbytes" },
250 #endif /* RLIMIT_RSS */
251   { 'n',        RLIMIT_OPENFILES, 1,    "open files",           (char *)NULL},
252   { 'p',        RLIMIT_PIPESIZE, 512,   "pipe size",            "512 bytes" },
253 #ifdef RLIMIT_MSGQUEUE
254   { 'q',        RLIMIT_MSGQUEUE, 1,     "POSIX message queues", "bytes" },
255 #endif
256 #ifdef RLIMIT_RTPRIO
257   { 'r',        RLIMIT_RTPRIO,  1,      "real-time priority",   (char *)NULL },
258 #endif
259 #ifdef RLIMIT_STACK
260   { 's',        RLIMIT_STACK, 1024,     "stack size",           "kbytes" },
261 #endif
262 #ifdef RLIMIT_CPU
263   { 't',        RLIMIT_CPU,      1,     "cpu time",             "seconds" },
264 #endif /* RLIMIT_CPU */
265   { 'u',        RLIMIT_MAXUPROC, 1,     "max user processes",   (char *)NULL },
266 #if defined (HAVE_RESOURCE)
267   { 'v',        RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" },
268 #endif
269 #ifdef RLIMIT_SWAP
270   { 'w',        RLIMIT_SWAP,    1024,   "swap size",            "kbytes" },
271 #endif
272 #ifdef RLIMIT_LOCKS
273   { 'x',        RLIMIT_LOCKS,   1,      "file locks",           (char *)NULL },
274 #endif
275   { -1, -1, -1, (char *)NULL, (char *)NULL }
276 };
277 #define NCMDS   (sizeof(limits) / sizeof(limits[0]))
278
279 typedef struct _cmd {
280   int cmd;
281   char *arg;
282 } ULCMD;
283
284 static ULCMD *cmdlist;
285 static int ncmd;
286 static int cmdlistsz;
287
288 #if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
289 long
290 ulimit (cmd, newlim)
291      int cmd;
292      long newlim;
293 {
294   errno = EINVAL;
295   return -1;
296 }
297 #endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
298
299 static int
300 _findlim (opt)
301      int opt;
302 {
303   register int i;
304
305   for (i = 0; limits[i].option > 0; i++)
306     if (limits[i].option == opt)
307       return i;
308   return -1;
309 }
310
311 static char optstring[4 + 2 * NCMDS];
312
313 /* Report or set limits associated with certain per-process resources.
314    See the help documentation in builtins.c for a full description. */
315 int
316 ulimit_builtin (list)
317      register WORD_LIST *list;
318 {
319   register char *s;
320   int c, limind, mode, opt, all_limits;
321
322   mode = 0;
323
324   all_limits = 0;
325
326   /* Idea stolen from pdksh -- build option string the first time called. */
327   if (optstring[0] == 0)
328     {
329       s = optstring;
330       *s++ = 'a'; *s++ = 'S'; *s++ = 'H';
331       for (c = 0; limits[c].option > 0; c++)
332         {
333           *s++ = limits[c].option;
334           *s++ = ';';
335         }
336       *s = '\0';
337     }
338
339   /* Initialize the command list. */
340   if (cmdlistsz == 0)
341     cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD));
342   ncmd = 0;
343
344   reset_internal_getopt ();
345   while ((opt = internal_getopt (list, optstring)) != -1)
346     {
347       switch (opt)
348         {
349         case 'a':
350           all_limits++;
351           break;
352
353         /* -S and -H are modifiers, not real options.  */
354         case 'S':
355           mode |= LIMIT_SOFT;
356           break;
357
358         case 'H':
359           mode |= LIMIT_HARD;
360           break;
361
362         case '?':
363           builtin_usage ();
364           return (EX_USAGE);
365
366         default:
367           if (ncmd >= cmdlistsz)
368             cmdlist = (ULCMD *)xrealloc (cmdlist, (cmdlistsz *= 2) * sizeof (ULCMD));
369           cmdlist[ncmd].cmd = opt;
370           cmdlist[ncmd++].arg = list_optarg;
371           break;
372         }
373     }
374   list = loptend;
375
376   if (all_limits)
377     {
378 #ifdef NOTYET
379       if (list)         /* setting */
380         {
381           if (STREQ (list->word->word, "unlimited") == 0)
382             {
383               builtin_error (_("%s: invalid limit argument"), list->word->word);
384               return (EXECUTION_FAILURE);
385             }
386           return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY));
387         }
388 #endif
389       print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
390       return (sh_chkwrite (EXECUTION_SUCCESS));
391     }
392
393   /* default is `ulimit -f' */
394   if (ncmd == 0)
395     {
396       cmdlist[ncmd].cmd = 'f';
397       /* `ulimit something' is same as `ulimit -f something' */
398       cmdlist[ncmd++].arg = list ? list->word->word : (char *)NULL;
399       if (list)
400         list = list->next;
401     }
402
403   /* verify each command in the list. */
404   for (c = 0; c < ncmd; c++)
405     {
406       limind = _findlim (cmdlist[c].cmd);
407       if (limind == -1)
408         {
409           builtin_error (_("`%c': bad command"), cmdlist[c].cmd);
410           return (EX_USAGE);
411         }
412     }
413
414   for (c = 0; c < ncmd; c++)
415     if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
416       return (EXECUTION_FAILURE);
417
418   return (EXECUTION_SUCCESS);
419 }
420
421 static int
422 ulimit_internal (cmd, cmdarg, mode, multiple)
423      int cmd;
424      char *cmdarg;
425      int mode, multiple;
426 {
427   int opt, limind, setting;
428   int block_factor;
429   RLIMTYPE soft_limit, hard_limit, real_limit, limit;
430
431   setting = cmdarg != 0;
432   limind = _findlim (cmd);
433   if (mode == 0)
434     mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
435   opt = get_limit (limind, &soft_limit, &hard_limit);
436   if (opt < 0)
437     {
438       builtin_error (_("%s: cannot get limit: %s"), limits[limind].description,
439                                                  strerror (errno));
440       return (EXECUTION_FAILURE);
441     }
442
443   if (setting == 0)     /* print the value of the specified limit */
444     {
445       printone (limind, (mode & LIMIT_SOFT) ? soft_limit : hard_limit, multiple);
446       return (EXECUTION_SUCCESS);
447     }
448  
449   /* Setting the limit. */
450   if (STREQ (cmdarg, "hard"))
451     real_limit = hard_limit;
452   else if (STREQ (cmdarg, "soft"))
453     real_limit = soft_limit;
454   else if (STREQ (cmdarg, "unlimited"))
455     real_limit = RLIM_INFINITY;
456   else if (all_digits (cmdarg))
457     {
458       limit = string_to_rlimtype (cmdarg);
459       block_factor = BLOCKSIZE(limits[limind].block_factor);
460       real_limit = limit * block_factor;
461
462       if ((real_limit / block_factor) != limit)
463         {
464           sh_erange (cmdarg, _("limit"));
465           return (EXECUTION_FAILURE);
466         }
467     }
468   else
469     {
470       sh_invalidnum (cmdarg);
471       return (EXECUTION_FAILURE);
472     }
473
474   if (set_limit (limind, real_limit, mode) < 0)
475     {
476       builtin_error (_("%s: cannot modify limit: %s"), limits[limind].description,
477                                                     strerror (errno));
478       return (EXECUTION_FAILURE);
479     }
480
481   return (EXECUTION_SUCCESS);
482 }
483
484 static int
485 get_limit (ind, softlim, hardlim)
486      int ind;
487      RLIMTYPE *softlim, *hardlim;
488 {
489   RLIMTYPE value;
490 #if defined (HAVE_RESOURCE)
491   struct rlimit limit;
492 #endif
493
494   if (limits[ind].parameter >= 256)
495     {
496       switch (limits[ind].parameter)
497         {
498         case RLIMIT_FILESIZE:
499           if (filesize (&value) < 0)
500             return -1;
501           break;
502         case RLIMIT_PIPESIZE:
503           if (pipesize (&value) < 0)
504             return -1;
505           break;
506         case RLIMIT_OPENFILES:
507           value = (RLIMTYPE)getdtablesize ();
508           break;
509         case RLIMIT_VIRTMEM:
510           return (getmaxvm (softlim, hardlim));
511         case RLIMIT_MAXUPROC:
512           if (getmaxuprc (&value) < 0)
513             return -1;
514           break;
515         default:
516           errno = EINVAL;
517           return -1;
518         }
519       *softlim = *hardlim = value;
520       return (0);
521     }
522   else
523     {
524 #if defined (HAVE_RESOURCE)
525       if (getrlimit (limits[ind].parameter, &limit) < 0)
526         return -1;
527       *softlim = limit.rlim_cur;
528       *hardlim = limit.rlim_max;
529 #  if defined (HPUX9)
530       if (limits[ind].parameter == RLIMIT_FILESIZE)
531         {
532           *softlim *= 512;
533           *hardlim *= 512;                      /* Ugh. */
534         }
535       else
536 #  endif /* HPUX9 */
537       return 0;
538 #else
539       errno = EINVAL;
540       return -1;
541 #endif
542     }
543 }
544
545 static int
546 set_limit (ind, newlim, mode)
547      int ind;
548      RLIMTYPE newlim;
549      int mode;
550 {
551 #if defined (HAVE_RESOURCE)
552    struct rlimit limit;
553    RLIMTYPE val;
554 #endif
555
556   if (limits[ind].parameter >= 256)
557     switch (limits[ind].parameter)
558       {
559       case RLIMIT_FILESIZE:
560 #if !defined (HAVE_RESOURCE)
561         return (ulimit (2, newlim / 512L));
562 #else
563         errno = EINVAL;
564         return -1;
565 #endif
566
567       case RLIMIT_OPENFILES:
568 #if defined (HAVE_SETDTABLESIZE)
569 #  if defined (__CYGWIN__)
570         /* Grrr... Cygwin declares setdtablesize as void. */
571         setdtablesize (newlim);
572         return 0;
573 #  else
574         return (setdtablesize (newlim));
575 #  endif
576 #endif
577       case RLIMIT_PIPESIZE:
578       case RLIMIT_VIRTMEM:
579       case RLIMIT_MAXUPROC:
580       default:
581         errno = EINVAL;
582         return -1;
583       }
584   else
585     {
586 #if defined (HAVE_RESOURCE)
587       if (getrlimit (limits[ind].parameter, &limit) < 0)
588         return -1;
589 #  if defined (HPUX9)
590       if (limits[ind].parameter == RLIMIT_FILESIZE)
591         newlim /= 512;                          /* Ugh. */
592 #  endif /* HPUX9 */
593       val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
594                (mode & LIMIT_HARD) == 0 &&              /* XXX -- test */
595                (limit.rlim_cur <= limit.rlim_max))
596                  ? limit.rlim_max : newlim;
597       if (mode & LIMIT_SOFT)
598         limit.rlim_cur = val;
599       if (mode & LIMIT_HARD)
600         limit.rlim_max = val;
601           
602       return (setrlimit (limits[ind].parameter, &limit));
603 #else
604       errno = EINVAL;
605       return -1;
606 #endif
607     }
608 }
609
610 static int
611 getmaxvm (softlim, hardlim)
612      RLIMTYPE *softlim, *hardlim;
613 {
614 #if defined (HAVE_RESOURCE)
615   struct rlimit datalim, stacklim;
616
617   if (getrlimit (RLIMIT_DATA, &datalim) < 0)
618     return -1;
619
620   if (getrlimit (RLIMIT_STACK, &stacklim) < 0)
621     return -1;
622
623   /* Protect against overflow. */
624   *softlim = (datalim.rlim_cur / 1024L) + (stacklim.rlim_cur / 1024L);
625   *hardlim = (datalim.rlim_max / 1024L) + (stacklim.rlim_max / 1024L);
626   return 0;
627 #else
628   errno = EINVAL;
629   return -1;
630 #endif /* HAVE_RESOURCE */
631 }
632
633 static int
634 filesize(valuep)
635      RLIMTYPE *valuep;
636 {
637 #if !defined (HAVE_RESOURCE)
638   long result;
639   if ((result = ulimit (1, 0L)) < 0)
640     return -1;
641   else
642     *valuep = (RLIMTYPE) result * 512;
643   return 0;
644 #else
645   errno = EINVAL;
646   return -1;
647 #endif
648 }
649
650 static int
651 pipesize (valuep)
652      RLIMTYPE *valuep;
653 {
654 #if defined (PIPE_BUF)
655   /* This is defined on Posix systems. */
656   *valuep = (RLIMTYPE) PIPE_BUF;
657   return 0;
658 #else
659 #  if defined (_POSIX_PIPE_BUF)
660   *valuep = (RLIMTYPE) _POSIX_PIPE_BUF;
661   return 0;
662 #  else
663 #    if defined (PIPESIZE)
664   /* This is defined by running a program from the Makefile. */
665   *valuep = (RLIMTYPE) PIPESIZE;
666   return 0;
667 #    else
668   errno = EINVAL;
669   return -1;  
670 #    endif /* PIPESIZE */
671 #  endif /* _POSIX_PIPE_BUF */
672 #endif /* PIPE_BUF */
673 }
674
675 static int
676 getmaxuprc (valuep)
677      RLIMTYPE *valuep;
678 {
679   long maxchild;
680
681   maxchild = getmaxchild ();
682   if (maxchild < 0)
683     {
684       errno = EINVAL;
685       return -1;
686     }
687   else
688     {
689       *valuep = (RLIMTYPE) maxchild;
690       return 0;
691     }
692 }
693
694 static void
695 print_all_limits (mode)
696      int mode;
697 {
698   register int i;
699   RLIMTYPE softlim, hardlim;
700
701   if (mode == 0)
702     mode |= LIMIT_SOFT;
703
704   for (i = 0; limits[i].option > 0; i++)
705     {
706       if (get_limit (i, &softlim, &hardlim) == 0)
707         printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
708       else if (errno != EINVAL)
709         builtin_error ("%s: cannot get limit: %s", limits[i].description,
710                                                    strerror (errno));
711     }
712 }
713
714 static void
715 printone (limind, curlim, pdesc)
716      int limind;
717      RLIMTYPE curlim;
718      int pdesc;
719 {
720   char unitstr[64];
721   int factor;
722
723   factor = BLOCKSIZE(limits[limind].block_factor);
724   if (pdesc)
725     {
726       if (limits[limind].units)
727         sprintf (unitstr, "(%s, -%c) ", limits[limind].units, limits[limind].option);
728       else
729         sprintf (unitstr, "(-%c) ", limits[limind].option);
730
731       printf ("%-20s %16s", limits[limind].description, unitstr);
732     }
733   if (curlim == RLIM_INFINITY)
734     puts ("unlimited");
735   else if (curlim == RLIM_SAVED_MAX)
736     puts ("hard");
737   else if (curlim == RLIM_SAVED_CUR)
738     puts ("soft");
739   else
740     print_rlimtype ((curlim / factor), 1);
741 }
742
743 /* Set all limits to NEWLIM.  NEWLIM currently must be RLIM_INFINITY, which
744    causes all limits to be set as high as possible depending on mode (like
745    csh `unlimit').  Returns -1 if NEWLIM is invalid, 0 if all limits
746    were set successfully, and 1 if at least one limit could not be set.
747
748    To raise all soft limits to their corresponding hard limits, use
749         ulimit -S -a unlimited
750    To attempt to raise all hard limits to infinity (superuser-only), use
751         ulimit -H -a unlimited
752    To attempt to raise all soft and hard limits to infinity, use
753         ulimit -a unlimited
754 */
755
756 static int
757 set_all_limits (mode, newlim)
758      int mode;
759      RLIMTYPE newlim;
760 {
761   register int i;
762   int retval = 0;
763
764   if (newlim != RLIM_INFINITY)
765     {
766       errno = EINVAL;
767       return -1;
768     }
769   
770   if (mode == 0)
771     mode = LIMIT_SOFT|LIMIT_HARD;
772
773   for (retval = i = 0; limits[i].option > 0; i++)
774     if (set_limit (i, newlim, mode) < 0)
775       {
776         builtin_error (_("%s: cannot modify limit: %s"), limits[i].description,
777                                                       strerror (errno));
778         retval = 1;
779       }
780   return retval;
781 }
782
783 #endif /* !_MINIX */