diff options
Diffstat (limited to 'usr.bin/limits/limits.c')
-rw-r--r-- | usr.bin/limits/limits.c | 987 |
1 files changed, 490 insertions, 497 deletions
diff --git a/usr.bin/limits/limits.c b/usr.bin/limits/limits.c index 655e0da..98a2b4c 100644 --- a/usr.bin/limits/limits.c +++ b/usr.bin/limits/limits.c @@ -20,7 +20,7 @@ * * Display/change(+runprogram)/eval resource limits. * - * $Id: limits.c,v 1.2 1997/02/22 19:55:37 peter Exp $ + * $Id: limits.c,v 1.3 1997/03/29 04:30:26 imp Exp $ */ #include <err.h> @@ -41,15 +41,15 @@ enum { - SH_NONE, - SH_SH, /* sh */ - SH_CSH, /* csh */ - SH_BASH, /* gnu bash */ - SH_TCSH, /* tcsh */ - SH_KSH, /* (pd)ksh */ - SH_ZSH, /* zsh */ - SH_RC, /* rc or es */ - SH_NUMBER + SH_NONE, + SH_SH, /* sh */ + SH_CSH, /* csh */ + SH_BASH, /* gnu bash */ + SH_TCSH, /* tcsh */ + SH_KSH, /* (pd)ksh */ + SH_ZSH, /* zsh */ + SH_RC, /* rc or es */ + SH_NUMBER }; @@ -59,147 +59,139 @@ enum * enough that they aren't very compatible from one to the other. */ static struct { - const char * name; /* Name of shell */ - const char * inf; /* Name used for 'unlimited' resource */ - const char * cmd; /* Intro text */ - const char * hard; /* Hard limit text */ - const char * soft; /* Soft limit text */ - const char * both; /* Hard+Soft limit text */ - struct { - const char * pfx; - const char * sfx; - int divisor; - } lprm[RLIM_NLIMITS]; + const char * name; /* Name of shell */ + const char * inf; /* Name used for 'unlimited' resource */ + const char * cmd; /* Intro text */ + const char * hard; /* Hard limit text */ + const char * soft; /* Soft limit text */ + const char * both; /* Hard+Soft limit text */ + struct { + const char * pfx; + const char * sfx; + int divisor; + } lprm[RLIM_NLIMITS]; } shellparm[] = { - { "", "infinity", "Resource limits%s%s:\n", "-max", "-cur", "", - { - { " cputime%-4s %8s", " secs\n", 1 }, - { " filesize%-4s %8s", " kb\n", 1024 }, - { " datasize%-4s %8s", " kb\n", 1024 }, - { " stacksize%-4s %8s", " kb\n", 1024 }, - { " coredumpsize%-4s %8s", " kb\n", 1024 }, - { " memoryuse%-4s %8s", " kb\n", 1024 }, - { " memorylocked%-4s %8s", " kb\n", 1024 }, - { " maxprocesses%-4s %8s", "\n", 1 }, - { " openfiles%-4s %8s", "\n", 1 } - } - }, - { "sh", "unlimited", "", " -H", " -S", "", - { - { "ulimit%s -t %s", ";\n", 1 }, - { "ulimit%s -f %s", ";\n", 512 }, - { "ulimit%s -d %s", ";\n", 1024 }, - { "ulimit%s -s %s", ";\n", 1024 }, - { "ulimit%s -c %s", ";\n", 512 }, - { "ulimit%s -m %s", ";\n", 1024 }, - { "ulimit%s -l %s", ";\n", 1024 }, - { "ulimit%s -u %s", ";\n", 1 }, - { "ulimit%s -n %s", ";\n", 1 } - } - }, - { "csh", "unlimited", "", " -h", "", NULL, - { - { "limit%s cputime %s", ";\n", 1 }, - { "limit%s filesize %s", ";\n", 1024 }, - { "limit%s datasize %s", ";\n", 1024 }, - { "limit%s stacksize %s", ";\n", 1024 }, - { "limit%s coredumpsize %s", ";\n", 1024 }, - { "limit%s memoryuse %s", ";\n", 1024 }, - { "limit%s memorylocked %s", ";\n", 1024 }, - { "limit%s maxproc %s", ";\n", 1 }, - { "limit%s openfiles %s", ";\n", 1 } - } - }, - { "bash", "unlimited", "", " -H", " -S", "", - { - { "ulimit%s -t %s", ";\n", 1 }, - { "ulimit%s -f %s", ";\n", 1024 }, - { "ulimit%s -d %s", ";\n", 1024 }, - { "ulimit%s -s %s", ";\n", 1024 }, - { "ulimit%s -c %s", ";\n", 1024 }, - { "ulimit%s -v %s", ";\n", 1024 }, - { "ulimit%s -m %s", ";\n", 1024 }, - { "ulimit%s -u %s", ";\n", 1 }, - { "ulimit%s -n %s", ";\n", 1 } - } - }, - { "tcsh", "unlimited", "", " -h", "", NULL, - { - { "limit%s cputime %s", ";\n", 1 }, - { "limit%s filesize %s", ";\n", 1024 }, - { "limit%s datasize %s", ";\n", 1024 }, - { "limit%s stacksize %s", ";\n", 1024 }, - { "limit%s coredumpsize %s", ";\n", 1024 }, - { "limit%s memoryuse %s", ";\n", 1024 }, - { "limit%s memorylocked %s", ";\n", 1024 }, - { "limit%s maxproc %s", ";\n", 1 }, - { "limit%s descriptors %s", ";\n", 1 } - } - }, - { "ksh|pdksh", "unlimited", "", " -H", " -S", "", - { - { "ulimit%s -t %s", ";\n", 1 }, - { "ulimit%s -f %s", ";\n", 512 }, - { "ulimit%s -d %s", ";\n", 1024 }, - { "ulimit%s -s %s", ";\n", 1024 }, - { "ulimit%s -c %s", ";\n", 512 }, - { "ulimit%s -m %s", ";\n", 1024 }, - { "ulimit%s -l %s", ";\n", 1024 }, - { "ulimit%s -p %s", ";\n", 1 }, - { "ulimit%s -n %s", ";\n", 1 } - } - }, - { "zsh", "unlimited", "", " -H", " -S", "", - { - { "ulimit%s -t %s", ";\n", 1 }, - { "ulimit%s -f %s", ";\n", 512 }, - { "ulimit%s -d %s", ";\n", 1024 }, - { "ulimit%s -s %s", ";\n", 1024 }, - { "ulimit%s -c %s", ";\n", 512 }, - { "ulimit%s -m %s", ";\n", 1024 }, - { "ulimit%s -l %s", ";\n", 1024 }, - { "ulimit%s -u %s", ";\n", 1 }, - { "ulimit%s -n %s", ";\n", 1 } - } - }, - /* Note: I recommend you don't use rc/es with 'limits' - * as this seems to be fairly buggy. The values below - * are set according to the manpage, but, for example, - * the string 'unlimited' is not actually accepted by - * the shell. 'es' is also prone to core dumping when - * displaying or modifying limits. Hopefully this will - * be fixed. DLN - Wed Jan 15 20:30 1997 - */ - { "rc|es", "unlimited", "", " -h", "", NULL, - { - { "limit%s cputime %s", ";\n", 1 }, - { "limit%s filesize %s", ";\n", 1024 }, - { "limit%s datasize %s", ";\n", 1024 }, - { "limit%s stacksize %s", ";\n", 1024 }, - { "limit%s coredumpsize %s", ";\n", 1024 }, - { "limit%s memoryuse %s", ";\n", 1024 }, - { "limit%s lockedmemory %s", ";\n", 1024 }, - { "limit%s processes %s", ";\n", 1 }, - { "limit%s descriptors %s", ";\n", 1 } - } - }, - { NULL } + { "", "infinity", "Resource limits%s%s:\n", "-max", "-cur", "", + { + { " cputime%-4s %8s", " secs\n", 1 }, + { " filesize%-4s %8s", " kb\n", 1024 }, + { " datasize%-4s %8s", " kb\n", 1024 }, + { " stacksize%-4s %8s", " kb\n", 1024 }, + { " coredumpsize%-4s %8s", " kb\n", 1024 }, + { " memoryuse%-4s %8s", " kb\n", 1024 }, + { " memorylocked%-4s %8s", " kb\n", 1024 }, + { " maxprocesses%-4s %8s", "\n", 1 }, + { " openfiles%-4s %8s", "\n", 1 } + } + }, + { "sh", "unlimited", "", " -H", " -S", "", + { + { "ulimit%s -t %s", ";\n", 1 }, + { "ulimit%s -f %s", ";\n", 512 }, + { "ulimit%s -d %s", ";\n", 1024 }, + { "ulimit%s -s %s", ";\n", 1024 }, + { "ulimit%s -c %s", ";\n", 512 }, + { "ulimit%s -m %s", ";\n", 1024 }, + { "ulimit%s -l %s", ";\n", 1024 }, + { "ulimit%s -u %s", ";\n", 1 }, + { "ulimit%s -n %s", ";\n", 1 } + } + }, + { "csh", "unlimited", "", " -h", "", NULL, + { + { "limit%s cputime %s", ";\n", 1 }, + { "limit%s filesize %s", ";\n", 1024 }, + { "limit%s datasize %s", ";\n", 1024 }, + { "limit%s stacksize %s", ";\n", 1024 }, + { "limit%s coredumpsize %s", ";\n", 1024 }, + { "limit%s memoryuse %s", ";\n", 1024 }, + { "limit%s memorylocked %s", ";\n", 1024 }, + { "limit%s maxproc %s", ";\n", 1 }, + { "limit%s openfiles %s", ";\n", 1 } + } + }, + { "bash|bash2", "unlimited", "", " -H", " -S", "", + { + { "ulimit%s -t %s", ";\n", 1 }, + { "ulimit%s -f %s", ";\n", 1024 }, + { "ulimit%s -d %s", ";\n", 1024 }, + { "ulimit%s -s %s", ";\n", 1024 }, + { "ulimit%s -c %s", ";\n", 1024 }, + { "ulimit%s -m %s", ";\n", 1024 }, + { "ulimit%s -l %s", ";\n", 1024 }, + { "ulimit%s -u %s", ";\n", 1 }, + { "ulimit%s -n %s", ";\n", 1 } + } + }, + { "tcsh", "unlimited", "", " -h", "", NULL, + { + { "limit%s cputime %s", ";\n", 1 }, + { "limit%s filesize %s", ";\n", 1024 }, + { "limit%s datasize %s", ";\n", 1024 }, + { "limit%s stacksize %s", ";\n", 1024 }, + { "limit%s coredumpsize %s", ";\n", 1024 }, + { "limit%s memoryuse %s", ";\n", 1024 }, + { "limit%s memorylocked %s", ";\n", 1024 }, + { "limit%s maxproc %s", ";\n", 1 }, + { "limit%s descriptors %s", ";\n", 1 } + } + }, + { "ksh|pdksh", "unlimited", "", " -H", " -S", "", + { + { "ulimit%s -t %s", ";\n", 1 }, + { "ulimit%s -f %s", ";\n", 512 }, + { "ulimit%s -d %s", ";\n", 1024 }, + { "ulimit%s -s %s", ";\n", 1024 }, + { "ulimit%s -c %s", ";\n", 512 }, + { "ulimit%s -m %s", ";\n", 1024 }, + { "ulimit%s -l %s", ";\n", 1024 }, + { "ulimit%s -p %s", ";\n", 1 }, + { "ulimit%s -n %s", ";\n", 1 } + } + }, + { "zsh", "unlimited", "", " -H", " -S", "", + { + { "ulimit%s -t %s", ";\n", 1 }, + { "ulimit%s -f %s", ";\n", 512 }, + { "ulimit%s -d %s", ";\n", 1024 }, + { "ulimit%s -s %s", ";\n", 1024 }, + { "ulimit%s -c %s", ";\n", 512 }, + { "ulimit%s -m %s", ";\n", 1024 }, + { "ulimit%s -l %s", ";\n", 1024 }, + { "ulimit%s -u %s", ";\n", 1 }, + { "ulimit%s -n %s", ";\n", 1 } + } + }, + { "rc|es", "unlimited", "", " -h", "", NULL, + { + { "limit%s cputime %s", ";\n", 1 }, + { "limit%s filesize %s", ";\n", 1024 }, + { "limit%s datasize %s", ";\n", 1024 }, + { "limit%s stacksize %s", ";\n", 1024 }, + { "limit%s coredumpsize %s", ";\n", 1024 }, + { "limit%s memoryuse %s", ";\n", 1024 }, + { "limit%s lockedmemory %s", ";\n", 1024 }, + { "limit%s processes %s", ";\n", 1 }, + { "limit%s descriptors %s", ";\n", 1 } + } + }, + { NULL } }; static struct { - const char * cap; - rlim_t (*func)(login_cap_t *, const char *, rlim_t, rlim_t); + const char * cap; + rlim_t (*func)(login_cap_t *, const char *, rlim_t, rlim_t); } resources[RLIM_NLIMITS] = { - { "cputime", login_getcaptime }, - { "filesize", login_getcapsize }, - { "datasize", login_getcapsize }, - { "stacksize", login_getcapsize }, - { "coredumpsize", login_getcapsize }, - { "memoryuse", login_getcapsize }, - { "memorylocked", login_getcapsize }, - { "maxproc", login_getcapnum, }, - { "openfiles", login_getcapnum } + { "cputime", login_getcaptime }, + { "filesize", login_getcapsize }, + { "datasize", login_getcapsize }, + { "stacksize", login_getcapsize }, + { "coredumpsize", login_getcapsize }, + { "memoryuse", login_getcapsize }, + { "memorylocked", login_getcapsize }, + { "maxproc", login_getcapnum, }, + { "openfiles", login_getcapnum } }; /* @@ -215,7 +207,8 @@ static struct { static rlim_t resource_num(int which, int ch, const char *str); static void usage(const char *msg, ...); static int getshelltype(void); -static void print_limit(rlim_t limit, unsigned divisor, const char * inf, const char * pfx, const char * sfx, const char * which); +static void print_limit(rlim_t limit, unsigned divisor, const char *inf, + const char *pfx, const char *sfx, const char *which); extern char **environ; static const char rcs_string[] = RCS_STRING; @@ -223,379 +216,379 @@ static const char rcs_string[] = RCS_STRING; int main(int argc, char *argv[]) { - char *p, *cls = NULL; - char *cleanenv[1]; - struct passwd * pwd = NULL; - int rcswhich, shelltype; - int i, num_limits = 0; - int ch, doeval = 0, doall = 0; - login_cap_t * lc = NULL; - enum { ANY=0, SOFT=1, HARD=2, BOTH=3, DISPLAYONLY=4 } type = ANY; - enum { RCSUNKNOWN=0, RCSSET=1, RCSSEL=2 } todo = RCSUNKNOWN; - int which_limits[RLIM_NLIMITS]; - rlim_t set_limits[RLIM_NLIMITS]; - struct rlimit limits[RLIM_NLIMITS]; - - /* init resource tables */ - for (i = 0; i < RLIM_NLIMITS; i++) - { - which_limits[i] = 0; /* Don't set/display any */ - set_limits[i] = RLIM_INFINITY; - /* Get current resource values */ - getrlimit(i, &limits[i]); - } - - optarg = NULL; - while ((ch = getopt(argc, argv, ":EeC:U:BSHac:d:f:l:m:n:s:t:u:")) != -1) { - switch(ch) { - case 'a': - doall = 1; - break; - case 'E': - environ = cleanenv; - cleanenv[0] = NULL; - break; - case 'e': - doeval = 1; - break; - case 'C': - cls = optarg; - break; - case 'U': - if ((pwd = getpwnam(optarg)) == NULL) { - if (!isdigit(*optarg) || (pwd = getpwuid(atoi(optarg))) == NULL) { - usage("Invalid user `%s'\n", optarg); - } - } - break; - case 'H': - type = HARD; - break; - case 'S': - type = SOFT; - break; - case 'B': - type = SOFT|HARD; - break; - default: - case ':': /* Without arg */ - if ((p = strchr(rcs_string, optopt)) != NULL) { - int rcswhich = p - rcs_string; - if (optarg && *optarg == '-') { /* 'arg' is actually a switch */ - --optind; /* back one arg, and make arg NULL */ - optarg = NULL; - } - todo = optarg == NULL ? RCSSEL : RCSSET; - if (type == ANY) - type = BOTH; - which_limits[rcswhich] = optarg ? type : DISPLAYONLY; - set_limits[rcswhich] = resource_num(rcswhich, optopt, optarg); - num_limits++; - break; - } - /* FALLTHRU */ - case '?': - usage(NULL); + char *p, *cls = NULL; + char *cleanenv[1]; + struct passwd * pwd = NULL; + int rcswhich, shelltype; + int i, num_limits = 0; + int ch, doeval = 0, doall = 0; + login_cap_t * lc = NULL; + enum { ANY=0, SOFT=1, HARD=2, BOTH=3, DISPLAYONLY=4 } type = ANY; + enum { RCSUNKNOWN=0, RCSSET=1, RCSSEL=2 } todo = RCSUNKNOWN; + int which_limits[RLIM_NLIMITS]; + rlim_t set_limits[RLIM_NLIMITS]; + struct rlimit limits[RLIM_NLIMITS]; + + /* init resource tables */ + for (i = 0; i < RLIM_NLIMITS; i++) { + which_limits[i] = 0; /* Don't set/display any */ + set_limits[i] = RLIM_INFINITY; + /* Get current resource values */ + getrlimit(i, &limits[i]); } + optarg = NULL; - } - - /* If user was specified, get class from that */ - if (pwd != NULL) - lc = login_getclass(pwd); - else if (cls != NULL) { - lc = login_getclassbyname(cls, NULL); - if (lc == NULL || strcmp(cls, lc->lc_class) != 0) - fprintf(stderr, "login class '%s' non-existent, using %s\n", cls, lc?lc->lc_class:"current settings"); - } - - /* If we have a login class, update resource table from that */ - if (lc != NULL) { - for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { - char str[40]; - rlim_t val; - - /* current value overridden by resourcename or resourcename-cur */ - sprintf(str, "%s-cur", resources[rcswhich].cap); - val = resources[rcswhich].func(lc, resources[rcswhich].cap, limits[rcswhich].rlim_cur, limits[rcswhich].rlim_cur); - limits[rcswhich].rlim_cur = resources[rcswhich].func(lc, str, val, val); - /* maximum value overridden by resourcename or resourcename-max */ - sprintf(str, "%s-max", resources[rcswhich].cap); - val = resources[rcswhich].func(lc, resources[rcswhich].cap, limits[rcswhich].rlim_max, limits[rcswhich].rlim_max); - limits[rcswhich].rlim_max = resources[rcswhich].func(lc, str, val, val); + while ((ch = getopt(argc, argv, ":EeC:U:BSHac:d:f:l:m:n:s:t:u:")) != -1) { + switch(ch) { + case 'a': + doall = 1; + break; + case 'E': + environ = cleanenv; + cleanenv[0] = NULL; + break; + case 'e': + doeval = 1; + break; + case 'C': + cls = optarg; + break; + case 'U': + if ((pwd = getpwnam(optarg)) == NULL) { + if (!isdigit(*optarg) || + (pwd = getpwuid(atoi(optarg))) == NULL) { + usage("Invalid user `%s'\n", optarg); + } + } + break; + case 'H': + type = HARD; + break; + case 'S': + type = SOFT; + break; + case 'B': + type = SOFT|HARD; + break; + default: + case ':': /* Without arg */ + if ((p = strchr(rcs_string, optopt)) != NULL) { + int rcswhich = p - rcs_string; + if (optarg && *optarg == '-') { /* 'arg' is actually a switch */ + --optind; /* back one arg, and make arg NULL */ + optarg = NULL; + } + todo = optarg == NULL ? RCSSEL : RCSSET; + if (type == ANY) + type = BOTH; + which_limits[rcswhich] = optarg ? type : DISPLAYONLY; + set_limits[rcswhich] = resource_num(rcswhich, optopt, optarg); + num_limits++; + break; + } + /* FALLTHRU */ + case '?': + usage(NULL); + } + optarg = NULL; } - } - /* now, let's determine what we wish to do with all this */ + /* If user was specified, get class from that */ + if (pwd != NULL) + lc = login_getpwclass(pwd); + else if (cls != NULL && *cls != '\0') { + lc = login_getclassbyname(cls, NULL); + if (lc == NULL || strcmp(cls, lc->lc_class) != 0) + fprintf(stderr, "login class '%s' non-existent, using %s\n", + cls, lc?lc->lc_class:"current settings"); + } + + /* If we have a login class, update resource table from that */ + if (lc != NULL) { + for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { + char str[40]; + rlim_t val; + + /* current value overridden by resourcename or resourcename-cur */ + sprintf(str, "%s-cur", resources[rcswhich].cap); + val = resources[rcswhich].func(lc, resources[rcswhich].cap, limits[rcswhich].rlim_cur, limits[rcswhich].rlim_cur); + limits[rcswhich].rlim_cur = resources[rcswhich].func(lc, str, val, val); + /* maximum value overridden by resourcename or resourcename-max */ + sprintf(str, "%s-max", resources[rcswhich].cap); + val = resources[rcswhich].func(lc, resources[rcswhich].cap, limits[rcswhich].rlim_max, limits[rcswhich].rlim_max); + limits[rcswhich].rlim_max = resources[rcswhich].func(lc, str, val, val); + } + } - argv += optind; + /* now, let's determine what we wish to do with all this */ - /* If we're setting limits or doing an eval (ie. we're not just - * displaying), then check that hard limits are not lower than - * soft limits, and force rasing the hard limit if we need to if - * we are raising the soft limit, or lower the soft limit if we - * are lowering the hard limit. - */ - if ((*argv || doeval) && getuid() == 0) { - for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { - if (limits[rcswhich].rlim_max != RLIM_INFINITY) { - if (limits[rcswhich].rlim_cur == RLIM_INFINITY) { - limits[rcswhich].rlim_max = RLIM_INFINITY; - which_limits[rcswhich] |= HARD; - } else if (limits[rcswhich].rlim_cur > limits[rcswhich].rlim_max) { - if (which_limits[rcswhich] == SOFT) { - limits[rcswhich].rlim_max = limits[rcswhich].rlim_cur; - which_limits[rcswhich] |= HARD; - } else if (which_limits[rcswhich] == HARD) { - limits[rcswhich].rlim_cur = limits[rcswhich].rlim_max; - which_limits[rcswhich] |= SOFT; - } else { - /* else.. if we're specifically setting both to - * silly values, then let it error out. - */ - } + argv += optind; + + /* If we're setting limits or doing an eval (ie. we're not just + * displaying), then check that hard limits are not lower than + * soft limits, and force rasing the hard limit if we need to if + * we are raising the soft limit, or lower the soft limit if we + * are lowering the hard limit. + */ + if ((*argv || doeval) && getuid() == 0) { + + for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { + if (limits[rcswhich].rlim_max != RLIM_INFINITY) { + if (limits[rcswhich].rlim_cur == RLIM_INFINITY) { + limits[rcswhich].rlim_max = RLIM_INFINITY; + which_limits[rcswhich] |= HARD; + } else if (limits[rcswhich].rlim_cur > limits[rcswhich].rlim_max) { + if (which_limits[rcswhich] == SOFT) { + limits[rcswhich].rlim_max = limits[rcswhich].rlim_cur; + which_limits[rcswhich] |= HARD; + } else if (which_limits[rcswhich] == HARD) { + limits[rcswhich].rlim_cur = limits[rcswhich].rlim_max; + which_limits[rcswhich] |= SOFT; + } else { + /* else.. if we're specifically setting both to + * silly values, then let it error out. + */ + } + } + } } - } } - } - /* See if we've overridden anything specific on the command line */ - if (num_limits && todo == RCSSET) { - for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { - if (which_limits[rcswhich] & HARD) - limits[rcswhich].rlim_max = set_limits[rcswhich]; - if (which_limits[rcswhich] & SOFT) - limits[rcswhich].rlim_cur = set_limits[rcswhich]; + /* See if we've overridden anything specific on the command line */ + if (num_limits && todo == RCSSET) { + for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { + if (which_limits[rcswhich] & HARD) + limits[rcswhich].rlim_max = set_limits[rcswhich]; + if (which_limits[rcswhich] & SOFT) + limits[rcswhich].rlim_cur = set_limits[rcswhich]; + } } - } - /* If *argv is not NULL, then we are being asked to - * (perhaps) set environment variables and run a program - */ - if (*argv) { - if (doeval) - usage("-e cannot be used with `cmd' option\n"); + /* If *argv is not NULL, then we are being asked to + * (perhaps) set environment variables and run a program + */ + if (*argv) { + if (doeval) + usage("-e cannot be used with `cmd' option\n"); - login_close(lc); + login_close(lc); - /* set leading environment variables, like eval(1) */ - while (*argv && (p = strchr(*argv, '='))) - (void)setenv(*argv++, ++p, 1); + /* set leading environment variables, like eval(1) */ + while (*argv && (p = strchr(*argv, '='))) + (void)setenv(*argv++, ++p, 1); - /* Set limits */ - for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { - if (doall || num_limits == 0 || which_limits[rcswhich] != 0) - if (setrlimit(rcswhich, &limits[rcswhich]) == -1) - err(1, "setrlimit %s", resources[rcswhich].cap); + /* Set limits */ + for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { + if (doall || num_limits == 0 || which_limits[rcswhich] != 0) + if (setrlimit(rcswhich, &limits[rcswhich]) == -1) + err(1, "setrlimit %s", resources[rcswhich].cap); + } + + if (*argv == NULL) + usage(NULL); + + execvp(*argv, argv); + err(1, "%s", *argv); } - if (*argv == NULL) - usage(NULL); - - execvp(*argv, argv); - err(1, "%s", *argv); - } - - shelltype = doeval ? getshelltype() : SH_NONE; - - if (type == ANY) /* Default to soft limits */ - type = SOFT; - - /* Display limits */ - printf(shellparm[shelltype].cmd, lc ? " for class " : " (current)", lc ? lc->lc_class : ""); - for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { - if (doall || num_limits == 0 || which_limits[rcswhich] != 0) { - if (which_limits[rcswhich] == ANY || which_limits[rcswhich]) - which_limits[rcswhich] = type; - if (shellparm[shelltype].lprm[rcswhich].pfx) { - if (shellparm[shelltype].both && limits[rcswhich].rlim_cur == limits[rcswhich].rlim_max) { - print_limit(limits[rcswhich].rlim_max, - shellparm[shelltype].lprm[rcswhich].divisor, - shellparm[shelltype].inf, - shellparm[shelltype].lprm[rcswhich].pfx, - shellparm[shelltype].lprm[rcswhich].sfx, - shellparm[shelltype].both); - } else { - if (which_limits[rcswhich] & HARD) { - print_limit(limits[rcswhich].rlim_max, - shellparm[shelltype].lprm[rcswhich].divisor, - shellparm[shelltype].inf, - shellparm[shelltype].lprm[rcswhich].pfx, - shellparm[shelltype].lprm[rcswhich].sfx, - shellparm[shelltype].hard); - } - if (which_limits[rcswhich] & SOFT) { - print_limit(limits[rcswhich].rlim_cur, - shellparm[shelltype].lprm[rcswhich].divisor, - shellparm[shelltype].inf, - shellparm[shelltype].lprm[rcswhich].pfx, - shellparm[shelltype].lprm[rcswhich].sfx, - shellparm[shelltype].soft); - } + shelltype = doeval ? getshelltype() : SH_NONE; + + if (type == ANY) /* Default to soft limits */ + type = SOFT; + + /* Display limits */ + printf(shellparm[shelltype].cmd, + lc ? " for class " : " (current)", + lc ? lc->lc_class : ""); + + for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { + if (doall || num_limits == 0 || which_limits[rcswhich] != 0) { + if (which_limits[rcswhich] == ANY || which_limits[rcswhich]) + which_limits[rcswhich] = type; + if (shellparm[shelltype].lprm[rcswhich].pfx) { + if (shellparm[shelltype].both && limits[rcswhich].rlim_cur == limits[rcswhich].rlim_max) { + print_limit(limits[rcswhich].rlim_max, + shellparm[shelltype].lprm[rcswhich].divisor, + shellparm[shelltype].inf, + shellparm[shelltype].lprm[rcswhich].pfx, + shellparm[shelltype].lprm[rcswhich].sfx, + shellparm[shelltype].both); + } else { + if (which_limits[rcswhich] & HARD) { + print_limit(limits[rcswhich].rlim_max, + shellparm[shelltype].lprm[rcswhich].divisor, + shellparm[shelltype].inf, + shellparm[shelltype].lprm[rcswhich].pfx, + shellparm[shelltype].lprm[rcswhich].sfx, + shellparm[shelltype].hard); + } + if (which_limits[rcswhich] & SOFT) { + print_limit(limits[rcswhich].rlim_cur, + shellparm[shelltype].lprm[rcswhich].divisor, + shellparm[shelltype].inf, + shellparm[shelltype].lprm[rcswhich].pfx, + shellparm[shelltype].lprm[rcswhich].sfx, + shellparm[shelltype].soft); + } + } + } } - } } - } - login_close(lc); - exit(EXIT_SUCCESS); + login_close(lc); + exit(EXIT_SUCCESS); } static void usage(char const *msg, ...) { - if (msg) { - va_list argp; - va_start(argp, msg); - vfprintf(stderr, msg, argp); - va_end(argp); - } - (void)fprintf(stderr, "limits [-C class|-U user] [-eaSHBE] [-cdflmnstu [val]] [[name=val ...] cmd]\n"); - exit(EXIT_FAILURE); + if (msg) { + va_list argp; + va_start(argp, msg); + vfprintf(stderr, msg, argp); + va_end(argp); + } + (void)fprintf(stderr, + "limits [-C class|-U user] [-eaSHBE] [-cdflmnstu [val]] [[name=val ...] cmd]\n"); + exit(EXIT_FAILURE); } static void print_limit(rlim_t limit, unsigned divisor, const char * inf, const char * pfx, const char * sfx, const char * which) { - char numbr[64]; - if (limit == RLIM_INFINITY) - strcpy(numbr, inf); - else -#ifdef RLIM_LONG - sprintf(numbr, "%ql", (long)((limit + divisor/2) / divisor)); -#else - sprintf(numbr, "%qd", (quad_t)((limit + divisor/2) / divisor)); -#endif - printf(pfx, which, numbr); - printf(sfx, which); + char numbr[64]; -} + if (limit == RLIM_INFINITY) + strcpy(numbr, inf); + else + sprintf(numbr, "%qd", (quad_t)((limit + divisor/2) / divisor)); + printf(pfx, which, numbr); + printf(sfx, which); +} -#ifdef RLIM_LONG -# define STRTOV strtol -#else -# define STRTOV strtoq -#endif static rlim_t resource_num(int which, int ch, const char *str) { - rlim_t res = RLIM_INFINITY; - - if (str != NULL && !(strcasecmp(str, "inf")==0 || strcasecmp(str, "infinity")==0 || strcasecmp(str, "unlimited")==0)) { - const char * s = str; - char *e; - switch (which) - { - case RLIMIT_CPU: /* time values */ - errno = 0; - res = 0; - while (*s) { - rlim_t tim = STRTOV(s, &e, 0); - if (e == NULL || e == s || errno) - break; - switch (*e++) { - case 0: /* end of string */ - e--; - default: - case 's': case 'S': /* seconds */ - break; - case 'm': case 'M': /* minutes */ - tim *= 60L; - break; - case 'h': case 'H': /* hours */ - tim *= (60L * 60L); - break; - case 'd': case 'D': /* days */ - tim *= (60L * 60L * 24L); - break; - case 'w': case 'W': /* weeks */ - tim *= (60L * 60L * 24L * 7L); - case 'y': case 'Y': /* Years */ - tim *= (60L * 60L * 24L * 365L); - } - s = e; - res += tim; - } - break; - case RLIMIT_FSIZE: /* Size values */ - case RLIMIT_DATA: - case RLIMIT_STACK: - case RLIMIT_CORE: - case RLIMIT_RSS: - case RLIMIT_MEMLOCK: - errno = 0; - res = 0; - while (*s) { - rlim_t mult, tim = STRTOV(s, &e, 0); - if (e == NULL || e == s || errno) - break; - switch (*e++) { - case 0: /* end of string */ - e--; - default: - mult = 1; - break; - case 'b': case 'B': /* 512-byte blocks */ - mult = 512; - break; - case 'k': case 'K': /* 1024-byte Kilobytes */ - mult = 1024; - break; - case 'm': case 'M': /* 1024-k kbytes */ - mult = 1024 * 1024; - break; - case 'g': case 'G': /* 1Gbyte */ - mult = 1024 * 1024 * 1024; - break; -#ifndef RLIM_LONG - case 't': case 'T': /* 1TBte */ - mult = 1024LL * 1024LL * 1024LL * 1024LL; - break; -#endif - } - s = e; - res += (tim * mult); - } - break; - case RLIMIT_NPROC: - case RLIMIT_NOFILE: - res = STRTOV(s, &e, 0); - s = e; - break; + rlim_t res = RLIM_INFINITY; + + if (str != NULL && + !(strcasecmp(str, "inf") == 0 || + strcasecmp(str, "infinity") == 0 || + strcasecmp(str, "unlimit") == 0 || + strcasecmp(str, "unlimited") == 0)) { + const char * s = str; + char *e; + + switch (which) { + case RLIMIT_CPU: /* time values */ + errno = 0; + res = 0; + while (*s) { + rlim_t tim = strtoq(s, &e, 0); + if (e == NULL || e == s || errno) + break; + switch (*e++) { + case 0: /* end of string */ + e--; + default: + case 's': case 'S': /* seconds */ + break; + case 'm': case 'M': /* minutes */ + tim *= 60L; + break; + case 'h': case 'H': /* hours */ + tim *= (60L * 60L); + break; + case 'd': case 'D': /* days */ + tim *= (60L * 60L * 24L); + break; + case 'w': case 'W': /* weeks */ + tim *= (60L * 60L * 24L * 7L); + case 'y': case 'Y': /* Years */ + tim *= (60L * 60L * 24L * 365L); + } + s = e; + res += tim; + } + break; + case RLIMIT_FSIZE: /* Size values */ + case RLIMIT_DATA: + case RLIMIT_STACK: + case RLIMIT_CORE: + case RLIMIT_RSS: + case RLIMIT_MEMLOCK: + errno = 0; + res = 0; + while (*s) { + rlim_t mult, tim = strtoq(s, &e, 0); + if (e == NULL || e == s || errno) + break; + switch (*e++) { + case 0: /* end of string */ + e--; + default: + mult = 1; + break; + case 'b': case 'B': /* 512-byte blocks */ + mult = 512; + break; + case 'k': case 'K': /* 1024-byte Kilobytes */ + mult = 1024; + break; + case 'm': case 'M': /* 1024-k kbytes */ + mult = 1024 * 1024; + break; + case 'g': case 'G': /* 1Gbyte */ + mult = 1024 * 1024 * 1024; + break; + case 't': case 'T': /* 1TBte */ + mult = 1024LL * 1024LL * 1024LL * 1024LL; + break; + } + s = e; + res += (tim * mult); + } + break; + case RLIMIT_NPROC: + case RLIMIT_NOFILE: + res = strtoq(s, &e, 0); + s = e; + break; + } + if (*s) + usage("invalid value -%c `%s'\n", ch, str); } - if (*s) - usage("invalid value -%c `%s'\n", ch, str); - } - return res; + return res; } static int getshellbyname(const char * shell) { - int i; - const char * q; - const char * p = strrchr(shell, '/'); - - p = p ? ++p : shell; - for (i = 0; (q = shellparm[i].name) != NULL; i++) { - while (*q) - { - int j = strcspn(q, "|"); - if (j == 0) - break; - if (strncmp(p, q, j) == 0) - return i; - if (*(q += j)) - ++q; + int i; + const char * q; + const char * p = strrchr(shell, '/'); + + p = p ? ++p : shell; + for (i = 0; (q = shellparm[i].name) != NULL; i++) { + while (*q) { + int j = strcspn(q, "|"); + + if (j == 0) + break; + if (strncmp(p, q, j) == 0) + return i; + if (*(q += j)) + ++q; + } } - } - return SH_SH; + return SH_SH; } + /* * Determine the type of shell our parent process is * This is quite tricky, not 100% reliable and probably @@ -607,31 +600,31 @@ getshellbyname(const char * shell) static int getshelltype(void) { - pid_t ppid = getppid(); - - if (ppid != 1) { - FILE * fp; - struct stat st; - char procdir[MAXPATHLEN], buf[128]; - int l = sprintf(procdir, "/proc/%ld/", (long)ppid); - char * shell = getenv("SHELL"); - - if (shell != NULL && stat(shell, &st) != -1) - { - struct stat st1; - strcpy(procdir+l, "file"); - /* $SHELL is actual shell? */ - if (stat(procdir, &st1) != -1 && memcmp(&st, &st1, sizeof st) == 0) - return getshellbyname(shell); - } - strcpy(procdir+l, "status"); - if (stat(procdir, &st) == 0 && (fp = fopen(procdir, "r")) != NULL) { - char * p = fgets(buf, sizeof buf, fp)==NULL ? NULL : strtok(buf, " \t"); - fclose(fp); - if (p != NULL) - return getshellbyname(p); + pid_t ppid = getppid(); + + if (ppid != 1) { + FILE * fp; + struct stat st; + char procdir[MAXPATHLEN], buf[128]; + int l = sprintf(procdir, "/proc/%ld/", (long)ppid); + char * shell = getenv("SHELL"); + + if (shell != NULL && stat(shell, &st) != -1) { + struct stat st1; + + strcpy(procdir+l, "file"); + /* $SHELL is actual shell? */ + if (stat(procdir, &st1) != -1 && memcmp(&st, &st1, sizeof st) == 0) + return getshellbyname(shell); + } + strcpy(procdir+l, "status"); + if (stat(procdir, &st) == 0 && (fp = fopen(procdir, "r")) != NULL) { + char * p = fgets(buf, sizeof buf, fp)==NULL ? NULL : strtok(buf, " \t"); + fclose(fp); + if (p != NULL) + return getshellbyname(p); + } } - } - return SH_SH; + return SH_SH; } |