$BUILTIN ulimit
$FUNCTION ulimit_builtin
$DEPENDS_ON !MINIX
-$SHORT_DOC ulimit [-SHacdfmstpnuv [limit]]
+$SHORT_DOC ulimit [-SHacdflmnpstuv] [limit]
Ulimit provides control over the resources available to processes
started by the shell, on systems that allow such control. If an
option is given, it is interpreted as follows:
-a all current limits are reported
-c the maximum size of core files created
-d the maximum size of a process's data segment
+ -f the maximum size of files created by the shell
+ -l the maximum size a process may lock into memory
-m the maximum resident set size
+ -n the maximum number of open file descriptors
+ -p the pipe buffer size
-s the maximum stack size
-t the maximum amount of cpu time in seconds
- -f the maximum size of files created by the shell
- -p the pipe buffer size
- -n the maximum number of open file descriptors
-u the maximum number of user processes
-v the size of virtual memory
If LIMIT is given, it is the new value of the specified resource.
Otherwise, the current value of the specified resource is printed.
-If no option is given, then -f is assumed. Values are in 1k
+If no option is given, then -f is assumed. Values are in 1024-byte
increments, except for -t, which is in seconds, -p, which is in
increments of 512 bytes, and -u, which is an unscaled number of
processes.
$END
-#include <stdio.h>
-#include <sys/types.h>
+#include <config.h>
+
+#include "../bashtypes.h"
#include <sys/param.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
#include <errno.h>
+
#include "../shell.h"
+#include "common.h"
+#include "bashgetopt.h"
#include "pipesize.h"
#if !defined (errno)
extern int errno;
#endif
+/* For some reason, HPUX chose to make these definitions visible only if
+ _KERNEL is defined, so we define _KERNEL before including <sys/resource.h>
+ and #undef it afterward. */
#if defined (HAVE_RESOURCE)
# include <sys/time.h>
+# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
+# define _KERNEL
+# endif
# include <sys/resource.h>
+# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
+# undef _KERNEL
+# endif
#else
# include <sys/times.h>
#endif
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
/* Check for the most basic symbols. If they aren't present, this
system's <sys/resource.h> isn't very useful to us. */
-#if !defined (RLIMIT_FSIZE) || defined (GETRLIMIT_MISSING)
+#if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
# undef HAVE_RESOURCE
#endif
# define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
#endif
-static void print_long ();
+#define DESCFMT "%-28s"
-/* **************************************************************** */
-/* */
-/* Ulimit builtin and Hacks. */
-/* */
-/* **************************************************************** */
+/* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
+#if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
+# define RLIMIT_NOFILE RLIMIT_OFILE
+#endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
-/* Block size for ulimit operations. */
-#define ULIMIT_BLOCK_SIZE ((long)1024)
+/* Some systems have these, some do not. */
+#ifdef RLIMIT_FSIZE
+# define RLIMIT_FILESIZE RLIMIT_FSIZE
+#else
+# define RLIMIT_FILESIZE 256
+#endif
+
+#define RLIMIT_PIPESIZE 257
-#define u_FILE_SIZE 0x001
-#define u_MAX_BREAK_VAL 0x002
-#define u_PIPE_SIZE 0x004
-#define u_CORE_FILE_SIZE 0x008
-#define u_DATA_SEG_SIZE 0x010
-#define u_PHYS_MEM_SIZE 0x020
-#define u_CPU_TIME_LIMIT 0x040
-#define u_STACK_SIZE 0x080
-#define u_NUM_OPEN_FILES 0x100
-#define u_MAX_VIRTUAL_MEM 0x200
-#define u_MAX_USER_PROCS 0x400
+#ifdef RLIMIT_NOFILE
+# define RLIMIT_OPENFILES RLIMIT_NOFILE
+#else
+# define RLIMIT_OPENFILES 258
+#endif
-#define u_ALL_LIMITS 0x7ff
+#ifdef RLIMIT_VMEM
+# define RLIMIT_VIRTMEM RLIMIT_VMEM
+# define RLIMIT_VMBLKSZ 1024
+#else
+# ifdef RLIMIT_AS
+# define RLIMIT_VIRTMEM RLIMIT_AS
+# define RLIMIT_VMBLKSZ 1024
+# else
+# define RLIMIT_VIRTMEM 259
+# define RLIMIT_VMBLKSZ 1
+# endif
+#endif
+
+#ifdef RLIMIT_NPROC
+# define RLIMIT_MAXUPROC RLIMIT_NPROC
+#else
+# define RLIMIT_MAXUPROC 260
+#endif
#if !defined (RLIM_INFINITY)
-# define RLIM_INFINITY 0x7fffffff
+# define RLIM_INFINITY 0x7fffffff
#endif
-/* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
-#if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
-# define RLIMIT_NOFILE RLIMIT_OFILE
-#endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
+#if !defined (RLIM_INVALID)
+# define RLIM_INVALID (RLIMTYPE)-1
+#endif
#define LIMIT_HARD 0x01
#define LIMIT_SOFT 0x02
-static RLIMTYPE shell_ulimit ();
+static int ulimit_internal ();
+static void printone ();
+static void print_all_limits ();
+
+static int get_limit ();
+static int set_limit ();
+
+static RLIMTYPE filesize ();
static RLIMTYPE pipesize ();
-static RLIMTYPE open_files ();
+static RLIMTYPE getmaxuprc ();
+static RLIMTYPE getmaxvm ();
+
+typedef struct {
+ int option; /* The ulimit option for this limit. */
+ int parameter; /* Parameter to pass to get_limit (). */
+ int block_factor; /* Blocking factor for specific limit. */
+ char *description; /* Descriptive string to output. */
+} RESOURCE_LIMITS;
+static RESOURCE_LIMITS limits[] = {
+#ifdef RLIMIT_CORE
+ { 'c', RLIMIT_CORE, 1024, "core file size (blocks)" },
+#endif
+#ifdef RLIMIT_DATA
+ { 'd', RLIMIT_DATA, 1024, "data seg size (kbytes)" },
+#endif
+ { 'f', RLIMIT_FILESIZE, 1024, "file size (blocks)" },
+#ifdef RLIMIT_MEMLOCK
+ { 'l', RLIMIT_MEMLOCK, 1024, "max locked memory (kbytes)" },
+#endif
+#ifdef RLIMIT_RSS
+ { 'm', RLIMIT_RSS, 1024, "max memory size (kbytes)" },
+#endif /* RLIMIT_RSS */
+ { 'n', RLIMIT_OPENFILES, 1, "open files" },
+ { 'p', RLIMIT_PIPESIZE, 512, "pipe size (512 bytes)" },
+#ifdef RLIMIT_STACK
+ { 's', RLIMIT_STACK, 1024, "stack size (kbytes)" },
+#endif
+#ifdef RLIMIT_CPU
+ { 't', RLIMIT_CPU, 1, "cpu time (seconds)" },
+#endif /* RLIMIT_CPU */
+ { 'u', RLIMIT_MAXUPROC, 1, "max user processes" },
#if defined (HAVE_RESOURCE)
-static RLIMTYPE getmaxvm ();
-#endif /* HAVE_RESOURCE */
+ { 'v', RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory (kbytes)" },
+#endif
+ { -1, -1, -1, (char *)NULL }
+};
+#define NCMDS (sizeof(limits) / sizeof(limits[0]))
-static void print_specific_limits ();
-static void print_all_limits ();
+typedef struct _cmd {
+ int cmd;
+ char *arg;
+} ULCMD;
-static char t[2];
+static ULCMD *cmdlist;
+static int ncmd;
+static int cmdlistsz;
-/* Return 1 if the limit associated with CMD can be raised from CURRENT
- to NEW. This is for USG systems without HAVE_RESOURCE, most of which
- do not allow any user other than root to raise limits. There are,
- however, exceptions. */
-#if !defined (HAVE_RESOURCE)
static int
-canraise (cmd, current, new)
- int cmd;
- RLIMTYPE current, new;
+_findlim (opt)
+ int opt;
{
-# if defined (HAVE_SETDTABLESIZE)
- if (cmd == u_NUM_OPEN_FILES)
- return (1);
-# endif /* HAVE_SETDTABLSIZE */
+ register int i;
- return ((current > new) || (current_user.uid == 0));
+ for (i = 0; limits[i].option > 0; i++)
+ if (limits[i].option == opt)
+ return i;
+ return -1;
}
-#endif /* !HAVE_RESOURCE */
-/* Report or set limits associated with certain per-process resources.
- See the help documentation in builtins.c for a full description.
+static char optstring[4 + 2 * NCMDS];
- Rewritten by Chet Ramey 6/30/91. */
+/* Report or set limits associated with certain per-process resources.
+ See the help documentation in builtins.c for a full description. */
int
ulimit_builtin (list)
register WORD_LIST *list;
{
register char *s;
- int c, setting, cmd, mode, verbose_print, opt_eof;
- int all_limits, specific_limits;
- long block_factor;
- RLIMTYPE current_limit, real_limit, limit;
+ int c, limind, mode, opt, all_limits;
- c = mode = verbose_print = opt_eof = 0;
- limit = (RLIMTYPE)-1;
+ mode = 0;
- do
- {
- cmd = setting = all_limits = specific_limits = 0;
- block_factor = ULIMIT_BLOCK_SIZE;
+ all_limits = 0;
- /* read_options: */
- if (list && !opt_eof && *list->word->word == '-')
+ /* Idea stolen from pdksh -- build option string the first time called. */
+ if (optstring[0] == 0)
+ {
+ s = optstring;
+ *s++ = 'a'; *s++ = 'S'; *s++ = 'H';
+ for (c = 0; limits[c].option > 0; c++)
{
- s = &(list->word->word[1]);
- list = list->next;
-
- while (*s && (c = *s++))
- {
- switch (c)
- {
-#define ADD_CMD(x) { if (cmd) specific_limits++; cmd |= (x); }
-
- case '-': /* ulimit -- */
- opt_eof++;
- break;
-
- case 'a':
- all_limits++;
- break;
-
- case 'f':
- ADD_CMD (u_FILE_SIZE);
- break;
-
-#if defined (HAVE_RESOURCE)
- /* -S and -H are modifiers, not real options. */
- case 'S':
- mode |= LIMIT_SOFT;
- break;
-
- case 'H':
- mode |= LIMIT_HARD;
- break;
-
- case 'c':
- ADD_CMD (u_CORE_FILE_SIZE);
- break;
-
- case 'd':
- ADD_CMD (u_DATA_SEG_SIZE);
- break;
-
-#if !defined (USGr4)
- case 'm':
- ADD_CMD (u_PHYS_MEM_SIZE);
- break;
-#endif /* USGr4 */
-
- case 't':
- ADD_CMD (u_CPU_TIME_LIMIT);
- block_factor = 1; /* seconds */
- break;
-
- case 's':
- ADD_CMD (u_STACK_SIZE);
- break;
-
- case 'v':
- ADD_CMD (u_MAX_VIRTUAL_MEM);
- block_factor = 1;
- break;
-
- case 'u':
- ADD_CMD (u_MAX_USER_PROCS);
- block_factor = 1;
- break;
-
-#endif /* HAVE_RESOURCE */
-
- case 'p':
- ADD_CMD (u_PIPE_SIZE);
- block_factor = 512;
- break;
-
- case 'n':
- ADD_CMD (u_NUM_OPEN_FILES);
- block_factor = 1;
- break;
-
- default: /* error_case: */
- t[0] = c;
- t[1] = '\0';
- bad_option (t);
-#if !defined (HAVE_RESOURCE)
- builtin_error("usage: ulimit [-afnp] [new limit]");
-#else
- builtin_error("usage: ulimit [-SHacmdstfnpuv] [new limit]");
-#endif
- return (EX_USAGE);
- }
- }
+ *s++ = limits[c].option;
+ *s++ = ';';
}
+ *s = '\0';
+ }
- if (all_limits)
- {
- print_all_limits (mode);
- return (EXECUTION_SUCCESS);
- }
-
- if (specific_limits)
- {
- print_specific_limits (cmd, mode);
- if (list)
- verbose_print++;
- continue;
- }
-
- if (cmd == 0)
- cmd = u_FILE_SIZE;
-
- /* If an argument was supplied for the command, then we want to
- set the limit. Note that `ulimit something' means a command
- of -f with argument `something'. */
- if (list)
- {
- if (opt_eof || (*list->word->word != '-'))
- {
- s = list->word->word;
- list = list->next;
-
- if (STREQ (s, "unlimited"))
- limit = RLIM_INFINITY;
- else if (all_digits (s))
- limit = string_to_rlimtype (s);
- else
- {
- builtin_error ("bad non-numeric arg `%s'", s);
- return (EXECUTION_FAILURE);
- }
- setting++;
- }
- else if (!opt_eof)
- verbose_print++;
- }
-
- if (limit == RLIM_INFINITY)
- block_factor = 1;
-
- real_limit = limit * block_factor;
-
- /* If more than one option is given, list each in a verbose format,
- the same that is used for -a. */
- if (!setting && verbose_print)
+ /* Initialize the command list. */
+ if (cmdlistsz == 0)
+ cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD));
+ ncmd = 0;
+
+ reset_internal_getopt ();
+ while ((opt = internal_getopt (list, optstring)) != -1)
+ {
+ switch (opt)
{
- print_specific_limits (cmd, mode);
- continue;
+ case 'a':
+ all_limits++;
+ break;
+
+ /* -S and -H are modifiers, not real options. */
+ case 'S':
+ mode |= LIMIT_SOFT;
+ break;
+
+ case 'H':
+ mode |= LIMIT_HARD;
+ break;
+
+ case '?':
+ builtin_usage ();
+ return (EX_USAGE);
+
+ default:
+ if (ncmd >= cmdlistsz)
+ cmdlist = (ULCMD *)xrealloc (cmdlist, (cmdlistsz *= 2) * sizeof (ULCMD));
+ cmdlist[ncmd].cmd = opt;
+ cmdlist[ncmd++].arg = list_optarg;
+ break;
}
+ }
+ list = loptend;
- current_limit = shell_ulimit (cmd, real_limit, 0, mode);
+ if (all_limits)
+ {
+ print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
+ return (EXECUTION_SUCCESS);
+ }
- if (setting)
- {
-#if !defined (HAVE_RESOURCE)
- /* Most USG systems do not most allow limits to be raised by any
- user other than root. There are, however, exceptions. */
- if (canraise (cmd, current_limit, real_limit) == 0)
- {
- builtin_error ("cannot raise limit: %s", strerror (EPERM));
- return (EXECUTION_FAILURE);
- }
-#endif /* !HAVE_RESOURCE */
-
- if (shell_ulimit (cmd, real_limit, 1, mode) == (RLIMTYPE)-1)
- {
- builtin_error ("cannot raise limit: %s", strerror (errno));
- return (EXECUTION_FAILURE);
- }
-
- continue;
- }
- else
+ /* default is `ulimit -f' */
+ if (ncmd == 0)
+ {
+ cmdlist[ncmd].cmd = 'f';
+ /* `ulimit something' is same as `ulimit -f something' */
+ cmdlist[ncmd++].arg = list ? list->word->word : (char *)NULL;
+ if (list)
+ list = list->next;
+ }
+
+ /* verify each command in the list. */
+ for (c = 0; c < ncmd; c++)
+ {
+ limind = _findlim (cmdlist[c].cmd);
+ if (limind == -1)
{
- if (current_limit < 0)
- builtin_error ("cannot get limit: %s", strerror (errno));
- else if (current_limit != RLIM_INFINITY)
- print_rlimtype ((current_limit / block_factor), 1);
- else
- printf ("unlimited\n");
+ builtin_error ("bad command: `%c'", cmdlist[c].cmd);
+ return (EX_USAGE);
}
}
- while (list);
+
+ for (c = 0; c < ncmd; c++)
+ if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
+ return (EXECUTION_FAILURE);
return (EXECUTION_SUCCESS);
}
-/* The ulimit that we call from within Bash.
+static int
+ulimit_internal (cmd, cmdarg, mode, multiple)
+ int cmd;
+ char *cmdarg;
+ int mode, multiple;
+{
+ int opt, limind, setting;
+ long block_factor;
+ RLIMTYPE current_limit, real_limit, limit;
- WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
- contains the desired new limit. Otherwise, the existing limit is
- returned. If mode & LIMIT_HARD, the hard limit is used; if
- mode & LIMIT_SOFT, the soft limit. Both may be set by specifying
- -H and -S; if both are specified, or if neither is specified, the
- soft limit will be returned.
+ limit = RLIM_INVALID;
+ setting = cmdarg != 0;
+ limind = _findlim (cmd);
+ if (mode == 0)
+ mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
+ opt = get_limit (limind, mode, ¤t_limit);
+ if (opt < 0)
+ {
+ builtin_error ("cannot get limit: %s", strerror (errno));
+ return (EXECUTION_FAILURE);
+ }
- Systems without BSD resource limits can specify only u_FILE_SIZE.
- This includes most USG systems.
+ if (setting == 0) /* print the value of the specified limit */
+ {
+ printone (limind, current_limit, multiple);
+ return (EXECUTION_SUCCESS);
+ }
+
+ /* Setting the limit. */
+ if (STREQ (cmdarg, "unlimited"))
+ limit = RLIM_INFINITY;
+ else if (all_digits (cmdarg))
+ limit = string_to_rlimtype (cmdarg);
+ else
+ {
+ builtin_error ("bad non-numeric arg `%s'", cmdarg);
+ return (EXECUTION_FAILURE);
+ }
- Chet Ramey supplied the BSD resource limit code. */
-static RLIMTYPE
-shell_ulimit (which, newlim, setting, mode)
- int which, setting, mode;
- RLIMTYPE newlim;
+ block_factor = (limit == RLIM_INFINITY) ? 1 : limits[limind].block_factor;
+ real_limit = limit * block_factor;
+
+ if (set_limit (limind, real_limit, mode) < 0)
+ {
+ builtin_error ("cannot modify limit: %s", strerror (errno));
+ return (EXECUTION_FAILURE);
+ }
+ return (EXECUTION_SUCCESS);
+}
+
+static int
+get_limit (ind, mode, limptr)
+ int ind, mode;
+ RLIMTYPE *limptr;
{
+ RLIMTYPE value;
#if defined (HAVE_RESOURCE)
struct rlimit limit;
- int cmd;
-
- if (mode == 0)
- mode |= LIMIT_SOFT;
#endif
- switch (which)
+ if (limits[ind].parameter >= 256)
{
-#if !defined (HAVE_RESOURCE)
-
- case u_FILE_SIZE:
- if (!setting)
+ switch (limits[ind].parameter)
{
- /* ulimit () returns a number that is in 512 byte blocks, thus we
- must multiply it by 512 to get back to bytes. This is false
- only under HP/UX 6.x. */
- RLIMTYPE result;
-
- result = ulimit (1, 0L);
-
-# if defined (hpux) && !defined (_POSIX_VERSION)
- return (result);
-# else
- return (result * 512);
-# endif /* hpux 6.x */
+ case RLIMIT_FILESIZE:
+ value = filesize ();
+ break;
+ case RLIMIT_PIPESIZE:
+ value = pipesize ();
+ break;
+ case RLIMIT_OPENFILES:
+ value = (RLIMTYPE)getdtablesize ();
+ break;
+ case RLIMIT_VIRTMEM:
+ value = getmaxvm (mode);
+ break;
+ case RLIMIT_MAXUPROC:
+ value = getmaxuprc (mode);
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
}
- else
- return (ulimit (2, newlim / 512L));
-
- break;
-
-#else /* defined (HAVE_RESOURCE) */
-
- case u_FILE_SIZE:
- cmd = RLIMIT_FSIZE;
- goto do_ulimit;
-
- case u_CORE_FILE_SIZE:
- cmd = RLIMIT_CORE;
- goto do_ulimit;
-
- case u_DATA_SEG_SIZE:
- cmd = RLIMIT_DATA;
- goto do_ulimit;
-
-#if !defined (USGr4)
- case u_PHYS_MEM_SIZE:
-# if defined (RLIMIT_RSS)
- cmd = RLIMIT_RSS;
-# else /* !RLIMIT_RSS */
- errno = EINVAL;
- return ((RLIMTYPE)-1);
-# endif /* !RLIMIT_RSS */
-
- goto do_ulimit;
-#endif /* USGr4 */
-
- case u_CPU_TIME_LIMIT:
-#if defined (RLIMIT_CPU)
- cmd = RLIMIT_CPU;
- goto do_ulimit;
+ *limptr = value;
+ return ((value == RLIM_INVALID) ? -1 : 0);
+ }
+ else
+ {
+#if defined (HAVE_RESOURCE)
+ if (getrlimit (limits[ind].parameter, &limit) < 0)
+ return -1;
+ value = (mode & LIMIT_SOFT) ? limit.rlim_cur : limit.rlim_max;
+ *limptr = value;
+ return 0;
#else
errno = EINVAL;
- return ((RLIMTYPE)-1);
-# endif /* !RLIMIT_CPU */
-
-
- case u_STACK_SIZE:
- cmd = RLIMIT_STACK;
-
- do_ulimit:
-
- if (getrlimit (cmd, &limit) != 0)
- return ((RLIMTYPE)-1);
-
- if (!setting)
- {
- if (mode & LIMIT_SOFT)
- return (limit.rlim_cur);
- else
- return (limit.rlim_max);
- }
- else
- {
- if (mode & LIMIT_SOFT)
- {
- /* Non-root users are only allowed to raise a limit up to the
- hard limit, not to infinity. */
- if (current_user.euid != 0 && newlim == RLIM_INFINITY)
- limit.rlim_cur = limit.rlim_max;
- else
- limit.rlim_cur = newlim;
- }
- if (mode & LIMIT_HARD)
- limit.rlim_max = newlim;
-
- return (setrlimit (cmd, &limit));
- }
-
- break;
-
-#endif /* HAVE_RESOURCE */
+ return -1;
+#endif
+ }
+}
- /* You can't get or set the pipe size with getrlimit, so we have to
- cheat. */
- case u_PIPE_SIZE:
- if (setting)
- {
- errno = EINVAL;
- return ((RLIMTYPE)-1);
- }
- return (pipesize ());
+static int
+set_limit (ind, newlim, mode)
+ int ind;
+ RLIMTYPE newlim;
+ int mode;
+{
+#if defined (HAVE_RESOURCE)
+ struct rlimit limit;
+ RLIMTYPE val;
+#endif
- case u_NUM_OPEN_FILES:
- if (setting)
- {
-#if defined (HAVE_RESOURCE) && defined (RLIMIT_NOFILE)
- cmd = RLIMIT_NOFILE;
- goto do_ulimit;
-#else
-# if defined (HAVE_SETDTABLESIZE)
- return (setdtablesize (newlim));
-# else
- errno = EINVAL;
- return ((RLIMTYPE)-1);
-# endif /* HAVE_SETDTABLESIZE */
-#endif /* !HAVE_RESOURCE || !RLIMIT_NOFILE */
- }
- else
- return (open_files (mode));
+ if (limits[ind].parameter >= 256)
+ switch (limits[ind].parameter)
+ {
+ case RLIMIT_FILESIZE:
+#if !defined (HAVE_RESOURCE)
+ return (ulimit (2, newlim / 512L));
+#endif
- case u_MAX_VIRTUAL_MEM:
- if (setting)
- {
- errno = EINVAL;
- return ((RLIMTYPE)-1);
- }
- else
- {
+ case RLIMIT_OPENFILES:
+#if defined (HAVE_SETDTABLESIZE)
+ return (setdtablesize (newlim));
+#endif
+ case RLIMIT_PIPESIZE:
+ case RLIMIT_VIRTMEM:
+ case RLIMIT_MAXUPROC:
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ else
+ {
#if defined (HAVE_RESOURCE)
- return (getmaxvm (mode));
-#else /* !HAVE_RESOURCE */
- errno = EINVAL;
- return ((RLIMTYPE)-1);
-#endif /* !HAVE_RESOURCE */
- }
-
- case u_MAX_USER_PROCS:
-#if defined (HAVE_RESOURCE) && defined (RLIMIT_NPROC)
- cmd = RLIMIT_NPROC;
- goto do_ulimit;
-#else /* !HAVE_RESOURCE || !RLIMIT_NPROC */
- errno = EINVAL;
- return ((RLIMTYPE)-1);
-#endif /* !HAVE_RESOURCE || !RLIMIT_NPROC */
-
- default:
+ if (getrlimit (limits[ind].parameter, &limit) < 0)
+ return -1;
+ val = (current_user.euid != 0 && newlim == RLIM_INFINITY)
+ ? limit.rlim_max : newlim;
+ if (mode & LIMIT_SOFT)
+ limit.rlim_cur = val;
+ if (mode & LIMIT_HARD)
+ limit.rlim_max = val;
+
+ return (setrlimit (limits[ind].parameter, &limit));
+#else
errno = EINVAL;
- return ((RLIMTYPE)-1);
+ return -1;
+#endif
}
}
-#if defined (HAVE_RESOURCE)
static RLIMTYPE
getmaxvm (mode)
int mode;
{
+#if defined (HAVE_RESOURCE)
struct rlimit rl;
-
-#if defined (RLIMIT_VMEM)
- if (getrlimit (RLIMIT_VMEM, &rl) < 0)
- return ((RLIMTYPE)-1);
- else
- return (((mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max) / 1024L);
-#else /* !RLIMIT_VMEM */
RLIMTYPE maxdata, maxstack;
if (getrlimit (RLIMIT_DATA, &rl) < 0)
- return ((RLIMTYPE)-1);
+ return (RLIM_INVALID);
else
maxdata = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
if (getrlimit (RLIMIT_STACK, &rl) < 0)
- return ((RLIMTYPE)-1);
+ return (RLIM_INVALID);
else
maxstack = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
/* Protect against overflow. */
return ((maxdata / 1024L) + (maxstack / 1024L));
-#endif /* !RLIMIT_VMEM */
-}
+#else
+ errno = EINVAL;
+ return RLIM_INVALID;
#endif /* HAVE_RESOURCE */
+}
static RLIMTYPE
-open_files (mode)
- int mode;
+filesize()
{
-#if !defined (RLIMIT_NOFILE)
- return ((RLIMTYPE)getdtablesize ());
+#if !defined (HAVE_RESOURCE)
+ return ((RLIMTYPE)ulimit (1, 0L));
#else
- struct rlimit rl;
-
- getrlimit (RLIMIT_NOFILE, &rl);
- if (mode & LIMIT_SOFT)
- return (rl.rlim_cur);
- else
- return (rl.rlim_max);
+ errno = EINVAL;
+ return RLIM_INVALID;
#endif
}
return ((RLIMTYPE) PIPESIZE);
# else
errno = EINVAL;
- return ((RLIMTYPE)-1);
+ return RLIM_INVALID;
# endif /* PIPESIZE */
#endif /* PIPE_BUF */
}
-/* ulimit(2) returns information about file size limits in terms of 512-byte
- blocks. This is the factor by which to divide to turn it into information
- in terms of 1024-byte blocks. Except for hpux 6.x, which returns it in
- terms of bytes. */
-#if !defined (hpux) || defined (_POSIX_VERSION)
-# define ULIMIT_DIVISOR 2
-#else
-# define ULIMIT_DIVISOR 1024
-#endif
-
-#if defined (HAVE_RESOURCE)
-
-typedef struct {
- int option_cmd; /* The ulimit command for this limit. */
- int parameter; /* Parameter to pass to getrlimit (). */
- int block_factor; /* Blocking factor for specific limit. */
- char *description; /* Descriptive string to output. */
-} BSD_RESOURCE_LIMITS;
-
-static BSD_RESOURCE_LIMITS limits[] = {
- { u_CORE_FILE_SIZE, RLIMIT_CORE, 1024, "core file size (blocks)" },
- { u_DATA_SEG_SIZE, RLIMIT_DATA, 1024, "data seg size (kbytes)" },
- { u_FILE_SIZE, RLIMIT_FSIZE, 1024, "file size (blocks)" },
-#if !defined (USGr4) && defined (RLIMIT_RSS)
- { u_PHYS_MEM_SIZE, RLIMIT_RSS, 1024, "max memory size (kbytes)" },
-#endif /* USGr4 && RLIMIT_RSS */
- { u_STACK_SIZE, RLIMIT_STACK, 1024, "stack size (kbytes)" },
-#if defined (RLIMIT_CPU)
- { u_CPU_TIME_LIMIT, RLIMIT_CPU, 1, "cpu time (seconds)" },
-#endif /* RLIMIT_CPU */
-#if defined (RLIMIT_NPROC)
- { u_MAX_USER_PROCS, RLIMIT_NPROC, 1, "max user processes" },
-#endif /* RLIMIT_NPROC */
- { 0, 0, 0, (char *)NULL }
-};
-
-static void
-print_bsd_limit (i, mode)
- int i, mode;
+static RLIMTYPE
+getmaxuprc (mode)
+ int mode;
{
- struct rlimit rl;
- RLIMTYPE limit;
-
- getrlimit (limits[i].parameter, &rl);
- if (mode & LIMIT_HARD)
- limit = rl.rlim_max;
- else
- limit = rl.rlim_cur;
- printf ("%-25s", limits[i].description);
- if (limit == RLIM_INFINITY)
- printf ("unlimited\n");
- else
- print_rlimtype ((limit / limits[i].block_factor), 1);
+# if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
+ return ((RLIMTYPE)sysconf (_SC_CHILD_MAX));
+# else /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
+# if defined (MAXUPRC)
+ return ((RLIMTYPE)MAXUPRC);
+# else /* MAXUPRC */
+ errno = EINVAL;
+ return RLIM_INVALID;
+# endif /* !MAXUPRC */
+# endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
}
static void
-print_specific_bsd_limits (cmd, mode)
- int cmd, mode;
+print_all_limits (mode)
+ int mode;
{
register int i;
+ RLIMTYPE value;
- for (i = 0; limits[i].option_cmd; i++)
- if (cmd & limits[i].option_cmd)
- print_bsd_limit (i, mode);
-}
-#endif /* HAVE_RESOURCE */
-
-/* Print the limits corresponding to a specific set of resources. This is
- called when an option string contains more than one character (e.g. -at),
- because limits may not be specified with that kind of argument. */
-static void
-print_specific_limits (cmd, mode)
- int cmd, mode;
-{
if (mode == 0)
- mode = LIMIT_SOFT;
-
-#if defined (HAVE_RESOURCE)
- print_specific_bsd_limits (cmd, mode);
-#else /* !HAVE_RESOURCE */
- if (cmd & u_FILE_SIZE)
- {
- printf ("%-25s", "file size (blocks)");
- print_rlimtype ((ulimit (1, 0L) / ULIMIT_DIVISOR), 1);
- }
-#endif /* !HAVE_RESOURCE */
-
- if (cmd & u_PIPE_SIZE)
- {
- printf ("%-25s", "pipe size (512 bytes)");
- print_rlimtype ((pipesize () / 512), 1);
- }
-
- if (cmd & u_NUM_OPEN_FILES)
- {
- printf ("%-25s", "open files");
- print_rlimtype (open_files (mode), 1);
- }
+ mode |= LIMIT_SOFT;
-#if defined (HAVE_RESOURCE)
- if (cmd & u_MAX_VIRTUAL_MEM)
+ for (i = 0; limits[i].option > 0; i++)
{
- printf ("%-25s", "virtual memory (kbytes)");
- print_rlimtype (getmaxvm (mode), 1);
+ if (get_limit (i, mode, &value) < 0)
+ value = RLIM_INVALID;
+ printone (i, value, 1);
}
-#endif /* HAVE_RESOURCE */
}
static void
-print_all_limits (mode)
- int mode;
+printone (limind, curlim, pdesc)
+ int limind;
+ RLIMTYPE curlim;
+ int pdesc;
{
- if (mode == 0)
- mode |= LIMIT_SOFT;
-
- print_specific_limits (u_ALL_LIMITS, mode);
+ if (pdesc)
+ printf (DESCFMT, limits[limind].description);
+ if (curlim == RLIM_INFINITY)
+ puts ("unlimited");
+ else if (curlim == RLIM_INVALID)
+ printf ("cannot get limit: %s\n", strerror (errno));
+ else
+ print_rlimtype ((curlim / limits[limind].block_factor), 1);
}