SECURITY: fix integer overflows related to file descriptor parsing
bug initially found by Pawel Wylecial (LP#1440685) additional bug found and suggested fix by enh (elliott hughes) This commit also renames struct ioword.flag to ioflag to disambiguate it from other members named “flag”, changes it to an unsigned type, and packs ioflag and unit into shorts each, to make the struct smaller (aligned even: 16 bytes on 32-bit systems) and reviews some of the code involved in fd handling, though there wasn’t much to be found.
This commit is contained in:
parent
3c5c5d02fd
commit
e1cda74d04
4
eval.c
4
eval.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.166 2015/02/20 07:14:29 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.167 2015/04/11 22:03:29 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* string expansion
|
* string expansion
|
||||||
@ -1353,7 +1353,7 @@ comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED)
|
|||||||
struct ioword *io = *t->ioact;
|
struct ioword *io = *t->ioact;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if ((io->flag & IOTYPE) != IOREAD)
|
if ((io->ioflag & IOTYPE) != IOREAD)
|
||||||
errorf("%s: %s", "funny $() command",
|
errorf("%s: %s", "funny $() command",
|
||||||
snptreef(NULL, 32, "%R", io));
|
snptreef(NULL, 32, "%R", io));
|
||||||
shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0,
|
shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0,
|
||||||
|
22
exec.c
22
exec.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.147 2015/03/20 23:37:54 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.148 2015/04/11 22:03:29 tg Exp $");
|
||||||
|
|
||||||
#ifndef MKSH_DEFAULT_EXECSHELL
|
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||||
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
||||||
@ -92,7 +92,7 @@ execute(struct op * volatile t,
|
|||||||
t->ioact != NULL && t->ioact[0] != NULL &&
|
t->ioact != NULL && t->ioact[0] != NULL &&
|
||||||
t->ioact[1] == NULL &&
|
t->ioact[1] == NULL &&
|
||||||
/* of type "here document" (or "here string") */
|
/* of type "here document" (or "here string") */
|
||||||
(t->ioact[0]->flag & IOTYPE) == IOHERE &&
|
(t->ioact[0]->ioflag & IOTYPE) == IOHERE &&
|
||||||
/* the variable assignment begins with a valid varname */
|
/* the variable assignment begins with a valid varname */
|
||||||
(ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
|
(ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
|
||||||
/* and has no right-hand side (i.e. "varname=") */
|
/* and has no right-hand side (i.e. "varname=") */
|
||||||
@ -1319,7 +1319,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
{
|
{
|
||||||
int u = -1;
|
int u = -1;
|
||||||
char *cp = iop->name;
|
char *cp = iop->name;
|
||||||
int iotype = iop->flag & IOTYPE;
|
int iotype = iop->ioflag & IOTYPE;
|
||||||
bool do_open = true, do_close = false;
|
bool do_open = true, do_close = false;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
struct ioword iotmp;
|
struct ioword iotmp;
|
||||||
@ -1331,7 +1331,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
/* Used for tracing and error messages to print expanded cp */
|
/* Used for tracing and error messages to print expanded cp */
|
||||||
iotmp = *iop;
|
iotmp = *iop;
|
||||||
iotmp.name = (iotype == IOHERE) ? NULL : cp;
|
iotmp.name = (iotype == IOHERE) ? NULL : cp;
|
||||||
iotmp.flag |= IONAMEXP;
|
iotmp.ioflag |= IONAMEXP;
|
||||||
|
|
||||||
if (Flag(FXTRACE)) {
|
if (Flag(FXTRACE)) {
|
||||||
change_xtrace(2, false);
|
change_xtrace(2, false);
|
||||||
@ -1354,7 +1354,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
* The stat() is here to allow redirections to
|
* The stat() is here to allow redirections to
|
||||||
* things like /dev/null without error.
|
* things like /dev/null without error.
|
||||||
*/
|
*/
|
||||||
if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) &&
|
if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB) &&
|
||||||
(stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
|
(stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
|
||||||
flags |= O_EXCL;
|
flags |= O_EXCL;
|
||||||
break;
|
break;
|
||||||
@ -1379,7 +1379,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
u = 1009;
|
u = 1009;
|
||||||
do_close = true;
|
do_close = true;
|
||||||
} else if ((u = check_fd(cp,
|
} else if ((u = check_fd(cp,
|
||||||
X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
|
X_OK | ((iop->ioflag & IORDUP) ? R_OK : W_OK),
|
||||||
&emsg)) < 0) {
|
&emsg)) < 0) {
|
||||||
char *sp;
|
char *sp;
|
||||||
|
|
||||||
@ -1388,7 +1388,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
afree(sp, ATEMP);
|
afree(sp, ATEMP);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if (u == iop->unit)
|
if (u == (int)iop->unit)
|
||||||
/* "dup from" == "dup to" */
|
/* "dup from" == "dup to" */
|
||||||
return (0);
|
return (0);
|
||||||
break;
|
break;
|
||||||
@ -1416,7 +1416,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
/* Do not save if it has already been redirected (i.e. "cat >x >y"). */
|
/* Do not save if it has already been redirected (i.e. "cat >x >y"). */
|
||||||
if (e->savefd[iop->unit] == 0) {
|
if (e->savefd[iop->unit] == 0) {
|
||||||
/* If these are the same, it means unit was previously closed */
|
/* If these are the same, it means unit was previously closed */
|
||||||
if (u == iop->unit)
|
if (u == (int)iop->unit)
|
||||||
e->savefd[iop->unit] = -1;
|
e->savefd[iop->unit] = -1;
|
||||||
else
|
else
|
||||||
/*
|
/*
|
||||||
@ -1431,7 +1431,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
|
|
||||||
if (do_close)
|
if (do_close)
|
||||||
close(iop->unit);
|
close(iop->unit);
|
||||||
else if (u != iop->unit) {
|
else if (u != (int)iop->unit) {
|
||||||
if (ksh_dup2(u, iop->unit, true) < 0) {
|
if (ksh_dup2(u, iop->unit, true) < 0) {
|
||||||
int eno;
|
int eno;
|
||||||
char *sp;
|
char *sp;
|
||||||
@ -1453,7 +1453,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
* causes the shell to close its copies
|
* causes the shell to close its copies
|
||||||
*/
|
*/
|
||||||
else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
|
else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
|
||||||
if (iop->flag & IORDUP)
|
if (iop->ioflag & IORDUP)
|
||||||
/* possible exec <&p */
|
/* possible exec <&p */
|
||||||
coproc_read_close(u);
|
coproc_read_close(u);
|
||||||
else
|
else
|
||||||
@ -1522,7 +1522,7 @@ herein(struct ioword *iop, char **resbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* lexer substitution flags */
|
/* lexer substitution flags */
|
||||||
i = (iop->flag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
|
i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
|
||||||
|
|
||||||
/* skip all the fd setup if we just want the value */
|
/* skip all the fd setup if we just want the value */
|
||||||
if (resbuf != NULL)
|
if (resbuf != NULL)
|
||||||
|
39
lex.c
39
lex.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.198 2015/03/20 23:37:39 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.199 2015/04/11 22:03:30 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* states while lexing word
|
* states while lexing word
|
||||||
@ -921,42 +921,41 @@ yylex(int cf)
|
|||||||
if (!ksh_isdigit(dp[c2 + 1]))
|
if (!ksh_isdigit(dp[c2 + 1]))
|
||||||
goto no_iop;
|
goto no_iop;
|
||||||
iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0';
|
iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0';
|
||||||
|
if (iop->unit >= FDBASE)
|
||||||
|
goto no_iop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iop->unit >= FDBASE)
|
|
||||||
goto no_iop;
|
|
||||||
|
|
||||||
if (c == '&') {
|
if (c == '&') {
|
||||||
if ((c2 = getsc()) != '>') {
|
if ((c2 = getsc()) != '>') {
|
||||||
ungetsc(c2);
|
ungetsc(c2);
|
||||||
goto no_iop;
|
goto no_iop;
|
||||||
}
|
}
|
||||||
c = c2;
|
c = c2;
|
||||||
iop->flag = IOBASH;
|
iop->ioflag = IOBASH;
|
||||||
} else
|
} else
|
||||||
iop->flag = 0;
|
iop->ioflag = 0;
|
||||||
|
|
||||||
c2 = getsc();
|
c2 = getsc();
|
||||||
/* <<, >>, <> are ok, >< is not */
|
/* <<, >>, <> are ok, >< is not */
|
||||||
if (c == c2 || (c == '<' && c2 == '>')) {
|
if (c == c2 || (c == '<' && c2 == '>')) {
|
||||||
iop->flag |= c == c2 ?
|
iop->ioflag |= c == c2 ?
|
||||||
(c == '>' ? IOCAT : IOHERE) : IORDWR;
|
(c == '>' ? IOCAT : IOHERE) : IORDWR;
|
||||||
if (iop->flag == IOHERE) {
|
if (iop->ioflag == IOHERE) {
|
||||||
if ((c2 = getsc()) == '-') {
|
if ((c2 = getsc()) == '-') {
|
||||||
iop->flag |= IOSKIP;
|
iop->ioflag |= IOSKIP;
|
||||||
c2 = getsc();
|
c2 = getsc();
|
||||||
} else if (c2 == '<')
|
} else if (c2 == '<')
|
||||||
iop->flag |= IOHERESTR;
|
iop->ioflag |= IOHERESTR;
|
||||||
ungetsc(c2);
|
ungetsc(c2);
|
||||||
if (c2 == '\n')
|
if (c2 == '\n')
|
||||||
iop->flag |= IONDELIM;
|
iop->ioflag |= IONDELIM;
|
||||||
}
|
}
|
||||||
} else if (c2 == '&')
|
} else if (c2 == '&')
|
||||||
iop->flag |= IODUP | (c == '<' ? IORDUP : 0);
|
iop->ioflag |= IODUP | (c == '<' ? IORDUP : 0);
|
||||||
else {
|
else {
|
||||||
iop->flag |= c == '>' ? IOWRITE : IOREAD;
|
iop->ioflag |= c == '>' ? IOWRITE : IOREAD;
|
||||||
if (c == '>' && c2 == '|')
|
if (c == '>' && c2 == '|')
|
||||||
iop->flag |= IOCLOB;
|
iop->ioflag |= IOCLOB;
|
||||||
else
|
else
|
||||||
ungetsc(c2);
|
ungetsc(c2);
|
||||||
}
|
}
|
||||||
@ -1124,7 +1123,7 @@ gethere(bool iseof)
|
|||||||
struct ioword **p;
|
struct ioword **p;
|
||||||
|
|
||||||
for (p = heres; p < herep; p++)
|
for (p = heres; p < herep; p++)
|
||||||
if (iseof && !((*p)->flag & IOHERESTR))
|
if (iseof && !((*p)->ioflag & IOHERESTR))
|
||||||
/* only here strings at EOF */
|
/* only here strings at EOF */
|
||||||
return;
|
return;
|
||||||
else
|
else
|
||||||
@ -1145,7 +1144,7 @@ readhere(struct ioword *iop)
|
|||||||
char *xp;
|
char *xp;
|
||||||
int xpos;
|
int xpos;
|
||||||
|
|
||||||
if (iop->flag & IOHERESTR) {
|
if (iop->ioflag & IOHERESTR) {
|
||||||
/* process the here string */
|
/* process the here string */
|
||||||
iop->heredoc = xp = evalstr(iop->delim, DOBLANK);
|
iop->heredoc = xp = evalstr(iop->delim, DOBLANK);
|
||||||
xpos = strlen(xp) - 1;
|
xpos = strlen(xp) - 1;
|
||||||
@ -1154,9 +1153,9 @@ readhere(struct ioword *iop)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eof = iop->flag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
|
eof = iop->ioflag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
|
||||||
|
|
||||||
if (!(iop->flag & IOEVAL))
|
if (!(iop->ioflag & IOEVAL))
|
||||||
ignore_backslash_newline++;
|
ignore_backslash_newline++;
|
||||||
|
|
||||||
Xinit(xs, xp, 256, ATEMP);
|
Xinit(xs, xp, 256, ATEMP);
|
||||||
@ -1165,7 +1164,7 @@ readhere(struct ioword *iop)
|
|||||||
/* beginning of line */
|
/* beginning of line */
|
||||||
eofp = eof;
|
eofp = eof;
|
||||||
xpos = Xsavepos(xs, xp);
|
xpos = Xsavepos(xs, xp);
|
||||||
if (iop->flag & IOSKIP) {
|
if (iop->ioflag & IOSKIP) {
|
||||||
/* skip over leading tabs */
|
/* skip over leading tabs */
|
||||||
while ((c = getsc()) == '\t')
|
while ((c = getsc()) == '\t')
|
||||||
; /* nothing */
|
; /* nothing */
|
||||||
@ -1227,7 +1226,7 @@ readhere(struct ioword *iop)
|
|||||||
Xput(xs, xp, '\0');
|
Xput(xs, xp, '\0');
|
||||||
iop->heredoc = Xclose(xs, xp);
|
iop->heredoc = Xclose(xs, xp);
|
||||||
|
|
||||||
if (!(iop->flag & IOEVAL))
|
if (!(iop->ioflag & IOEVAL))
|
||||||
ignore_backslash_newline--;
|
ignore_backslash_newline--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
main.c
15
main.c
@ -34,7 +34,7 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.290 2015/03/14 05:23:15 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.291 2015/04/11 22:03:30 tg Exp $");
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
@ -1453,13 +1453,20 @@ closepipe(int *pv)
|
|||||||
int
|
int
|
||||||
check_fd(const char *name, int mode, const char **emsgp)
|
check_fd(const char *name, int mode, const char **emsgp)
|
||||||
{
|
{
|
||||||
int fd, fl;
|
int fd = 0, fl;
|
||||||
|
|
||||||
if (name[0] == 'p' && !name[1])
|
if (name[0] == 'p' && !name[1])
|
||||||
return (coproc_getfd(mode, emsgp));
|
return (coproc_getfd(mode, emsgp));
|
||||||
for (fd = 0; ksh_isdigit(*name); ++name)
|
while (ksh_isdigit(*name)) {
|
||||||
fd = (fd * 10) + *name - '0';
|
fd = (fd * 10) + *name - '0';
|
||||||
if (*name || fd >= FDBASE) {
|
if (fd >= FDBASE) {
|
||||||
|
if (emsgp)
|
||||||
|
*emsgp = "file descriptor too large";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
++name;
|
||||||
|
}
|
||||||
|
if (*name) {
|
||||||
if (emsgp)
|
if (emsgp)
|
||||||
*emsgp = "illegal file descriptor name";
|
*emsgp = "illegal file descriptor name";
|
||||||
return (-1);
|
return (-1);
|
||||||
|
12
sh.h
12
sh.h
@ -169,7 +169,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.721 2015/03/20 23:37:55 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.722 2015/04/11 22:03:31 tg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R50 2015/03/20"
|
#define MKSH_VERSION "R50 2015/03/20"
|
||||||
|
|
||||||
@ -1341,11 +1341,11 @@ struct op {
|
|||||||
* IO redirection
|
* IO redirection
|
||||||
*/
|
*/
|
||||||
struct ioword {
|
struct ioword {
|
||||||
int unit; /* unit affected */
|
char *name; /* filename (unused if heredoc) */
|
||||||
int flag; /* action (below) */
|
char *delim; /* delimiter for <<, <<- */
|
||||||
char *name; /* file name (unused if heredoc) */
|
char *heredoc; /* content of heredoc */
|
||||||
char *delim; /* delimiter for <<,<<- */
|
unsigned short ioflag; /* action (below) */
|
||||||
char *heredoc; /* content of heredoc */
|
short unit; /* unit (fd) affected */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ioword.flag - type of redirection */
|
/* ioword.flag - type of redirection */
|
||||||
|
19
syn.c
19
syn.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.99 2015/03/14 05:23:18 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.100 2015/04/11 22:03:32 tg Exp $");
|
||||||
|
|
||||||
struct nesting_state {
|
struct nesting_state {
|
||||||
int start_token; /* token than began nesting (eg, FOR) */
|
int start_token; /* token than began nesting (eg, FOR) */
|
||||||
@ -189,16 +189,16 @@ synio(int cf)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
ACCEPT;
|
ACCEPT;
|
||||||
iop = yylval.iop;
|
iop = yylval.iop;
|
||||||
if (iop->flag & IONDELIM)
|
if (iop->ioflag & IONDELIM)
|
||||||
goto gotnulldelim;
|
goto gotnulldelim;
|
||||||
ishere = (iop->flag & IOTYPE) == IOHERE;
|
ishere = (iop->ioflag & IOTYPE) == IOHERE;
|
||||||
musthave(LWORD, ishere ? HEREDELIM : 0);
|
musthave(LWORD, ishere ? HEREDELIM : 0);
|
||||||
if (ishere) {
|
if (ishere) {
|
||||||
iop->delim = yylval.cp;
|
iop->delim = yylval.cp;
|
||||||
if (*ident != 0) {
|
if (*ident != 0) {
|
||||||
/* unquoted */
|
/* unquoted */
|
||||||
gotnulldelim:
|
gotnulldelim:
|
||||||
iop->flag |= IOEVAL;
|
iop->ioflag |= IOEVAL;
|
||||||
}
|
}
|
||||||
if (herep > &heres[HERES - 1])
|
if (herep > &heres[HERES - 1])
|
||||||
yyerror("too many %ss\n", "<<");
|
yyerror("too many %ss\n", "<<");
|
||||||
@ -206,7 +206,7 @@ synio(int cf)
|
|||||||
} else
|
} else
|
||||||
iop->name = yylval.cp;
|
iop->name = yylval.cp;
|
||||||
|
|
||||||
if (iop->flag & IOBASH) {
|
if (iop->ioflag & IOBASH) {
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
nextiop = alloc(sizeof(*iop), ATEMP);
|
nextiop = alloc(sizeof(*iop), ATEMP);
|
||||||
@ -220,9 +220,9 @@ synio(int cf)
|
|||||||
*cp++ = '0' + (iop->unit % 10);
|
*cp++ = '0' + (iop->unit % 10);
|
||||||
*cp = EOS;
|
*cp = EOS;
|
||||||
|
|
||||||
iop->flag &= ~IOBASH;
|
iop->ioflag &= ~IOBASH;
|
||||||
nextiop->unit = 2;
|
nextiop->unit = 2;
|
||||||
nextiop->flag = IODUP;
|
nextiop->ioflag = IODUP;
|
||||||
nextiop->delim = NULL;
|
nextiop->delim = NULL;
|
||||||
nextiop->heredoc = NULL;
|
nextiop->heredoc = NULL;
|
||||||
}
|
}
|
||||||
@ -996,9 +996,10 @@ dbtestp_isa(Test_env *te, Test_meta meta)
|
|||||||
ret = c == /*(*/ ')' ? TO_NONNULL : TO_NONOP;
|
ret = c == /*(*/ ')' ? TO_NONNULL : TO_NONOP;
|
||||||
else if (meta == TM_UNOP || meta == TM_BINOP) {
|
else if (meta == TM_UNOP || meta == TM_BINOP) {
|
||||||
if (meta == TM_BINOP && c == REDIR &&
|
if (meta == TM_BINOP && c == REDIR &&
|
||||||
(yylval.iop->flag == IOREAD || yylval.iop->flag == IOWRITE)) {
|
(yylval.iop->ioflag == IOREAD ||
|
||||||
|
yylval.iop->ioflag == IOWRITE)) {
|
||||||
ret = TO_NONNULL;
|
ret = TO_NONNULL;
|
||||||
save = wdcopy(yylval.iop->flag == IOREAD ?
|
save = wdcopy(yylval.iop->ioflag == IOREAD ?
|
||||||
db_lthan : db_gthan, ATEMP);
|
db_lthan : db_gthan, ATEMP);
|
||||||
} else if (uqword && (ret = test_isop(meta, ident)))
|
} else if (uqword && (ret = test_isop(meta, ident)))
|
||||||
save = yylval.cp;
|
save = yylval.cp;
|
||||||
|
30
tree.c
30
tree.c
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||||
* 2011, 2012, 2013
|
* 2011, 2012, 2013, 2015
|
||||||
* Thorsten Glaser <tg@mirbsd.org>
|
* Thorsten Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72 2013/09/24 20:19:45 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.73 2015/04/11 22:03:32 tg Exp $");
|
||||||
|
|
||||||
#define INDENT 8
|
#define INDENT 8
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ ptree(struct op *t, int indent, struct shf *shf)
|
|||||||
t->ioact != NULL && t->ioact[0] != NULL &&
|
t->ioact != NULL && t->ioact[0] != NULL &&
|
||||||
t->ioact[1] == NULL &&
|
t->ioact[1] == NULL &&
|
||||||
/* of type "here document" (or "here string") */
|
/* of type "here document" (or "here string") */
|
||||||
(t->ioact[0]->flag & IOTYPE) == IOHERE) {
|
(t->ioact[0]->ioflag & IOTYPE) == IOHERE) {
|
||||||
fptreef(shf, indent, "%S", t->vars[0]);
|
fptreef(shf, indent, "%S", t->vars[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -221,12 +221,12 @@ ptree(struct op *t, int indent, struct shf *shf)
|
|||||||
struct ioword *iop = *ioact++;
|
struct ioword *iop = *ioact++;
|
||||||
|
|
||||||
/* heredoc is NULL when tracing (set -x) */
|
/* heredoc is NULL when tracing (set -x) */
|
||||||
if ((iop->flag & (IOTYPE | IOHERESTR)) == IOHERE &&
|
if ((iop->ioflag & (IOTYPE | IOHERESTR)) == IOHERE &&
|
||||||
iop->heredoc) {
|
iop->heredoc) {
|
||||||
shf_putc('\n', shf);
|
shf_putc('\n', shf);
|
||||||
shf_puts(iop->heredoc, shf);
|
shf_puts(iop->heredoc, shf);
|
||||||
fptreef(shf, indent, "%s",
|
fptreef(shf, indent, "%s",
|
||||||
iop->flag & IONDELIM ? "<<" :
|
iop->ioflag & IONDELIM ? "<<" :
|
||||||
evalstr(iop->delim, 0));
|
evalstr(iop->delim, 0));
|
||||||
need_nl = true;
|
need_nl = true;
|
||||||
}
|
}
|
||||||
@ -246,16 +246,16 @@ ptree(struct op *t, int indent, struct shf *shf)
|
|||||||
static void
|
static void
|
||||||
pioact(struct shf *shf, struct ioword *iop)
|
pioact(struct shf *shf, struct ioword *iop)
|
||||||
{
|
{
|
||||||
int flag = iop->flag;
|
unsigned short flag = iop->ioflag;
|
||||||
int type = flag & IOTYPE;
|
unsigned short type = flag & IOTYPE;
|
||||||
int expected;
|
short expected;
|
||||||
|
|
||||||
expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
|
expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
|
||||||
(type == IOCAT || type == IOWRITE) ? 1 :
|
(type == IOCAT || type == IOWRITE) ? 1 :
|
||||||
(type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
|
(type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
|
||||||
iop->unit + 1;
|
iop->unit + 1;
|
||||||
if (iop->unit != expected)
|
if (iop->unit != expected)
|
||||||
shf_fprintf(shf, "%d", iop->unit);
|
shf_fprintf(shf, "%d", (int)iop->unit);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IOREAD:
|
case IOREAD:
|
||||||
@ -285,10 +285,10 @@ pioact(struct shf *shf, struct ioword *iop)
|
|||||||
if (type == IOHERE) {
|
if (type == IOHERE) {
|
||||||
if (iop->delim)
|
if (iop->delim)
|
||||||
wdvarput(shf, iop->delim, 0, WDS_TPUTS);
|
wdvarput(shf, iop->delim, 0, WDS_TPUTS);
|
||||||
if (iop->flag & IOHERESTR)
|
if (flag & IOHERESTR)
|
||||||
shf_putc(' ', shf);
|
shf_putc(' ', shf);
|
||||||
} else if (iop->name) {
|
} else if (iop->name) {
|
||||||
if (iop->flag & IONAMEXP)
|
if (flag & IONAMEXP)
|
||||||
print_value_quoted(shf, iop->name);
|
print_value_quoted(shf, iop->name);
|
||||||
else
|
else
|
||||||
wdvarput(shf, iop->name, 0, WDS_TPUTS);
|
wdvarput(shf, iop->name, 0, WDS_TPUTS);
|
||||||
@ -910,9 +910,9 @@ dumpioact(struct shf *shf, struct op *t)
|
|||||||
|
|
||||||
shf_puts("{IOACT", shf);
|
shf_puts("{IOACT", shf);
|
||||||
while ((iop = *ioact++) != NULL) {
|
while ((iop = *ioact++) != NULL) {
|
||||||
int type = iop->flag & IOTYPE;
|
unsigned short type = iop->ioflag & IOTYPE;
|
||||||
#define DT(x) case x: shf_puts(#x, shf); break;
|
#define DT(x) case x: shf_puts(#x, shf); break;
|
||||||
#define DB(x) if (iop->flag & x) shf_puts("|" #x, shf);
|
#define DB(x) if (iop->ioflag & x) shf_puts("|" #x, shf);
|
||||||
|
|
||||||
shf_putc(';', shf);
|
shf_putc(';', shf);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -933,14 +933,14 @@ dumpioact(struct shf *shf, struct op *t)
|
|||||||
DB(IOBASH)
|
DB(IOBASH)
|
||||||
DB(IOHERESTR)
|
DB(IOHERESTR)
|
||||||
DB(IONDELIM)
|
DB(IONDELIM)
|
||||||
shf_fprintf(shf, ",unit=%d", iop->unit);
|
shf_fprintf(shf, ",unit=%d", (int)iop->unit);
|
||||||
if (iop->delim) {
|
if (iop->delim) {
|
||||||
shf_puts(",delim<", shf);
|
shf_puts(",delim<", shf);
|
||||||
dumpwdvar(shf, iop->delim);
|
dumpwdvar(shf, iop->delim);
|
||||||
shf_putc('>', shf);
|
shf_putc('>', shf);
|
||||||
}
|
}
|
||||||
if (iop->name) {
|
if (iop->name) {
|
||||||
if (iop->flag & IONAMEXP) {
|
if (iop->ioflag & IONAMEXP) {
|
||||||
shf_puts(",name=", shf);
|
shf_puts(",name=", shf);
|
||||||
print_value_quoted(shf, iop->name);
|
print_value_quoted(shf, iop->name);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user