svn commit: trunk/busybox/shell

vda at busybox.net vda at busybox.net
Sun Oct 5 18:39:32 UTC 2008


Author: vda
Date: 2008-10-05 11:39:31 -0700 (Sun, 05 Oct 2008)
New Revision: 23584

Log:
ash: implement ">&file" bashism. ~100 bytes.



Modified:
   trunk/busybox/shell/ash.c


Changeset:
Modified: trunk/busybox/shell/ash.c
===================================================================
--- trunk/busybox/shell/ash.c	2008-10-04 16:40:17 UTC (rev 23583)
+++ trunk/busybox/shell/ash.c	2008-10-05 18:39:31 UTC (rev 23584)
@@ -8,7 +8,6 @@
  * Copyright (c) 1997-2005 Herbert Xu <herbert at gondor.apana.org.au>
  * was re-ported from NetBSD and debianized.
  *
- *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
  *
@@ -28,7 +27,6 @@
  * used in busybox and size optimizations,
  * rewrote arith (see notes to this), added locale support,
  * rewrote dynamic variables.
- *
  */
 
 /*
@@ -247,8 +245,17 @@
 } while (0)
 
 
+/* ============ Utility functions */
+static int isdigit_str9(const char *str)
+{
+	int maxlen = 9 + 1; /* max 9 digits: 999999999 */
+	while (--maxlen && isdigit(*str))
+		str++;
+	return (*str == '\0');
+}
+
+
 /* ============ Interrupts / exceptions */
-
 /*
  * These macros allow the user to suspend the handling of interrupt signals
  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
@@ -500,32 +507,35 @@
 	CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
 };
 
-#define NCMD 0
-#define NPIPE 1
-#define NREDIR 2
-#define NBACKGND 3
+#define NCMD      0
+#define NPIPE     1
+#define NREDIR    2
+#define NBACKGND  3
 #define NSUBSHELL 4
-#define NAND 5
-#define NOR 6
-#define NSEMI 7
-#define NIF 8
-#define NWHILE 9
-#define NUNTIL 10
-#define NFOR 11
-#define NCASE 12
-#define NCLIST 13
-#define NDEFUN 14
-#define NARG 15
-#define NTO 16
-#define NCLOBBER 17
-#define NFROM 18
-#define NFROMTO 19
-#define NAPPEND 20
-#define NTOFD 21
-#define NFROMFD 22
-#define NHERE 23
-#define NXHERE 24
-#define NNOT 25
+#define NAND      5
+#define NOR       6
+#define NSEMI     7
+#define NIF       8
+#define NWHILE    9
+#define NUNTIL   10
+#define NFOR     11
+#define NCASE    12
+#define NCLIST   13
+#define NDEFUN   14
+#define NARG     15
+#define NTO      16
+#if ENABLE_ASH_BASH_COMPAT
+#define NTO2     17
+#endif
+#define NCLOBBER 18
+#define NFROM    19
+#define NFROMTO  20
+#define NAPPEND  21
+#define NTOFD    22
+#define NFROMFD  23
+#define NHERE    24
+#define NXHERE   25
+#define NNOT     26
 
 union node;
 
@@ -588,20 +598,26 @@
 	struct nodelist *backquote;
 };
 
+/* nfile and ndup layout must match!
+ * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
+ * that it is actually NTO2 (>&file), and change its type.
+ */
 struct nfile {
 	smallint type;
 	union node *next;
 	int fd;
+	int _unused_dupfd;
 	union node *fname;
 	char *expfname;
 };
 
 struct ndup {
 	smallint type;
-	union node *next; /* must match nfile's layout */
-	int fd; /* must match nfile's layout */
+	union node *next;
+	int fd;
 	int dupfd;
 	union node *vname;
+	char *_unused_expfname;
 };
 
 struct nhere {
@@ -904,8 +920,11 @@
 		case NTO:      s = ">>"+1; dftfd = 1; break;
 		case NCLOBBER: s = ">|"; dftfd = 1; break;
 		case NAPPEND:  s = ">>"; dftfd = 1; break;
+#if ENABLE_ASH_BASH_COMPAT
+		case NTO2:
+#endif
 		case NTOFD:    s = ">&"; dftfd = 1; break;
-		case NFROM:    s = "<";  break;
+		case NFROM:    s = "<"; break;
 		case NFROMFD:  s = "<&"; break;
 		case NFROMTO:  s = "<>"; break;
 		default:       s = "*error*"; break;
@@ -4408,6 +4427,9 @@
 	case NAPPEND:
 		p = ">>";
 		goto redir;
+#if ENABLE_ASH_BASH_COMPAT
+	case NTO2:
+#endif
 	case NTOFD:
 		p = ">&";
 		goto redir;
@@ -4797,6 +4819,9 @@
 			goto ecreate;
 		break;
 	case NTO:
+#if ENABLE_ASH_BASH_COMPAT
+	case NTO2:
+#endif
 		/* Take care of noclobber mode. */
 		if (Cflag) {
 			fname = redir->nfile.expfname;
@@ -4959,6 +4984,10 @@
 		union node *tmp = redir;
 		do {
 			sv_pos++;
+#if ENABLE_ASH_BASH_COMPAT
+			if (redir->nfile.type == NTO2)
+				sv_pos++;
+#endif
 			tmp = tmp->nfile.next;
 		} while (tmp);
 		sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
@@ -4997,6 +5026,9 @@
 				continue;
 			}
 		}
+#if ENABLE_ASH_BASH_COMPAT
+ redirect_more:
+#endif
 		if (need_to_remember(sv, fd)) {
 			/* Copy old descriptor */
 			i = fcntl(fd, F_DUPFD, 10);
@@ -5039,8 +5071,19 @@
 			}
 		} else if (fd != newfd) { /* move newfd to fd */
 			copyfd(newfd, fd | COPYFD_EXACT);
-			close(newfd);
+#if ENABLE_ASH_BASH_COMPAT
+			if (!(redir->nfile.type == NTO2 && fd == 2))
+#endif
+				close(newfd);
 		}
+#if ENABLE_ASH_BASH_COMPAT
+		if (redir->nfile.type == NTO2 && fd == 1) {
+			/* We already redirected it to fd 1, now copy it to 2 */
+			newfd = 1;
+			fd = 2;
+			goto redirect_more;
+		}
+#endif
 	} while ((redir = redir->nfile.next) != NULL);
 
 	INT_ON;
@@ -7641,6 +7684,9 @@
 		calcsize(n->narg.next);
 		break;
 	case NTO:
+#if ENABLE_ASH_BASH_COMPAT
+	case NTO2:
+#endif
 	case NCLOBBER:
 	case NFROM:
 	case NFROMTO:
@@ -7754,6 +7800,9 @@
 		new->narg.next = copynode(n->narg.next);
 		break;
 	case NTO:
+#if ENABLE_ASH_BASH_COMPAT
+	case NTO2:
+#endif
 	case NCLOBBER:
 	case NFROM:
 	case NFROMTO:
@@ -8175,17 +8224,33 @@
 		case NFROMTO:
 		case NFROM:
 		case NTO:
+#if ENABLE_ASH_BASH_COMPAT
+		case NTO2:
+#endif
 		case NCLOBBER:
 		case NAPPEND:
 			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+#if ENABLE_ASH_BASH_COMPAT
+ store_expfname:
+#endif
 			redir->nfile.expfname = fn.list->text;
 			break;
 		case NFROMFD:
-		case NTOFD:
+		case NTOFD: /* >& */
 			if (redir->ndup.vname) {
 				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
 				if (fn.list == NULL)
 					ash_msg_and_raise_error("redir error");
+#if ENABLE_ASH_BASH_COMPAT
+//FIXME: we used expandarg with different args!
+				if (!isdigit_str9(fn.list->text)) {
+					/* >&file, not >&fd */
+					if (redir->nfile.fd != 1) /* 123>&file - BAD */
+						ash_msg_and_raise_error("redir error");
+					redir->type = NTO2;
+					goto store_expfname;
+				}
+#endif
 				fixredir(redir, fn.list->text, 1);
 			}
 			break;
@@ -10126,7 +10191,7 @@
 		n->ndup.dupfd = -1;
 	else {
 		if (err)
-			raise_error_syntax("Bad fd number");
+			raise_error_syntax("bad fd number");
 		n->ndup.vname = makename();
 	}
 }
@@ -10169,7 +10234,7 @@
 			n->type = NXHERE;
 		TRACE(("Here document %d\n", n->type));
 		if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
-			raise_error_syntax("Illegal eof marker for << redirection");
+			raise_error_syntax("illegal eof marker for << redirection");
 		rmescapes(wordtext);
 		here->eofmark = wordtext;
 		here->next = NULL;
@@ -10261,7 +10326,7 @@
 				if (!goodname(name)
 				 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
 				) {
-					raise_error_syntax("Bad function name");
+					raise_error_syntax("bad function name");
 				}
 				n->type = NDEFUN;
 				checkkwd = CHKNL | CHKKWD | CHKALIAS;
@@ -10346,7 +10411,7 @@
 	}
 	case TFOR:
 		if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
-			raise_error_syntax("Bad for loop variable");
+			raise_error_syntax("bad for loop variable");
 		n1 = stzalloc(sizeof(struct nfor));
 		n1->type = NFOR;
 		n1->nfor.var = wordtext;
@@ -10748,25 +10813,21 @@
  endword:
 #if ENABLE_ASH_MATH_SUPPORT
 	if (syntax == ARISYNTAX)
-		raise_error_syntax("Missing '))'");
+		raise_error_syntax("missing '))'");
 #endif
 	if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
-		raise_error_syntax("Unterminated quoted string");
+		raise_error_syntax("unterminated quoted string");
 	if (varnest != 0) {
 		startlinno = plinno;
 		/* { */
-		raise_error_syntax("Missing '}'");
+		raise_error_syntax("missing '}'");
 	}
 	USTPUTC('\0', out);
 	len = out - (char *)stackblock();
 	out = stackblock();
 	if (eofmark == NULL) {
 		if ((c == '>' || c == '<') && quotef == 0) {
-			int maxlen = 9 + 1; /* max 9 digit fd#: 999999999 */
-			char *np = out;
-			while (--maxlen && isdigit(*np))
-				np++;
-			if (*np == '\0') {
+			if (isdigit_str9(out)) {
 				PARSEREDIR(); /* passed as params: out, c */
 				lasttoken = TREDIR;
 				return lasttoken;
@@ -10841,6 +10902,7 @@
 			np->type = NCLOBBER;
 		else if (c == '&')
 			np->type = NTOFD;
+			/* it also can be NTO2 (>&file), but we can't figure it out yet */
 		else {
 			np->type = NTO;
 			pungetc();
@@ -10954,8 +11016,10 @@
 		} else if (is_special(c)) {
 			USTPUTC(c, out);
 			c = pgetc();
-		} else
- badsub:		raise_error_syntax("Bad substitution");
+		} else {
+ badsub:
+			raise_error_syntax("bad substitution");
+		}
 
 		STPUTC('=', out);
 		flags = 0;




More information about the busybox-cvs mailing list