source: vendor/bash/3.1/builtins/ulimit.def

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 17.5 KB
Line 
1This file is ulimit.def, from which is created ulimit.c.
2It implements the builtin "ulimit" in Bash.
3
4Copyright (C) 1987-2005 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
20Foundation, 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]
28Ulimit provides control over the resources available to processes
29started by the shell, on systems that allow such control. If an
30option 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
50If LIMIT is given, it is the new value of the specified resource;
51the special LIMIT values `soft', `hard', and `unlimited' stand for
52the current soft limit, the current hard limit, and no limit, respectively.
53Otherwise, the current value of the specified resource is printed.
54If no option is given, then -f is assumed. Values are in 1024-byte
55increments, except for -t, which is in seconds, -p, which is in
56increments of 512 bytes, and -u, which is an unscaled number of
57processes.
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)
84extern 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
173static int _findlim __P((int));
174
175static int ulimit_internal __P((int, char *, int, int));
176
177static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *));
178static int set_limit __P((int, RLIMTYPE, int));
179
180static void printone __P((int, RLIMTYPE, int));
181static void print_all_limits __P((int));
182
183static int set_all_limits __P((int, RLIMTYPE));
184
185static int filesize __P((RLIMTYPE *));
186static int pipesize __P((RLIMTYPE *));
187static int getmaxuprc __P((RLIMTYPE *));
188static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *));
189
190typedef 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
198static 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
240typedef struct _cmd {
241 int cmd;
242 char *arg;
243} ULCMD;
244
245static ULCMD *cmdlist;
246static int ncmd;
247static int cmdlistsz;
248
249#if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
250long
251ulimit (cmd, newlim)
252 int cmd;
253 long newlim;
254{
255 errno = EINVAL;
256 return -1;
257}
258#endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
259
260static 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
272static 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. */
276int
277ulimit_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
382static int
383ulimit_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
445static int
446get_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
506static int
507set_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
571static int
572getmaxvm (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
594static int
595filesize(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
611static int
612pipesize (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
636static int
637getmaxuprc (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
655static void
656print_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
675static void
676printone (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
715static int
716set_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 */
Note: See TracBrowser for help on using the repository browser.