• 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

15
check.t

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.186 2008/04/20 01:23:49 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.187 2008/04/20 21:30:28 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -4977,3 +4977,16 @@ expected-stdout:
000001A0 BF 0A FF 0A C2 0A EF BF - C0 0A C0 80 0A E0 80 80 |.<EFBFBD>.<EFBFBD>.<EFBFBD><EFBFBD><EFBFBD>.<EFBFBD><EFBFBD>.<EFBFBD><EFBFBD><EFBFBD>| 000001A0 BF 0A FF 0A C2 0A EF BF - C0 0A C0 80 0A E0 80 80 |.<EFBFBD>.<EFBFBD>.<EFBFBD><EFBFBD><EFBFBD>.<EFBFBD><EFBFBD>.<EFBFBD><EFBFBD><EFBFBD>|
000001B0 0A EF BF BD EF BF BE EF - BF BF 0A |.<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.| 000001B0 0A EF BF BD EF BF BE EF - BF BF 0A |.<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.|
--- ---
name: ulimit-1
description:
Check if we can use a specific syntax idiom for ulimit
stdin:
if ! x=$(ulimit -d); then
print expected to fail on this OS
else
ulimit -dS $x && print okay
fi
expected-stdout:
okay
---

162
funcs.c

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

9
mksh.1

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.122 2008/04/20 01:47:59 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.123 2008/04/20 21:30:29 tg Exp $
.\" $OpenBSD: ksh.1,v 1.121 2008/03/21 12:51:19 millert Exp $ .\" $OpenBSD: ksh.1,v 1.121 2008/03/21 12:51:19 millert Exp $
.\"- .\"-
.\" Try to make GNU groff and AT&T nroff more compatible .\" Try to make GNU groff and AT&T nroff more compatible
@ -4092,16 +4092,15 @@ unless they are also given on the same command line.
.Pp .Pp
.It Xo .It Xo
.Ic ulimit .Ic ulimit
.Op Fl acdfHLlmnpSsTtvw Op Ar value .Op Fl acdfHLlmnpSsTtvw
.Ar ... .Op Ar value
.Xc .Xc
Display or set process limits. Display or set process limits.
If no options are used, the file size limit If no options are used, the file size limit
.Pq Fl f .Pq Fl f
is assumed. is assumed.
.Ar value , .Ar value ,
if specified, may be either an arithmetic expression starting with a if specified, may be either an arithmetic expression or the word
number or the word
.Dq unlimited . .Dq unlimited .
The limits affect the shell and any processes created by the shell after a The limits affect the shell and any processes created by the shell after a
limit is imposed. limit is imposed.