diff --git a/check.t b/check.t index 1bdc28e..b990b30 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.206 2008/07/09 20:31:19 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.207 2008/07/09 21:32:42 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 $ @@ -7,7 +7,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R34 2008/07/06 + @(#)MIRBSD KSH R34 2008/07/09 description: Check version of shell. stdin: @@ -5171,3 +5171,24 @@ expected-stdout: ras dwa --- +name: mkshiop-1 +description: + Check for support of more than 9 file descriptors +stdin: + read -u10 foo 10<<< bar + print x$foo +expected-stdout: + xbar +--- +name: mkshiop-2 +description: + Check for support of more than 9 file descriptors +stdin: + exec 12>foo + print -u12 bar + print baz >&12 + cat foo +expected-stdout: + bar + baz +--- diff --git a/lex.c b/lex.c index 0fb4816..7923be7 100644 --- a/lex.c +++ b/lex.c @@ -2,7 +2,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.64 2008/07/09 20:41:23 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.65 2008/07/09 21:32:43 tg Exp $"); /* * states while lexing word @@ -775,16 +775,22 @@ yylex(int cf) state = SBASE; dp = Xstring(ws, wp); - if ((c == '<' || c == '>' || c == '&') && state == SBASE && - ((c2 = Xlength(ws, wp)) == 0 || - (c2 == 2 && dp[0] == CHAR && ksh_isdigit(dp[1])))) { + if ((c == '<' || c == '>' || c == '&') && state == SBASE) { struct ioword *iop = (struct ioword *)alloc(sizeof (*iop), ATEMP); - if (c2 == 2) - iop->unit = dp[1] - '0'; - else + if (Xlength(ws, wp) == 0) iop->unit = c == '<' ? 0 : 1; + else for (iop->unit = 0, c2 = 0; c2 < Xlength(ws, wp); c2 += 2) { + if (dp[c2] != CHAR) + goto no_iop; + if (!ksh_isdigit(dp[c2 + 1])) + goto no_iop; + iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0'; + } + + if (iop->unit >= FDBASE) + goto no_iop; if (c == '&') { if ((c2 = getsc()) != '>') { diff --git a/main.c b/main.c index 994f7bb..45f0320 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,4 @@ +#include /* $OpenBSD: main.c,v 1.44 2008/07/05 07:25:18 djm Exp $ */ /* $OpenBSD: tty.c,v 1.9 2006/03/14 22:08:01 deraadt Exp $ */ /* $OpenBSD: io.c,v 1.22 2006/03/17 16:30:13 millert Exp $ */ @@ -13,7 +14,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.99 2008/07/08 22:28:26 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.100 2008/07/09 21:32:43 tg Exp $"); extern char **environ; @@ -1007,32 +1008,35 @@ check_fd(const char *name, int mode, const char **emsgp) { int fd, fl; - if (ksh_isdigit(name[0]) && !name[1]) { - if ((fl = fcntl(fd = name[0] - '0', F_GETFL, 0)) < 0) { - if (emsgp) - *emsgp = "bad file descriptor"; - return -1; - } - fl &= O_ACCMODE; - /* X_OK is a kludge to disable this check for dups (x<&1): - * historical shells never did this check (XXX don't know what - * posix has to say). - */ - if (!(mode & X_OK) && fl != O_RDWR && - (((mode & R_OK) && fl != O_RDONLY) || - ((mode & W_OK) && fl != O_WRONLY))) { - if (emsgp) - *emsgp = (fl == O_WRONLY) ? - "fd not open for reading" : - "fd not open for writing"; - return -1; - } - return fd; - } else if (name[0] == 'p' && !name[1]) - return coproc_getfd(mode, emsgp); - if (emsgp) - *emsgp = "illegal file descriptor name"; - return -1; + if (name[0] == 'p' && !name[1]) + return (coproc_getfd(mode, emsgp)); + for (fd = 0; ksh_isdigit(*name); ++name) + fd = (fd * 10) + *name - '0'; + if (*name || fd >= FDBASE) { + if (emsgp) + *emsgp = "illegal file descriptor name"; + return (-1); + } + if ((fl = fcntl(fd, F_GETFL, 0)) < 0) { + if (emsgp) + *emsgp = "bad file descriptor"; + return (-1); + } + fl &= O_ACCMODE; + /* X_OK is a kludge to disable this check for dups (x<&1): + * historical shells never did this check (XXX don't know what + * posix has to say). + */ + if (!(mode & X_OK) && fl != O_RDWR && ( + ((mode & R_OK) && fl != O_RDONLY) || + ((mode & W_OK) && fl != O_WRONLY))) { + if (emsgp) + *emsgp = (fl == O_WRONLY) ? + "fd not open for reading" : + "fd not open for writing"; + return (-1); + } + return (fd); } /* Called once from main */ diff --git a/mksh.1 b/mksh.1 index 4719d30..8f7e3d6 100644 --- a/mksh.1 +++ b/mksh.1 @@ -1,4 +1,4 @@ -.\" $MirOS: src/bin/mksh/mksh.1,v 1.130 2008/06/28 22:51:55 tg Exp $ +.\" $MirOS: src/bin/mksh/mksh.1,v 1.131 2008/07/09 21:32:43 tg Exp $ .\" $OpenBSD: ksh.1,v 1.122 2008/05/17 23:31:52 sobrado Exp $ .\"- .\" Try to make GNU groff and AT&T nroff more compatible @@ -30,7 +30,7 @@ .el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 .. .\"- -.Dd $Mdocdate: June 28 2008 $ +.Dd $Mdocdate: July 9 2008 $ .Dt MKSH 1 .Os MirBSD .Sh NAME @@ -2005,13 +2005,16 @@ This is called a here string. Standard input is duplicated from file descriptor .Ar fd . .Ar fd -can be a single digit, indicating the number of an existing file descriptor; +can be a number, indicating the number of an existing file descriptor; the letter .Ql p , indicating the file descriptor associated with the output of the current co-process; or the character .Ql \- , indicating standard input is to be closed. +Note that +.Ar fd +is limited to a single digit in most shell implementations. .It \*(Gt& Ar fd Same as .Ic \*(Lt& , @@ -2023,7 +2026,7 @@ This is a GNU .Nm bash extension supported by .Nm -which also supports the preceding explicit fd digit, for example, +which also supports the preceding explicit fd number, for example, .Ic 3&\*(Gt Ar file is the same as .Ic 3\*(Gt Ar file 2\*(Gt&3 @@ -2052,7 +2055,7 @@ extensions. In any of the above redirections, the file descriptor that is redirected (i.e. standard input or standard output) can be explicitly given by preceding the -redirection with a single digit. +redirection with a number (portably, only a single digit). Parameter, command, and arithmetic substitutions, tilde substitutions, and (if the shell is interactive) file name generation are all performed on the diff --git a/sh.h b/sh.h index 5028077..fd79a5d 100644 --- a/sh.h +++ b/sh.h @@ -100,9 +100,9 @@ #define __SCCSID(x) __IDSTRING(sccsid,x) #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.221 2008/07/06 22:41:09 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.222 2008/07/09 21:32:44 tg Exp $"); #endif -#define MKSH_VERSION "R34 2008/07/06" +#define MKSH_VERSION "R34 2008/07/09" #ifndef MKSH_INCLUDES_ONLY @@ -268,8 +268,13 @@ extern int __cdecl setegid(gid_t); /* Table flag type - needs > 16 and < 32 bits */ typedef int32_t Tflag; +#ifdef MKSH_SMALL #define NUFILE 32 /* Number of user-accessible files */ #define FDBASE 10 /* First file usable by Shell */ +#else +#define NUFILE 256 /* Number of user-accessible files */ +#define FDBASE 100 /* First file usable by Shell */ +#endif /* Make MAGIC a char that might be printed to make bugs more obvious, but * not a char that is used often. Also, can't use the high bit as it causes diff --git a/tree.c b/tree.c index ec7ced6..6f14dbb 100644 --- a/tree.c +++ b/tree.c @@ -2,7 +2,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.17 2008/05/17 18:47:02 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.18 2008/07/09 21:32:45 tg Exp $"); #define INDENT 4 @@ -197,7 +197,7 @@ pioact(struct shf *shf, int indent, struct ioword *iop) (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit : iop->unit + 1; if (iop->unit != expected) - tputc('0' + iop->unit, shf); + shf_fprintf(shf, "%d", iop->unit); switch (type) { case IOREAD: