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