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