aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c289
1 files changed, 127 insertions, 162 deletions
diff --git a/shell/ash.c b/shell/ash.c
index fe99b02cb..b34f0583f 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1214,7 +1214,7 @@ static char *nodesavestr(char *);
-static void evalstring(char *, int);
+static void evalstring(char *);
union node; /* BLETCH for ansi C */
static void evaltree(union node *, int);
static void evalbackcmd(union node *, struct backcmd *);
@@ -2704,7 +2704,7 @@ evalcmd(int argc, char **argv)
STPUTC('\0', concat);
p = grabstackstr(concat);
}
- evalstring(p, EV_TESTED);
+ evalstring(p);
}
return exitstatus;
}
@@ -2715,7 +2715,7 @@ evalcmd(int argc, char **argv)
*/
static void
-evalstring(char *s, int flag)
+evalstring(char *s)
{
union node *n;
struct stackmark smark;
@@ -2724,7 +2724,7 @@ evalstring(char *s, int flag)
setinputstring(s);
while ((n = parsecmd(0)) != NEOF) {
- evaltree(n, flag);
+ evaltree(n, 0);
popstackmark(&smark);
if (evalskip)
break;
@@ -4496,10 +4496,9 @@ static char *exptilde(char *, char *, int);
static void expbackq(union node *, int, int);
static const char *subevalvar(char *, char *, int, int, int, int, int);
static char *evalvar(char *, int);
-static int varisset(char *, int);
static void strtodest(const char *, int, int);
static void memtodest(const char *p, size_t len, int syntax, int quotes);
-static void varvalue(char *, int, int);
+static ssize_t varvalue(char *, int, int);
static void recordregion(int, int, int);
static void removerecordregions(int);
static void ifsbreakup(char *, struct arglist *);
@@ -5112,9 +5111,8 @@ evalvar(char *p, int flag)
char *var;
int patloc;
int c;
- int set;
int startloc;
- size_t varlen;
+ ssize_t varlen;
int easy;
int quotes;
int quoted;
@@ -5125,48 +5123,22 @@ evalvar(char *p, int flag)
quoted = varflags & VSQUOTE;
var = p;
easy = (!quoted || (*var == '@' && shellparam.nparam));
- varlen = 0;
startloc = expdest - (char *)stackblock();
p = strchr(p, '=') + 1;
- if (!is_name(*var)) {
- set = varisset(var, varflags & VSNUL);
- set--;
- if (subtype == VSPLUS)
- goto vsplus;
- if (++set) {
- varvalue(var, quoted, flag);
- if (subtype == VSLENGTH) {
- varlen =
- expdest - (char *)stackblock() -
- startloc;
- STADJUST(-varlen, expdest);
- goto vslen;
- }
- }
- } else {
- const char *val;
again:
- /* jump here after setting a variable with ${var=text} */
- val = lookupvar(var);
- set = !val || ((varflags & VSNUL) && !*val);
- if (subtype == VSPLUS)
- goto vsplus;
- if (--set) {
- varlen = strlen(val);
- if (subtype == VSLENGTH)
- goto vslen;
- memtodest(
- val, varlen, quoted ? DQSYNTAX : BASESYNTAX,
- quotes
- );
- }
- }
+ varlen = varvalue(var, varflags, flag);
+ if (varflags & VSNUL)
+ varlen--;
+ if (subtype == VSPLUS) {
+ varlen = -1 - varlen;
+ goto vsplus;
+ }
if (subtype == VSMINUS) {
vsplus:
- if (!set) {
+ if (varlen < 0) {
argstr(
p, flag | EXP_TILDE |
(quoted ? EXP_QWORD : EXP_WORD)
@@ -5179,7 +5151,7 @@ vsplus:
}
if (subtype == VSASSIGN || subtype == VSQUESTION) {
- if (!set) {
+ if (varlen < 0) {
if (subevalvar(p, var, 0, subtype, startloc,
varflags, 0)) {
varflags &= ~VSNUL;
@@ -5197,12 +5169,11 @@ vsplus:
goto end;
}
- if (!set && uflag)
+ if (varlen < 0 && uflag)
varunset(p, var, 0, 0);
if (subtype == VSLENGTH) {
-vslen:
- cvtnum(varlen);
+ cvtnum(varlen > 0 ? varlen : 0);
goto record;
}
@@ -5226,7 +5197,7 @@ record:
}
#endif
- if (set) {
+ if (varlen >= 0) {
/*
* Terminate the string and start recording the pattern
* right after it
@@ -5252,7 +5223,7 @@ end:
if ((c = *p++) == CTLESC)
p++;
else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
- if (set)
+ if (varlen >= 0)
argbackq = argbackq->next;
} else if (c == CTLVAR) {
if ((*p++ & VSTYPE) != VSNORMAL)
@@ -5267,47 +5238,6 @@ end:
}
-
-/*
- * Test whether a specialized variable is set.
- */
-
-static int
-varisset(char *name, int nulok)
-{
- if (*name == '!')
- return backgndpid != 0;
- else if (*name == '@' || *name == '*') {
- if (*shellparam.p == NULL)
- return 0;
-
- if (nulok) {
- char **av;
-
- for (av = shellparam.p; *av; av++)
- if (**av != '\0')
- return 1;
- return 0;
- }
- } else if (is_digit(*name)) {
- char *ap;
- int num = atoi(name);
-
- if (num > shellparam.nparam)
- return 0;
-
- if (num == 0)
- ap = arg0;
- else
- ap = shellparam.p[num - 1];
-
- if (nulok && (ap == NULL || *ap == '\0'))
- return 0;
- }
- return 1;
-}
-
-
/*
* Put a string on the stack.
*/
@@ -5342,19 +5272,24 @@ strtodest(const char *p, int syntax, int quotes)
* Add the value of a specialized variable to the stack string.
*/
-static void
-varvalue(char *name, int quoted, int flags)
+static ssize_t
+varvalue(char *name, int varflags, int flags)
{
int num;
char *p;
int i;
- int sep;
+ int sep = 0;
int sepq = 0;
+ ssize_t len = 0;
char **ap;
int syntax;
- int allow_split = flags & EXP_FULL;
+ int quoted = varflags & VSQUOTE;
+ int subtype = varflags & VSTYPE;
int quotes = flags & (EXP_FULL | EXP_CASE);
+ if (quoted && (flags & EXP_FULL))
+ sep = 1 << CHAR_BIT;
+
syntax = quoted ? DQSYNTAX : BASESYNTAX;
switch (*name) {
case '$':
@@ -5368,48 +5303,86 @@ varvalue(char *name, int quoted, int flags)
goto numvar;
case '!':
num = backgndpid;
+ if (num == 0)
+ return -1;
numvar:
- cvtnum(num);
+ len = cvtnum(num);
break;
case '-':
- for (i = 0 ; i < NOPTS ; i++) {
- if (optlist[i])
- STPUTC(optletters(i), expdest);
+ p = makestrspace(NOPTS, expdest);
+ for (i = NOPTS - 1; i >= 0; i--) {
+ if (optlist[i]) {
+ USTPUTC(optletters(i), p);
+ len++;
+ }
}
+ expdest = p;
break;
case '@':
- if (allow_split && quoted) {
- sep = 1 << CHAR_BIT;
+ if (sep)
goto param;
- }
/* fall through */
case '*':
sep = ifsset() ? ifsval()[0] : ' ';
- if (quotes) {
- sepq = (SIT(sep, syntax) == CCTL) || (SIT(sep, syntax) == CBACK);
- }
+ if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
+ sepq = 1;
param:
- for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
- strtodest(p, syntax, quotes);
- if (*ap && sep) {
- p = expdest;
+ if (!(ap = shellparam.p))
+ return -1;
+ while ((p = *ap++)) {
+ size_t partlen;
+
+ partlen = strlen(p);
+
+ len += partlen;
+ if (len > partlen && sep) {
+ char *q;
+
+ len++;
+ if (subtype == VSPLUS || subtype == VSLENGTH) {
+ continue;
+ }
+ q = expdest;
if (sepq)
- STPUTC(CTLESC, p);
- STPUTC(sep, p);
- expdest = p;
+ STPUTC(CTLESC, q);
+ STPUTC(sep, q);
+ expdest = q;
}
+
+ if (!(subtype == VSPLUS || subtype == VSLENGTH))
+ memtodest(p, partlen, syntax, quotes);
}
- break;
+ return len;
case '0':
- strtodest(arg0, syntax, quotes);
- break;
- default:
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
num = atoi(name);
- if (num > 0 && num <= shellparam.nparam) {
- strtodest(shellparam.p[num - 1], syntax, quotes);
- }
- break;
+ if (num < 0 || num > shellparam.nparam)
+ return -1;
+ p = num ? shellparam.p[num - 1] : arg0;
+ goto value;
+ default:
+ p = lookupvar(name);
+value:
+ if (!p)
+ return -1;
+
+ len = strlen(p);
+ if (!(subtype == VSPLUS || subtype == VSLENGTH))
+ memtodest(p, len, syntax, quotes);
+ return len;
}
+
+ if (subtype == VSPLUS || subtype == VSLENGTH)
+ STADJUST(-len, expdest);
+ return len;
}
@@ -7946,7 +7919,7 @@ state2:
state3:
state = 4;
if (minusc)
- evalstring(minusc, 0);
+ evalstring(minusc);
if (sflag || minusc == NULL) {
#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
@@ -7988,8 +7961,8 @@ cmdloop(int top)
int numeof = 0;
TRACE(("cmdloop(%d) called\n", top));
- setstackmark(&smark);
for (;;) {
+ setstackmark(&smark);
if (pendingsigs)
dotrap();
#if JOBS
@@ -8020,13 +7993,11 @@ cmdloop(int top)
evaltree(n, 0);
}
popstackmark(&smark);
- setstackmark(&smark);
- if (evalskip == SKIPFILE) {
+ if (evalskip) {
evalskip = 0;
break;
}
}
- popstackmark(&smark);
}
@@ -11778,7 +11749,7 @@ dotrap(void)
p = trap[p - q + 1];
if (!p)
continue;
- evalstring(p, 0);
+ evalstring(p);
exitstatus = savestatus;
}
}
@@ -11870,7 +11841,7 @@ exitshell(void)
handler = &loc;
if ((p = trap[0]) != NULL && *p != '\0') {
trap[0] = NULL;
- evalstring(p, 0);
+ evalstring(p);
}
flushall();
#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
@@ -12497,7 +12468,7 @@ letcmd(int argc, char **argv)
#undef rflag
#ifdef __GLIBC__
-#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
typedef enum __rlimit_resource rlim_t;
#endif
#endif
@@ -12694,34 +12665,52 @@ static const struct limits limits[] = {
{ "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
#endif
#ifdef RLIMIT_NPROC
- { "process(processes)", RLIMIT_NPROC, 1, 'p' },
+ { "process", RLIMIT_NPROC, 1, 'p' },
#endif
#ifdef RLIMIT_NOFILE
- { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
+ { "nofiles", RLIMIT_NOFILE, 1, 'n' },
#endif
-#ifdef RLIMIT_VMEM
- { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
+#ifdef RLIMIT_AS
+ { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
#endif
-#ifdef RLIMIT_SWAP
- { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
+#ifdef RLIMIT_LOCKS
+ { "locks", RLIMIT_LOCKS, 1, 'w' },
#endif
{ (char *) 0, 0, 0, '\0' }
};
+enum limtype { SOFT = 0x1, HARD = 0x2 };
+
+static void printlim(enum limtype how, const struct rlimit *limit,
+ const struct limits *l)
+{
+ rlim_t val;
+
+ val = limit->rlim_max;
+ if (how & SOFT)
+ val = limit->rlim_cur;
+
+ if (val == RLIM_INFINITY)
+ out1fmt("unlimited\n");
+ else {
+ val /= l->factor;
+ out1fmt("%lld\n", (long long) val);
+ }
+}
+
int
ulimitcmd(int argc, char **argv)
{
int c;
rlim_t val = 0;
- enum { SOFT = 0x1, HARD = 0x2 }
- how = SOFT | HARD;
+ enum limtype how = SOFT | HARD;
const struct limits *l;
int set, all = 0;
int optc, what;
struct rlimit limit;
what = 'f';
- while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
+ while ((optc = nextopt("HSatfdsmcnplvw")) != '\0')
switch (optc) {
case 'H':
how = HARD;
@@ -12736,10 +12725,8 @@ ulimitcmd(int argc, char **argv)
what = optc;
}
- for (l = limits; l->name && l->option != what; l++)
+ for (l = limits; l->option != what; l++)
;
- if (!l->name)
- error("internal error (%c)", what);
set = *argptr ? 1 : 0;
if (set) {
@@ -12766,19 +12753,8 @@ ulimitcmd(int argc, char **argv)
if (all) {
for (l = limits; l->name; l++) {
getrlimit(l->cmd, &limit);
- if (how & SOFT)
- val = limit.rlim_cur;
- else if (how & HARD)
- val = limit.rlim_max;
-
out1fmt("%-20s ", l->name);
- if (val == RLIM_INFINITY)
- out1fmt("unlimited\n");
- else
- {
- val /= l->factor;
- out1fmt("%lld\n", (long long) val);
- }
+ printlim(how, &limit, l);
}
return 0;
}
@@ -12792,18 +12768,7 @@ ulimitcmd(int argc, char **argv)
if (setrlimit(l->cmd, &limit) < 0)
error("error setting limit (%m)");
} else {
- if (how & SOFT)
- val = limit.rlim_cur;
- else if (how & HARD)
- val = limit.rlim_max;
-
- if (val == RLIM_INFINITY)
- out1fmt("unlimited\n");
- else
- {
- val /= l->factor;
- out1fmt("%lld\n", (long long) val);
- }
+ printlim(how, &limit, l);
}
return 0;
}