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
------------------------------------------------------------------------------