blob: fc676c7c76b484f465c8a1fcfada142bc6ebbb1c [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001This file is ulimit.def, from which is created ulimit.c.
2It implements the builtin "ulimit" in Bash.
3
Chet Ramey495aee42011-11-22 19:11:26 -05004Copyright (C) 1987-2010 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
Jari Aalto31859422009-01-12 13:36:28 +00008Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
Jari Aalto726f6381996-08-26 18:22:31 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
Jari Aalto726f6381996-08-26 18:22:31 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
Jari Aalto726f6381996-08-26 18:22:31 +000020
21$PRODUCES ulimit.c
22
23$BUILTIN ulimit
24$FUNCTION ulimit_builtin
Jari Aaltocce855b1998-04-17 19:52:44 +000025$DEPENDS_ON !_MINIX
Chet Rameyac50fba2014-02-26 09:36:43 -050026$SHORT_DOC ulimit [-SHabcdefilmnpqrstuvxT] [limit]
Jari Aalto31859422009-01-12 13:36:28 +000027Modify shell resource limits.
Jari Aalto726f6381996-08-26 18:22:31 +000028
Jari Aalto31859422009-01-12 13:36:28 +000029Provides control over the resources available to the shell and processes
30it creates, on systems that allow such control.
Jari Aalto726f6381996-08-26 18:22:31 +000031
Jari Aalto31859422009-01-12 13:36:28 +000032Options:
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
Chet Rameyac50fba2014-02-26 09:36:43 -050053 -T the maximum number of threads
54
55Not all options are available on all platforms.
Jari Aalto31859422009-01-12 13:36:28 +000056
57If LIMIT is given, it is the new value of the specified resource; the
58special LIMIT values `soft', `hard', and `unlimited' stand for the
59current soft limit, the current hard limit, and no limit, respectively.
60Otherwise, the current value of the specified resource is printed. If
61no option is given, then -f is assumed.
62
63Values 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
65number of processes.
66
67Exit Status:
68Returns success unless an invalid option is supplied or an error occurs.
Jari Aalto726f6381996-08-26 18:22:31 +000069$END
70
Jari Aaltocce855b1998-04-17 19:52:44 +000071#if !defined (_MINIX)
72
Jari Aaltoccc6cda1996-12-23 17:02:34 +000073#include <config.h>
74
75#include "../bashtypes.h"
Chet Rameyac50fba2014-02-26 09:36:43 -050076#if defined (HAVE_SYS_PARAM_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000077# include <sys/param.h>
78#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000079
80#if defined (HAVE_UNISTD_H)
81# include <unistd.h>
82#endif
83
84#include <stdio.h>
Jari Aalto726f6381996-08-26 18:22:31 +000085#include <errno.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000086
Jari Aaltob80f6442004-07-27 13:29:18 +000087#include "../bashintl.h"
88
Jari Aalto726f6381996-08-26 18:22:31 +000089#include "../shell.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000090#include "common.h"
91#include "bashgetopt.h"
Jari Aalto726f6381996-08-26 18:22:31 +000092#include "pipesize.h"
93
94#if !defined (errno)
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +010095#include <errno.h>
Jari Aalto726f6381996-08-26 18:22:31 +000096#endif
97
Jari Aaltoccc6cda1996-12-23 17:02:34 +000098/* 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. */
Jari Aalto726f6381996-08-26 18:22:31 +0000101#if defined (HAVE_RESOURCE)
102# include <sys/time.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000103# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
104# define _KERNEL
105# endif
Jari Aalto726f6381996-08-26 18:22:31 +0000106# include <sys/resource.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000107# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
108# undef _KERNEL
109# endif
Jari Aalto31859422009-01-12 13:36:28 +0000110#elif defined (HAVE_SYS_TIMES_H)
Jari Aalto726f6381996-08-26 18:22:31 +0000111# include <sys/times.h>
112#endif
113
Jari Aalto726f6381996-08-26 18:22:31 +0000114#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. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000120#if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
Jari Aalto726f6381996-08-26 18:22:31 +0000121# undef HAVE_RESOURCE
122#endif
123
Chet Ramey495aee42011-11-22 19:11:26 -0500124#if !defined (HAVE_RESOURCE) && defined (HAVE_ULIMIT_H)
125# include <ulimit.h>
126#endif
127
Jari Aalto726f6381996-08-26 18:22:31 +0000128#if !defined (RLIMTYPE)
129# define RLIMTYPE long
Jari Aaltocce855b1998-04-17 19:52:44 +0000130# define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
Jari Aalto726f6381996-08-26 18:22:31 +0000131# define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
132#endif
133
Jari Aalto726f6381996-08-26 18:22:31 +0000134/* 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
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000139/* 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
Chet Rameyac50fba2014-02-26 09:36:43 -0500173#if !defined (RLIMIT_PTHREAD) && defined (RLIMIT_NTHR)
174# define RLIMIT_PTHREAD RLIMIT_NTHR
175#endif
176
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000177#if !defined (RLIM_INFINITY)
178# define RLIM_INFINITY 0x7fffffff
179#endif
180
Jari Aaltof73dda02001-11-13 17:56:06 +0000181#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
Jari Aalto726f6381996-08-26 18:22:31 +0000189#define LIMIT_HARD 0x01
190#define LIMIT_SOFT 0x02
191
Jari Aalto31859422009-01-12 13:36:28 +0000192/* "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
198extern int posixly_correct;
199
Jari Aaltof73dda02001-11-13 17:56:06 +0000200static int _findlim __P((int));
201
Jari Aaltob72432f1999-02-19 17:11:39 +0000202static int ulimit_internal __P((int, char *, int, int));
Jari Aaltof73dda02001-11-13 17:56:06 +0000203
204static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *));
205static int set_limit __P((int, RLIMTYPE, int));
206
Jari Aaltob72432f1999-02-19 17:11:39 +0000207static void printone __P((int, RLIMTYPE, int));
208static void print_all_limits __P((int));
Jari Aalto726f6381996-08-26 18:22:31 +0000209
Jari Aaltof73dda02001-11-13 17:56:06 +0000210static int set_all_limits __P((int, RLIMTYPE));
Jari Aalto726f6381996-08-26 18:22:31 +0000211
Jari Aaltob72432f1999-02-19 17:11:39 +0000212static int filesize __P((RLIMTYPE *));
213static int pipesize __P((RLIMTYPE *));
Jari Aaltof73dda02001-11-13 17:56:06 +0000214static int getmaxuprc __P((RLIMTYPE *));
215static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000216
217typedef 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. */
Jari Aalto31859422009-01-12 13:36:28 +0000221 const char * const description; /* Descriptive string to output. */
222 const char * const units; /* scale */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000223} RESOURCE_LIMITS;
224
225static RESOURCE_LIMITS limits[] = {
Jari Aalto31859422009-01-12 13:36:28 +0000226#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
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000232#ifdef RLIMIT_CORE
Jari Aalto31859422009-01-12 13:36:28 +0000233 { 'c', RLIMIT_CORE, POSIXBLK, "core file size", "blocks" },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000234#endif
235#ifdef RLIMIT_DATA
Jari Aaltof73dda02001-11-13 17:56:06 +0000236 { 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000237#endif
Jari Aalto06285672006-10-10 14:15:34 +0000238#ifdef RLIMIT_NICE
239 { 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL },
240#endif
Jari Aalto31859422009-01-12 13:36:28 +0000241 { 'f', RLIMIT_FILESIZE, POSIXBLK, "file size", "blocks" },
Jari Aalto95732b42005-12-07 14:08:12 +0000242#ifdef RLIMIT_SIGPENDING
243 { 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
244#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000245#ifdef RLIMIT_MEMLOCK
Jari Aaltof73dda02001-11-13 17:56:06 +0000246 { 'l', RLIMIT_MEMLOCK, 1024, "max locked memory", "kbytes" },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000247#endif
248#ifdef RLIMIT_RSS
Jari Aaltof73dda02001-11-13 17:56:06 +0000249 { 'm', RLIMIT_RSS, 1024, "max memory size", "kbytes" },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000250#endif /* RLIMIT_RSS */
Jari Aaltof73dda02001-11-13 17:56:06 +0000251 { 'n', RLIMIT_OPENFILES, 1, "open files", (char *)NULL},
252 { 'p', RLIMIT_PIPESIZE, 512, "pipe size", "512 bytes" },
Jari Aalto95732b42005-12-07 14:08:12 +0000253#ifdef RLIMIT_MSGQUEUE
254 { 'q', RLIMIT_MSGQUEUE, 1, "POSIX message queues", "bytes" },
255#endif
Jari Aalto06285672006-10-10 14:15:34 +0000256#ifdef RLIMIT_RTPRIO
257 { 'r', RLIMIT_RTPRIO, 1, "real-time priority", (char *)NULL },
258#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000259#ifdef RLIMIT_STACK
Jari Aaltof73dda02001-11-13 17:56:06 +0000260 { 's', RLIMIT_STACK, 1024, "stack size", "kbytes" },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000261#endif
262#ifdef RLIMIT_CPU
Jari Aaltof73dda02001-11-13 17:56:06 +0000263 { 't', RLIMIT_CPU, 1, "cpu time", "seconds" },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000264#endif /* RLIMIT_CPU */
Jari Aaltof73dda02001-11-13 17:56:06 +0000265 { 'u', RLIMIT_MAXUPROC, 1, "max user processes", (char *)NULL },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000266#if defined (HAVE_RESOURCE)
Jari Aaltof73dda02001-11-13 17:56:06 +0000267 { 'v', RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" },
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000268#endif
Jari Aalto28ef6c32001-04-06 19:14:31 +0000269#ifdef RLIMIT_SWAP
Jari Aaltof73dda02001-11-13 17:56:06 +0000270 { 'w', RLIMIT_SWAP, 1024, "swap size", "kbytes" },
Jari Aalto28ef6c32001-04-06 19:14:31 +0000271#endif
Jari Aalto95732b42005-12-07 14:08:12 +0000272#ifdef RLIMIT_LOCKS
273 { 'x', RLIMIT_LOCKS, 1, "file locks", (char *)NULL },
274#endif
Jari Aaltof73dda02001-11-13 17:56:06 +0000275 { -1, -1, -1, (char *)NULL, (char *)NULL }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000276};
277#define NCMDS (sizeof(limits) / sizeof(limits[0]))
278
279typedef struct _cmd {
280 int cmd;
281 char *arg;
282} ULCMD;
283
284static ULCMD *cmdlist;
285static int ncmd;
286static int cmdlistsz;
287
Jari Aaltod166f041997-06-05 14:59:13 +0000288#if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
289long
290ulimit (cmd, newlim)
291 int cmd;
292 long newlim;
293{
294 errno = EINVAL;
295 return -1;
296}
297#endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
298
Jari Aalto726f6381996-08-26 18:22:31 +0000299static int
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000300_findlim (opt)
301 int opt;
Jari Aalto726f6381996-08-26 18:22:31 +0000302{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000303 register int i;
Jari Aalto726f6381996-08-26 18:22:31 +0000304
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000305 for (i = 0; limits[i].option > 0; i++)
306 if (limits[i].option == opt)
307 return i;
308 return -1;
Jari Aalto726f6381996-08-26 18:22:31 +0000309}
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000310
311static char optstring[4 + 2 * NCMDS];
Jari Aalto726f6381996-08-26 18:22:31 +0000312
313/* Report or set limits associated with certain per-process resources.
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000314 See the help documentation in builtins.c for a full description. */
Jari Aalto726f6381996-08-26 18:22:31 +0000315int
316ulimit_builtin (list)
317 register WORD_LIST *list;
318{
319 register char *s;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000320 int c, limind, mode, opt, all_limits;
Jari Aalto726f6381996-08-26 18:22:31 +0000321
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000322 mode = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000323
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000324 all_limits = 0;
325
326 /* Idea stolen from pdksh -- build option string the first time called. */
327 if (optstring[0] == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000328 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000329 s = optstring;
330 *s++ = 'a'; *s++ = 'S'; *s++ = 'H';
331 for (c = 0; limits[c].option > 0; c++)
Jari Aalto726f6381996-08-26 18:22:31 +0000332 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000333 *s++ = limits[c].option;
334 *s++ = ';';
Jari Aalto726f6381996-08-26 18:22:31 +0000335 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000336 *s = '\0';
337 }
Jari Aalto726f6381996-08-26 18:22:31 +0000338
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000339 /* Initialize the command list. */
340 if (cmdlistsz == 0)
341 cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD));
342 ncmd = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000343
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000344 reset_internal_getopt ();
345 while ((opt = internal_getopt (list, optstring)) != -1)
346 {
347 switch (opt)
Jari Aalto726f6381996-08-26 18:22:31 +0000348 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000349 case 'a':
350 all_limits++;
351 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000352
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000353 /* -S and -H are modifiers, not real options. */
354 case 'S':
355 mode |= LIMIT_SOFT;
356 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000357
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000358 case 'H':
359 mode |= LIMIT_HARD;
360 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000361
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000362 case '?':
363 builtin_usage ();
364 return (EX_USAGE);
Jari Aalto726f6381996-08-26 18:22:31 +0000365
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000366 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;
Jari Aalto726f6381996-08-26 18:22:31 +0000372 }
373 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000374 list = loptend;
375
376 if (all_limits)
377 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000378#ifdef NOTYET
379 if (list) /* setting */
380 {
381 if (STREQ (list->word->word, "unlimited") == 0)
382 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000383 builtin_error (_("%s: invalid limit argument"), list->word->word);
Jari Aaltof73dda02001-11-13 17:56:06 +0000384 return (EXECUTION_FAILURE);
385 }
386 return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY));
387 }
388#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000389 print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
Jari Aalto31859422009-01-12 13:36:28 +0000390 return (sh_chkwrite (EXECUTION_SUCCESS));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000391 }
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 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000409 builtin_error (_("`%c': bad command"), cmdlist[c].cmd);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000410 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);
Jari Aalto726f6381996-08-26 18:22:31 +0000417
418 return (EXECUTION_SUCCESS);
419}
420
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000421static int
422ulimit_internal (cmd, cmdarg, mode, multiple)
423 int cmd;
424 char *cmdarg;
425 int mode, multiple;
Jari Aalto726f6381996-08-26 18:22:31 +0000426{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000427 int opt, limind, setting;
Jari Aaltof73dda02001-11-13 17:56:06 +0000428 int block_factor;
429 RLIMTYPE soft_limit, hard_limit, real_limit, limit;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000430
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000431 setting = cmdarg != 0;
432 limind = _findlim (cmd);
433 if (mode == 0)
434 mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
Jari Aaltof73dda02001-11-13 17:56:06 +0000435 opt = get_limit (limind, &soft_limit, &hard_limit);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000436 if (opt < 0)
437 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000438 builtin_error (_("%s: cannot get limit: %s"), limits[limind].description,
Jari Aalto7117c2d2002-07-17 14:10:11 +0000439 strerror (errno));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000440 return (EXECUTION_FAILURE);
441 }
442
443 if (setting == 0) /* print the value of the specified limit */
444 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000445 printone (limind, (mode & LIMIT_SOFT) ? soft_limit : hard_limit, multiple);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000446 return (EXECUTION_SUCCESS);
447 }
448
449 /* Setting the limit. */
Jari Aaltof73dda02001-11-13 17:56:06 +0000450 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;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000456 else if (all_digits (cmdarg))
Jari Aaltof73dda02001-11-13 17:56:06 +0000457 {
458 limit = string_to_rlimtype (cmdarg);
Jari Aalto31859422009-01-12 13:36:28 +0000459 block_factor = BLOCKSIZE(limits[limind].block_factor);
Jari Aaltof73dda02001-11-13 17:56:06 +0000460 real_limit = limit * block_factor;
461
462 if ((real_limit / block_factor) != limit)
463 {
Jari Aalto31859422009-01-12 13:36:28 +0000464 sh_erange (cmdarg, _("limit"));
Jari Aaltof73dda02001-11-13 17:56:06 +0000465 return (EXECUTION_FAILURE);
466 }
467 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000468 else
469 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000470 sh_invalidnum (cmdarg);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000471 return (EXECUTION_FAILURE);
472 }
473
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000474 if (set_limit (limind, real_limit, mode) < 0)
475 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000476 builtin_error (_("%s: cannot modify limit: %s"), limits[limind].description,
Jari Aalto7117c2d2002-07-17 14:10:11 +0000477 strerror (errno));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000478 return (EXECUTION_FAILURE);
479 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000480
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000481 return (EXECUTION_SUCCESS);
482}
483
484static int
Jari Aaltof73dda02001-11-13 17:56:06 +0000485get_limit (ind, softlim, hardlim)
486 int ind;
487 RLIMTYPE *softlim, *hardlim;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000488{
489 RLIMTYPE value;
Jari Aalto726f6381996-08-26 18:22:31 +0000490#if defined (HAVE_RESOURCE)
491 struct rlimit limit;
Jari Aalto726f6381996-08-26 18:22:31 +0000492#endif
493
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000494 if (limits[ind].parameter >= 256)
Jari Aalto726f6381996-08-26 18:22:31 +0000495 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000496 switch (limits[ind].parameter)
Jari Aalto726f6381996-08-26 18:22:31 +0000497 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000498 case RLIMIT_FILESIZE:
Jari Aaltob72432f1999-02-19 17:11:39 +0000499 if (filesize (&value) < 0)
500 return -1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000501 break;
502 case RLIMIT_PIPESIZE:
Jari Aaltob72432f1999-02-19 17:11:39 +0000503 if (pipesize (&value) < 0)
504 return -1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000505 break;
506 case RLIMIT_OPENFILES:
507 value = (RLIMTYPE)getdtablesize ();
508 break;
509 case RLIMIT_VIRTMEM:
Jari Aaltof73dda02001-11-13 17:56:06 +0000510 return (getmaxvm (softlim, hardlim));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000511 case RLIMIT_MAXUPROC:
Jari Aaltof73dda02001-11-13 17:56:06 +0000512 if (getmaxuprc (&value) < 0)
Jari Aaltob72432f1999-02-19 17:11:39 +0000513 return -1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000514 break;
515 default:
Jari Aalto726f6381996-08-26 18:22:31 +0000516 errno = EINVAL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000517 return -1;
Jari Aalto726f6381996-08-26 18:22:31 +0000518 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000519 *softlim = *hardlim = value;
Jari Aaltob72432f1999-02-19 17:11:39 +0000520 return (0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000521 }
522 else
523 {
Jari Aalto726f6381996-08-26 18:22:31 +0000524#if defined (HAVE_RESOURCE)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000525 if (getrlimit (limits[ind].parameter, &limit) < 0)
526 return -1;
Jari Aaltof73dda02001-11-13 17:56:06 +0000527 *softlim = limit.rlim_cur;
528 *hardlim = limit.rlim_max;
Jari Aaltob72432f1999-02-19 17:11:39 +0000529# if defined (HPUX9)
530 if (limits[ind].parameter == RLIMIT_FILESIZE)
Jari Aaltof73dda02001-11-13 17:56:06 +0000531 {
532 *softlim *= 512;
533 *hardlim *= 512; /* Ugh. */
534 }
Jari Aaltob72432f1999-02-19 17:11:39 +0000535 else
536# endif /* HPUX9 */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000537 return 0;
538#else
Jari Aalto726f6381996-08-26 18:22:31 +0000539 errno = EINVAL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000540 return -1;
541#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000542 }
543}
544
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000545static int
546set_limit (ind, newlim, mode)
547 int ind;
548 RLIMTYPE newlim;
549 int mode;
550{
Jari Aalto726f6381996-08-26 18:22:31 +0000551#if defined (HAVE_RESOURCE)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000552 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));
Jari Aaltod166f041997-06-05 14:59:13 +0000562#else
563 errno = EINVAL;
564 return -1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000565#endif
566
567 case RLIMIT_OPENFILES:
568#if defined (HAVE_SETDTABLESIZE)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000569# if defined (__CYGWIN__)
570 /* Grrr... Cygwin declares setdtablesize as void. */
571 setdtablesize (newlim);
572 return 0;
573# else
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000574 return (setdtablesize (newlim));
Jari Aalto28ef6c32001-04-06 19:14:31 +0000575# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000576#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;
Jari Aaltob72432f1999-02-19 17:11:39 +0000589# if defined (HPUX9)
590 if (limits[ind].parameter == RLIMIT_FILESIZE)
591 newlim /= 512; /* Ugh. */
592# endif /* HPUX9 */
Jari Aaltod166f041997-06-05 14:59:13 +0000593 val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
Jari Aalto28ef6c32001-04-06 19:14:31 +0000594 (mode & LIMIT_HARD) == 0 && /* XXX -- test */
Jari Aaltod166f041997-06-05 14:59:13 +0000595 (limit.rlim_cur <= limit.rlim_max))
596 ? limit.rlim_max : newlim;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000597 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
Jari Aaltob72432f1999-02-19 17:11:39 +0000610static int
Jari Aaltof73dda02001-11-13 17:56:06 +0000611getmaxvm (softlim, hardlim)
612 RLIMTYPE *softlim, *hardlim;
Jari Aalto726f6381996-08-26 18:22:31 +0000613{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000614#if defined (HAVE_RESOURCE)
Jari Aaltof73dda02001-11-13 17:56:06 +0000615 struct rlimit datalim, stacklim;
Jari Aalto726f6381996-08-26 18:22:31 +0000616
Jari Aaltof73dda02001-11-13 17:56:06 +0000617 if (getrlimit (RLIMIT_DATA, &datalim) < 0)
Jari Aaltob72432f1999-02-19 17:11:39 +0000618 return -1;
Jari Aalto726f6381996-08-26 18:22:31 +0000619
Jari Aaltof73dda02001-11-13 17:56:06 +0000620 if (getrlimit (RLIMIT_STACK, &stacklim) < 0)
Jari Aaltob72432f1999-02-19 17:11:39 +0000621 return -1;
Jari Aalto726f6381996-08-26 18:22:31 +0000622
623 /* Protect against overflow. */
Jari Aaltof73dda02001-11-13 17:56:06 +0000624 *softlim = (datalim.rlim_cur / 1024L) + (stacklim.rlim_cur / 1024L);
625 *hardlim = (datalim.rlim_max / 1024L) + (stacklim.rlim_max / 1024L);
Jari Aaltob72432f1999-02-19 17:11:39 +0000626 return 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000627#else
628 errno = EINVAL;
Jari Aaltob72432f1999-02-19 17:11:39 +0000629 return -1;
Jari Aalto726f6381996-08-26 18:22:31 +0000630#endif /* HAVE_RESOURCE */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000631}
Jari Aalto726f6381996-08-26 18:22:31 +0000632
Jari Aaltob72432f1999-02-19 17:11:39 +0000633static int
634filesize(valuep)
635 RLIMTYPE *valuep;
Jari Aalto726f6381996-08-26 18:22:31 +0000636{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000637#if !defined (HAVE_RESOURCE)
Jari Aaltob72432f1999-02-19 17:11:39 +0000638 long result;
639 if ((result = ulimit (1, 0L)) < 0)
640 return -1;
641 else
Jari Aaltof73dda02001-11-13 17:56:06 +0000642 *valuep = (RLIMTYPE) result * 512;
Jari Aaltob72432f1999-02-19 17:11:39 +0000643 return 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000644#else
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000645 errno = EINVAL;
Jari Aaltob72432f1999-02-19 17:11:39 +0000646 return -1;
Jari Aalto726f6381996-08-26 18:22:31 +0000647#endif
648}
649
Jari Aaltob72432f1999-02-19 17:11:39 +0000650static int
651pipesize (valuep)
652 RLIMTYPE *valuep;
Jari Aalto726f6381996-08-26 18:22:31 +0000653{
654#if defined (PIPE_BUF)
655 /* This is defined on Posix systems. */
Jari Aaltob72432f1999-02-19 17:11:39 +0000656 *valuep = (RLIMTYPE) PIPE_BUF;
657 return 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000658#else
Jari Aalto95732b42005-12-07 14:08:12 +0000659# if defined (_POSIX_PIPE_BUF)
660 *valuep = (RLIMTYPE) _POSIX_PIPE_BUF;
661 return 0;
662# else
663# if defined (PIPESIZE)
Jari Aalto726f6381996-08-26 18:22:31 +0000664 /* This is defined by running a program from the Makefile. */
Jari Aaltob72432f1999-02-19 17:11:39 +0000665 *valuep = (RLIMTYPE) PIPESIZE;
666 return 0;
Jari Aalto95732b42005-12-07 14:08:12 +0000667# else
Jari Aalto726f6381996-08-26 18:22:31 +0000668 errno = EINVAL;
Jari Aaltob72432f1999-02-19 17:11:39 +0000669 return -1;
Jari Aalto95732b42005-12-07 14:08:12 +0000670# endif /* PIPESIZE */
671# endif /* _POSIX_PIPE_BUF */
Jari Aalto726f6381996-08-26 18:22:31 +0000672#endif /* PIPE_BUF */
673}
674
Jari Aaltob72432f1999-02-19 17:11:39 +0000675static int
Jari Aaltof73dda02001-11-13 17:56:06 +0000676getmaxuprc (valuep)
Jari Aaltob72432f1999-02-19 17:11:39 +0000677 RLIMTYPE *valuep;
Jari Aalto726f6381996-08-26 18:22:31 +0000678{
Jari Aaltob72432f1999-02-19 17:11:39 +0000679 long maxchild;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000680
681 maxchild = getmaxchild ();
Jari Aaltob72432f1999-02-19 17:11:39 +0000682 if (maxchild < 0)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000683 {
684 errno = EINVAL;
685 return -1;
686 }
Jari Aaltob72432f1999-02-19 17:11:39 +0000687 else
Jari Aalto7117c2d2002-07-17 14:10:11 +0000688 {
689 *valuep = (RLIMTYPE) maxchild;
690 return 0;
691 }
Jari Aalto726f6381996-08-26 18:22:31 +0000692}
693
694static void
695print_all_limits (mode)
696 int mode;
697{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000698 register int i;
Jari Aaltof73dda02001-11-13 17:56:06 +0000699 RLIMTYPE softlim, hardlim;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000700
Jari Aalto726f6381996-08-26 18:22:31 +0000701 if (mode == 0)
702 mode |= LIMIT_SOFT;
703
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000704 for (i = 0; limits[i].option > 0; i++)
705 {
Jari Aalto95732b42005-12-07 14:08:12 +0000706 if (get_limit (i, &softlim, &hardlim) == 0)
707 printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
708 else if (errno != EINVAL)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000709 builtin_error ("%s: cannot get limit: %s", limits[i].description,
710 strerror (errno));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000711 }
712}
713
714static void
715printone (limind, curlim, pdesc)
716 int limind;
717 RLIMTYPE curlim;
718 int pdesc;
719{
Jari Aaltof73dda02001-11-13 17:56:06 +0000720 char unitstr[64];
Jari Aalto31859422009-01-12 13:36:28 +0000721 int factor;
Jari Aaltof73dda02001-11-13 17:56:06 +0000722
Jari Aalto31859422009-01-12 13:36:28 +0000723 factor = BLOCKSIZE(limits[limind].block_factor);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000724 if (pdesc)
Jari Aaltof73dda02001-11-13 17:56:06 +0000725 {
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
Jari Aalto95732b42005-12-07 14:08:12 +0000731 printf ("%-20s %16s", limits[limind].description, unitstr);
Jari Aaltof73dda02001-11-13 17:56:06 +0000732 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000733 if (curlim == RLIM_INFINITY)
734 puts ("unlimited");
Jari Aaltof73dda02001-11-13 17:56:06 +0000735 else if (curlim == RLIM_SAVED_MAX)
736 puts ("hard");
737 else if (curlim == RLIM_SAVED_CUR)
738 puts ("soft");
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000739 else
Jari Aalto31859422009-01-12 13:36:28 +0000740 print_rlimtype ((curlim / factor), 1);
Jari Aalto726f6381996-08-26 18:22:31 +0000741}
Jari Aaltof73dda02001-11-13 17:56:06 +0000742
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
756static int
757set_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 {
Jari Aalto31859422009-01-12 13:36:28 +0000776 builtin_error (_("%s: cannot modify limit: %s"), limits[i].description,
Jari Aalto7117c2d2002-07-17 14:10:11 +0000777 strerror (errno));
Jari Aaltof73dda02001-11-13 17:56:06 +0000778 retval = 1;
779 }
780 return retval;
781}
782
Jari Aaltocce855b1998-04-17 19:52:44 +0000783#endif /* !_MINIX */