Subject: /bin/sh fixes to make printf a builtin and 'fix' echo
To: <>
From: David Laight <david@l8s.co.uk>
List: current-users
Date: 06/11/2002 14:08:57
--IJpNTDwzlM2Ie8A6
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
>
> >(fixed a buffer overflow problem in printf at the same time,
> >printf "%1111111111111111111111111111111111111111111111111111111111111111111111111111111111d\n" 42
> >generates a core dump.)
>
> That's cool that it is fixed.
OK fixes are attached, summary/change comments:
bin/sh/bltin
Makefile: Make printf builtin
builtins.def: Make printf builtin
mkinit.c: Fix delta 1.14
mksyntax.c: Use bounds of CTL chars instead of naming them all
parser.h: Add defns for bounds of CTL chars
error.c: Add warnx (for builtin printf)
error.h: Add warnx (for builtin printf)
options.c: Generic code for mutually exclusive options,
Support named options with no letter equivalent.
options.h: Make 'V' and 'E' (vi and emacs) mutually exclusive,
Add new options '-o posix' and '-o SuS'
expand.c: Ignore options that have no single letter form when
expanding $-
bin/sh/bltin
bltin.h: #undef stdio defs before redefining them,
Don't define a (broken) macro version of warnx
echo.c: Make output depend on state of '-o posix' and
'-o SuS' flags
usr.bin/printf
printf.c: Make compile as a builtin for netbsd sh.
Stop core dump processing (very) long integer
format strings.
David
--
David Laight: david@l8s.co.uk
--IJpNTDwzlM2Ie8A6
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=sh_diffs
Index: Makefile
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/Makefile,v
retrieving revision 1.57
diff -u -u -r1.57 Makefile
--- Makefile 2002/05/15 20:45:17 1.57
+++ Makefile 2002/06/11 12:36:16
@@ -8,7 +8,7 @@
SHSRCS= alias.c cd.c echo.c error.c eval.c exec.c expand.c \
histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
mystring.c options.c parser.c redir.c show.c trap.c output.c var.c \
- test.c
+ test.c printf.c
GENSRCS=arith.c arith.h arith_lex.c builtins.c builtins.h init.c nodes.c \
nodes.h syntax.c syntax.h token.h
SRCS= ${SHSRCS} ${GENSRCS}
@@ -25,7 +25,7 @@
CPPFLAGS+=-DSMALL
.endif
-.PATH: ${.CURDIR}/bltin ${.CURDIR}/../test
+.PATH: ${.CURDIR}/bltin ${.CURDIR}/../test ${.CURDIR}/../../usr.bin/printf
CLEANFILES+= mkinit mknodes mksyntax
CLEANFILES+= ${GENSRCS} y.tab.h
Index: mkinit.c
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/mkinit.c,v
retrieving revision 1.20
diff -u -u -r1.20 mkinit.c
--- mkinit.c 2000/07/18 19:13:20 1.20
+++ mkinit.c 2002/06/11 12:36:40
@@ -218,8 +218,6 @@
doinclude(line);
if (line[0] == 'M' && match("MKINIT", line))
dodecl(line, fp);
- if (line[0] == '#' && gooddefine(line))
- addstr(line, &defines);
if (line[0] == '#' && gooddefine(line)) {
char *cp;
char line2[1024];
Index: builtins.def
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/builtins.def,v
retrieving revision 1.15
diff -u -u -r1.15 builtins.def
--- builtins.def 2000/04/09 23:27:03 1.15
+++ builtins.def 2002/06/11 12:36:41
@@ -73,7 +73,7 @@
#linecmd line
localcmd local
#nlechocmd nlecho
-#printfcmd printf
+printfcmd printf
pwdcmd pwd
readcmd read
returncmd return
Index: mksyntax.c
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/mksyntax.c,v
retrieving revision 1.25
diff -u -u -r1.25 mksyntax.c
--- mksyntax.c 2002/05/31 16:18:48 1.25
+++ mksyntax.c 2002/06/11 12:36:43
@@ -296,26 +296,15 @@
static void
init()
{
+ int ctl;
+
filltable("CWORD");
syntax[0] = "CEOF";
+ for (ctl = CTL_FIRST; ctl <= CTL_LAST; ctl++ )
#ifdef TARGET_CHAR
- syntax[base + (TARGET_CHAR)CTLESC] = "CCTL";
- syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL";
- syntax[base + (TARGET_CHAR)CTLENDVAR] = "CCTL";
- syntax[base + (TARGET_CHAR)CTLBACKQ] = "CCTL";
- syntax[base + (TARGET_CHAR)CTLBACKQ + (TARGET_CHAR)CTLQUOTE] = "CCTL";
- syntax[base + (TARGET_CHAR)CTLARI] = "CCTL";
- syntax[base + (TARGET_CHAR)CTLENDARI] = "CCTL";
- syntax[base + (TARGET_CHAR)CTLQUOTEMARK] = "CCTL";
+ syntax[base + (TARGET_CHAR)ctl ] = "CCTL";
#else
- syntax[base + CTLESC] = "CCTL";
- syntax[base + CTLVAR] = "CCTL";
- syntax[base + CTLENDVAR] = "CCTL";
- syntax[base + CTLBACKQ] = "CCTL";
- syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
- syntax[base + CTLARI] = "CCTL";
- syntax[base + CTLENDARI] = "CCTL";
- syntax[base + CTLQUOTEMARK] = "CCTL";
+ syntax[base + ctl] = "CCTL";
#endif /* TARGET_CHAR */
}
@@ -374,9 +363,9 @@
static char *macro[] = {
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
- "#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
- "#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
- "#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
+ "#define is_alpha(c)\t((c) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char) (c)))",
+ "#define is_name(c)\t((c) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char) (c))))",
+ "#define is_in_name(c)\t((c) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char) (c))))",
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
NULL
};
Index: parser.h
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/parser.h,v
retrieving revision 1.14
diff -u -u -r1.14 parser.h
--- parser.h 2000/07/27 04:09:28 1.14
+++ parser.h 2002/06/11 12:36:44
@@ -39,15 +39,17 @@
*/
/* control characters in argument strings */
-#define CTLESC '\201'
-#define CTLVAR '\202'
+#define CTL_FIRST '\201' /* first 'special' character */
+#define CTLESC '\201' /* escape next character */
+#define CTLVAR '\202' /* variable defn */
#define CTLENDVAR '\203'
#define CTLBACKQ '\204'
#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
/* CTLBACKQ | CTLQUOTE == '\205' */
-#define CTLARI '\206'
+#define CTLARI '\206' /* arithmetic expression */
#define CTLENDARI '\207'
#define CTLQUOTEMARK '\210'
+#define CTL_LAST '\210' /* last 'special' character */
/* variable substitution byte (follows CTLVAR) */
#define VSTYPE 0x0f /* type of variable substitution */
Index: error.c
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/error.c,v
retrieving revision 1.25
diff -u -u -r1.25 error.c
--- error.c 2002/05/25 23:09:06 1.25
+++ error.c 2002/06/11 12:42:29
@@ -123,9 +123,17 @@
/* NOTREACHED */
}
+static void
+exvwarning( const char *msg, va_list ap )
+{
+ if (commandname)
+ outfmt(&errout, "%s: ", commandname);
+ doformat(&errout, msg, ap);
+ out2c('\n');
+}
/*
- * Exverror is called to raise the error exception. If the first argument
+ * Exverror is called to raise the error exception. If the second argument
* is not NULL then error prints an error message using printf style
* formatting. It then raises the error exception.
*/
@@ -144,12 +152,9 @@
else
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
#endif
- if (msg) {
- if (commandname)
- outfmt(&errout, "%s: ", commandname);
- doformat(&errout, msg, ap);
- out2c('\n');
- }
+ if (msg)
+ exvwarning( msg, ap );
+
flushall();
exraise(cond);
/* NOTREACHED */
@@ -176,6 +181,16 @@
va_start(ap, msg);
exverror(cond, msg, ap);
/* NOTREACHED */
+ va_end(ap);
+}
+
+void
+warnx(const char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ exvwarning( msg, ap);
va_end(ap);
}
Index: error.h
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/error.h,v
retrieving revision 1.14
diff -u -u -r1.14 error.h
--- error.h 2001/02/04 19:52:06 1.14
+++ error.h 2002/06/11 12:36:46
@@ -93,6 +93,7 @@
void onint __P((void));
void error __P((const char *, ...)) __attribute__((__noreturn__));
void exerror __P((int, const char *, ...)) __attribute__((__noreturn__));
+void warnx __P((const char *, ...));
const char *errmsg __P((int, int));
Index: options.c
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/options.c,v
retrieving revision 1.31
diff -u -u -r1.31 options.c
--- options.c 2001/02/26 13:06:43 1.31
+++ options.c 2002/06/11 12:36:48
@@ -200,6 +200,21 @@
}
}
+static void
+set_opt_val( int i, int val )
+{
+ int j;
+ int flag;
+
+ if (val && (flag = optlist[i].opt_set)) {
+ /* some options (eg vi/emacs) are mutually exclusive */
+ for (j = 0; j < NOPTS; j++)
+ if (optlist[j].opt_set == flag)
+ optlist[j].val = 0;
+ }
+ optlist[i].val = val;
+}
+
STATIC void
minus_o(name, val)
char *name;
@@ -215,7 +230,7 @@
} else {
for (i = 0; i < NOPTS; i++)
if (equal(name, optlist[i].name)) {
- setoption(optlist[i].letter, val);
+ set_opt_val(i, val);
return;
}
error("Illegal option -o %s", name);
@@ -227,19 +242,12 @@
setoption(flag, val)
char flag;
int val;
- {
+{
int i;
for (i = 0; i < NOPTS; i++)
if (optlist[i].letter == flag) {
- optlist[i].val = val;
- if (val) {
- /* #%$ hack for ksh semantics */
- if (flag == 'V')
- Eflag = 0;
- else if (flag == 'E')
- Vflag = 0;
- }
+ set_opt_val( i, val );
return;
}
error("Illegal option -%c", flag);
@@ -269,7 +277,7 @@
void
setparam(argv)
char **argv;
- {
+{
char **newparam;
char **ap;
int nparam;
@@ -295,7 +303,7 @@
void
freeparam(param)
volatile struct shparam *param;
- {
+{
char **ap;
if (param->malloc) {
@@ -514,7 +522,7 @@
int
nextopt(optstring)
const char *optstring;
- {
+{
char *p;
const char *q;
char c;
Index: options.h
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/options.h,v
retrieving revision 1.14
diff -u -u -r1.14 options.h
--- options.h 2001/02/04 19:52:06 1.14
+++ options.h 2002/06/11 12:36:49
@@ -65,13 +65,16 @@
#define bflag optlist[13].val
#define uflag optlist[14].val
#define qflag optlist[15].val
+#define posix_flag optlist[16].val /* posix variants */
+#define SuS_flag optlist[17].val /* Single Unix Spec variants */
-#define NOPTS 16
+#define NOPTS 18
struct optent {
- const char *name;
- const char letter;
- char val;
+ const char *name; /* for set -o <name> */
+ const char letter; /* set [+/-]<letter> */
+ char val; /* value of <letter>flag */
+ const char opt_set; /* only one of each set may be non zero */
};
#ifdef DEFINE_OPTIONS
@@ -85,13 +88,15 @@
{ "stdin", 's', 0 },
{ "xtrace", 'x', 0 },
{ "verbose", 'v', 0 },
- { "vi", 'V', 0 },
- { "emacs", 'E', 0 },
+ { "vi", 'V', 0, 'V' },
+ { "emacs", 'E', 0, 'V' },
{ "noclobber", 'C', 0 },
{ "allexport", 'a', 0 },
{ "notify", 'b', 0 },
{ "nounset", 'u', 0 },
{ "quietprofile", 'q', 0 },
+ { "posix", 0, 0, 1 },
+ { "SuS", 0, 0, 1 },
};
#else
extern struct optent optlist[NOPTS];
Index: expand.c
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/expand.c,v
retrieving revision 1.53
diff -u -u -r1.53 expand.c
--- expand.c 2002/05/15 14:59:21 1.53
+++ expand.c 2002/06/11 12:36:54
@@ -883,7 +883,7 @@
break;
case '-':
for (i = 0 ; i < NOPTS ; i++) {
- if (optlist[i].val)
+ if (optlist[i].val && optlist[i].letter)
STPUTC(optlist[i].letter, expdest);
}
break;
Index: bltin.h
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/bltin/bltin.h,v
retrieving revision 1.9
diff -u -u -r1.9 bltin.h
--- bltin.h 1997/07/04 21:02:29 1.9
+++ bltin.h 2002/06/11 12:37:22
@@ -48,6 +48,10 @@
#include "../mystring.h"
#ifdef SHELL
#include "../output.h"
+#undef stdout
+#undef stderr
+#undef putc
+#undef putchar
#define stdout out1
#define stderr out2
#define printf out1fmt
@@ -57,11 +61,6 @@
#define fputs outstr
#define fflush flushout
#define INITARGS(argv)
-#define warnx(a, b, c) { \
- char buf[64]; \
- (void)snprintf(buf, sizeof(buf), a, b, c); \
- error("%s", buf); \
-}
#else
#undef NULL
@@ -71,7 +70,8 @@
#endif
pointer stalloc __P((int));
-void error __P((char *, ...));
+void error __P((const char *, ...));
+void warnx __P((const char *, ...));
int echocmd __P((int, char **));
Index: echo.c
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/bltin/echo.c,v
retrieving revision 1.8
diff -u -u -r1.8 echo.c
--- echo.c 1996/11/02 18:26:06 1.8
+++ echo.c 2002/06/11 12:37:23
@@ -40,13 +40,24 @@
/*
* Echo command.
+ *
+ * echo is steeped in tradition - several of them!
+ * netbsd has supported 'echo [-n | -e] args' in spite of -e not being
+ * documented anywhere.
+ * Posix requires that -n be supported, output from strings containing
+ * \ is implementation defined
+ * The Single Unix Spec requires that \ escapes be treated (as below)
+ * but that -n not be treated as an argument.
+ * (ksh supports 'echo [-eEn] args')
*/
#define main echocmd
#include "bltin.h"
+#include "options.h"
-/* #define eflag 1 */
+#undef nflag
+#undef eflag
int
main(argc, argv) char **argv; {
@@ -55,28 +66,31 @@
register char c;
int count;
int nflag = 0;
-#ifndef eflag
int eflag = 0;
-#endif
ap = argv;
if (argc)
ap++;
- if ((p = *ap) != NULL) {
- if (equal(p, "-n")) {
- nflag++;
- ap++;
- } else if (equal(p, "-e")) {
-#ifndef eflag
- eflag++;
-#endif
- ap++;
- }
+
+ if (SuS_flag) {
+ eflag = 1;
+ } else {
+ if ((p = *ap) != NULL) {
+ if (equal(p, "-n")) {
+ nflag = 1;
+ ap++;
+ } else if (!posix_flag && equal(p, "-e")) {
+ eflag = 1;
+ ap++;
+ }
+ }
}
+
while ((p = *ap++) != NULL) {
while ((c = *p++) != '\0') {
if (c == '\\' && eflag) {
switch (*p++) {
+ case 'a': c = '\a'; break;
case 'b': c = '\b'; break;
case 'c': return 0; /* exit */
case 'f': c = '\f'; break;
Index: printf.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/printf/printf.c,v
retrieving revision 1.22
diff -u -r1.22 printf.c
--- printf.c 2001/05/05 17:29:39 1.22
+++ printf.c 2002/06/11 12:49:22
@@ -72,7 +72,6 @@
static intmax_t getintmax __P((void));
static uintmax_t getuintmax __P ((void));
static char *getstr __P((void));
-static char *mklong __P((const char *, int));
static void check_conversion __P((const char *, const char *));
static void usage __P((void));
@@ -80,9 +79,7 @@
static char **gargv;
#ifdef BUILTIN
-int progprintf __P((int, char **));
-#else
-int main __P((int, char **));
+#define main progprintf
#endif
#define isodigit(c) ((c) >= '0' && (c) <= '7')
@@ -92,38 +89,6 @@
#ifdef SHELL
#define main printfcmd
#include "../../bin/sh/bltin/bltin.h"
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <vararg.h>
-#endif
-
-static void warnx __P((const char *fmt, ...));
-
-static void
-#ifdef __STDC__
-warnx(const char *fmt, ...)
-#else
-warnx(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
-
- char buf[64];
- va_list ap;
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- vsprintf(buf, fmt, ap);
- va_end(ap);
-
- error(buf);
-}
#endif /* SHELL */
#define PF(f, func) { \
@@ -138,19 +103,13 @@
(void)printf(f, func); \
}
-int
-#ifdef BUILTIN
-progprintf(argc, argv)
-#else
-main(argc, argv)
-#endif
- int argc;
- char *argv[];
+int main __P((int, char **));
+int main(int argc, char *argv[])
{
char *fmt, *start;
int fieldwidth, precision;
- char convch, nextch;
- char *format;
+ char convch, nextch, next2ch;
+ static char *format = 0;
int ch;
#if !defined(SHELL) && !defined(BUILTIN)
@@ -173,7 +132,13 @@
return (1);
}
- format = *argv;
+ /* we might need to overwrite the byte after the null.... */
+ if (format)
+ free( format );
+ format = malloc( strlen( *argv ) + 2 );
+ if (!format)
+ return 2;
+ strcpy( format, *argv );
gargv = ++argv;
#define SKIP1 "#-+ 0"
@@ -223,6 +188,7 @@
convch = *fmt;
nextch = *(fmt + 1);
+ next2ch = *(fmt + 2);
*(fmt + 1) = '\0';
switch(convch) {
case 'c': {
@@ -237,18 +203,24 @@
}
case 'd':
case 'i': {
- char *f = mklong(start, convch);
intmax_t p = getintmax();
- PF(f, p);
+ fmt[0] = 'j';
+ fmt[1] = convch;
+ fmt[2] = 0;
+ PF(start, p);
+ fmt[0] = convch;
break;
}
case 'o':
case 'u':
case 'x':
case 'X': {
- char *f = mklong(start, convch);
uintmax_t p = getuintmax();
- PF(f, p);
+ fmt[0] = 'j';
+ fmt[1] = convch;
+ fmt[2] = 0;
+ PF(start, p);
+ fmt[0] = convch;
break;
}
case 'e':
@@ -265,6 +237,7 @@
return(1);
}
*(fmt + 1) = nextch;
+ *(fmt + 2) = next2ch;
break;
case '\\':
@@ -422,22 +395,6 @@
}
return 1;
-}
-
-static char *
-mklong(str, ch)
- const char *str;
- char ch;
-{
- static char copy[64];
- size_t len;
-
- len = strlen(str) + 2;
- (void)memmove(copy, str, len - 3);
- copy[len - 3] = 'j';
- copy[len - 2] = ch;
- copy[len - 1] = '\0';
- return (copy);
}
static int
--IJpNTDwzlM2Ie8A6--