• 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
View File

@ -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: 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 $
@ -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>|
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
---

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)
{

9
mksh.1
View File

@ -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 $
.\"-
.\" 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
.It Xo
.Ic ulimit
.Op Fl acdfHLlmnpSsTtvw Op Ar value
.Ar ...
.Op Fl acdfHLlmnpSsTtvw
.Op Ar value
.Xc
Display or set process limits.
If no options are used, the file size limit
.Pq Fl f
is assumed.
.Ar value ,
if specified, may be either an arithmetic expression starting with a
number or the word
if specified, may be either an arithmetic expression or the word
.Dq unlimited .
The limits affect the shell and any processes created by the shell after a
limit is imposed.