• revert the oksh code to be able to set multiple ulimits in one

invocation, until it works with a common idiom: “ulimit -dS 262144”
  (but keep some goodies)
• add a regression test for that
This commit is contained in:
tg
2008-04-20 21:30:29 +00:00
parent d6f3f726a6
commit 7dd741a401
3 changed files with 89 additions and 113 deletions

178
funcs.c
View File

@ -5,7 +5,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.77 2008/04/19 22:15:03 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.78 2008/04/20 21:30:29 tg Exp $");
/* A leading = means assignments before command are kept;
* a leading * means a POSIX special builtin;
@ -2860,9 +2860,6 @@ struct limits {
char option;
};
static void print_ulimit(const struct limits *, int);
static int set_ulimit(const struct limits *, const char *, int);
int
c_ulimit(const char **wp)
{
@ -2909,23 +2906,23 @@ c_ulimit(const char **wp)
#endif
{ NULL, 0, 0, 0 }
};
static char opts[4 + NELEM(limits) * 2];
int how = SOFT | HARD, optc;
bool all = false;
static char opts[3 + NELEM(limits)];
rlim_t val = (rlim_t)0;
int how = SOFT | HARD, optc, what;
bool all = false, set;
const struct limits *l;
struct rlimit limit;
if (!opts[0]) {
/* build options string on first call - yuck */
char *p = opts;
*p++ = 'H'; *p++ = 'S'; *p++ = 'a';
for (l = limits; l->name; l++) {
for (l = limits; l->name; l++)
*p++ = l->option;
*p++ = '#';
}
*p = '\0';
}
/* first check for -a, -H and -S */
what = 'f';
while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
switch (optc) {
case 'H':
@ -2940,96 +2937,85 @@ c_ulimit(const char **wp)
case '?':
return (1);
default:
break;
what = optc;
}
if (wp[builtin_opt.optind] != NULL) {
bi_errorf("usage: ulimit [-acdfHLlmnpSsTtvw] [value]");
for (l = limits; l->name && l->option != what; l++)
;
if (!l->name) {
internal_warningf("ulimit: %c", what);
return (1);
}
/* then parse and act on the actual limits, one at a time */
ksh_getopt_reset(&builtin_opt, GF_ERROR);
while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
switch (optc) {
case 'a':
case 'H':
case 'S':
break;
case '?':
return (1);
default:
for (l = limits; l->name && l->option != optc; l++)
;
if (!l->name) {
internal_warningf("ulimit: %c", optc);
return (1);
}
if (!builtin_opt.optarg)
print_ulimit(l, how);
else if (set_ulimit(l, builtin_opt.optarg, how))
return (1);
break;
}
wp += builtin_opt.optind;
if ((set = *wp ? true : false)) {
if (all || wp[1]) {
bi_errorf("too many arguments");
return (1);
}
if (strcmp(wp[0], "unlimited") == 0)
val = (rlim_t)RLIM_INFINITY;
else {
long rval;
if (all)
if (!evaluate(wp[0], &rval, KSH_RETURN_ERROR, false))
return (1);
/* Avoid problems caused by typos that
* evaluate misses due to evaluating unset
* parameters to 0...
* If this causes problems, will have to
* add parameter to evaluate() to control
* if unset params are 0 or an error.
*/
if (!rval && !ksh_isdigit(wp[0][0])) {
bi_errorf("invalid limit: %s", wp[0]);
return (1);
}
val = (rlim_t)((rlim_t)rval * l->factor);
}
}
if (all) {
for (l = limits; l->name; l++) {
shprintf("%-20s ", l->name);
print_ulimit(l, how);
if (getrlimit(l->resource, &limit)) {
shf_puts("unknown\n", shl_stdout);
continue;
}
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
if (val == (rlim_t)RLIM_INFINITY)
shf_puts("unlimited\n", shl_stdout);
else {
val = (rlim_t)(val / l->factor);
shprintf("%ld\n", (long)val);
}
}
else if (builtin_opt.optind == 1) {
/* no limit specified, use file size as default */
#ifndef RLIMIT_FSIZE
internal_warningf("ulimit: need argument");
return (1);
#else
#ifdef RLIMIT_CPU
l = &limits[1];
#else
l = &limits[0];
#endif
if (!wp[0])
print_ulimit(l, how);
else if (set_ulimit(l, wp[0], how))
return(1);
#endif
return 0;
}
return (0);
}
static int
set_ulimit(const struct limits *l, const char *v, int how)
{
rlim_t val = (rlim_t)0;
struct rlimit limit;
if (strcmp(v, "unlimited") == 0)
val = (rlim_t)RLIM_INFINITY;
else {
long rval;
if (!evaluate(v, &rval, KSH_RETURN_ERROR, false))
return (1);
/*
* Avoid problems caused by typos that evaluate misses due
* to evaluating unset parameters to 0...
* If this causes problems, will have to add parameter to
* evaluate() to control if unset params are 0 or an error.
*/
if (!rval && !ksh_isdigit(v[0])) {
bi_errorf("invalid limit: %s", v);
return (1);
}
val = (rlim_t)rval * l->factor;
}
if (getrlimit(l->resource, &limit) < 0) {
/* some cannot be read, e.g. Linux RLIMIT_LOCKS */
if (!set) {
shf_puts("unknown\n", shl_stdout);
return (0);
}
limit.rlim_cur = RLIM_INFINITY;
limit.rlim_max = RLIM_INFINITY;
}
if (!set) {
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
if (val == (rlim_t)RLIM_INFINITY)
shf_puts("unlimited\n", shl_stdout);
else {
val = (rlim_t)(val / l->factor);
shprintf("%ld\n", (long)val);
}
return (0);
}
if (how & SOFT)
limit.rlim_cur = val;
if (how & HARD)
@ -3044,28 +3030,6 @@ set_ulimit(const struct limits *l, const char *v, int how)
return (0);
}
static void
print_ulimit(const struct limits *l, int how)
{
rlim_t val = (rlim_t)0;
struct rlimit limit;
if (getrlimit(l->resource, &limit)) {
shf_puts("unknown\n", shl_stdout);
return;
}
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
if (val == RLIM_INFINITY)
shf_puts("unlimited\n", shl_stdout);
else {
val /= l->factor;
shprintf("%ld\n", (long)val);
}
}
int
c_rename(const char **wp)
{