Subject: Bourne shell bug fixes...
To: None <current-users@sun-lamp.cs.berkeley.edu>
From: Christos Zoulas <christos@deshaw.com>
List: current-users
Date: 06/13/1994 01:27:48
Here are three fixes for the Bourne shell... This should make scripts work
a bit better...

christos

1. The following script does not work because the shell does not know
   how to escape - in [-].

#!/bin/sh

cp /dev/null 'a-d'
cp /dev/null 'acd'
cp /dev/null 'axd'
cp /dev/null 'akd'
cp /dev/null "a'd"
cp /dev/null "a\d"

echo "expected : a-d acd         : " a[-c]d
echo "expected : a-d acd         : " a[\-c]d
echo "expected : a-d acd         : " a[c-]d
echo "expected : a-d acd         : " a[c'-']d
echo "expected : acd akd axd     : " a[c-x]d
echo "expected : a-d acd axd     : " a[c\-x]d
echo "expected : a'd acd         : " a[c"'"]d

echo "expected : a\d acd akd axd : " a[c\\-x]d
echo "expected : a-d a\d acd axd : " a[c\\\-x]d

FIX::

*** mksyntax.c.orig	Sun Jun 12 06:01:37 1994
--- mksyntax.c	Mon Jun 13 01:16:23 1994
***************
*** 208,220 ****
  	add("`", "CBQUOTE");
  	add("$", "CVAR");
  	add("}", "CENDVAR");
! 	add("!*?[=~:/", "CCTL");	/* ':/' for tilde - yuck */
  	print("dqsyntax");
  	init();
  	fputs("\n/* syntax table used when in single quotes */\n", cfile);
  	add("\n", "CNL");
  	add("'", "CENDQUOTE");
! 	add("!*?[=~:/", "CCTL");	/* ':/' for tilde - yuck */
  	print("sqsyntax");
  	init();
  	fputs("\n/* syntax table used when in arithmetic */\n", cfile);
--- 208,222 ----
  	add("`", "CBQUOTE");
  	add("$", "CVAR");
  	add("}", "CENDVAR");
! 	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
! 	add("!*?[=~:/-", "CCTL");
  	print("dqsyntax");
  	init();
  	fputs("\n/* syntax table used when in single quotes */\n", cfile);
  	add("\n", "CNL");
  	add("'", "CENDQUOTE");
! 	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
! 	add("!*?[=~:/-", "CCTL");
  	print("sqsyntax");
  	init();
  	fputs("\n/* syntax table used when in arithmetic */\n", cfile);


2. The shell does not have a -t option to execute a single command.

FIX::

*** options.h.orig	Sun Jun 12 06:01:41 1994
--- options.h	Mon Jun 13 01:16:30 1994
***************
*** 62,69 ****
  #define	aflag optlist[12].val
  #define	bflag optlist[13].val
  #define	uflag optlist[14].val
  
! #define NOPTS	15
  
  struct optent {
  	const char *name;
--- 62,70 ----
  #define	aflag optlist[12].val
  #define	bflag optlist[13].val
  #define	uflag optlist[14].val
+ #define	tflag optlist[15].val
  
! #define NOPTS	16
  
  struct optent {
  	const char *name;
***************
*** 88,93 ****
--- 89,95 ----
  	"allexport",	'a',	0,
  	"notify",	'b',	0,
  	"nounset",	'u',	0,
+ 	"onecommand",	't',	0,
  };
  #else
  extern struct optent optlist[NOPTS];
*** main.c.orig	Sun Jun 12 06:01:35 1994
--- main.c	Mon Jun 13 01:16:29 1994
***************
*** 221,226 ****
--- 221,228 ----
  			evaltree(n, 0);
  		}
  		popstackmark(&smark);
+ 		if (tflag)
+ 			return;
  	}
  	popstackmark(&smark);		/* unnecessary */
  }


3. The shell does not expand correctly >&$var
   z=2
   echo >&$z

   does not work.

FIX::
*** eval.c.orig	Sun Jun 12 06:01:30 1994
--- eval.c	Mon Jun 13 01:16:36 1994
***************
*** 434,446 ****
  	register union node *redir;
  
  	for (redir = n ; redir ; redir = redir->nfile.next) {
! 		if (redir->type == NFROM
! 		 || redir->type == NTO
! 		 || redir->type == NAPPEND) {
! 			struct arglist fn;
! 			fn.lastp = &fn.list;
  			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
  			redir->nfile.expfname = fn.list->text;
  		}
  	}
  }
--- 434,455 ----
  	register union node *redir;
  
  	for (redir = n ; redir ; redir = redir->nfile.next) {
! 		struct arglist fn;
! 		fn.lastp = &fn.list;
! 		switch (redir->type) {
! 		case NFROM:
! 		case NTO:
! 		case NAPPEND:
  			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
  			redir->nfile.expfname = fn.list->text;
+ 			break;
+ 		case NFROMFD:
+ 		case NTOFD:
+ 			if (redir->ndup.vname) {
+ 				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
+ 				fixredir(redir, fn.list->text, 1);
+ 			}
+ 			break;
  		}
  	}
  }
*** nodetypes.orig	Sun Jun 12 06:01:39 1994
--- nodetypes	Mon Jun 13 01:16:37 1994
***************
*** 131,136 ****
--- 131,137 ----
  	next	  nodeptr		# next redirection in list
  	fd	  int			# file descriptor being redirected
  	dupfd	  int			# file descriptor to duplicate
+ 	vname	  nodeptr		# file name if fd>&$var
  
  NHERE nhere			# fd<<\!
  NXHERE nhere			# fd<<!
*** parser.c.orig	Sun Jun 12 06:01:42 1994
--- parser.c	Mon Jun 13 01:16:37 1994
***************
*** 104,109 ****
--- 104,110 ----
  STATIC union node *pipeline __P((void));
  STATIC union node *command __P((void));
  STATIC union node *simplecmd __P((union node **, union node *));
+ STATIC union node *makename __P((void));
  STATIC void parsefname __P((void));
  STATIC void parseheredoc __P((void));
  STATIC int readtoken __P((void));
***************
*** 540,545 ****
--- 541,580 ----
  	return n;
  }
  
+ STATIC union node *
+ makename() {
+ 	union node *n;
+ 
+ 	n = (union node *)stalloc(sizeof (struct narg));
+ 	n->type = NARG;
+ 	n->narg.next = NULL;
+ 	n->narg.text = wordtext;
+ 	n->narg.backquote = backquotelist;
+ 	return n;
+ }
+ 
+ void fixredir(n, text, err)
+ 	union node *n;
+ 	const char *text;
+ 	int err;
+ 	{
+ 	TRACE(("Fix redir %s %d\n", text, err));
+ 	if (!err)
+ 		n->ndup.vname = NULL;
+ 
+ 	if (is_digit(text[0]) && text[1] == '\0')
+ 		n->ndup.dupfd = digit_val(text[0]);
+ 	else if (text[0] == '-' && text[1] == '\0')
+ 		n->ndup.dupfd = -1;
+ 	else {
+ 		
+ 		if (err)
+ 			synerror("Bad fd number");
+ 		else
+ 			n->ndup.vname = makename();
+ 	}
+ }
+ 
  
  STATIC void
  parsefname() {
***************
*** 571,593 ****
  			p->next = here;
  		}
  	} else if (n->type == NTOFD || n->type == NFROMFD) {
! 		if (is_digit(wordtext[0]))
! 			n->ndup.dupfd = digit_val(wordtext[0]);
! 		else if (wordtext[0] == '-')
! 			n->ndup.dupfd = -1;
! 		else
! 			goto bad;
! 		if (wordtext[1] != '\0') {
! bad:
! 			synerror("Bad fd number");
! 		}
  	} else {
! 		n->nfile.fname = (union node *)stalloc(sizeof (struct narg));
! 		n = n->nfile.fname;
! 		n->type = NARG;
! 		n->narg.next = NULL;
! 		n->narg.text = wordtext;
! 		n->narg.backquote = backquotelist;
  	}
  }
  
--- 606,614 ----
  			p->next = here;
  		}
  	} else if (n->type == NTOFD || n->type == NFROMFD) {
! 		fixredir(n, wordtext, 0);
  	} else {
! 		n->nfile.fname = makename();
  	}
  }
  
*** parser.h.orig	Sun Jun 12 06:01:43 1994
--- parser.h	Mon Jun 13 01:16:38 1994
***************
*** 74,81 ****
--- 74,83 ----
  union node *parsecmd(int);
  int goodname(char *);
  char *getprompt(void *);
+ void fixredir(union node *, const char *, int);
  #else
  union node *parsecmd();
  int goodname();
  char *getprompt();
+ void fixredir();
  #endif

------------------------------------------------------------------------------