Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 15319
Collapse All | Expand All

(-)bin_NetBSD-1.6release.orig/src/bin/sh/alias.c (-93 / +73 lines)
Lines 60-67 Link Here
60
struct alias *atab[ATABSIZE];
60
struct alias *atab[ATABSIZE];
61
61
62
STATIC void setalias __P((char *, char *));
62
STATIC void setalias __P((char *, char *));
63
STATIC int unalias __P((char *));
63
STATIC struct alias **hashalias __P((const char *));
64
STATIC struct alias **hashalias __P((char *));
64
STATIC struct alias *freealias __P((struct alias *));
65
STATIC struct alias **__lookupalias __P((const char *));
65
66
66
STATIC
67
STATIC
67
void
68
void
Lines 70-179 Link Here
70
{
71
{
71
	struct alias *ap, **app;
72
	struct alias *ap, **app;
72
73
73
	app = hashalias(name);
74
	app = __lookupalias(name);
74
	for (ap = *app; ap; ap = ap->next) {
75
	ap = *app;
75
		if (equal(name, ap->name)) {
76
			INTOFF;
76
			INTOFF;
77
	if (ap) {
78
		if (!(ap->flag & ALIASINUSE)) {
77
			ckfree(ap->val);
79
			ckfree(ap->val);
78
			ap->val	= savestr(val);
79
			INTON;
80
			return;
81
		}
82
	}
80
	}
81
		ap->val	= savestr(val);
82
		ap->flag &= ~ALIASDEAD;
83
	} else {
83
	/* not found */
84
	/* not found */
84
	INTOFF;
85
	ap = ckmalloc(sizeof (struct alias));
85
	ap = ckmalloc(sizeof (struct alias));
86
	ap->name = savestr(name);
86
	ap->name = savestr(name);
87
	/*
88
	 * XXX - HACK: in order that the parser will not finish reading the
89
	 * alias value off the input before processing the next alias, we
90
	 * dummy up an extra space at the end of the alias.  This is a crock
91
	 * and should be re-thought.  The idea (if you feel inclined to help)
92
	 * is to avoid alias recursions.  The mechanism used is: when
93
	 * expanding an alias, the value of the alias is pushed back on the
94
	 * input as a string and a pointer to the alias is stored with the
95
	 * string.  The alias is marked as being in use.  When the input
96
	 * routine finishes reading the string, it markes the alias not
97
	 * in use.  The problem is synchronization with the parser.  Since
98
	 * it reads ahead, the alias is marked not in use before the
99
	 * resulting token(s) is next checked for further alias sub.  The
100
	 * H A C K is that we add a little fluff after the alias value
101
	 * so that the string will not be exhausted.  This is a good
102
	 * idea ------- ***NOT***
103
	 */
104
#ifdef notyet
105
	ap->val = savestr(val);
87
	ap->val = savestr(val);
106
#else /* hack */
88
		ap->flag = 0;
107
	{
89
		ap->next = 0;
108
	int len = strlen(val);
109
	ap->val = ckmalloc(len + 2);
110
	memcpy(ap->val, val, len);
111
	ap->val[len] = ' ';	/* fluff */
112
	ap->val[len+1] = '\0';
113
	}
114
#endif
115
	ap->next = *app;
116
	*app = ap;
90
	*app = ap;
91
	}
117
	INTON;
92
	INTON;
118
}
93
}
119
94
120
STATIC int
95
int
121
unalias(name)
96
unalias(name)
122
	char *name;
97
	char *name;
123
	{
98
	{
124
	struct alias *ap, **app;
99
	struct alias **app;
125
100
126
	app = hashalias(name);
101
	app = __lookupalias(name);
127
102
128
	for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
103
	if (*app) {
129
		if (equal(name, ap->name)) {
130
			/*
131
			 * if the alias is currently in use (i.e. its
132
			 * buffer is being used by the input routine) we
133
			 * just null out the name instead of freeing it.
134
			 * We could clear it out later, but this situation
135
			 * is so rare that it hardly seems worth it.
136
			 */
137
			if (ap->flag & ALIASINUSE)
138
				*ap->name = '\0';
139
			else {
140
				INTOFF;
104
				INTOFF;
141
				*app = ap->next;
105
		*app = freealias(*app);
142
				ckfree(ap->name);
143
				ckfree(ap->val);
144
				ckfree(ap);
145
				INTON;
106
				INTON;
146
			}
147
			return (0);
107
			return (0);
148
		}
108
		}
149
	}
150
109
151
	return (1);
110
	return (1);
152
}
111
}
153
112
154
#ifdef mkinit
155
MKINIT void rmaliases __P((void));
156
157
SHELLPROC {
158
	rmaliases();
159
}
160
#endif
161
162
void
113
void
163
rmaliases() {
114
rmaliases() {
164
	struct alias *ap, *tmp;
115
	struct alias *ap, **app;
165
	int i;
116
	int i;
166
117
167
	INTOFF;
118
	INTOFF;
168
	for (i = 0; i < ATABSIZE; i++) {
119
	for (i = 0; i < ATABSIZE; i++) {
169
		ap = atab[i];
120
		app = &atab[i];
170
		atab[i] = NULL;
121
		for (ap = *app; ap; ap = *app) {
171
		while (ap) {
122
			*app = freealias(*app);
172
			ckfree(ap->name);
123
			if (ap == *app) {
173
			ckfree(ap->val);
124
				app = &ap->next;
174
			tmp = ap;
125
			}
175
			ap = ap->next;
176
			ckfree(tmp);
177
		}
126
		}
178
	}
127
	}
179
	INTON;
128
	INTON;
Lines 181-200 Link Here
181
130
182
struct alias *
131
struct alias *
183
lookupalias(name, check)
132
lookupalias(name, check)
184
	char *name;
133
	const char *name;
185
	int check;
134
	int check;
186
{
135
{
187
	struct alias *ap = *hashalias(name);
136
	struct alias *ap = *__lookupalias(name);
188
137
189
	for (; ap; ap = ap->next) {
138
	if (check && ap && (ap->flag & ALIASINUSE))
190
		if (equal(name, ap->name)) {
191
			if (check && (ap->flag & ALIASINUSE))
192
				return (NULL);
139
				return (NULL);
193
			return (ap);
140
			return (ap);
194
		}
195
	}
196
197
	return (NULL);
198
}
141
}
199
142
200
/*
143
/*
Lines 214-231 Link Here
214
157
215
		for (i = 0; i < ATABSIZE; i++)
158
		for (i = 0; i < ATABSIZE; i++)
216
			for (ap = atab[i]; ap; ap = ap->next) {
159
			for (ap = atab[i]; ap; ap = ap->next) {
217
				if (*ap->name != '\0')
160
				printalias(ap);
218
				    out1fmt("alias %s=%s\n", ap->name, ap->val);
219
			}
161
			}
220
		return (0);
162
		return (0);
221
	}
163
	}
222
	while ((n = *++argv) != NULL) {
164
	while ((n = *++argv) != NULL) {
223
		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
165
		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
224
			if ((ap = lookupalias(n, 0)) == NULL) {
166
			if ((ap = *__lookupalias(n)) == NULL) {
225
				outfmt(out2, "alias: %s not found\n", n);
167
				outfmt(out2, "%s: %s not found\n", "alias", n);
226
				ret = 1;
168
				ret = 1;
227
			} else
169
			} else
228
				out1fmt("alias %s=%s\n", n, ap->val);
170
				printalias(ap);
229
		}
171
		}
230
		else {
172
		else {
231
			*v++ = '\0';
173
			*v++ = '\0';
Lines 249-263 Link Here
249
			return (0);
191
			return (0);
250
		}
192
		}
251
	}
193
	}
252
	for (i = 0; *argptr; argptr++)
194
	for (i = 0; *argptr; argptr++) {
253
		i = unalias(*argptr);
195
		if (unalias(*argptr)) {
196
			outfmt(out2, "%s: %s not found\n", "unalias", *argptr);
197
			i = 1;
198
		}
199
	}
254
200
255
	return (i);
201
	return (i);
256
}
202
}
257
203
258
STATIC struct alias **
204
STATIC struct alias **
259
hashalias(p)
205
hashalias(p)
260
	char *p;
206
	const char *p;
261
	{
207
	{
262
	unsigned int hashval;
208
	unsigned int hashval;
263
209
Lines 266-268 Link Here
266
		hashval+= *p++;
212
		hashval+= *p++;
267
	return &atab[hashval % ATABSIZE];
213
	return &atab[hashval % ATABSIZE];
268
}
214
}
215
216
STATIC struct alias *
217
freealias(struct alias *ap) {
218
	struct alias *next;
219
220
	if (ap->flag & ALIASINUSE) {
221
		ap->flag |= ALIASDEAD;
222
		return ap;
223
	}
224
225
	next = ap->next;
226
	ckfree(ap->name);
227
	ckfree(ap->val);
228
	ckfree(ap);
229
	return next;
230
}
231
232
void
233
printalias(const struct alias *ap) {
234
	out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
235
}
236
237
STATIC struct alias **
238
__lookupalias(const char *name) {
239
	struct alias **app = hashalias(name);
240
241
	for (; *app; app = &(*app)->next) {
242
		if (equal(name, (*app)->name)) {
243
			break;
244
		}
245
	}
246
247
	return app;
248
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/alias.h (-1 / +4 lines)
Lines 39-44 Link Here
39
 */
39
 */
40
40
41
#define ALIASINUSE	1
41
#define ALIASINUSE	1
42
#define ALIASDEAD	2
42
43
43
struct alias {
44
struct alias {
44
	struct alias *next;
45
	struct alias *next;
Lines 47-53 Link Here
47
	int flag;
48
	int flag;
48
};
49
};
49
50
50
struct alias *lookupalias __P((char *, int));
51
struct alias *lookupalias __P((const char *, int));
51
int aliascmd __P((int, char **));
52
int aliascmd __P((int, char **));
52
int unaliascmd __P((int, char **));
53
int unaliascmd __P((int, char **));
53
void rmaliases __P((void));
54
void rmaliases __P((void));
55
int unalias __P((char *));
56
void printalias __P((const struct alias *));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/arith_lex.l (-2 / +2 lines)
Lines 52-58 Link Here
52
#include "expand.h"
52
#include "expand.h"
53
53
54
extern int yylval;
54
extern int yylval;
55
extern char *arith_buf, *arith_startbuf;
55
extern const char *arith_buf, *arith_startbuf;
56
#undef YY_INPUT
56
#undef YY_INPUT
57
#define YY_INPUT(buf,result,max) \
57
#define YY_INPUT(buf,result,max) \
58
	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
58
	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
Lines 84-90 Link Here
84
"-"	{ return(ARITH_SUB); }
84
"-"	{ return(ARITH_SUB); }
85
"~"	{ return(ARITH_BNOT); }
85
"~"	{ return(ARITH_BNOT); }
86
"!"	{ return(ARITH_NOT); }
86
"!"	{ return(ARITH_NOT); }
87
.	{ error("arith: syntax error: \"%s\"\n", arith_startbuf); }
87
.	{ error("arith: syntax error: \"%s\"", arith_startbuf); }
88
%%
88
%%
89
89
90
void
90
void
(-)bin_NetBSD-1.6release.orig/src/bin/sh/arith.y (-3 / +4 lines)
Lines 55-60 Link Here
55
55
56
const char *arith_buf, *arith_startbuf;
56
const char *arith_buf, *arith_startbuf;
57
57
58
int yyparse __P((void));
58
void yyerror __P((const char *));
59
void yyerror __P((const char *));
59
#ifdef TESTARITH
60
#ifdef TESTARITH
60
int main __P((int , char *[]));
61
int main __P((int , char *[]));
Lines 84-91 Link Here
84
85
85
86
86
expr:	ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
87
expr:	ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
87
	| expr ARITH_OR expr	= { $$ = $1 ? $1 : $3 ? $3 : 0; }
88
	| expr ARITH_OR expr	= { $$ = $1 || $3; }
88
	| expr ARITH_AND expr	= { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
89
	| expr ARITH_AND expr	= { $$ = $1 && $3; }
89
	| expr ARITH_BOR expr	= { $$ = $1 | $3; }
90
	| expr ARITH_BOR expr	= { $$ = $1 | $3; }
90
	| expr ARITH_BXOR expr	= { $$ = $1 ^ $3; }
91
	| expr ARITH_BXOR expr	= { $$ = $1 ^ $3; }
91
	| expr ARITH_BAND expr	= { $$ = $1 & $3; }
92
	| expr ARITH_BAND expr	= { $$ = $1 & $3; }
Lines 166-172 Link Here
166
			p = grabstackstr(concat);
167
			p = grabstackstr(concat);
167
		}
168
		}
168
	} else
169
	} else
169
		p = "";
170
		p = nullstr;
170
171
171
	i = arith(p);
172
	i = arith(p);
172
173
(-)bin_NetBSD-1.6release.orig/src/bin/sh/arith_yylex.c (+162 lines)
Line 0 Link Here
1
/*	$Id: arith_yylex.c,v 1.3 2002/10/26 11:37:45 herbert Exp $	*/
2
3
/*-
4
 * Copyright (c) 2002
5
 *	Herbert Xu.
6
 * Copyright (c) 1993
7
 *	The Regents of the University of California.  All rights reserved.
8
 *
9
 * This code is derived from software contributed to Berkeley by
10
 * Kenneth Almquist.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions and the following disclaimer.
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 *    notice, this list of conditions and the following disclaimer in the
19
 *    documentation and/or other materials provided with the distribution.
20
 * 3. Neither the name of the University nor the names of its contributors
21
 *    may be used to endorse or promote products derived from this software
22
 *    without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
 * SUCH DAMAGE.
35
 */
36
37
#include <stdlib.h>
38
#include "arith.h"
39
#include "expand.h"
40
#include "error.h"
41
42
extern int yylval;
43
extern const char *arith_buf, *arith_startbuf;
44
45
int
46
yylex()
47
{
48
	int value;
49
	const char *buf = arith_buf;
50
51
	for (;;) {
52
		switch (*buf) {
53
		case ' ':
54
		case '\t':
55
		case '\n':
56
			buf++;
57
			continue;
58
		default:
59
err:
60
			error("arith: syntax error: \"%s\"", arith_startbuf);
61
			/* NOTREACHED */
62
		case '0':
63
		case '1':
64
		case '2':
65
		case '3':
66
		case '4':
67
		case '5':
68
		case '6':
69
		case '7':
70
		case '8':
71
		case '9':
72
			yylval = strtol(buf, (char **) &arith_buf, 0);
73
			return ARITH_NUM;
74
		case '=':
75
			if (*++buf != '=') {
76
				goto err;
77
			}
78
			value = ARITH_EQ;
79
			break;
80
		case '>':
81
			switch (*++buf) {
82
			case '=':
83
				value = ARITH_GE;
84
				break;
85
			case '>':
86
				value = ARITH_RSHIFT;
87
				break;
88
			default:
89
				value = ARITH_GT;
90
				goto out;
91
			}
92
			break;
93
		case '<':
94
			switch (*++buf) {
95
			case '=':
96
				value = ARITH_LE;
97
				break;
98
			case '<':
99
				value = ARITH_LSHIFT;
100
				break;
101
			default:
102
				value = ARITH_LT;
103
				goto out;
104
			}
105
			break;
106
		case '|':
107
			if (*++buf != '|') {
108
				value = ARITH_BOR;
109
				goto out;
110
			}
111
			value = ARITH_OR;
112
			break;
113
		case '&':
114
			if (*++buf != '&') {
115
				value = ARITH_BAND;
116
				goto out;
117
			}
118
			value = ARITH_AND;
119
			break;
120
		case '!':
121
			if (*++buf != '=') {
122
				value = ARITH_NOT;
123
				goto out;
124
			}
125
			value = ARITH_NE;
126
			break;
127
		case 0:
128
			value = 0;
129
			goto out;
130
		case '(':
131
			value = ARITH_LPAREN;
132
			break;
133
		case ')':
134
			value = ARITH_RPAREN;
135
			break;
136
		case '*':
137
			value = ARITH_MUL;
138
			break;
139
		case '/':
140
			value = ARITH_DIV;
141
			break;
142
		case '%':
143
			value = ARITH_REM;
144
			break;
145
		case '+':
146
			value = ARITH_ADD;
147
			break;
148
		case '-':
149
			value = ARITH_SUB;
150
			break;
151
		case '~':
152
			value = ARITH_BNOT;
153
			break;
154
		}
155
		break;
156
	}
157
158
	buf++;
159
out:
160
	arith_buf = buf;
161
	return value;
162
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/assignbltins.def (+4 lines)
Line 0 Link Here
1
alias
2
export
3
local
4
readonly
(-)bin_NetBSD-1.6release.orig/src/bin/sh/bltin/bltin.h (-7 / +5 lines)
Lines 47-53 Link Here
47
#include "../shell.h"
47
#include "../shell.h"
48
#include "../mystring.h"
48
#include "../mystring.h"
49
#ifdef SHELL
49
#ifdef SHELL
50
#include "../error.h"
51
#include "../memalloc.h"
50
#include "../output.h"
52
#include "../output.h"
53
#ifndef USE_GLIBC_STDIO
51
#define stdout out1
54
#define stdout out1
52
#define stderr out2
55
#define stderr out2
53
#define printf out1fmt
56
#define printf out1fmt
Lines 56-67 Link Here
56
#define fprintf outfmt
59
#define fprintf outfmt
57
#define fputs outstr
60
#define fputs outstr
58
#define fflush flushout
61
#define fflush flushout
62
#define ferror outerr
63
#endif
59
#define INITARGS(argv)
64
#define INITARGS(argv)
60
#define warnx(a, b, c) {				\
61
	char buf[64];					\
62
	(void)snprintf(buf, sizeof(buf), a, b, c);	\
63
	error("%s", buf);				\
64
}
65
65
66
#else
66
#else
67
#undef NULL
67
#undef NULL
Lines 70-77 Link Here
70
#define INITARGS(argv)	if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
70
#define INITARGS(argv)	if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
71
#endif
71
#endif
72
72
73
pointer stalloc __P((int));
74
void error __P((char *, ...));
75
int	echocmd __P((int, char **));
73
int	echocmd __P((int, char **));
76
74
77
75
(-)bin_NetBSD-1.6release.orig/src/bin/sh/bltin/echo.c (-46 / +30 lines)
Lines 44-107 Link Here
44
44
45
#define main echocmd
45
#define main echocmd
46
46
47
#ifdef USE_GLIBC_STDIO
48
#include <stdio.h>
49
50
#include "../mystring.h"
51
#else
47
#include "bltin.h"
52
#include "bltin.h"
53
#endif
48
54
49
/* #define eflag 1 */
55
int print_escape_str(const char *);
50
56
51
int
57
int
52
main(argc, argv)  char **argv; {
58
main(int argc, char **argv) {
53
	register char **ap;
54
	register char *p;
55
	register char c;
56
	int count;
57
	int nflag = 0;
59
	int nflag = 0;
58
#ifndef eflag
60
	int c = ' ';
59
	int eflag = 0;
60
#endif
61
61
62
	ap = argv;
62
	argv++;
63
	if (argc)
63
	if (*argv && equal(*argv, "-n")) {
64
		ap++;
64
		argv++;
65
	if ((p = *ap) != NULL) {
65
		nflag = 1;
66
		if (equal(p, "-n")) {
67
			nflag++;
68
			ap++;
69
		} else if (equal(p, "-e")) {
70
#ifndef eflag
71
			eflag++;
72
#endif
73
			ap++;
74
		}
66
		}
67
68
	if (!*argv) {
69
		goto end;
75
	}
70
	}
76
	while ((p = *ap++) != NULL) {
71
77
		while ((c = *p++) != '\0') {
72
	do {
78
			if (c == '\\' && eflag) {
73
		if (print_escape_str(*argv)) {
79
				switch (*p++) {
80
				case 'b':  c = '\b';  break;
81
				case 'c':  return 0;		/* exit */
82
				case 'f':  c = '\f';  break;
83
				case 'n':  c = '\n';  break;
84
				case 'r':  c = '\r';  break;
85
				case 't':  c = '\t';  break;
86
				case 'v':  c = '\v';  break;
87
				case '\\':  break;		/* c = '\\' */
88
				case '0':
89
					c = 0;
90
					count = 3;
91
					while (--count >= 0 && (unsigned)(*p - '0') < 8)
92
						c = (c << 3) + (*p++ - '0');
93
					break;
74
					break;
94
				default:
75
		}
95
					p--;
76
		if (!*++argv) {
77
end:
78
			if (nflag) {
96
					break;
79
					break;
97
				}
80
				}
81
			c = '\n';
98
			}
82
			}
99
			putchar(c);
83
			putchar(c);
100
		}
84
	} while (c == ' ');
101
		if (*ap)
85
#ifdef SHELL
102
			putchar(' ');
103
	}
104
	if (! nflag)
105
		putchar('\n');
106
	return 0;
86
	return 0;
87
#else
88
	fflush(stdout);
89
	return ferror(stdout);
90
#endif
107
}
91
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/bltin/printf.1 (+281 lines)
Line 0 Link Here
1
.\"	$NetBSD: printf.1,v 1.15 2002/02/08 01:36:31 ross Exp $
2
.\"
3
.\" Copyright (c) 1989, 1990, 1993
4
.\"	The Regents of the University of California.  All rights reserved.
5
.\"
6
.\" This code is derived from software contributed to Berkeley by
7
.\" the Institute of Electrical and Electronics Engineers, Inc.
8
.\"
9
.\" Redistribution and use in source and binary forms, with or without
10
.\" modification, are permitted provided that the following conditions
11
.\" are met:
12
.\" 1. Redistributions of source code must retain the above copyright
13
.\"    notice, this list of conditions and the following disclaimer.
14
.\" 2. Redistributions in binary form must reproduce the above copyright
15
.\"    notice, this list of conditions and the following disclaimer in the
16
.\"    documentation and/or other materials provided with the distribution.
17
.\" 3. All advertising materials mentioning features or use of this software
18
.\"    must display the following acknowledgement:
19
.\"	This product includes software developed by the University of
20
.\"	California, Berkeley and its contributors.
21
.\" 4. Neither the name of the University nor the names of its contributors
22
.\"    may be used to endorse or promote products derived from this software
23
.\"    without specific prior written permission.
24
.\"
25
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
.\" SUCH DAMAGE.
36
.\"
37
.\"	from: @(#)printf.1	8.1 (Berkeley) 6/6/93
38
.\"
39
.Dd November 5, 1993
40
.Dt PRINTF 1
41
.Os
42
.Sh NAME
43
.Nm printf
44
.Nd formatted output
45
.Sh SYNOPSIS
46
.Nm
47
.Ar format
48
.Op Ar arguments  ...
49
.Sh DESCRIPTION
50
.Nm
51
formats and prints its arguments, after the first, under control
52
of the
53
.Ar format  .
54
The
55
.Ar format
56
is a character string which contains three types of objects: plain characters,
57
which are simply copied to standard output, character escape sequences which
58
are converted and copied to the standard output, and format specifications,
59
each of which causes printing of the next successive
60
.Ar argument  .
61
.Pp
62
The
63
.Ar arguments
64
after the first are treated as strings if the corresponding format is
65
either
66
.Cm b ,
67
.Cm c
68
or
69
.Cm s ;
70
otherwise it is evaluated as a C constant, with the following extensions:
71
.Pp
72
.Bl -bullet -offset indent -compact
73
.It
74
A leading plus or minus sign is allowed.
75
.It
76
If the leading character is a single or double quote, the value is the
77
.Tn ASCII
78
code of the next character.
79
.El
80
.Pp
81
The format string is reused as often as necessary to satisfy the
82
.Ar arguments  .
83
Any extra format specifications are evaluated with zero or the null
84
string.
85
.Pp
86
Character escape sequences are in backslash notation as defined in
87
.St -ansiC .
88
The characters and their meanings
89
are as follows:
90
.Bl -tag -width Ds -offset indent
91
.It Cm \ee
92
Write an \*[Lt]escape\*[Gt] character.
93
.It Cm \ea
94
Write a \*[Lt]bell\*[Gt] character.
95
.It Cm \eb
96
Write a \*[Lt]backspace\*[Gt] character.
97
.It Cm \ef
98
Write a \*[Lt]form-feed\*[Gt] character.
99
.It Cm \en
100
Write a \*[Lt]new-line\*[Gt] character.
101
.It Cm \er
102
Write a \*[Lt]carriage return\*[Gt] character.
103
.It Cm \et
104
Write a \*[Lt]tab\*[Gt] character.
105
.It Cm \ev
106
Write a \*[Lt]vertical tab\*[Gt] character.
107
.It Cm \e\'
108
Write a \*[Lt]single quote\*[Gt] character.
109
.It Cm \e\e
110
Write a backslash character.
111
.It Cm \e Ns Ar num
112
Write an 8-bit character whose
113
.Tn ASCII
114
value is the 1-, 2-, or 3-digit
115
octal number
116
.Ar num .
117
.El
118
.Pp
119
Each format specification is introduced by the percent character
120
(``%'').
121
The remainder of the format specification includes,
122
in the following order:
123
.Bl -tag -width Ds
124
.It "Zero or more of the following flags:"
125
.Bl -tag -width Ds
126
.It Cm #
127
A `#' character
128
specifying that the value should be printed in an ``alternative form''.
129
For
130
.Cm c  ,
131
.Cm d ,
132
and
133
.Cm s  ,
134
formats, this option has no effect.  For the
135
.Cm o
136
formats the precision of the number is increased to force the first
137
character of the output string to a zero.  For the
138
.Cm x
139
.Pq Cm X
140
format, a non-zero result has the string
141
.Li 0x
142
.Pq Li 0X
143
prepended to it.  For
144
.Cm e  ,
145
.Cm E ,
146
.Cm f  ,
147
.Cm g ,
148
and
149
.Cm G  ,
150
formats, the result will always contain a decimal point, even if no
151
digits follow the point (normally, a decimal point only appears in the
152
results of those formats if a digit follows the decimal point).  For
153
.Cm g
154
and
155
.Cm G
156
formats, trailing zeros are not removed from the result as they
157
would otherwise be;
158
.It Cm \&\-
159
A minus sign `\-' which specifies
160
.Em left adjustment
161
of the output in the indicated field;
162
.It Cm \&+
163
A `+' character specifying that there should always be
164
a sign placed before the number when using signed formats.
165
.It Sq \&\ \&
166
A space specifying that a blank should be left before a positive number
167
for a signed format.  A `+' overrides a space if both are used;
168
.It Cm \&0
169
A zero `0' character indicating that zero-padding should be used
170
rather than blank-padding.  A `\-' overrides a `0' if both are used;
171
.El
172
.It "Field Width:"
173
An optional digit string specifying a
174
.Em field width ;
175
if the output string has fewer characters than the field width it will
176
be blank-padded on the left (or right, if the left-adjustment indicator
177
has been given) to make up the field width (note that a leading zero
178
is a flag, but an embedded zero is part of a field width);
179
.It Precision :
180
An optional period,
181
.Sq Cm \&.\& ,
182
followed by an optional digit string giving a
183
.Em precision
184
which specifies the number of digits to appear after the decimal point,
185
for
186
.Cm e
187
and
188
.Cm f
189
formats, or the maximum number of characters to be printed
190
from a string; if the digit string is missing, the precision is treated
191
as zero;
192
.It Format :
193
A character which indicates the type of format to use (one of
194
.Cm diouxXfwEgGbcs ) .
195
.El
196
.Pp
197
A field width or precision may be
198
.Sq Cm \&*
199
instead of a digit string.
200
In this case an
201
.Ar argument
202
supplies the field width or precision.
203
.Pp
204
The format characters and their meanings are:
205
.Bl -tag -width Fl
206
.It Cm diouXx
207
The
208
.Ar argument
209
is printed as a signed decimal (d or i), unsigned octal, unsigned decimal,
210
or unsigned hexadecimal (X or x), respectively.
211
.It Cm f
212
The
213
.Ar argument
214
is printed in the style
215
.Sm off
216
.Pf [\-]ddd Cm \&. No ddd
217
.Sm on
218
where the number of d's
219
after the decimal point is equal to the precision specification for
220
the argument.
221
If the precision is missing, 6 digits are given; if the precision
222
is explicitly 0, no digits and no decimal point are printed.
223
.It Cm eE
224
The
225
.Ar argument
226
is printed in the style
227
.Sm off
228
.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd
229
.Sm on
230
where there
231
is one digit before the decimal point and the number after is equal to
232
the precision specification for the argument; when the precision is
233
missing, 6 digits are produced.
234
An upper-case E is used for an `E' format.
235
.It Cm gG
236
The
237
.Ar argument
238
is printed in style
239
.Cm f
240
or in style
241
.Cm e
242
.Pq Cm E
243
whichever gives full precision in minimum space.
244
.It Cm b
245
Characters from the string
246
.Ar argument
247
are printed with backslash-escape sequences expanded.
248
.It Cm c
249
The first character of
250
.Ar argument
251
is printed.
252
.It Cm s
253
Characters from the string
254
.Ar argument
255
are printed until the end is reached or until the number of characters
256
indicated by the precision specification is reached; however if the
257
precision is 0 or missing, all characters in the string are printed.
258
.It Cm \&%
259
Print a `%'; no argument is used.
260
.El
261
.Pp
262
In no case does a non-existent or small field width cause truncation of
263
a field; padding takes place only if the specified field width exceeds
264
the actual width.
265
.Sh EXIT STATUS
266
.Nm
267
exits 0 on success, 1 on failure.
268
.Sh SEE ALSO
269
.Xr echo 1 ,
270
.Xr printf 3 ,
271
.Xr printf 9
272
.Sh STANDARDS
273
The
274
.Nm
275
utility conforms to
276
.St -p1003.2-92 .
277
.Sh BUGS
278
Since the floating point numbers are translated from
279
.Tn ASCII
280
to floating-point and
281
then back again, floating-point precision may be lost.
(-)bin_NetBSD-1.6release.orig/src/bin/sh/bltin/printf.c (+532 lines)
Line 0 Link Here
1
/*	$NetBSD: printf.c,v 1.24 2002/06/14 11:32:15 tron Exp $	*/
2
3
/*
4
 * Copyright (c) 1989, 1993
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 * 3. All advertising materials mentioning features or use of this software
16
 *    must display the following acknowledgement:
17
 *	This product includes software developed by the University of
18
 *	California, Berkeley and its contributors.
19
 * 4. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include <sys/cdefs.h>
37
#ifndef lint
38
#if !defined(BUILTIN) && !defined(SHELL)
39
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
40
	The Regents of the University of California.  All rights reserved.\n");
41
#endif
42
#endif
43
44
#ifndef lint
45
#if 0
46
static char sccsid[] = "@(#)printf.c	8.2 (Berkeley) 3/22/95";
47
#else
48
__RCSID("$NetBSD: printf.c,v 1.24 2002/06/14 11:32:15 tron Exp $");
49
#endif
50
#endif /* not lint */
51
52
#include <sys/types.h>
53
54
#include <ctype.h>
55
#include <err.h>
56
#include <errno.h>
57
#include <inttypes.h>
58
#include <limits.h>
59
#include <locale.h>
60
#include <stdarg.h>
61
#ifndef SHELL
62
#include <stdio.h>
63
#endif
64
#include <stdlib.h>
65
#include <string.h>
66
#include <unistd.h>
67
68
int		 print_escape_str(const char *);
69
static size_t	 print_escape(const char *);
70
71
static int	 getchr(void);
72
static double	 getdouble(void);
73
static intmax_t	 getintmax(void);
74
static uintmax_t getuintmax __P ((void));
75
static char	*getstr(void);
76
static char	*mklong(const char *, int); 
77
static void      check_conversion(const char *, const char *);
78
static void	 usage(void); 
79
     
80
static int	rval;
81
static char  **gargv;
82
83
#ifdef BUILTIN
84
int progprintf(int, char **);
85
#else
86
int main(int, char **);
87
#endif
88
89
#define isodigit(c)	((c) >= '0' && (c) <= '7')
90
#define octtobin(c)	((c) - '0')
91
#define hextobin(c)	((c) >= 'A' && (c) <= 'F' ? c - 'A' + 10 : (c) >= 'a' && (c) <= 'f' ? c - 'a' + 10 : c - '0')
92
93
#ifdef SHELL
94
#define main printfcmd
95
#include "bltin.h"
96
#else
97
#define nullstr ""
98
#endif
99
100
#define PF(f, func) { \
101
	switch (param - array) { \
102
	case 0: \
103
		(void)printf(f, func); \
104
		break; \
105
	case 1: \
106
		(void)printf(f, array[0], func); \
107
		break; \
108
	default: \
109
		(void)printf(f, array[0], array[1], func); \
110
		break; \
111
	} \
112
}
113
114
int
115
#ifdef BUILTIN
116
progprintf(int argc, char **argv)
117
#else
118
main(int argc, char **argv)
119
#endif
120
{
121
	char *fmt;
122
	char *format;
123
124
#if !defined(SHELL) && !defined(BUILTIN)
125
	(void)setlocale (LC_ALL, "");
126
#endif
127
128
	if (--argc < 1) {
129
		usage();
130
		return (1);
131
	}
132
133
	format = *++argv;
134
	gargv = ++argv;
135
136
#define SKIP1	"#-+ 0"
137
#define SKIP2	"*0123456789"
138
	do {
139
		/*
140
		 * Basic algorithm is to scan the format string for conversion
141
		 * specifications -- once one is found, find out if the field
142
		 * width or precision is a '*'; if it is, gather up value. 
143
		 * Note, format strings are reused as necessary to use up the
144
		 * provided arguments, arguments of zero/null string are 
145
		 * provided to use up the format string.
146
		 */
147
148
		/* find next format specification */
149
		for (fmt = format; *fmt; fmt++) {
150
			switch (*fmt) {
151
			case '%': {
152
				char *start;
153
				char convch, nextch;
154
				int array[2];
155
				int *param;
156
157
				start = fmt++;
158
159
				if (*fmt == '%') {
160
					(void)putchar('%');
161
					break;
162
				} else if (*fmt == 'b') {
163
					char *p = getstr();
164
					if (print_escape_str(p)) {
165
						return (rval);
166
					}
167
					break;
168
				}
169
170
				param = array;
171
172
				/* skip to field width */
173
				fmt += strspn(fmt, SKIP1);
174
				if (*fmt == '*')
175
					*param++ = getintmax();
176
177
				/* skip to possible '.', get following precision */
178
				fmt += strspn(fmt, SKIP2);
179
				if (*fmt == '.')
180
					++fmt;
181
				if (*fmt == '*')
182
					*param++ = getintmax();
183
184
				fmt += strspn(fmt, SKIP2);
185
				if (!*fmt) {
186
					warnx ("missing format character");
187
					return(1);
188
				}
189
190
				convch = *fmt;
191
				nextch = *(fmt + 1);
192
				*(fmt + 1) = '\0';
193
				switch(convch) {
194
				case 'c': {
195
					char p = getchr();
196
					PF(start, p);
197
					break;
198
				}
199
				case 's': {
200
					char *p = getstr();
201
					PF(start, p);
202
					break;
203
				}
204
				case 'd':
205
				case 'i': {
206
					char *f = mklong(start, convch);
207
					intmax_t p = getintmax();
208
					PF(f, p);
209
					break;
210
				}
211
				case 'o':
212
				case 'u':
213
				case 'x':
214
				case 'X': {
215
					char *f = mklong(start, convch);
216
					uintmax_t p = getuintmax();
217
					PF(f, p);
218
					break;
219
				}
220
				case 'e':
221
				case 'E':
222
				case 'f':
223
				case 'g':
224
				case 'G': {
225
					double p = getdouble();
226
					PF(start, p);
227
					break;
228
				}
229
				default:
230
					warnx ("%s: invalid directive", start);
231
					return(1);
232
				}
233
				*(fmt + 1) = nextch;
234
				break;
235
			}
236
237
			case '\\':
238
				fmt += print_escape(fmt);
239
				break;
240
241
			default:
242
				(void)putchar(*fmt);
243
				break;
244
			}
245
		}
246
	} while (gargv > argv && *gargv);
247
248
#ifdef SHELL
249
	return (rval);
250
#else
251
	fflush(stdout);
252
	return (rval ? rval : ferror(stdout));
253
#endif
254
}
255
256
257
/*
258
 * Print SysV echo(1) style escape string 
259
 *	Halts processing string and returns 1 if a \c escape is encountered.
260
 */
261
int
262
print_escape_str(const char *str)
263
{
264
	char value;
265
	char c;
266
267
	for (; (value = *str); str++) {
268
		if (value == '\\') {
269
			c = *++str;
270
			/* 
271
			 * %b string octal constants are not like those in C.
272
			 * They start with a \0, and are followed by 0, 1, 2, 
273
			 * or 3 octal digits. 
274
			 */
275
			if (c == '0') {
276
				unsigned j;
277
				unsigned char i;
278
				i = 3;
279
				j = 0;
280
				do {
281
					unsigned k = octtobin(*++str);
282
					if (k > 7) {
283
						str--;
284
						break;
285
					}
286
					j <<= 3;
287
					j += k;
288
				} while (--i);
289
				value = j;
290
			} else if (c == 'c') {
291
				return 1;
292
			} else {
293
				str--;			
294
				str += print_escape(str);
295
				continue;
296
			}
297
		}
298
		putchar(value);
299
	}
300
301
	return 0;
302
}
303
304
/*
305
 * Print "standard" escape characters 
306
 */
307
static size_t
308
print_escape(const char *str)
309
{
310
	const char *start = str;
311
	int value;
312
	size_t c = 1;
313
314
	str++;
315
316
	switch (*str) {
317
	case '0': case '1': case '2': case '3':
318
	case '4': case '5': case '6': case '7':
319
		for (c = 4, value = 0; --c && isodigit(*str); str++) {
320
			value <<= 3;
321
			value += octtobin(*str);
322
		}
323
		c = str - start - 1;
324
		break;
325
326
#ifdef notrequired
327
	case 'x':
328
		str++;
329
		for (value = 0; isxdigit((unsigned char)*str); str++) {
330
			value <<= 4;
331
			value += hextobin(*str);
332
		}
333
		if (value > UCHAR_MAX) {
334
			warnx ("escape sequence out of range for character");
335
			rval = 1;
336
		}
337
		c = str - start - 1;
338
		break;
339
#endif
340
341
	case '\\':			/* backslash */
342
		value = '\\';
343
		break;
344
345
#ifdef notrequired
346
	case '\'':			/* single quote */
347
		value = '\'';
348
		break;
349
350
	case '"':			/* double quote */
351
		value = '"';
352
		break;
353
#endif
354
355
	case 'a':			/* alert */
356
		value = '\a';
357
		break;
358
359
	case 'b':			/* backspace */
360
		value = '\b';
361
		break;
362
363
#ifdef notrequired
364
	case 'e':			/* escape */
365
#ifdef __GNUC__
366
		value = '\e';
367
#else
368
		value = 033;
369
#endif
370
		break;
371
#endif
372
373
	case 'f':			/* form-feed */
374
		value = '\f';
375
		break;
376
377
	case 'n':			/* newline */
378
		value = '\n';
379
		break;
380
381
	case 'r':			/* carriage-return */
382
		value = '\r';
383
		break;
384
385
	case 't':			/* tab */
386
		value = '\t';
387
		break;
388
389
	case 'v':			/* vertical-tab */
390
		value = '\v';
391
		break;
392
393
	default:
394
#if 0
395
		value = *str;
396
		warnx("unknown escape sequence `\\%c'", *str);
397
		rval = 1;
398
#else
399
		value = '\\';
400
		c = 0;
401
#endif
402
		break;
403
	}
404
405
	putchar(value);
406
	return c;
407
}
408
409
static char *
410
mklong(const char *str, int ch)
411
{
412
	static char copy[64];
413
	size_t len;	
414
415
	len = strlen(str) + 2;
416
	(void)memmove(copy, str, len - 3);
417
	copy[len - 3] = 'j';
418
	copy[len - 2] = ch;
419
	copy[len - 1] = '\0';
420
	return (copy);	
421
}
422
423
static int
424
getchr(void)
425
{
426
	int val = 0;
427
428
	if (*gargv)
429
		val = **gargv++;
430
	return val;
431
}
432
433
static char *
434
getstr(void)
435
{
436
	char *val = nullstr;
437
438
	if (*gargv)
439
		val = *gargv++;
440
	return val;
441
}
442
443
static intmax_t
444
getintmax(void)
445
{
446
	intmax_t val = 0;
447
	char *ep;
448
	const char *arg = *gargv;
449
450
	if (!arg)
451
		goto out;
452
453
	gargv++;
454
455
	val = (unsigned char) arg[1];
456
	if (*arg == '\"' || *arg == '\'')
457
		goto out;
458
459
	errno = 0;
460
	val = strtoimax(arg, &ep, 0);
461
	check_conversion(arg, ep);
462
out:
463
	return val;
464
}
465
466
static uintmax_t
467
getuintmax(void)
468
{
469
	uintmax_t val = 0;
470
	char *ep;
471
	const char *arg = *gargv;
472
473
	if (!arg)
474
		goto out;
475
476
	gargv++;
477
478
	val = (unsigned char) arg[1];
479
	if (*arg == '\"' || *arg == '\'')
480
		goto out;
481
482
	errno = 0;
483
	val = strtoumax(arg, &ep, 0);
484
	check_conversion(arg, ep);
485
out:
486
	return val;
487
}
488
489
static double
490
getdouble(void)
491
{
492
	double val = 0;
493
	char *ep;
494
	const char *arg = *gargv;
495
496
	if (!arg)
497
		goto out;
498
499
	gargv++;
500
501
	if (*arg == '\"' || *arg == '\'') {
502
		val = (unsigned char) arg[1];
503
		goto out;
504
	}
505
506
	errno = 0;
507
	val = strtod(arg, &ep);
508
	check_conversion(arg, ep);
509
out:
510
	return val;
511
}
512
513
static void
514
check_conversion(const char *s, const char *ep)
515
{
516
	if (*ep) {
517
		if (ep == s)
518
			warnx ("%s: expected numeric value", s);
519
		else
520
			warnx ("%s: not completely converted", s);
521
		rval = 1;
522
	} else if (errno == ERANGE) {
523
		warnx ("%s: %s", s, strerror(ERANGE));
524
		rval = 1;
525
	}
526
}
527
528
static void
529
usage(void)
530
{
531
	(void)fprintf(stderr, "usage: printf format [arg ...]\n");
532
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/bltin/test.1 (+312 lines)
Line 0 Link Here
1
.\"	$NetBSD: test.1,v 1.17 2002/02/08 01:22:01 ross Exp $
2
.\"
3
.\" Copyright (c) 1991, 1993
4
.\"	The Regents of the University of California.  All rights reserved.
5
.\"
6
.\" This code is derived from software contributed to Berkeley by
7
.\" the Institute of Electrical and Electronics Engineers, Inc.
8
.\"
9
.\" Redistribution and use in source and binary forms, with or without
10
.\" modification, are permitted provided that the following conditions
11
.\" are met:
12
.\" 1. Redistributions of source code must retain the above copyright
13
.\"    notice, this list of conditions and the following disclaimer.
14
.\" 2. Redistributions in binary form must reproduce the above copyright
15
.\"    notice, this list of conditions and the following disclaimer in the
16
.\"    documentation and/or other materials provided with the distribution.
17
.\" 3. All advertising materials mentioning features or use of this software
18
.\"    must display the following acknowledgement:
19
.\"	This product includes software developed by the University of
20
.\"	California, Berkeley and its contributors.
21
.\" 4. Neither the name of the University nor the names of its contributors
22
.\"    may be used to endorse or promote products derived from this software
23
.\"    without specific prior written permission.
24
.\"
25
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
.\" SUCH DAMAGE.
36
.\"
37
.\"     @(#)test.1	8.1 (Berkeley) 5/31/93
38
.\"
39
.Dd May 31, 1993
40
.Dt TEST 1
41
.Os
42
.Sh NAME
43
.Nm test ,
44
.Nm \&[
45
.Nd condition evaluation utility
46
.Sh SYNOPSIS
47
.Nm test
48
.Ar expression
49
.Nm \&[
50
.Ar expression Cm ]
51
.Sh DESCRIPTION
52
The
53
.Nm test
54
utility evaluates the expression and, if it evaluates
55
to true, returns a zero (true) exit status; otherwise
56
it returns 1 (false).
57
If there is no expression, test also
58
returns 1 (false).
59
.Pp
60
All operators and flags are separate arguments to the
61
.Nm test
62
utility.
63
.Pp
64
The following primaries are used to construct expression:
65
.Bl -tag -width Ar
66
.It Fl b Ar file
67
True if
68
.Ar file
69
exists and is a block special
70
file.
71
.It Fl c Ar file
72
True if
73
.Ar file
74
exists and is a character
75
special file.
76
.It Fl d Ar file
77
True if
78
.Ar file
79
exists and is a directory.
80
.It Fl e Ar file
81
True if
82
.Ar file
83
exists (regardless of type).
84
.It Fl f Ar file
85
True if
86
.Ar file
87
exists and is a regular file.
88
.It Fl g Ar file
89
True if
90
.Ar file
91
exists and its set group ID flag
92
is set.
93
.It Fl h Ar file
94
True if
95
.Ar file
96
exists and is a symbolic link.
97
.It Fl k Ar file
98
True if
99
.Ar file
100
exists and its sticky bit is set.
101
.It Fl n Ar string
102
True if the length of
103
.Ar string
104
is nonzero.
105
.It Fl p Ar file
106
True if
107
.Ar file
108
is a named pipe
109
.Po Tn FIFO Pc .
110
.It Fl r Ar file
111
True if
112
.Ar file
113
exists and is readable.
114
.It Fl s Ar file
115
True if
116
.Ar file
117
exists and has a size greater
118
than zero.
119
.It Fl t Ar file_descriptor
120
True if the file whose file descriptor number
121
is
122
.Ar file_descriptor
123
is open and is associated with a terminal.
124
.It Fl u Ar file
125
True if
126
.Ar file
127
exists and its set user ID flag
128
is set.
129
.It Fl w Ar file
130
True if
131
.Ar file
132
exists and is writable.
133
True
134
indicates only that the write flag is on.
135
The file is not writable on a read-only file
136
system even if this test indicates true.
137
.It Fl x Ar file
138
True if
139
.Ar file
140
exists and is executable.
141
True
142
indicates only that the execute flag is on.
143
If
144
.Ar file
145
is a directory, true indicates that
146
.Ar file
147
can be searched.
148
.It Fl z Ar string
149
True if the length of
150
.Ar string
151
is zero.
152
.It Fl L Ar file
153
True if
154
.Ar file
155
exists and is a symbolic link.
156
This operator is retained for compatibility with previous versions of
157
this program. Do not rely on its existence; use
158
.Fl h
159
instead.
160
.It Fl O Ar file
161
True if
162
.Ar file
163
exists and its owner matches the effective user id of this process.
164
.It Fl G Ar file
165
True if
166
.Ar file
167
exists and its group matches the effective group id of this process.
168
.It Fl S Ar file
169
True if
170
.Ar file
171
exists and is a socket.
172
.It Ar file1 Fl nt Ar file2
173
True if
174
.Ar file1
175
exists and is newer than
176
.Ar file2 .
177
.It Ar file1 Fl ot Ar file2
178
True if
179
.Ar file1
180
exists and is older than
181
.Ar file2 .
182
.It Ar file1 Fl ef Ar file2
183
True if
184
.Ar file1
185
and
186
.Ar file2
187
exist and refer to the same file.
188
.It Ar string
189
True if
190
.Ar string
191
is not the null
192
string.
193
.It Ar \&s\&1 Cm \&= Ar \&s\&2
194
True if the strings
195
.Ar \&s\&1
196
and
197
.Ar \&s\&2
198
are identical.
199
.It Ar \&s\&1 Cm \&!= Ar \&s\&2
200
True if the strings
201
.Ar \&s\&1
202
and
203
.Ar \&s\&2
204
are not identical.
205
.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2
206
True if string
207
.Ar \&s\&1
208
comes before
209
.Ar \&s\&2
210
based on the ASCII value of their characters.
211
.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2
212
True if string
213
.Ar \&s\&1
214
comes after
215
.Ar \&s\&2
216
based on the ASCII value of their characters.
217
.It Ar \&n\&1 Fl \&eq Ar \&n\&2
218
True if the integers
219
.Ar \&n\&1
220
and
221
.Ar \&n\&2
222
are algebraically
223
equal.
224
.It Ar \&n\&1 Fl \&ne Ar \&n\&2
225
True if the integers
226
.Ar \&n\&1
227
and
228
.Ar \&n\&2
229
are not
230
algebraically equal.
231
.It Ar \&n\&1 Fl \&gt Ar \&n\&2
232
True if the integer
233
.Ar \&n\&1
234
is algebraically
235
greater than the integer
236
.Ar \&n\&2 .
237
.It Ar \&n\&1 Fl \&ge Ar \&n\&2
238
True if the integer
239
.Ar \&n\&1
240
is algebraically
241
greater than or equal to the integer
242
.Ar \&n\&2 .
243
.It Ar \&n\&1 Fl \&lt Ar \&n\&2
244
True if the integer
245
.Ar \&n\&1
246
is algebraically less
247
than the integer
248
.Ar \&n\&2 .
249
.It Ar \&n\&1 Fl \&le Ar \&n\&2
250
True if the integer
251
.Ar \&n\&1
252
is algebraically less
253
than or equal to the integer
254
.Ar \&n\&2 .
255
.El
256
.Pp
257
These primaries can be combined with the following operators:
258
.Bl -tag -width Ar
259
.It Cm \&! Ar expression
260
True if
261
.Ar expression
262
is false.
263
.It Ar expression1 Fl a Ar expression2
264
True if both
265
.Ar expression1
266
and
267
.Ar expression2
268
are true.
269
.It Ar expression1 Fl o Ar expression2
270
True if either
271
.Ar expression1
272
or
273
.Ar expression2
274
are true.
275
.It Cm \&( Ns Ar expression Ns Cm \&)
276
True if expression is true.
277
.El
278
.Pp
279
The
280
.Fl a
281
operator has higher precedence than the
282
.Fl o
283
operator.
284
.Sh GRAMMAR AMBIGUITY
285
The
286
.Nm test
287
grammar is inherently ambiguous.  In order to assure a degree of consistency,
288
the cases described in
289
.St -p1003.2
290
section 4.62.4,
291
are evaluated consistently according to the rules specified in the
292
standards document.  All other cases are subject to the ambiguity in the
293
command semantics.
294
.Sh EXIT STATUS
295
The
296
.Nm test
297
utility exits with one of the following values:
298
.Bl -tag -width Ds
299
.It 0
300
expression evaluated to true.
301
.It 1
302
expression evaluated to false or expression was
303
missing.
304
.It \*[Gt]1
305
An error occurred.
306
.El
307
.Sh STANDARDS
308
The
309
.Nm test
310
utility implements a superset of the
311
.St -p1003.2
312
specification.
(-)bin_NetBSD-1.6release.orig/src/bin/sh/bltin/test.c (+545 lines)
Line 0 Link Here
1
/* $NetBSD: test.c,v 1.25 2002/05/25 23:12:16 wiz Exp $ */
2
3
/*
4
 * test(1); version 7-like  --  author Erik Baalbergen
5
 * modified by Eric Gisin to be used as built-in.
6
 * modified by Arnold Robbins to add SVR3 compatibility
7
 * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
8
 * modified by J.T. Conklin for NetBSD.
9
 *
10
 * This program is in the Public Domain.
11
 */
12
13
#include <sys/cdefs.h>
14
#ifndef lint
15
__RCSID("$NetBSD: test.c,v 1.25 2002/05/25 23:12:16 wiz Exp $");
16
#endif
17
18
#include <sys/stat.h>
19
#include <sys/types.h>
20
21
#include <ctype.h>
22
#include <err.h>
23
#include <errno.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <stdarg.h>
28
#include "bltin.h"
29
30
/* test(1) accepts the following grammar:
31
	oexpr	::= aexpr | aexpr "-o" oexpr ;
32
	aexpr	::= nexpr | nexpr "-a" aexpr ;
33
	nexpr	::= primary | "!" primary
34
	primary	::= unary-operator operand
35
		| operand binary-operator operand
36
		| operand
37
		| "(" oexpr ")"
38
		;
39
	unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
40
		"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
41
42
	binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
43
			"-nt"|"-ot"|"-ef";
44
	operand ::= <any legal UNIX file name>
45
*/
46
47
enum token {
48
	EOI,
49
	FILRD,
50
	FILWR,
51
	FILEX,
52
	FILEXIST,
53
	FILREG,
54
	FILDIR,
55
	FILCDEV,
56
	FILBDEV,
57
	FILFIFO,
58
	FILSOCK,
59
	FILSYM,
60
	FILGZ,
61
	FILTT,
62
	FILSUID,
63
	FILSGID,
64
	FILSTCK,
65
	FILNT,
66
	FILOT,
67
	FILEQ,
68
	FILUID,
69
	FILGID,
70
	STREZ,
71
	STRNZ,
72
	STREQ,
73
	STRNE,
74
	STRLT,
75
	STRGT,
76
	INTEQ,
77
	INTNE,
78
	INTGE,
79
	INTGT,
80
	INTLE,
81
	INTLT,
82
	UNOT,
83
	BAND,
84
	BOR,
85
	LPAREN,
86
	RPAREN,
87
	OPERAND
88
};
89
90
enum token_types {
91
	UNOP,
92
	BINOP,
93
	BUNOP,
94
	BBINOP,
95
	PAREN
96
};
97
98
static struct t_op {
99
	const char *op_text;
100
	short op_num, op_type;
101
} const ops [] = {
102
	{"-r",	FILRD,	UNOP},
103
	{"-w",	FILWR,	UNOP},
104
	{"-x",	FILEX,	UNOP},
105
	{"-e",	FILEXIST,UNOP},
106
	{"-f",	FILREG,	UNOP},
107
	{"-d",	FILDIR,	UNOP},
108
	{"-c",	FILCDEV,UNOP},
109
	{"-b",	FILBDEV,UNOP},
110
	{"-p",	FILFIFO,UNOP},
111
	{"-u",	FILSUID,UNOP},
112
	{"-g",	FILSGID,UNOP},
113
	{"-k",	FILSTCK,UNOP},
114
	{"-s",	FILGZ,	UNOP},
115
	{"-t",	FILTT,	UNOP},
116
	{"-z",	STREZ,	UNOP},
117
	{"-n",	STRNZ,	UNOP},
118
	{"-h",	FILSYM,	UNOP},		/* for backwards compat */
119
	{"-O",	FILUID,	UNOP},
120
	{"-G",	FILGID,	UNOP},
121
	{"-L",	FILSYM,	UNOP},
122
	{"-S",	FILSOCK,UNOP},
123
	{"=",	STREQ,	BINOP},
124
	{"!=",	STRNE,	BINOP},
125
	{"<",	STRLT,	BINOP},
126
	{">",	STRGT,	BINOP},
127
	{"-eq",	INTEQ,	BINOP},
128
	{"-ne",	INTNE,	BINOP},
129
	{"-ge",	INTGE,	BINOP},
130
	{"-gt",	INTGT,	BINOP},
131
	{"-le",	INTLE,	BINOP},
132
	{"-lt",	INTLT,	BINOP},
133
	{"-nt",	FILNT,	BINOP},
134
	{"-ot",	FILOT,	BINOP},
135
	{"-ef",	FILEQ,	BINOP},
136
	{"!",	UNOT,	BUNOP},
137
	{"-a",	BAND,	BBINOP},
138
	{"-o",	BOR,	BBINOP},
139
	{"(",	LPAREN,	PAREN},
140
	{")",	RPAREN,	PAREN},
141
	{0,	0,	0}
142
};
143
144
static char **t_wp;
145
static struct t_op const *t_wp_op;
146
147
static void syntax(const char *, const char *);
148
static int oexpr(enum token);
149
static int aexpr(enum token);
150
static int nexpr(enum token);
151
static int primary(enum token);
152
static int binop(void);
153
static int filstat(char *, enum token);
154
static enum token t_lex(char *);
155
static int isoperand(void);
156
static int getn(const char *);
157
static int newerf(const char *, const char *);
158
static int olderf(const char *, const char *);
159
static int equalf(const char *, const char *);
160
static int test_eaccess(const char *, int);
161
static int bash_group_member(gid_t);
162
163
#ifndef SHELL
164
static void error(const char *, ...) __attribute__((__noreturn__));
165
166
static void
167
error(const char *msg, ...)
168
{
169
	va_list ap;
170
171
	va_start(ap, msg);
172
	verrx(2, msg, ap);
173
	/*NOTREACHED*/
174
	va_end(ap);
175
}
176
#endif
177
178
#ifdef SHELL
179
int testcmd(int, char **);
180
181
int
182
testcmd(int argc, char **argv)
183
#else
184
int main(int, char *[]);
185
186
int
187
main(int argc, char *argv[])
188
#endif
189
{
190
	int res;
191
192
#ifndef SHELL
193
	setprogname(argv[0]);
194
#endif
195
	if (strcmp(argv[0], "[") == 0) {
196
		if (strcmp(argv[--argc], "]"))
197
			error("missing ]");
198
		argv[argc] = NULL;
199
	}
200
201
	if (argc < 2)
202
		return 1;
203
204
	t_wp = &argv[1];
205
	res = !oexpr(t_lex(*t_wp));
206
207
	if (*t_wp != NULL && *++t_wp != NULL)
208
		syntax(*t_wp, "unexpected operator");
209
210
	return res;
211
}
212
213
static void
214
syntax(const char *op, const char *msg)
215
{
216
	if (op && *op)
217
		error("%s: %s", op, msg);
218
	else
219
		error("%s", msg);
220
}
221
222
static int
223
oexpr(enum token n)
224
{
225
	int res;
226
227
	res = aexpr(n);
228
	if (t_lex(*++t_wp) == BOR)
229
		return oexpr(t_lex(*++t_wp)) || res;
230
	t_wp--;
231
	return res;
232
}
233
234
static int
235
aexpr(enum token n)
236
{
237
	int res;
238
239
	res = nexpr(n);
240
	if (t_lex(*++t_wp) == BAND)
241
		return aexpr(t_lex(*++t_wp)) && res;
242
	t_wp--;
243
	return res;
244
}
245
246
static int
247
nexpr(enum token n)
248
{
249
	if (n == UNOT)
250
		return !nexpr(t_lex(*++t_wp));
251
	return primary(n);
252
}
253
254
static int
255
primary(enum token n)
256
{
257
	enum token nn;
258
	int res;
259
260
	if (n == EOI)
261
		return 0;		/* missing expression */
262
	if (n == LPAREN) {
263
		if ((nn = t_lex(*++t_wp)) == RPAREN)
264
			return 0;	/* missing expression */
265
		res = oexpr(nn);
266
		if (t_lex(*++t_wp) != RPAREN)
267
			syntax(NULL, "closing paren expected");
268
		return res;
269
	}
270
	if (t_wp_op && t_wp_op->op_type == UNOP) {
271
		/* unary expression */
272
		if (*++t_wp == NULL)
273
			syntax(t_wp_op->op_text, "argument expected");
274
		switch (n) {
275
		case STREZ:
276
			return strlen(*t_wp) == 0;
277
		case STRNZ:
278
			return strlen(*t_wp) != 0;
279
		case FILTT:
280
			return isatty(getn(*t_wp));
281
		default:
282
			return filstat(*t_wp, n);
283
		}
284
	}
285
286
	if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
287
		return binop();
288
	}	  
289
290
	return strlen(*t_wp) > 0;
291
}
292
293
static int
294
binop(void)
295
{
296
	const char *opnd1, *opnd2;
297
	struct t_op const *op;
298
299
	opnd1 = *t_wp;
300
	(void) t_lex(*++t_wp);
301
	op = t_wp_op;
302
303
	if ((opnd2 = *++t_wp) == (char *)0)
304
		syntax(op->op_text, "argument expected");
305
		
306
	switch (op->op_num) {
307
	case STREQ:
308
		return strcmp(opnd1, opnd2) == 0;
309
	case STRNE:
310
		return strcmp(opnd1, opnd2) != 0;
311
	case STRLT:
312
		return strcmp(opnd1, opnd2) < 0;
313
	case STRGT:
314
		return strcmp(opnd1, opnd2) > 0;
315
	case INTEQ:
316
		return getn(opnd1) == getn(opnd2);
317
	case INTNE:
318
		return getn(opnd1) != getn(opnd2);
319
	case INTGE:
320
		return getn(opnd1) >= getn(opnd2);
321
	case INTGT:
322
		return getn(opnd1) > getn(opnd2);
323
	case INTLE:
324
		return getn(opnd1) <= getn(opnd2);
325
	case INTLT:
326
		return getn(opnd1) < getn(opnd2);
327
	case FILNT:
328
		return newerf (opnd1, opnd2);
329
	case FILOT:
330
		return olderf (opnd1, opnd2);
331
	case FILEQ:
332
		return equalf (opnd1, opnd2);
333
	default:
334
		abort();
335
		/* NOTREACHED */
336
	}
337
}
338
339
static int
340
filstat(char *nm, enum token mode)
341
{
342
	struct stat64 s;
343
344
	if (mode == FILSYM ? lstat64(nm, &s) : stat64(nm, &s))
345
		return 0;
346
347
	switch (mode) {
348
	case FILRD:
349
		return test_eaccess(nm, R_OK) == 0;
350
	case FILWR:
351
		return test_eaccess(nm, W_OK) == 0;
352
	case FILEX:
353
		return test_eaccess(nm, X_OK) == 0;
354
	case FILEXIST:
355
		return 1;
356
	case FILREG:
357
		return S_ISREG(s.st_mode);
358
	case FILDIR:
359
		return S_ISDIR(s.st_mode);
360
	case FILCDEV:
361
		return S_ISCHR(s.st_mode);
362
	case FILBDEV:
363
		return S_ISBLK(s.st_mode);
364
	case FILFIFO:
365
		return S_ISFIFO(s.st_mode);
366
	case FILSOCK:
367
		return S_ISSOCK(s.st_mode);
368
	case FILSYM:
369
		return S_ISLNK(s.st_mode);
370
	case FILSUID:
371
		return (s.st_mode & S_ISUID) != 0;
372
	case FILSGID:
373
		return (s.st_mode & S_ISGID) != 0;
374
	case FILSTCK:
375
		return (s.st_mode & S_ISVTX) != 0;
376
	case FILGZ:
377
		return s.st_size > (off_t)0;
378
	case FILUID:
379
		return s.st_uid == geteuid();
380
	case FILGID:
381
		return s.st_gid == getegid();
382
	default:
383
		return 1;
384
	}
385
}
386
387
static enum token
388
t_lex(char *s)
389
{
390
	struct t_op const *op;
391
392
	op = ops;
393
394
	if (s == 0) {
395
		t_wp_op = (struct t_op *)0;
396
		return EOI;
397
	}
398
	while (op->op_text) {
399
		if (strcmp(s, op->op_text) == 0) {
400
			if ((op->op_type == UNOP && isoperand()) ||
401
			    (op->op_num == LPAREN && *(t_wp+1) == 0))
402
				break;
403
			t_wp_op = op;
404
			return op->op_num;
405
		}
406
		op++;
407
	}
408
	t_wp_op = (struct t_op *)0;
409
	return OPERAND;
410
}
411
412
static int
413
isoperand(void)
414
{
415
	struct t_op const *op;
416
	char *s, *t;
417
418
	op = ops;
419
	if ((s  = *(t_wp+1)) == 0)
420
		return 1;
421
	if ((t = *(t_wp+2)) == 0)
422
		return 0;
423
	while (op->op_text) {
424
		if (strcmp(s, op->op_text) == 0)
425
	    		return op->op_type == BINOP &&
426
	    		    (t[0] != ')' || t[1] != '\0'); 
427
		op++;
428
	}
429
	return 0;
430
}
431
432
/* atoi with error detection */
433
static int
434
getn(const char *s)
435
{
436
	char *p;
437
	long r;
438
439
	errno = 0;
440
	r = strtol(s, &p, 10);
441
442
	if (errno != 0)
443
	      error("%s: out of range", s);
444
445
	while (isspace((unsigned char)*p))
446
	      p++;
447
	
448
	if (*p)
449
	      error("%s: bad number", s);
450
451
	return (int) r;
452
}
453
454
static int
455
newerf (const char *f1, const char *f2)
456
{
457
	struct stat b1, b2;
458
459
	return (stat (f1, &b1) == 0 &&
460
		stat (f2, &b2) == 0 &&
461
		b1.st_mtime > b2.st_mtime);
462
}
463
464
static int
465
olderf (const char *f1, const char *f2)
466
{
467
	struct stat b1, b2;
468
469
	return (stat (f1, &b1) == 0 &&
470
		stat (f2, &b2) == 0 &&
471
		b1.st_mtime < b2.st_mtime);
472
}
473
474
static int
475
equalf (const char *f1, const char *f2)
476
{
477
	struct stat b1, b2;
478
479
	return (stat (f1, &b1) == 0 &&
480
		stat (f2, &b2) == 0 &&
481
		b1.st_dev == b2.st_dev &&
482
		b1.st_ino == b2.st_ino);
483
}
484
485
/* Do the same thing access(2) does, but use the effective uid and gid,
486
   and don't make the mistake of telling root that any file is
487
   executable. */
488
static int
489
test_eaccess(const char *path, int mode)
490
{
491
	struct stat64 st;
492
	int euid = geteuid();
493
494
	if (stat64(path, &st) < 0)
495
		return (-1);
496
497
	if (euid == 0) {
498
		/* Root can read or write any file. */
499
		if (mode != X_OK)
500
		return (0);
501
502
		/* Root can execute any file that has any one of the execute
503
		   bits set. */
504
		if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
505
			return (0);
506
	}
507
508
	if (st.st_uid == euid)		/* owner */
509
		mode <<= 6;
510
	else if (bash_group_member(st.st_gid))
511
		mode <<= 3;
512
513
	if (st.st_mode & mode)
514
		return (0);
515
516
	return (-1);
517
}
518
519
/* Return non-zero if GID is one that we have in our groups list. */
520
static int
521
bash_group_member(gid_t gid)
522
{
523
	register int i;
524
	gid_t *group_array;
525
	int ngroups;
526
527
	/* Short-circuit if possible, maybe saving a call to getgroups(). */
528
	if (gid == getgid() || gid == getegid())
529
		return (1);
530
531
	ngroups = getgroups(0, NULL);
532
#ifdef SHELL
533
	group_array = stalloc(ngroups * sizeof(gid_t));
534
#else
535
	group_array = alloca(ngroups * sizeof(gid_t));
536
#endif
537
	getgroups(ngroups, group_array);
538
539
	/* Search through the list looking for GID. */
540
	for (i = 0; i < ngroups; i++)
541
		if (gid == group_array[i])
542
			return (1);
543
544
	return (0);
545
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/bltin/times.c (+32 lines)
Line 0 Link Here
1
/*
2
 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3
 * This file contains code for the times builtin.
4
 * $Id: times.c,v 1.6 2001/12/12 20:35:08 herbert Exp $
5
 */
6
7
#include <sys/times.h>
8
#include <unistd.h>
9
#ifdef USE_GLIBC_STDIO
10
#include <stdio.h>
11
#else
12
#include "bltin.h"
13
#endif
14
15
#define main timescmd
16
17
int main() {
18
	struct tms buf;
19
	long int clk_tck = sysconf(_SC_CLK_TCK);
20
21
	times(&buf);
22
	printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
23
	       (int) (buf.tms_utime / clk_tck / 60),
24
	       ((double) buf.tms_utime) / clk_tck,
25
	       (int) (buf.tms_stime / clk_tck / 60),
26
	       ((double) buf.tms_stime) / clk_tck,
27
	       (int) (buf.tms_cutime / clk_tck / 60),
28
	       ((double) buf.tms_cutime) / clk_tck,
29
	       (int) (buf.tms_cstime / clk_tck / 60),
30
	       ((double) buf.tms_cstime) / clk_tck);
31
	return 0;
32
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/builtins.def (-3 / +6 lines)
Lines 49-60 Link Here
49
#
49
#
50
# NOTE: bltincmd must come first!
50
# NOTE: bltincmd must come first!
51
51
52
bltincmd	command
52
bltincmd	builtin
53
#alloccmd	alloc
53
#alloccmd	alloc
54
bgcmd -j	bg
54
bgcmd -j	bg
55
breakcmd	break continue
55
breakcmd	break continue
56
#catfcmd	catf
56
#catfcmd	catf
57
cdcmd		cd chdir
57
cdcmd		cd chdir
58
commandcmd	command
58
dotcmd		.
59
dotcmd		.
59
echocmd		echo
60
echocmd		echo
60
evalcmd		eval
61
evalcmd		eval
Lines 68-79 Link Here
68
fgcmd -j	fg
69
fgcmd -j	fg
69
getoptscmd	getopts
70
getoptscmd	getopts
70
hashcmd		hash
71
hashcmd		hash
71
jobidcmd	jobid
72
#jobidcmd	jobid
72
jobscmd		jobs
73
jobscmd		jobs
74
killcmd -j	kill
73
#linecmd		line
75
#linecmd		line
74
localcmd	local
76
localcmd	local
75
#nlechocmd	nlecho
77
#nlechocmd	nlecho
76
#printfcmd	printf
78
printfcmd	printf
77
pwdcmd		pwd
79
pwdcmd		pwd
78
readcmd		read
80
readcmd		read
79
returncmd	return
81
returncmd	return
Lines 91-93 Link Here
91
aliascmd	alias
93
aliascmd	alias
92
ulimitcmd	ulimit
94
ulimitcmd	ulimit
93
testcmd		test [
95
testcmd		test [
96
timescmd	times
(-)bin_NetBSD-1.6release.orig/src/bin/sh/cd.c (-240 / +182 lines)
Lines 70-82 Link Here
70
#include "show.h"
70
#include "show.h"
71
#include "cd.h"
71
#include "cd.h"
72
72
73
STATIC int docd __P((char *, int));
73
#define CD_PHYSICAL 1
74
STATIC char *getcomponent __P((void));
74
#define CD_PRINT 2
75
STATIC void updatepwd __P((char *));
76
75
77
char *curdir = NULL;		/* current working directory */
76
STATIC int docd __P((const char *, int));
78
char *prevdir;			/* previous working directory */
77
STATIC const char *updatepwd __P((const char *));
79
STATIC char *cdcomppath;
78
STATIC char *getpwd __P((void));
79
STATIC int cdopt __P((void));
80
81
STATIC char *curdir = nullstr;		/* current working directory */
82
STATIC char *physdir = nullstr;		/* physical working directory */
83
84
STATIC int
85
cdopt()
86
{
87
	int flags = 0;
88
	int i, j;
89
90
	j = 'L';
91
	while ((i = nextopt("LP"))) {
92
		if (i != j) {
93
			flags ^= CD_PHYSICAL;
94
			j = i;
95
		}
96
	}
97
98
	return flags;
99
}
80
100
81
int
101
int
82
cdcmd(argc, argv)
102
cdcmd(argc, argv)
Lines 85-380 Link Here
85
{
105
{
86
	const char *dest;
106
	const char *dest;
87
	const char *path;
107
	const char *path;
88
	char *p;
108
	const char *p;
109
	char c;
89
	struct stat statb;
110
	struct stat statb;
90
	int print = 0;
111
	int flags;
91
112
92
	nextopt(nullstr);
113
	flags = cdopt();
93
	if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
114
	dest = *argptr;
94
		error("HOME not set");
115
	if (!dest)
95
	if (*dest == '\0')
116
		dest = bltinlookup(homestr);
96
	        dest = ".";
117
	else if (dest[0] == '-' && dest[1] == '\0') {
97
	if (dest[0] == '-' && dest[1] == '\0') {
118
		dest = bltinlookup("OLDPWD");
98
		dest = prevdir ? prevdir : curdir;
119
		flags |= CD_PRINT;
99
		print = 1;
120
		goto step7;
100
		if (dest)
101
		        print = 1;
102
		else
103
		        dest = ".";
104
	}
121
	}
105
	if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
122
	if (!dest)
106
		path = nullstr;
123
		dest = nullstr;
107
	while ((p = padvance(&path, dest)) != NULL) {
124
	if (*dest == '/')
108
		if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
125
		goto step7;
109
			if (!print) {
126
	if (*dest == '.') {
110
				/*
127
		c = dest[1];
111
				 * XXX - rethink
128
dotdot:
112
				 */
129
		switch (c) {
113
				if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
130
		case '\0':
114
					p += 2;
131
		case '/':
115
				print = strcmp(p, dest);
132
			goto step6;
133
		case '.':
134
			c = dest[2];
135
			if (c != '.')
136
				goto dotdot;
116
			}
137
			}
117
			if (docd(p, print) >= 0)
118
				return 0;
119
120
		}
138
		}
139
	if (!*dest)
140
		dest = ".";
141
	if (!(path = bltinlookup("CDPATH"))) {
142
step6:
143
step7:
144
		p = dest;
145
		goto docd;
146
	}
147
	do {
148
		c = *path;
149
		p = padvance(&path, dest);
150
		if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
151
			if (c && c != ':')
152
				flags |= CD_PRINT;
153
docd:
154
			if (!docd(p, flags))
155
				goto out;
156
			break;
121
	}
157
	}
158
	} while (path);
122
	error("can't cd to %s", dest);
159
	error("can't cd to %s", dest);
123
	/* NOTREACHED */
160
	/* NOTREACHED */
161
out:
162
	if (flags & CD_PRINT)
163
		out1fmt(snlfmt, curdir);
164
	return 0;
124
}
165
}
125
166
126
167
127
/*
168
/*
128
 * Actually do the chdir.  In an interactive shell, print the
169
 * Actually do the chdir.  We also call hashcd to let the routines in exec.c
129
 * directory name if "print" is nonzero.
170
 * know that the current directory has changed.
130
 */
171
 */
131
172
132
STATIC int
173
STATIC int
133
docd(dest, print)
174
docd(const char *dest, int flags)
134
	char *dest;
135
	int print;
136
{
175
{
137
	char *p;
176
	const char *dir = 0;
138
	char *q;
177
	int err;
139
	char *component;
140
	struct stat statb;
141
	int first;
142
	int badstat;
143
144
	TRACE(("docd(\"%s\", %d) called\n", dest, print));
145
178
146
	/*
179
	TRACE(("docd(\"%s\", %d) called\n", dest, flags));
147
	 *  Check each component of the path. If we find a symlink or
148
	 *  something we can't stat, clear curdir to force a getcwd()
149
	 *  next time we get the value of the current directory.
150
	 */
151
	badstat = 0;
152
	cdcomppath = stalloc(strlen(dest) + 1);
153
	scopy(dest, cdcomppath);
154
	STARTSTACKSTR(p);
155
	if (*dest == '/') {
156
		STPUTC('/', p);
157
		cdcomppath++;
158
	}
159
	first = 1;
160
	while ((q = getcomponent()) != NULL) {
161
		if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
162
			continue;
163
		if (! first)
164
			STPUTC('/', p);
165
		first = 0;
166
		component = q;
167
		while (*q)
168
			STPUTC(*q++, p);
169
		if (equal(component, ".."))
170
			continue;
171
		STACKSTRNUL(p);
172
		if ((lstat(stackblock(), &statb) < 0)
173
		    || (S_ISLNK(statb.st_mode)))  {
174
			/* print = 1; */
175
			badstat = 1;
176
			break;
177
		}
178
	}
179
180
180
	INTOFF;
181
	INTOFF;
181
	if (chdir(dest) < 0) {
182
	if (!(flags & CD_PHYSICAL)) {
182
		INTON;
183
		dir = updatepwd(dest);
183
		return -1;
184
		if (dir)
185
			dest = dir;
184
	}
186
	}
185
	updatepwd(badstat ? NULL : dest);
187
	err = chdir(dest);
188
	if (err)
189
		goto out;
190
	setpwd(dir, 1);
191
	hashcd();
192
out:
186
	INTON;
193
	INTON;
187
	if (print && iflag && curdir)
194
	return err;
188
		out1fmt("%s\n", curdir);
189
	return 0;
190
}
191
192
193
/*
194
 * Get the next component of the path name pointed to by cdcomppath.
195
 * This routine overwrites the string pointed to by cdcomppath.
196
 */
197
198
STATIC char *
199
getcomponent() {
200
	char *p;
201
	char *start;
202
203
	if ((p = cdcomppath) == NULL)
204
		return NULL;
205
	start = cdcomppath;
206
	while (*p != '/' && *p != '\0')
207
		p++;
208
	if (*p == '\0') {
209
		cdcomppath = NULL;
210
	} else {
211
		*p++ = '\0';
212
		cdcomppath = p;
213
	}
214
	return start;
215
}
195
}
216
196
217
197
218
219
/*
198
/*
220
 * Update curdir (the name of the current directory) in response to a
199
 * Update curdir (the name of the current directory) in response to a
221
 * cd command.  We also call hashcd to let the routines in exec.c know
200
 * cd command.
222
 * that the current directory has changed.
223
 */
201
 */
224
202
225
STATIC void
203
STATIC const char *
226
updatepwd(dir)
204
updatepwd(const char *dir)
227
	char *dir;
205
{
228
	{
229
	char *new;
206
	char *new;
230
	char *p;
207
	char *p;
208
	char *cdcomppath;
209
	const char *lim;
231
210
232
	hashcd();				/* update command hash table */
211
	cdcomppath = sstrdup(dir);
233
234
	/*
235
	 * If our argument is NULL, we don't know the current directory
236
	 * any more because we traversed a symbolic link or something
237
	 * we couldn't stat().
238
	 */
239
	if (dir == NULL || curdir == NULL)  {
240
		if (prevdir)
241
			ckfree(prevdir);
242
		INTOFF;
243
		prevdir = curdir;
244
		curdir = NULL;
245
		getpwd();
246
		setvar("PWD", curdir, VEXPORT);
247
		INTON;
248
		return;
249
	}
250
	cdcomppath = stalloc(strlen(dir) + 1);
251
	scopy(dir, cdcomppath);
252
	STARTSTACKSTR(new);
212
	STARTSTACKSTR(new);
253
	if (*dir != '/') {
213
	if (*dir != '/') {
254
		p = curdir;
214
		if (curdir == nullstr)
255
		while (*p)
215
			return 0;
256
			STPUTC(*p++, new);
216
		new = stputs(curdir, new);
257
		if (p[-1] == '/')
217
	}
218
	new = makestrspace(strlen(dir) + 2, new);
219
	lim = stackblock() + 1;
220
	if (*dir != '/') {
221
		if (new[-1] != '/')
222
			USTPUTC('/', new);
223
		if (new > lim && *lim == '/')
224
			lim++;
225
	} else {
226
		USTPUTC('/', new);
227
		cdcomppath++;
228
		if (dir[1] == '/' && dir[2] != '/') {
229
			USTPUTC('/', new);
230
			cdcomppath++;
231
			lim++;
232
		}
233
	}
234
	p = strtok(cdcomppath, "/");
235
	while (p) {
236
		switch(*p) {
237
		case '.':
238
			if (p[1] == '.' && p[2] == '\0') {
239
				while (new > lim) {
258
			STUNPUTC(new);
240
			STUNPUTC(new);
241
					if (new[-1] == '/')
242
						break;
259
	}
243
	}
260
	while ((p = getcomponent()) != NULL) {
244
				break;
261
		if (equal(p, "..")) {
245
			} else if (p[1] == '\0')
262
			while (new > stackblock() && (STUNPUTC(new), *new) != '/');
246
				break;
263
		} else if (*p != '\0' && ! equal(p, ".")) {
247
			/* fall through */
264
			STPUTC('/', new);
248
		default:
265
			while (*p)
249
			new = stputs(p, new);
266
				STPUTC(*p++, new);
250
			USTPUTC('/', new);
267
		}
251
		}
252
		p = strtok(0, "/");
268
	}
253
	}
269
	if (new == stackblock())
254
	if (new > lim)
270
		STPUTC('/', new);
255
		STUNPUTC(new);
271
	STACKSTRNUL(new);
256
	*new = 0;
272
	INTOFF;
257
	return stackblock();
273
	if (prevdir)
274
		ckfree(prevdir);
275
	prevdir = curdir;
276
	curdir = savestr(stackblock());
277
	setvar("PWD", curdir, VEXPORT);
278
	INTON;
279
}
258
}
280
259
281
260
261
#define MAXPWD 256
262
263
/*
264
 * Find out what the current directory is. If we already know the current
265
 * directory, this routine returns immediately.
266
 */
267
inline
268
STATIC char *
269
getpwd()
270
{
271
	char *dir = getcwd(0, 0);
272
	return dir ? dir : nullstr;
273
}
282
274
283
int
275
int
284
pwdcmd(argc, argv)
276
pwdcmd(argc, argv)
285
	int argc;
277
	int argc;
286
	char **argv;
278
	char **argv;
287
{
279
{
288
	getpwd();
280
	int flags;
289
	out1str(curdir);
281
	const char *dir = curdir;
290
	out1c('\n');
282
283
	flags = cdopt();
284
	if (flags) {
285
		if (physdir == nullstr)
286
			setpwd(dir, 0);
287
		dir = physdir;
288
	}
289
	out1fmt(snlfmt, dir);
291
	return 0;
290
	return 0;
292
}
291
}
293
292
294
295
296
297
#define MAXPWD 256
298
299
/*
300
 * Find out what the current directory is. If we already know the current
301
 * directory, this routine returns immediately.
302
 */
303
void
293
void
304
getpwd()
294
setpwd(const char *val, int setold)
305
{
295
{
306
	char buf[MAXPWD];
296
	char *oldcur, *dir;
307
308
	if (curdir)
309
		return;
310
	/*
311
	 * Things are a bit complicated here; we could have just used
312
	 * getcwd, but traditionally getcwd is implemented using popen
313
	 * to /bin/pwd. This creates a problem for us, since we cannot
314
	 * keep track of the job if it is being ran behind our backs.
315
	 * So we re-implement getcwd(), and we suppress interrupts
316
	 * throughout the process. This is not completely safe, since
317
	 * the user can still break out of it by killing the pwd program.
318
	 * We still try to use getcwd for systems that we know have a
319
	 * c implementation of getcwd, that does not open a pipe to
320
	 * /bin/pwd.
321
	 */
322
#if defined(__NetBSD__) || defined(__SVR4)
323
		
297
		
324
	if (getcwd(buf, sizeof(buf)) == NULL) {
298
	oldcur = dir = curdir;
325
		char *pwd = getenv("PWD");
326
		struct stat stdot, stpwd;
327
299
328
		if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
300
	if (setold) {
329
		    stat(pwd, &stpwd) != -1 &&
301
		setvar("OLDPWD", oldcur, VEXPORT);
330
		    stdot.st_dev == stpwd.st_dev &&
331
		    stdot.st_ino == stpwd.st_ino) {
332
			curdir = savestr(pwd);
333
			return;
334
		}
335
		error("getcwd() failed: %s", strerror(errno));
336
	}
302
	}
337
	curdir = savestr(buf);
338
#else
339
	{
340
		char *p;
341
		int i;
342
		int status;
343
		struct job *jp;
344
		int pip[2];
345
346
		INTOFF;
303
		INTOFF;
347
		if (pipe(pip) < 0)
304
	if (physdir != nullstr) {
348
			error("Pipe call failed");
305
		if (physdir != oldcur)
349
		jp = makejob((union node *)NULL, 1);
306
			free(physdir);
350
		if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
307
		physdir = nullstr;
351
			(void) close(pip[0]);
352
			if (pip[1] != 1) {
353
				close(1);
354
				copyfd(pip[1], 1);
355
				close(pip[1]);
356
			}
357
			(void) execl("/bin/pwd", "pwd", (char *)0);
358
			error("Cannot exec /bin/pwd");
359
		}
360
		(void) close(pip[1]);
361
		pip[1] = -1;
362
		p = buf;
363
		while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
364
		     || (i == -1 && errno == EINTR)) {
365
			if (i > 0)
366
				p += i;
367
		}
308
		}
368
		(void) close(pip[0]);
309
	if (oldcur == val || !val) {
369
		pip[0] = -1;
310
		char *s = getpwd();
370
		status = waitforjob(jp);
311
		physdir = s;
371
		if (status != 0)
312
		if (!val)
372
			error((char *)0);
313
			dir = s;
373
		if (i < 0 || p == buf || p[-1] != '\n')
314
	} else
374
			error("pwd command failed");
315
		dir = savestr(val);
375
		p[-1] = '\0';
316
	if (oldcur != dir && oldcur != nullstr) {
317
		free(oldcur);
376
	}
318
	}
377
	curdir = savestr(buf);
319
	curdir = dir;
378
	INTON;
320
	INTON;
379
#endif
321
	setvar("PWD", dir, VEXPORT);
380
}
322
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/cd.h (-1 / +1 lines)
Lines 34-39 Link Here
34
 *
34
 *
35
 */
35
 */
36
36
37
void	getpwd __P((void));
38
int	cdcmd __P((int, char **));
37
int	cdcmd __P((int, char **));
39
int	pwdcmd __P((int, char **));
38
int	pwdcmd __P((int, char **));
39
void	setpwd __P((const char *, int));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/ash.dirs (+2 lines)
Line 0 Link Here
1
bin
2
usr/share/man/man1
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/ash.postinst (+54 lines)
Line 0 Link Here
1
#!/bin/sh
2
#
3
# post-install script for the Debian GNU/Linux ash package
4
#
5
# $Id: ash.postinst,v 1.9 2002/10/26 11:27:48 herbert Exp $
6
7
set -e
8
9
check_divert() {
10
	div=$(dpkg-divert --list $1)
11
	distrib=${3:-$1.distrib}
12
	case $div in
13
	'' | *by\ dash)
14
		;;
15
	*by\ ash)
16
		dst=${div% by ash}
17
		dst=${dst##* to }
18
19
		# Work around dpkg-divert bug.
20
		if [ -e "$dst" ]; then
21
			mv "$dst" "$dst.ash-tmp"
22
		fi
23
		dpkg-divert --remove $1
24
		if [ -e "$dst.ash-tmp" ]; then
25
			mv "$dst.ash-tmp" "$dst"
26
		fi
27
28
		dpkg-divert --package dash --divert $distrib --add $1
29
		if [ "$dst" != $distrib ] && [ -e "$dst" ]; then
30
			mv "$dst" $distrib
31
		fi
32
		ln -sf $2 $1
33
		;;
34
	*)
35
		d=${1%/*}
36
		if
37
			[ -h $1 ] && [ -f $1 ] && [ -f $d/$4 ] &&
38
			cmp $1 $d/$4
39
		then
40
			ln -sf $2 $1
41
		fi
42
		;;
43
	esac
44
}
45
46
dcv='dpkg --compare-versions'
47
48
if [ "$1" = configure ] && [ -n "$2" ] && $dcv "$2" lt 0.4.3; then
49
	check_divert /bin/sh dash '' ash
50
	check_divert /usr/share/man/man1/sh.1.gz dash.1.gz \
51
		/usr/share/man/man1/sh.distrib.1.gz ash.1.gz
52
fi
53
54
#DEBHELPER#
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/bsdyacc (+20 lines)
Line 0 Link Here
1
#!/bin/sh -e
2
3
if echo "$@" | grep -q -- -o; then
4
	OUTPUT=$(echo "$@" |
5
		 sed 's/.*-o[[:blank:]]\+\([^[:blank:]]\+\)\.c.*/\1/')
6
	OPTIONS=$(echo "$@" |
7
		 sed 's/\(.*\)-o[[:blank:]]\+[^[:blank:]]\+\(.*\)/\1\2/')
8
	NEW=1
9
else
10
	OUTPUT=$(echo "$@" |
11
		 sed -e 's/.*[[:blank:]]\+\([^[:blank:]]\+\)\.y.*/\1/')
12
	OPTIONS="$@"
13
	NEW=0
14
fi
15
16
byacc $OPTIONS
17
if [ $NEW = 1 ]; then
18
	mv y.tab.c $OUTPUT.c
19
fi
20
mv y.tab.h $OUTPUT.h
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/changelog (+868 lines)
Line 0 Link Here
1
dash (0.4.10) unstable; urgency=low
2
3
  * Fixed redirection fd leak when execing.
4
5
 -- Herbert Xu <herbert@debian.org>  Sun, 19 Jan 2003 13:25:41 +1100
6
7
dash (0.4.9) unstable; urgency=low
8
9
  * Reset exitstatus in evalsubshell if backgnd is true.
10
  * Fixed glibc glob syntax error in expand.c.
11
12
 -- Herbert Xu <herbert@debian.org>  Sat, 11 Jan 2003 16:04:02 +1100
13
14
dash (0.4.8) unstable; urgency=low
15
16
  * Removed backgnd flag from ncmd due to previous redirection change.
17
  * Set lim after the stack stablises in updatepwd (closes: #173884).
18
  * Do not clobber the exitstatus after redirection.
19
20
 -- Herbert Xu <herbert@debian.org>  Mon, 23 Dec 2002 19:50:06 +1100
21
22
dash (0.4.7) unstable; urgency=low
23
24
  * Merged clearredir with reset code in redir.c.
25
  * Redirect before command search in evalcommand (closes: #168862).
26
  * Build binary-all packages in binary-indep (closes: #173191).
27
28
 -- Herbert Xu <herbert@debian.org>  Sat, 21 Dec 2002 13:52:37 +1100
29
30
dash (0.4.6) unstable; urgency=low
31
32
  * Restored code for leaving job control.
33
34
 -- Herbert Xu <herbert@debian.org>  Sun,  8 Dec 2002 15:21:58 +1100
35
36
dash (0.4.5) unstable; urgency=low
37
38
  * Optimised doformat so that vsnprintf is usually called only once.
39
  * Reset redirlist in clearredir so that popredir can work (closes: #170247).
40
41
 -- Herbert Xu <herbert@debian.org>  Sat, 23 Nov 2002 22:09:59 +1100
42
43
dash (0.4.4) unstable; urgency=low
44
45
  * Fixed duplicate define warnings in init.c.
46
  * Set debhelper compat to 4.
47
  * Vanishing mail boxes no longer elicit "you have mail" messages.
48
  * Function redirection errors no longer abort the shell.
49
  * Fixed potential memory leak in redirect.
50
  * Only allocate memory if necessary in redirect.
51
  * Reap dead here documents.
52
  * Do not strdup default values of static shell variables.
53
  * Removed unnecessary setprompt(0) calls.
54
  * Read in BUFSIZ chunks rather than BUFSIZ - 1.
55
  * Documented undefined escape behaviour for echo(1) (closes: #167893).
56
  * Do va_copy when we use a va_list twice (closes: #169503).
57
58
 -- Herbert Xu <herbert@debian.org>  Wed, 20 Nov 2002 19:48:31 +1100
59
60
dash (0.4.3) unstable; urgency=low
61
62
  * Added manual entry for PPID.
63
  * Exporting an unset variable no longer causes it to be set.
64
  * Fixed fd0 redirection in asynchronous lists.
65
  * Only stat if necessary in cdcmd (see #42880).
66
  * Removed extra newline in error message in arith lexer.
67
  * Set heredoclist to 0 ASAP in parseheredoc.
68
  * Removed BSD advertising clause from copyright file.
69
  * Check non-ash diversions as well in dash.postinst.
70
  * Duplicated diversion checking in ash.postinst (closes: #166441).
71
72
 -- Herbert Xu <herbert@debian.org>  Sat, 26 Oct 2002 21:28:33 +1000
73
74
dash (0.4.2) unstable; urgency=low
75
76
  * Give benefits of dash in templates (closes: #161527).
77
  * Fixed signed/unsigned on result of xwrite (closes: #161606).
78
  * Removed support for SIG prefixes in kill and trap.
79
  * Added -- processing in trap.
80
  * Dropped use of unset in postinst (closes: 161868).
81
  * Fixed printf(1) %* processing on bad integers and zero.
82
  * Use stat64 in test(1).
83
  * Allocate group_array with stalloc in test(1).
84
  * Disabled alias checking after a pattern in a case statement.
85
  * Wait now returns 128 + last trapped signal.
86
  * Printf now keeps going after errors.
87
  * Empty non-trivial parameter expansions are now removed correctly.
88
  * Call reset() before exitshell() is called.  This fixes the bug where
89
    returning an error from a function running under set -e caused the exit
90
    trap to be taken with evalskip set.
91
  * Fixed quoting of empty strings in single_quote().
92
  * Show line numbers on all errors.
93
  * Function names must be valid identifiers.
94
  * Removed unused dependency on groff.
95
  * Fixed race condition before entering a function.
96
  * Fixed getopts initialisation for functions.
97
  * Added memory barriers in INT macros.
98
  * Banned empty compound lists in most places.
99
  * Keep usage counters on functions (closes: #164234).
100
  * Updated copyright file.
101
  * Check evalskip in evalstring (closes: #165056).
102
  * Merged changes from NetBSD 1.6:
103
   . Added intmax support in printf(1).
104
   . Implemented set -u.
105
106
 -- Herbert Xu <herbert@debian.org>  Sat, 19 Oct 2002 14:23:11 +1000
107
108
dash (0.4.1) unstable; urgency=low
109
110
  * Removed extra new line in command -v output for aliases.
111
  * Removed alais prefix in the output of alias.
112
  * Recognise octal and hex numbers in arith expansion (closes: #151449).
113
  * Added sh(1) entries for echo, printf and test (closes: #156446).
114
  * Renamed to dash --- the Debian Almquist Shell.
115
  * Cleaned up rules file (Matej Vela).
116
  * Check mtime instead of size in chkmail per POSIX.
117
  * Added support for LFS (closes: #157884).
118
  * Added SuS options to cd and pwd (closes: #145828).
119
120
 -- Herbert Xu <herbert@debian.org>  Fri, 13 Sep 2002 20:35:06 +1000
121
122
ash (0.3.8-38) unstable; urgency=low
123
124
  * Turned pre-dependency to dependency in udeb since the former is not allowed
125
    (closes: #143749).
126
127
 -- Herbert Xu <herbert@debian.org>  Sun, 28 Apr 2002 11:59:05 +1000
128
129
ash (0.3.8-37) unstable; urgency=low
130
131
  * Added Japanese debconf translation (Tomohiro KUBOTA, closes: #137431).
132
  * Added missing escapes in manual page (Aaron Schrab, closes: #137966).
133
  * Added Russian debconf translation (Ilgiz Kalmetev, closes: #137618).
134
  * Fixed trap(1) documentation (closes: #140973).
135
  * Do not abort if getcwd fails.
136
137
 -- Herbert Xu <herbert@debian.org>  Wed,  3 Apr 2002 20:58:09 +1000
138
139
ash (0.3.8-36) unstable; urgency=low
140
141
  * Added library dependency for ash-udeb.
142
  * Handle null case statements correctly.
143
  * Fixed alias expansions in case statements (NetBSD).
144
  * Disabled unused jobid command.
145
  * Corrected documentation about shifting too much.
146
  * Added French debconf translation (Denis Barbier, closes: #134625).
147
  * Updated Spanish debconf translation (Carlos Valdivia, closes: #136366).
148
149
 -- Herbert Xu <herbert@debian.org>  Sat,  2 Mar 2002 18:31:22 +1100
150
151
ash (0.3.8-35) unstable; urgency=low
152
153
  * Moved PWD initialisation into var.c (closes: #124032).
154
155
 -- Herbert Xu <herbert@debian.org>  Mon, 24 Dec 2001 09:34:55 +1100
156
157
ash (0.3.8-34) unstable; urgency=low
158
159
  * NSEMI must be NOR + 1.
160
  * Set exitstatus to zero before evaluating cases (closes: #124066).
161
  * Explicitly set default answer of the ash/sh question to false so that
162
    people whose debconf priority is set to low and who keeps banging on their
163
    keyboards don't accidently end up with ash as /bin/sh.
164
165
 -- Herbert Xu <herbert@debian.org>  Fri, 21 Dec 2001 20:30:49 +1100
166
167
ash (0.3.8-33) unstable; urgency=low
168
169
  * Added missing inclusion of bltin.h in bltin/times.c.
170
171
 -- Herbert Xu <herbert@debian.org>  Thu, 13 Dec 2001 18:46:07 +1100
172
173
ash (0.3.8-32) unstable; urgency=low
174
175
  * Back slashes in expansions are now escaped (closes: #121516).
176
177
 -- Herbert Xu <herbert@debian.org>  Wed, 28 Nov 2001 20:15:01 +1100
178
179
ash (0.3.8-31) unstable; urgency=low
180
181
  * Made sure all back slashes are escaped.
182
183
 -- Herbert Xu <herbert@debian.org>  Mon, 26 Nov 2001 19:10:27 +1100
184
185
ash (0.3.8-30) unstable; urgency=low
186
187
  * Restored fnmatch(3) code.
188
  * Treat escaped slashes correctly while globbing.
189
  * Restored missing EV_EXIT check in evalcommand (closes: #120364).
190
  * Fixed stack corruption in _rmescapes.
191
192
 -- Herbert Xu <herbert@debian.org>  Sun, 25 Nov 2001 17:51:19 +1100
193
194
ash (0.3.8-29) unstable; urgency=low
195
196
  * Added missing va_end in fmtstr (NetBSD).
197
  * Removed shellproc crap.
198
  * Updated Swedish debconf translation (Mikael Hedin, closes: #116097).
199
  * Updated German debconf translation (Andreas Metzler, closes: #117160).
200
  * Break now treats illegal numbers according to SuS.
201
  * Errors in special builtins now rise to the top.
202
  * Normal redirection errors no longer abort the shell.
203
  * Functions now have the same variable assignment properties as special
204
    builtins.
205
206
 -- Herbert Xu <herbert@debian.org>  Sat,  3 Nov 2001 11:36:36 +1100
207
208
ash (0.3.8-28) unstable; urgency=low
209
210
  * Local variables are now unset properly in shprocvar() (closes: #114917).
211
212
 -- Herbert Xu <herbert@debian.org>  Sat, 13 Oct 2001 14:07:21 +1000
213
214
ash (0.3.8-27) unstable; urgency=low
215
216
  * Kill no longer aborts if it fails to kill someone.
217
218
 -- Herbert Xu <herbert@debian.org>  Sun, 30 Sep 2001 22:20:36 +1000
219
220
ash (0.3.8-26) unstable; urgency=low
221
222
  * The sh.1.gz diversion now agrees with reality (closes: #113831).
223
224
 -- Herbert Xu <herbert@debian.org>  Sat, 29 Sep 2001 08:43:27 +1000
225
226
ash (0.3.8-25) unstable; urgency=low
227
228
  * Only read ENV if the shell is interactive (closes: #110421).
229
230
 -- Herbert Xu <herbert@debian.org>  Wed, 29 Aug 2001 19:18:53 +1000
231
232
ash (0.3.8-24) unstable; urgency=low
233
234
  * Handle SIGINT when waiting even if there is no trap (closes: #107699).
235
  * Protect all makejob/forkshell/waitforjobs sequences from SIGINT.
236
  * Work around gcc bug that generates bad ..ng references (closes: #107994).
237
238
 -- Herbert Xu <herbert@debian.org>  Wed,  8 Aug 2001 20:28:28 +1000
239
240
ash (0.3.8-23) unstable; urgency=low
241
242
  * Fixed fence post error in scanleft (closes: #107229).
243
  * Removed stunalloc in expname as it interferes with addfname.
244
  * Fixed CTLESC skipping in scanright.
245
246
 -- Herbert Xu <herbert@debian.org>  Thu,  2 Aug 2001 20:06:00 +1000
247
248
ash (0.3.8-22) unstable; urgency=low
249
250
  * Fixed trailing back slash bug in echo/printf (closes: #106693).
251
  * Some quoted's are meant to be quotes.
252
  * Added Brazilian translation (Andre Luis Lopes, closes: #107041).
253
254
 -- Herbert Xu <herbert@debian.org>  Mon, 30 Jul 2001 20:21:52 +1000
255
256
ash (0.3.8-21) unstable; urgency=low
257
258
  * Fixed EV_EXIT/redirection bugs that caused core dumps.
259
260
 -- Herbert Xu <herbert@debian.org>  Sat, 28 Jul 2001 17:03:28 +1000
261
262
ash (0.3.8-20) unstable; urgency=low
263
264
  * Don't save fd2 if job control is turned off.
265
  * Don't push redirections when EV_EXIT is set.
266
  * Fixed assignment recognition in the presence of back ticks.
267
  * Combined checkkwd and checkalias.
268
269
 -- Herbert Xu <herbert@debian.org>  Fri, 27 Jul 2001 22:29:41 +1000
270
271
ash (0.3.8-19) unstable; urgency=low
272
273
  * Recompute strings after growing in subevalvar (closes: #106050).
274
275
 -- Herbert Xu <herbert@debian.org>  Mon, 23 Jul 2001 21:16:50 +1000
276
277
ash (0.3.8-18) unstable; urgency=low
278
279
  * Added more space optimisations for udeb on i386.
280
  * Set stack mark in patmatch (closes: #106050).
281
  * Fixed theoretical bug in expari.
282
283
 -- Herbert Xu <herbert@debian.org>  Sat, 21 Jul 2001 20:08:15 +1000
284
285
ash (0.3.8-17) unstable; urgency=low
286
287
  * Don't complain about unknown escape codes in echo and printf
288
    (closes: #105659).
289
  * Updated build-time dependency on groff-base (closes: #105612).
290
291
 -- Herbert Xu <herbert@debian.org>  Wed, 18 Jul 2001 19:33:20 +1000
292
293
ash (0.3.8-16) unstable; urgency=low
294
295
  * Fixed backslash bug in new pattern matching code.
296
297
 -- Herbert Xu <herbert@debian.org>  Mon, 16 Jul 2001 21:47:39 +1000
298
299
ash (0.3.8-15) unstable; urgency=low
300
301
  * Added Swedish translation of templates (Martin Sjögren, closes: #103158).
302
  * Restored escape code support in echo.
303
  * Removed assignment builtins since it is at best undefined by the SuS and
304
    also can't be implemented consistently.
305
  * Removed extraneous volatile modifier (closes: #104518).
306
  * General overhaul of word expansion (closes: #96588).
307
  * Redirection prefixes no longer stop assignments from being recognised.
308
309
 -- Herbert Xu <herbert@debian.org>  Sun, 15 Jul 2001 17:27:03 +1000
310
311
ash (0.3.8-14) unstable; urgency=low
312
313
  * Divert sh.1.gz to sh.distrib.1.gz (closes: #102251).
314
  * Added HETIO support for ^D and ^U (Aaron Lehmann, closes: #102215).
315
  * Added Spaniash translation of debconf templates (Carlos Valdivia Yagüe,
316
    closes: #103040).
317
  * Added versioned build-time dependency on groff.
318
319
 -- Herbert Xu <herbert@debian.org>  Mon,  2 Jul 2001 19:32:03 +1000
320
321
ash (0.3.8-13) unstable; urgency=low
322
323
  * Fixed a bug where errors in pipelines which are part of andor lists were
324
    not ignored when -e is in effect.
325
326
 -- Herbert Xu <herbert@debian.org>  Mon, 25 Jun 2001 19:40:27 +1000
327
328
ash (0.3.8-12) unstable; urgency=low
329
330
  * Rewrote arith_lex.l in C (Aaron Lehmann, closes: #101741).
331
  * && and || in arithmetic expansions now return either 0 or 1.
332
333
 -- Herbert Xu <herbert@debian.org>  Sun, 24 Jun 2001 20:14:29 +1000
334
335
ash (0.3.8-11) unstable; urgency=low
336
337
  * Check for NULL argument in evaltree() (closes: #98865, #98867).
338
339
 -- Herbert Xu <herbert@debian.org>  Sun, 27 May 2001 17:53:14 +1000
340
341
ash (0.3.8-10) unstable; urgency=low
342
343
  * Use /bin/ash in postinst to sidestep bugs in other shells (closes: #98739).
344
  * Exit status is now tested on non-negated pipelines (closes: #98736).
345
346
 -- Herbert Xu <herbert@debian.org>  Sat, 26 May 2001 23:56:07 +1000
347
348
ash (0.3.8-9) unstable; urgency=medium
349
350
  * IFS is now fetched using bltinlookup() again in read (closes: #98343).
351
  * Divert sh(1) man page as well as /bin/sh (closes: #98525).
352
353
 -- Herbert Xu <herbert@debian.org>  Fri, 25 May 2001 20:30:06 +1000
354
355
ash (0.3.8-8) unstable; urgency=low
356
357
  * Fixed diversion removal in prerm (duh, closes: #98031).
358
359
 -- Herbert Xu <herbert@debian.org>  Mon, 21 May 2001 20:52:48 +1000
360
361
ash (0.3.8-7) unstable; urgency=low
362
363
  * Fixed diversion test in prerm (closes: #98031).
364
365
 -- Herbert Xu <herbert@debian.org>  Sun, 20 May 2001 12:30:53 +1000
366
367
ash (0.3.8-6) unstable; urgency=low
368
369
  * Make sure that fd2 is closed when clearing redirects (closes: #96619).
370
  * Fixed memory corruption in stunalloc().
371
  * The output of export/readonly/set is now correctly quoted.
372
  * Fixed newline eating bug in expbackq().
373
  * Set OLDPWD.
374
  * Removed ash-medium as neither bf or di uses it.
375
  * Wait now waits for all its argument rather than the first one.
376
  * Wait will exit with 129 when interrupted by a signal for a which a trap has
377
    been set.
378
379
 -- Herbert Xu <herbert@debian.org>  Fri, 18 May 2001 21:51:41 +1000
380
381
ash (0.3.8-5) unstable; urgency=low
382
383
  * Added German translation to template file (Sebastian Feltel,
384
    closes: #96203).
385
  * Added missing initialisation in setalias() (closes: #95433).
386
387
 -- Herbert Xu <herbert@debian.org>  Fri,  4 May 2001 20:54:31 +1000
388
389
ash (0.3.8-4) unstable; urgency=low
390
391
  * Disabled fnmatch code as fnmatch(3) in glibc is broken.
392
  * Fixed echo example in man page (Kalle Olavi Niemitalo, closes: #96014).
393
  * Fixed trailing semicolon bug with eval (NetBSD).
394
  * Fixed globbing inconsistency with broken symlinks (NetBSD).
395
396
 -- Herbert Xu <herbert@debian.org>  Wed,  2 May 2001 22:57:16 +1000
397
398
ash (0.3.8-3) unstable; urgency=low
399
400
  * Work around broken autoconf scripts (closes: #95430).
401
402
 -- Herbert Xu <herbert@debian.org>  Tue,  1 May 2001 18:27:50 +1000
403
404
ash (0.3.8-2) unstable; urgency=low
405
406
  * Save checkalias before calling xxreadtoken() (closes: #95628).
407
408
 -- Herbert Xu <herbert@debian.org>  Sun, 29 Apr 2001 17:36:01 +1000
409
410
ash (0.3.8-1) unstable; urgency=low
411
412
  * NetBSD-current version as of 20010316.
413
  * Removed code that sets IFS.
414
  * Fixed memory leak with PWD.
415
  * Set PPID.
416
  * Fixed inconsistencies in alias expansion.
417
  * Restored original output code.
418
  * Enabled fnmatch code again.
419
  * Added builtin printf.
420
  * Offer to divert /bin/sh (closes: #70462).
421
422
 -- Herbert Xu <herbert@debian.org>  Wed, 25 Apr 2001 22:32:39 +1000
423
424
ash (0.3.7-16) unstable; urgency=low
425
426
  * Fixed incorrect default IFS in readcmd (closes: #88950).
427
  * Added missing return in hashcmd.
428
429
 -- Herbert Xu <herbert@debian.org>  Fri,  9 Mar 2001 20:44:40 +1100
430
431
ash (0.3.7-15) unstable; urgency=low
432
433
  * Unknown escape codes are now prnted literally by echo (closes: #82869).
434
  * Made hetio_read_input() fail if fd is not stdin.
435
  * Some uses of VSQUOTE were really meant to be quotes (closes: #88777).
436
  * Build different ashes in different subdirectories.
437
438
 -- Herbert Xu <herbert@debian.org>  Thu,  8 Mar 2001 21:32:28 +1100
439
 
440
ash (0.3.7-14) unstable; urgency=low
441
442
  * Removed predependency from udeb (closes: #81995).
443
  * Added /bin/sh symlink to udeb (closes: #81967).
444
445
 -- Herbert Xu <herbert@debian.org>  Sat, 13 Jan 2001 15:23:21 +1100
446
447
ash (0.3.7-13) unstable; urgency=low
448
449
  * Renamed the udeb to ash-udeb.
450
451
 -- Herbert Xu <herbert@debian.org>  Wed, 20 Dec 2000 19:32:34 +1100
452
453
ash (0.3.7-12) unstable; urgency=low
454
455
  * Added support for udebs (Randolph Chung, closes: #79237).
456
457
 -- Herbert Xu <herbert@debian.org>  Sat, 16 Dec 2000 13:53:28 +1100
458
459
ash (0.3.7-11) unstable; urgency=low
460
461
  * Preserve the previous exit status upon entering a function
462
    (closes: #78374).
463
464
 -- Herbert Xu <herbert@debian.org>  Sun,  3 Dec 2000 13:34:27 +1100
465
466
ash (0.3.7-10) unstable; urgency=low
467
468
  * Merged changes for GNU from Igor Khavkine.
469
  * Minimise the number of sigactions.
470
471
 -- Herbert Xu <herbert@debian.org>  Fri,  3 Nov 2000 20:31:52 +1100
472
473
ash (0.3.7-9) unstable; urgency=low
474
475
  * Predepend on the libraries.
476
  * Always save fd 2 when it is redirected (closes: #75302).
477
478
 -- Herbert Xu <herbert@debian.org>  Sun, 22 Oct 2000 08:40:40 +1100
479
480
ash (0.3.7-8) unstable; urgency=high
481
482
  * More redirection fixes (closes: #73613).
483
484
 -- Herbert Xu <herbert@debian.org>  Thu,  5 Oct 2000 18:22:17 +1100
485
486
ash (0.3.7-7) unstable; urgency=high
487
488
  * Added missing break in redirection code (closes: #72956).
489
490
 -- Herbert Xu <herbert@debian.org>  Tue,  3 Oct 2000 07:58:04 +1100
491
492
ash (0.3.7-6) unstable; urgency=low
493
494
  * command -[vV] no longer displays an error message on stdout.
495
  * Redirecting to /proc/self/fd/* now works (closes: #72852).
496
497
 -- Herbert Xu <herbert@debian.org>  Sun,  1 Oct 2000 12:56:39 +1100
498
499
ash (0.3.7-5) unstable; urgency=low
500
501
  * Implemented set -a.
502
503
 -- Herbert Xu <herbert@debian.org>  Sat, 30 Sep 2000 16:00:33 +1100
504
505
ash (0.3.7-4) unstable; urgency=low
506
507
  * Added build-time dependency on debhelper (closes: #69920).
508
  * Extended maximum length of arithmetic expansions to match 32-bit integers.
509
510
 -- Herbert Xu <herbert@debian.org>  Wed, 20 Sep 2000 14:28:16 +1100
511
512
ash (0.3.7-3) unstable; urgency=low
513
514
  * Switch to the old globbing code since glob(3) is hopelessly broken
515
    (closes: #69455).
516
517
 -- Herbert Xu <herbert@debian.org>  Mon, 21 Aug 2000 20:37:15 +1000
518
519
ash (0.3.7-2) unstable; urgency=low
520
521
  * Call glob(3) with GLOB_NOMAGIC (ouch).
522
523
 -- Herbert Xu <herbert@debian.org>  Sun,  6 Aug 2000 17:47:08 +1000
524
525
ash (0.3.7-1) unstable; urgency=low
526
527
  * NetBSD-current version as of 20000729.
528
  * Use fnmatch(3) and glob(3).
529
  * Fixed the use of backslashes in the pattern in parameter substitutions,
530
    hopefully for the last time.
531
  * Applied HETIO patch and built ash.medium (closes: #50788).  Will do ash.big
532
    when readline is fixed so that it doesn't leak anymore.
533
534
 -- Herbert Xu <herbert@debian.org>  Fri,  4 Aug 2000 21:36:44 +1000
535
536
ash (0.3.6-5) unstable; urgency=low
537
538
  * Fixed manpage entry for read with patch from Kevin Ryde (closes: #62500).
539
  * Fixed a file descriptor leak for pipelines.
540
541
 -- Herbert Xu <herbert@debian.org>  Wed, 19 Apr 2000 18:56:20 +1000
542
543
ash (0.3.6-4) unstable; urgency=low
544
545
  * Fixed the case of an empty command with redirections.
546
547
 -- Herbert Xu <herbert@debian.org>  Fri,  7 Apr 2000 12:07:18 +1000
548
549
ash (0.3.6-3) unstable; urgency=low
550
551
  * ! is now recognised correctly.
552
  * Ash is now more strict on the syntax, e.g., a lone ! is no longer accepted
553
    as an alternative to ! true.
554
555
 -- Herbert Xu <herbert@debian.org>  Fri,  7 Apr 2000 10:46:06 +1000
556
557
ash (0.3.6-2) unstable; urgency=low
558
559
  * Fixed a problem with fmtstr() which broke getopts.
560
561
 -- Herbert Xu <herbert@debian.org>  Sun,  2 Apr 2000 10:49:26 +1000
562
563
ash (0.3.6-1) unstable; urgency=low
564
565
  * NetBSD-current version as of 20000326.
566
  * Added a Build-Depends on groff (closes: #61041).
567
  * Implemented noclobber (closes: #59028).
568
  * Rewrote output.c to use stream IO.
569
570
 -- Herbert Xu <herbert@debian.org>  Sat,  1 Apr 2000 19:24:31 +1000
571
572
ash (0.3.5-10) frozen unstable; urgency=low
573
574
  * Don't stat mail boxes in non-interactive mode (closes: #59213).
575
  * Added an fflush(stdout) to the times builtin (closes: #59027).
576
  * Documented the times builtin.
577
  * Added source depends.
578
579
 -- Herbert Xu <herbert@debian.org>  Sat, 18 Mar 2000 18:58:44 +1100
580
581
ash (0.3.5-9) unstable; urgency=low
582
583
  * Double quotes inside paramater substitutions inside double quotes are now
584
    ignored as in bash (the originial behaviour was POSIX compliant too but
585
    IMHO this one makes a little bit more sense).
586
    This one broke mwm (but it was actually mwm's fault).
587
  * Corrected backslash/CTLESC treatment for patterns in parameter
588
    substitutions.
589
590
 -- Herbert Xu <herbert@debian.org>  Sat,  6 Nov 1999 18:13:19 +1100
591
592
ash (0.3.5-8) unstable; urgency=low
593
594
  * Replaced use of echo -n in manual page with escape codes.
595
  * Made FHS compliant (closes: #47978).
596
  * Restored echo's option processing ability.
597
598
 -- Herbert Xu <herbert@debian.org>  Fri, 22 Oct 1999 10:20:58 +1000
599
600
ash (0.3.5-7) unstable; urgency=low
601
602
  * echo no longer supports options.
603
  * Don't quote patterns inside parameter substitutions enclosed by double
604
    quotes (closes: #47842).
605
606
 -- Herbert Xu <herbert@debian.org>  Wed, 20 Oct 1999 20:28:14 +1000
607
608
ash (0.3.5-6) unstable; urgency=low
609
610
  * Use getcwd() instead of /bin/pwd -- Zack Weinberg (closes: #46981).
611
612
 -- Herbert Xu <herbert@debian.org>  Sun, 10 Oct 1999 16:31:49 +1000
613
614
ash (0.3.5-5) unstable; urgency=low
615
616
  * Only test for -e on simple commands (fixes #44559).
617
618
 -- Herbert Xu <herbert@debian.org>  Wed,  8 Sep 1999 22:18:27 +1000
619
620
ash (0.3.5-4) unstable; urgency=low
621
622
  * Don't wait for stopped children if job control is disabled (fixes #42814).
623
  * Allow an option '(' in a case statement (fixes #42364).
624
625
 -- Herbert Xu <herbert@debian.org>  Thu, 12 Aug 1999 23:30:30 +1000
626
627
ash (0.3.5-3) unstable; urgency=low
628
629
  * OK, the fix to the esoteric problem in 0.3.5-1 actually breaks VSASSIGN
630
    and VSQUESTION, they should work properly now (fixes #41327).
631
632
 -- Herbert Xu <herbert@debian.org>  Thu, 15 Jul 1999 22:47:13 +1000
633
634
ash (0.3.5-2) unstable; urgency=low
635
636
  * PATH search and execution is now correct.
637
  * hash no longer shows builtins.
638
  * Added kill builtin.
639
  * New description from James R. van Zandt reformatted by Josip Rodin.
640
641
 -- Herbert Xu <herbert@debian.org>  Mon, 12 Jul 1999 18:51:42 +1000
642
643
ash (0.3.5-1) unstable; urgency=low
644
645
  * New upstream release.
646
  * Adapted to new pmake (fixes #38737).
647
  * Fixed behvaiour of backslashes preceding a closing brace for a parameter
648
    substituion inside double quotes (even bash messes this one up :).
649
  * Fixed command (fixes #34639).
650
  * Fixed a pipe bug where stdin may be wrongly closed (fixes #35452).
651
  * Revamped getopts (fixes #39694).
652
653
 -- Herbert Xu <herbert@debian.org>  Sun,  4 Jul 1999 12:19:01 +1000
654
655
ash (0.3.4-7) unstable; urgency=low
656
657
  * Fixed a glibc 2.1 compatitibility problem.
658
  * Fixed a PWD inconsistency that stuffed up the kernel compilation.
659
660
 -- Herbert Xu <herbert@debian.org>  Mon, 17 May 1999 23:14:57 +1000
661
662
ash (0.3.4-6) unstable; urgency=low
663
664
  * Fixed incorrect -e test due to the last bug fix (fixes #26509).
665
666
 -- Herbert Xu <herbert@debian.org>  Tue,  8 Sep 1998 10:02:46 +1000
667
668
ash (0.3.4-5) unstable; urgency=low
669
670
  * Use test_eaccess from bash instead of access(2) (fixes #26110).
671
672
 -- Herbert Xu <herbert@debian.org>  Wed, 26 Aug 1998 21:22:49 +1000
673
674
ash (0.3.4-4) unstable; urgency=low
675
676
  * Only upload to unstable.
677
678
 -- Herbert Xu <herbert@debian.org>  Tue,  5 May 1998 18:01:02 +1000
679
680
ash (0.3.4-3) frozen unstable; urgency=low
681
682
  * Applied sparc patch (fixes #21562).
683
684
 -- Herbert Xu <herbert@debian.org>  Fri,  1 May 1998 19:48:13 +1000
685
686
ash (0.3.4-2) frozen unstable; urgency=low
687
688
  * Fixed the incorrect trap fixes (fixes #20363).
689
690
 -- Herbert Xu <herbert@debian.org>  Thu, 16 Apr 1998 21:07:10 +1000
691
692
ash (0.3.4-1) unstable; urgency=low
693
694
  * New upstream release.
695
  * Reverted word splitting change in 0.3.2-1 since the fix was broken and
696
    major work (the quote removal is done too quickly at the moment) is needed
697
    to fix it properly.
698
  * Fixed more trap noncompliance.
699
700
 -- Herbert Xu <herbert@debian.org>  Thu, 19 Mar 1998 22:59:12 +1100
701
702
ash (0.3.2-5) unstable; urgency=low
703
704
  * Fixed a bug when doing pattern matching in parameter expansions.
705
706
 -- Herbert Xu <herbert@debian.org>  Tue, 10 Mar 1998 21:25:40 +1100
707
708
ash (0.3.2-4) unstable; urgency=low
709
710
  * Allow ] to be quoted in bracket expressions (fixes #17533).
711
  * Move dh_fixperms to second last spot (fixes #18267).
712
  * Don't do field splitting in evalfor.
713
714
 -- Herbert Xu <herbert@debian.org>  Tue, 17 Feb 1998 13:32:09 +1100
715
716
ash (0.3.2-3) unstable; urgency=low
717
718
  * Fixed stupid core dump.
719
720
 -- Herbert Xu <herbert@debian.org>  Wed, 11 Feb 1998 21:33:55 +1100
721
722
ash (0.3.2-2) unstable; urgency=low
723
724
  * Hack for special builtins (fixes #18055).
725
  * Hack for command.
726
727
 -- Herbert Xu <herbert@debian.org>  Wed, 11 Feb 1998 21:19:46 +1100
728
729
ash (0.3.2-1) unstable; urgency=low
730
731
  * NetBSD-current version as of 19980209.
732
  * Fixed a word splitting problem after parameter expansion thanks to Alexey
733
    Marinichev.
734
  * Converted to debhelper (fixes #14612, #15005).
735
736
 -- Herbert Xu <herbert@debian.org>  Mon,  9 Feb 1998 16:53:48 +1100
737
738
ash (0.3.1-20) unstable; urgency=low
739
740
  * Fixed -e problem with eval.
741
742
 -- Herbert Xu <herbert@debian.org>  Sun,  7 Dec 1997 20:19:00 +1100
743
744
ash (0.3.1-19) unstable; urgency=low
745
746
  * Fixed -e problem with command substitution.
747
748
 -- Herbert Xu <herbert@debian.org>  Sun,  7 Dec 1997 19:44:49 +1100
749
750
ash (0.3.1-18) unstable; urgency=low
751
752
  * Do not link with ncurses (#15485).
753
754
 -- Herbert Xu <herbert@debian.org>  Sun, 30 Nov 1997 12:00:11 +1100
755
756
ash (0.3.1-17) unstable; urgency=low
757
758
  * Set PATH like bash (#15238).
759
760
 -- Herbert Xu <herbert@debian.org>  Wed, 26 Nov 1997 16:17:27 +1100
761
762
ash (0.3.1-16) unstable; urgency=low
763
764
  * Fixed incorrect assignment builtin code.
765
766
 -- Herbert Xu <herbert@debian.org>  Mon, 24 Nov 1997 16:19:10 +1100
767
768
ash (0.3.1-15) unstable; urgency=low
769
770
  * hash now returns error codes (needed by the Linux kernel).
771
772
 -- Herbert Xu <herbert@debian.org>  Sun, 23 Nov 1997 21:37:08 +1100
773
774
ash (0.3.1-14) unstable; urgency=low
775
776
  * Disabled word-splitting for assignment builtins.
777
778
 -- Herbert Xu <herbert@debian.org>  Sun, 23 Nov 1997 12:45:15 +1100
779
780
ash (0.3.1-13) unstable; urgency=low
781
782
  * ! is now recognised even after &&/||.
783
784
 -- Herbert Xu <herbert@debian.org>  Fri, 21 Nov 1997 22:09:05 +1100
785
786
ash (0.3.1-12) unstable; urgency=low
787
788
  * More fixes to the handling of SIGINT when forking.
789
790
 -- Herbert Xu <herbert@debian.org>  Fri, 14 Nov 1997 15:14:32 +1100
791
792
ash (0.3.1-11) unstable; urgency=low
793
794
  * Ignore SIGINT when forking non-interactively.
795
796
 -- Herbert Xu <herbert@debian.org>  Mon,  3 Nov 1997 12:00:02 +1100
797
798
ash (0.3.1-10) unstable; urgency=low
799
800
  * echo now handles options correctly.
801
  * echo nolonger returns 0 if erorrs occured while writing to stdout.
802
  * New code from GNU echo merged.
803
  * Error messages from test now work.
804
805
 -- Herbert Xu <herbert@debian.org>  Wed,  8 Oct 1997 21:47:13 +1000
806
807
ash (0.3.1-9) unstable; urgency=low
808
809
  * ! is recognised at pipeline level like bash.
810
811
 -- Herbert Xu <herbert@debian.org>  Mon, 15 Sep 1997 23:13:45 +1000
812
813
ash (0.3.1-8) unstable; urgency=medium
814
815
  * Old patch regarding SIGCHLD in again.
816
817
 -- Herbert Xu <herbert@debian.org>  Sun, 31 Aug 1997 11:20:27 +1000
818
819
ash (0.3.1-7) unstable; urgency=low
820
821
  * /bin/sh -e is behaving even better now (for loops within conditionals).
822
823
 -- Herbert Xu <herbert@debian.org>  Sat, 23 Aug 1997 22:08:19 +1000
824
825
ash (0.3.1-6) unstable; urgency=low
826
827
  * /bin/sh -e is behaving better now.
828
829
 -- Herbert Xu <herbert@debian.org>  Sat, 23 Aug 1997 13:16:26 +1000
830
831
ash (0.3.1-5) unstable; urgency=low
832
833
  * hash -v /dir/command doesn't coredump anymore.
834
  * type /dir/command now works correctly.
835
836
 -- Herbert Xu <herbert@debian.org>  Fri,  1 Aug 1997 20:48:19 +1000
837
838
ash (0.3.1-4) unstable; urgency=low
839
840
  * trap now understands symbolic signal names.
841
842
 -- Herbert Xu <herbert@debian.org>  Sat, 26 Jul 1997 14:04:46 +1000
843
844
ash (0.3.1-3) unstable; urgency=low
845
846
  * Added the builtin test command.
847
848
 -- Herbert Xu <herbert@debian.org>  Sun, 20 Jul 1997 15:00:14 +1000
849
850
ash (0.3.1-2) unstable; urgency=medium
851
852
  * Fixed a coredump involving $*.
853
854
 -- Herbert Xu <herbert@debian.org>  Sat, 19 Jul 1997 12:03:02 +1000
855
856
ash (0.3.1-1) unstable; urgency=medium
857
858
  * NetBSD-current version as of 19970715.
859
  * Fixed a "use after free" bug (#11294).
860
861
 -- Herbert Xu <herbert@debian.org>  Fri, 18 Jul 1997 13:48:09 +1000
862
863
ash (0.3-1) unstable; urgency=low
864
865
  * Initial Release.
866
867
 -- Herbert Xu <herbert@debian.org>  Thu, 19 Jun 1997 19:29:16 +1000
868
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/compat (+1 lines)
Line 0 Link Here
1
4
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/control (+53 lines)
Line 0 Link Here
1
Source: dash
2
Section: shells
3
Priority: optional
4
Maintainer: Herbert Xu <herbert@debian.org>
5
Build-Depends: byacc, debhelper (>= 4), pmake
6
Standards-Version: 3.5.8
7
8
Package: dash
9
Architecture: any
10
Pre-Depends: ${shlibs:Depends}
11
Description: The Debian Almquist Shell
12
 "dash" is a POSIX compliant shell that is much smaller than "bash".
13
 We take advantage of that by making it the shell on the installation
14
 root floppy, where space is at a premium.
15
 .
16
 It can be usefully installed as /bin/sh (because it executes scripts
17
 somewhat faster than "bash"), or as the default shell either of root
18
 or of a second user with a userid of 0 (because it depends on fewer
19
 libraries, and is therefore less likely to be affected by an upgrade
20
 problem or a disk failure).  It is also useful for checking that a
21
 script uses only POSIX syntax.
22
 .
23
 "bash" is a better shell for most users, since it has some nice
24
 features absent from "dash", and is a required part of the system.
25
26
Package: dash-udeb
27
Architecture: any
28
Depends: ${shlibs:Depends}
29
Section: debian-installer
30
Priority: standard
31
Description: The Debian Almquist Shell for boot floppies
32
 "dash" is a POSIX compliant shell that is much smaller than "bash".
33
 We take advantage of that by making it the shell on the installation
34
 root floppy, where space is at a premium.
35
 .
36
 It can be usefully installed as /bin/sh (because it executes scripts
37
 somewhat faster than "bash"), or as the default shell either of root
38
 or of a second user with a userid of 0 (because it depends on fewer
39
 libraries, and is therefore less likely to be affected by an upgrade
40
 problem or a disk failure).  It is also useful for checking that a
41
 script uses only POSIX syntax.
42
 .
43
 "bash" is a better shell for most users, since it has some nice
44
 features absent from "dash", and is a required part of the system.
45
46
Package: ash
47
Architecture: all
48
Pre-Depends: dash
49
Description: Compatibility package for the Debian Almquist Shell
50
 This package exists so that users of the "ash" package can upgrade to the
51
 "dash" package which replaces the former.  It includes the /bin/ash symlink.
52
 You can remove this package if you do not use /bin/ash explicitly.
53
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/copyright (+44 lines)
Line 0 Link Here
1
This package was debianized by Mark W. Eichin eichin@kitten.gen.ma.us on
2
Mon, 24 Feb 1997 16:00:16 -0500.
3
4
This package was re-ported from NetBSD and debianized by
5
Herbert Xu herbert@debian.org on Thu, 19 Jun 1997 19:29:16 +1000.
6
7
It was downloaded from ftp.netbsd.org.
8
9
Copyright:
10
11
Copyright (c) 1989-1994
12
	The Regents of the University of California.  All rights reserved.
13
Copyright (c) 1997-2002
14
	Herbert Xu <herbert@debian.org>
15
16
This code is derived from software contributed to Berkeley by Kenneth Almquist.
17
18
Please refer to /usr/share/common-licenses/BSD for details.
19
20
mksignames.c:
21
22
This file is not directly linked with dash.  However, its output is.
23
24
Copyright (C) 1992 Free Software Foundation, Inc.
25
26
This file is part of GNU Bash, the Bourne Again SHell.
27
28
Bash is free software; you can redistribute it and/or modify it under
29
the terms of the GNU General Public License as published by the Free
30
Software Foundation; either version 2, or (at your option) any later
31
version.
32
33
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
34
WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
36
for more details.
37
38
You should have received a copy of the GNU General Public License with
39
your Debian GNU/Linux system, in /usr/share/common-licenses/GPL, or with the
40
Debian GNU/Linux hello source package as the file COPYING.  If not,
41
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
42
Boston, MA 02111 USA.
43
44
$Id: copyright,v 1.6 2003/01/01 01:51:50 herbert Exp $
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.config (+39 lines)
Line 0 Link Here
1
#!/bin/sh
2
#
3
# debconf script for the Debian GNU/Linux ash package
4
#
5
# $Id: dash.config,v 1.1 2002/09/14 06:17:50 herbert Exp $
6
7
set -e
8
9
. /usr/share/debconf/confmodule
10
11
db_version 2.0
12
13
if [ "$1" = configure ] && [ -z "$2" ]; then
14
	set +e
15
	db_fget ash/sh seen
16
	err=$?
17
	set -e
18
19
	case $err in
20
	0)
21
		if [ "$RET" = true ]; then
22
			db_fset dash/sh seen true
23
			db_get ash/sh
24
			db_set dash/sh "$RET"
25
			exit
26
		fi
27
		;;
28
	10)
29
		# ash/sh does not exist
30
		;;
31
	*)
32
		echo "db_fget exited with $err" >&2
33
		exit $err
34
		;;
35
	esac
36
fi
37
38
db_input low dash/sh || true
39
db_go
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.dirs (+2 lines)
Line 0 Link Here
1
bin
2
usr/share/man/man1
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.postinst (+81 lines)
Line 0 Link Here
1
#!/bin/sh
2
#
3
# post-install script for the Debian GNU/Linux dash package
4
#
5
# $Id: dash.postinst,v 1.3 2002/10/26 11:26:55 herbert Exp $
6
7
set -e
8
9
check_divert() {
10
	div=$(dpkg-divert --list $2)
11
	distrib=${4:-$2.distrib}
12
	case "$1" in
13
	true)
14
		if [ -z "$div" ]; then
15
			dpkg-divert --package dash --divert $distrib --add $2
16
			cp -dp $2 $distrib
17
			ln -sf $3 $2
18
		fi
19
		;;
20
	false)
21
		if [ -n "$div" ] && [ -z "${div%%*by dash}" ]; then
22
			mv $distrib $2
23
			dpkg-divert --remove $2
24
		fi
25
		;;
26
	ash)
27
		case $div in
28
		'')
29
			;;
30
		*by\ ash)
31
			dst=${div% by ash}
32
			dst=${dst##* to }
33
34
			# Work around dpkg-divert bug.
35
			if [ -e "$dst" ]; then
36
				mv "$dst" "$dst.dash-tmp"
37
			fi
38
			dpkg-divert --remove $2
39
			if [ -e "$dst.dash-tmp" ]; then
40
				mv "$dst.dash-tmp" "$dst"
41
			fi
42
43
			dpkg-divert --package dash --divert $distrib --add $2
44
			if [ "$dst" != $distrib ] && [ -e "$dst" ]; then
45
				mv "$dst" $distrib
46
			fi
47
			ln -sf $3 $2
48
			;;
49
		*)
50
			d=${2%/*}
51
			if
52
				[ -h $2 ] && [ -f $2 ] && [ -f $d/$5 ] &&
53
				cmp $2 $d/$5
54
			then
55
				ln -sf $3 $2
56
			fi
57
			;;
58
		esac
59
	esac
60
}
61
62
debconf=
63
if [ -f /usr/share/debconf/confmodule ]; then
64
	. /usr/share/debconf/confmodule
65
	debconf=yes
66
fi
67
68
if [ "$1" = configure ] && [ -z "$2" ]; then
69
	check_divert ash /bin/sh dash '' ash
70
	check_divert ash /usr/share/man/man1/sh.1.gz dash.1.gz \
71
		/usr/share/man/man1/sh.distrib.1.gz ash.1.gz
72
fi
73
74
if [ $debconf ]; then
75
	db_get dash/sh
76
	check_divert "$RET" /bin/sh dash
77
	check_divert "$RET" /usr/share/man/man1/sh.1.gz dash.1.gz \
78
		/usr/share/man/man1/sh.distrib.1.gz
79
fi
80
81
#DEBHELPER#
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.prerm (+24 lines)
Line 0 Link Here
1
#!/bin/sh
2
#
3
# pre-removal script for the Debian GNU/Linux ash package
4
#
5
# $Id: dash.prerm,v 1.1 2002/09/14 06:17:50 herbert Exp $
6
7
set -e
8
9
remove_divert() {
10
	div=$(dpkg-divert --list $1)
11
	if [ -n "$div" ] && [ -z "${div%%*by dash}" ]; then
12
		distrib=${div% by dash}
13
		distrib=${distrib##* to }
14
		mv $distrib $1
15
		dpkg-divert --remove $1
16
	fi
17
}
18
19
if [ "$1" = remove ] || [ "$1" = deconfigure ]; then
20
	remove_divert /bin/sh
21
	remove_divert /usr/share/man/man1/sh.1.gz
22
fi
23
24
#DEBHELPER#
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates (+10 lines)
Line 0 Link Here
1
Template: dash/sh
2
Type: boolean
3
Default: false
4
Description: Install dash as /bin/sh?
5
 Bash is the default /bin/sh on a Debian system.  However, since our policy
6
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
7
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
8
 it can be used as /bin/sh.  You may wish to do this because dash is faster
9
 and smaller than bash.
10
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.de (+13 lines)
Line 0 Link Here
1
Template: dash/sh
2
Description: Install dash as /bin/sh?
3
 Bash is the default /bin/sh on a Debian system.  However, since our policy
4
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
5
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
6
 it can be used as /bin/sh.
7
Description-de: dash als /bin/sh installieren?
8
 Bash ist die Standard-Shell (/bin/sh) auf einem Debian-System. Da die
9
 Debian-Policy von allen Shellscripts, die /bin/sh benutzen,
10
 POSIX-Kompatibilität verlangt, kann für /bin/sh jede POSIX-kompatible Shell
11
 benutzt werden. Dash ist POSIX-kompatibel und kann daher als /bin/sh verwendet
12
 werden.
13
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.es (+13 lines)
Line 0 Link Here
1
Template: dash/sh
2
Description: Install dash as /bin/sh?
3
 Bash is the default /bin/sh on a Debian system.  However, since our policy
4
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
5
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
6
 it can be used as /bin/sh.
7
Description-es: ¿Instalar dash como /bin/sh?
8
 Bash es el intérprte de comandos /bin/sh por defecto de los sistemas Debian.
9
 Sin embargo, dado que nuestras normas obligan a que todos los scripts para el
10
 intérprete de comandos se atengan a las normas POSIX, cualquier intérprete
11
 compatible con POSIX puede servir como /bin/sh.  Puesto que dash lo es, puede
12
 usarse como /bin/sh.
13
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.fr (+12 lines)
Line 0 Link Here
1
Template: dash/sh
2
Description: Install dash as /bin/sh?
3
 Bash is the default /bin/sh on a Debian system.  However, since our policy
4
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
5
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
6
 it can be used as /bin/sh.
7
Description-fr: Mettre un lien de /bin/sh vers dash ?
8
 Sur un système Debian, /bin/sh est bash par défaut. Cependant, comme notre
9
 charte impose que tous les scripts shells utilisant /bin/sh soient conformes
10
 à la norme POSIX, /bin/sh peut être n'importe quel shell conforme à cette
11
 norme. Et comme dash l'est, il peut servir de /bin/sh.
12
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.ja (+13 lines)
Line 0 Link Here
1
Template: dash/sh
2
Description: Install dash as /bin/sh?
3
 Bash is the default /bin/sh on a Debian system.  However, since our policy
4
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
5
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
6
 it can be used as /bin/sh.
7
Description-ja: dash ¤ò /bin/sh ¤È¤·¤Æ¥¤¥ó¥¹¥È¡¼¥ë¤·¤Þ¤¹¤«?
8
 Debian ¥·¥¹¥Æ¥à¤Ç¤Ï bash ¤¬¥Ç¥Õ¥©¥ë¥È¤Î /bin/sh ¤Ç¤¹¡£¤·¤«¤·¡¢Debian
9
 ¤Î¥Ý¥ê¥·¡¼¤Ë¤è¤Ã¤Æ¡¢/bin/sh ¤òÍѤ¤¤ëÁ´¤Æ¤Î¥·¥§¥ë¥¹¥¯¥ê¥×¥È¤Ï POSIX
10
 ½àµò¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤¿¤á¡¢POSIX ¤òËþ¤¿¤¹¥·¥§¥ë¤Ï¤É¤ì¤Ç¤â /bin/sh
11
 ¤È¤Ê¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£dash ¤Ï POSIX ½àµò¤Ç¤¹¤Î¤Ç¡¢/bin/sh ¤È¤·¤Æ»È¤¦
12
 ¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
13
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.pt_BR (+12 lines)
Line 0 Link Here
1
Template: dash/sh
2
Description: Install dash as /bin/sh?
3
 Bash is the default /bin/sh on a Debian system.  However, since our policy
4
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
5
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
6
 it can be used as /bin/sh.
7
Description-pt_BR: Instalar dash como /bin/sh ?
8
 Bash é o /bin/sh padrão em um sistema Debian. Porém, uma vez que nossa
9
 política requer que todos os shell scripts usando /bin/sh sejam compatíveis
10
 POSIX, qualquer shell que esteja em conformidade POSIX pode servir como
11
 /bin/sh. Uma vez que dash é compatível POSIX, pode ser usado como /bin/sh.
12
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.ru (+13 lines)
Line 0 Link Here
1
Template: dash/sh
2
Description: Install dash as /bin/sh?
3
 Bash is the default /bin/sh on a Debian system.  However, since our policy
4
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
5
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
6
 it can be used as /bin/sh.
7
Description-ru: õÓÔÁÎÏ×ÉÔØ dash ËÁË /bin/sh?
8
 Bash - ÜÔÏ /bin/sh ÐÏ ÕÍÏÌÞÁÎÉÀ × ÓÉÓÔÅÍÅ Debian. ïÄÎÁËÏ, ÔÁË ËÁË ÎÁÛÁ
9
 ÐÏÌÉÔÉËÁ  ÔÒÅÂÕÅÔ,  ÞÔÏÂÙ ×ÓÅ ÓÃÅÎÁÒÉÉ ÏÂÏÌÏÞËÉ, ÉÓÐÏÌØÚÕÀÝÉÅ /bin/sh,
10
 ÂÙÌÉ  ÓÏ×ÍÅÓÔÉÍÙÍÉ  Ó  POSIX,  ÔÏ  ÒÁÂÏÔÁÔØ  ËÁË  /bin/sh  ÍÏÖÅÔ ÌÀÂÁÑ 
11
 ÏÂÏÌÏÞËÁ,  ÓÏ×ÍÅÓÔÉÍÁÑ  Ó  POSIX. ôÁË ËÁË dash ÓÏ×ÍÅÓÔÉÍ Ó POSIX, ÔÏ ÏÎ
12
 ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØÓÑ ËÁË /bin/sh.
13
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash.templates.sv (+13 lines)
Line 0 Link Here
1
Template: dash/sh
2
Type: boolean
3
Description: Install dash as /bin/sh?
4
 Bash is the default /bin/sh on a Debian system.  However, since our policy
5
 requires all shell scripts using /bin/sh to be POSIX compliant, any shell
6
 that conforms to POSIX can serve as /bin/sh.  Since dash is POSIX compliant,
7
 it can be used as /bin/sh.
8
Description-sv: Installera dash som /bin/sh?
9
 Bash är standardinställningen för /bin/sh på Debiansystem.  Eftersom vår
10
 policy kräver att alla script som använder /bin/sh måste vara
11
 POSIX-kompatibla, kan vilket POSIX-kompatibelt skal som helst vara /bi/sh.  Då
12
 dash är POSIX-kompatibelt kan det användas som /bin/sh.
13
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/dash-udeb.dirs (+1 lines)
Line 0 Link Here
1
bin
(-)bin_NetBSD-1.6release.orig/src/bin/sh/debian/rules (+101 lines)
Line 0 Link Here
1
#!/usr/bin/make -f
2
# $Id: rules,v 1.38 2002/12/16 08:07:10 herbert Exp $
3
4
# Uncomment this to turn on verbose mode.
5
#export DH_VERBOSE=1
6
7
# This has to be exported to make some magic below work.
8
export DH_OPTIONS
9
10
DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH)
11
12
CDEF := \
13
	-Wall -DBSD=1 -DSMALL -D_GNU_SOURCE -DGLOB_BROKEN -DHAVE_VASPRINTF=1 \
14
	-DIFS_BROKEN -DGCC_BROKEN_NG \
15
	-D__COPYRIGHT\(x\)= -D__RCSID\(x\)= -D_DIAGASSERT\(x\)=
16
17
OPT := -g -O2 -fstrict-aliasing
18
OPTSM := -g -Os -fstrict-aliasing -fomit-frame-pointer -DREALLY_SMALL
19
20
ifeq ($(DEB_HOST_ARCH),i386)
21
OPTSM += \
22
	-malign-loops=0 -malign-jumps=0 -malign-functions=0 \
23
	-mpreferred-stack-boundary=2 -DUSE_NORETURN
24
endif
25
26
setup: setup-stamp
27
setup-stamp:
28
	rm -rf obj obj-udeb
29
	mkdir obj obj-udeb
30
	chmod u+x debian/bsdyacc
31
	touch setup-stamp
32
33
build: setup-stamp
34
	dh_testdir
35
36
	pmake CFLAGS:='$(CDEF) $(OPT)' \
37
		YACC:='$${.CURDIR}/debian/bsdyacc'
38
	MAKEOBJDIR=obj-udeb pmake CFLAGS:='$(CDEF) $(OPTSM)' \
39
		YACC:='$${.CURDIR}/debian/bsdyacc'
40
41
clean:
42
	dh_testdir
43
	dh_testroot
44
	rm -f setup-stamp
45
46
	rm -rf obj obj-udeb
47
48
	dh_clean
49
50
install: build
51
	dh_testdir
52
	dh_testroot
53
	dh_clean -k
54
	dh_installdirs
55
56
	install obj/sh debian/dash/bin/dash
57
	install -m 644 sh.1 debian/dash/usr/share/man/man1/dash.1
58
	install obj-udeb/sh debian/dash-udeb/bin/dash
59
	ln -s dash debian/dash-udeb/bin/sh
60
	ln -s dash debian/ash/bin/ash
61
	ln -s dash.1.gz debian/ash/usr/share/man/man1/ash.1.gz
62
63
# This single target is used to build all the packages, all at once, or
64
# one at a time. So keep in mind: any options passed to commands here will
65
# affect _all_ packages. Anything you want to only affect one package
66
# should be put in another target, such as the install target.
67
binary-common:
68
	dh_testdir
69
	dh_testroot
70
	dh_installdebconf
71
	dh_installdocs -Ndash-udeb
72
	dh_installexamples
73
	dh_installmenu
74
	dh_installcron
75
	dh_installchangelogs -Ndash-udeb
76
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
77
	dh_strip
78
endif
79
	dh_compress
80
	dh_fixperms
81
	dh_installdeb -Ndash-udeb
82
	dh_shlibdeps
83
	dh_gencontrol
84
	dh_md5sums
85
	dh_builddeb
86
87
# Build architecture-independent files here.
88
binary-indep: install
89
	$(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
90
91
# Build architecture-dependent files here.
92
binary-arch: install
93
	$(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
94
95
	for i in ../dash-udeb_*.deb; do mv $$i $${i%deb}udeb; done
96
	sed '/^[^ ]*\.udeb/d; s/^\(dash-udeb_[^ ]*\.\)deb/\1udeb/' \
97
		debian/files > debian/files.new
98
	mv debian/files.new debian/files
99
100
binary: binary-indep binary-arch
101
.PHONY: build clean binary-indep binary-arch binary binary-common install setup
(-)bin_NetBSD-1.6release.orig/src/bin/sh/error.c (-111 / +71 lines)
Lines 1-4 Link Here
1
/*	$NetBSD: error.c,v 1.24 2002/05/15 16:33:35 christos Exp $	*/
1
/*	$NetBSD: error.c,v 1.25 2002/05/25 23:09:06 wiz Exp $	*/
2
2
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
Lines 41-47 Link Here
41
#if 0
41
#if 0
42
static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
42
static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
43
#else
43
#else
44
__RCSID("$NetBSD: error.c,v 1.24 2002/05/15 16:33:35 christos Exp $");
44
__RCSID("$NetBSD: error.c,v 1.25 2002/05/25 23:09:06 wiz Exp $");
45
#endif
45
#endif
46
#endif /* not lint */
46
#endif /* not lint */
47
47
Lines 51-56 Link Here
51
51
52
#include <signal.h>
52
#include <signal.h>
53
#include <stdlib.h>
53
#include <stdlib.h>
54
#include <string.h>
54
#include <unistd.h>
55
#include <unistd.h>
55
#include <errno.h>
56
#include <errno.h>
56
57
Lines 60-65 Link Here
60
#include "output.h"
61
#include "output.h"
61
#include "error.h"
62
#include "error.h"
62
#include "show.h"
63
#include "show.h"
64
#include "eval.h"
65
#include "parser.h"
63
66
64
67
65
/*
68
/*
Lines 68-80 Link Here
68
71
69
struct jmploc *handler;
72
struct jmploc *handler;
70
int exception;
73
int exception;
71
volatile int suppressint;
74
int suppressint;
72
volatile int intpending;
75
volatile sig_atomic_t intpending;
73
char *commandname;
74
76
75
77
76
static void exverror __P((int, const char *, va_list))
78
static void exverror(int, const char *, va_list) __attribute__((__noreturn__));
77
    __attribute__((__noreturn__));
79
static void vwarn(const char *, va_list);
78
80
79
/*
81
/*
80
 * Called to raise an exception.  Since C doesn't include exceptions, we
82
 * Called to raise an exception.  Since C doesn't include exceptions, we
Lines 86-93 Link Here
86
exraise(e)
88
exraise(e)
87
	int e;
89
	int e;
88
{
90
{
91
#ifdef DEBUG
89
	if (handler == NULL)
92
	if (handler == NULL)
90
		abort();
93
		abort();
94
#endif
95
	INTOFF;
96
91
	exception = e;
97
	exception = e;
92
	longjmp(handler->loc, 1);
98
	longjmp(handler->loc, 1);
93
}
99
}
Lines 97-125 Link Here
97
 * Called from trap.c when a SIGINT is received.  (If the user specifies
103
 * Called from trap.c when a SIGINT is received.  (If the user specifies
98
 * that SIGINT is to be trapped or ignored using the trap builtin, then
104
 * that SIGINT is to be trapped or ignored using the trap builtin, then
99
 * this routine is not called.)  Suppressint is nonzero when interrupts
105
 * this routine is not called.)  Suppressint is nonzero when interrupts
100
 * are held using the INTOFF macro.  The call to _exit is necessary because
106
 * are held using the INTOFF macro.  (The test for iflag is just
101
 * there is a short period after a fork before the signal handlers are
107
 * defensive programming.)
102
 * set to the appropriate value for the child.  (The test for iflag is
103
 * just defensive programming.)
104
 */
108
 */
105
109
106
void
110
void
107
onint() {
111
onint() {
108
	sigset_t sigset;
109
110
	if (suppressint) {
111
		intpending++;
112
		return;
113
	}
114
	intpending = 0;
112
	intpending = 0;
115
	sigemptyset(&sigset);
113
	if (!(rootshell && iflag)) {
116
	sigprocmask(SIG_SETMASK, &sigset, NULL);
117
	if (rootshell && iflag)
118
		exraise(EXINT);
119
	else {
120
		signal(SIGINT, SIG_DFL);
114
		signal(SIGINT, SIG_DFL);
121
		raise(SIGINT);
115
		raise(SIGINT);
122
	}
116
	}
117
	exraise(EXINT);
123
	/* NOTREACHED */
118
	/* NOTREACHED */
124
}
119
}
125
120
Lines 135-207 Link Here
135
	const char *msg;
130
	const char *msg;
136
	va_list ap;
131
	va_list ap;
137
{
132
{
138
	CLEAR_PENDING_INT;
139
	INTOFF;
140
141
#ifdef DEBUG
133
#ifdef DEBUG
142
	if (msg)
134
	if (msg)
143
		TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
135
		TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
144
	else
136
	else
145
		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
137
		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
146
#endif
138
#endif
147
	if (msg) {
139
	vwarn(msg, ap);
148
		if (commandname)
149
			outfmt(&errout, "%s: ", commandname);
150
		doformat(&errout, msg, ap);
151
		out2c('\n');
152
	}
153
	flushall();
140
	flushall();
154
	exraise(cond);
141
	exraise(cond);
155
	/* NOTREACHED */
142
	/* NOTREACHED */
156
}
143
}
157
144
158
145
159
#ifdef __STDC__
160
void
146
void
161
error(const char *msg, ...)
147
error(const char *msg, ...)
162
#else
163
void
164
error(va_alist)
165
	va_dcl
166
#endif
167
{
148
{
168
#ifndef __STDC__
169
	const char *msg;
170
#endif
171
	va_list ap;
149
	va_list ap;
172
#ifdef __STDC__
150
173
	va_start(ap, msg);
151
	va_start(ap, msg);
174
#else
175
	va_start(ap);
176
	msg = va_arg(ap, const char *);
177
#endif
178
	exverror(EXERROR, msg, ap);
152
	exverror(EXERROR, msg, ap);
179
	/* NOTREACHED */
153
	/* NOTREACHED */
180
	va_end(ap);
154
	va_end(ap);
181
}
155
}
182
156
183
157
184
#ifdef __STDC__
185
void
158
void
186
exerror(int cond, const char *msg, ...)
159
exerror(int cond, const char *msg, ...)
187
#else
188
void
189
exerror(va_alist)
190
	va_dcl
191
#endif
192
{
160
{
193
#ifndef __STDC__
194
	int cond;
195
	const char *msg;
196
#endif
197
	va_list ap;
161
	va_list ap;
198
#ifdef __STDC__
162
199
	va_start(ap, msg);
163
	va_start(ap, msg);
200
#else
201
	va_start(ap);
202
	cond = va_arg(ap, int);
203
	msg = va_arg(ap, const char *);
204
#endif
205
	exverror(cond, msg, ap);
164
	exverror(cond, msg, ap);
206
	/* NOTREACHED */
165
	/* NOTREACHED */
207
	va_end(ap);
166
	va_end(ap);
Lines 223-278 Link Here
223
#define ALL (E_OPEN|E_CREAT|E_EXEC)
182
#define ALL (E_OPEN|E_CREAT|E_EXEC)
224
183
225
STATIC const struct errname errormsg[] = {
184
STATIC const struct errname errormsg[] = {
226
	{ EINTR,	ALL,	"interrupted" },
185
	{ ENOENT,	E_OPEN,	"No such file" },
227
	{ EACCES,	ALL,	"permission denied" },
186
	{ ENOENT,	E_CREAT,"Directory nonexistent" },
228
	{ EIO,		ALL,	"I/O error" },
229
	{ EEXIST,	ALL,	"file exists" },
230
	{ ENOENT,	E_OPEN,	"no such file" },
231
	{ ENOENT,	E_CREAT,"directory nonexistent" },
232
	{ ENOENT,	E_EXEC,	"not found" },
187
	{ ENOENT,	E_EXEC,	"not found" },
233
	{ ENOTDIR,	E_OPEN,	"no such file" },
188
	{ ENOTDIR,	E_OPEN,	"No such file" },
234
	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
189
	{ ENOTDIR,	E_CREAT,"Directory nonexistent" },
235
	{ ENOTDIR,	E_EXEC,	"not found" },
190
	{ ENOTDIR,	E_EXEC,	"not found" },
236
	{ EISDIR,	ALL,	"is a directory" },
237
#ifdef notdef
238
	{ EMFILE,	ALL,	"too many open files" },
239
#endif
240
	{ ENFILE,	ALL,	"file table overflow" },
241
	{ ENOSPC,	ALL,	"file system full" },
242
#ifdef EDQUOT
243
	{ EDQUOT,	ALL,	"disk quota exceeded" },
244
#endif
245
#ifdef ENOSR
246
	{ ENOSR,	ALL,	"no streams resources" },
247
#endif
248
	{ ENXIO,	ALL,	"no such device or address" },
249
	{ EROFS,	ALL,	"read-only file system" },
250
	{ ETXTBSY,	ALL,	"text busy" },
251
#ifdef SYSV
191
#ifdef SYSV
252
	{ EAGAIN,	E_EXEC,	"not enough memory" },
192
	{ EAGAIN,	E_EXEC,	"Not enough memory" },
253
#endif
254
	{ ENOMEM,	ALL,	"not enough memory" },
255
#ifdef ENOLINK
256
	{ ENOLINK,	ALL,	"remote access failed" },
257
#endif
258
#ifdef EMULTIHOP
259
	{ EMULTIHOP,	ALL,	"remote access failed" },
260
#endif
261
#ifdef ECOMM
262
	{ ECOMM,	ALL,	"remote access failed" },
263
#endif
264
#ifdef ESTALE
265
	{ ESTALE,	ALL,	"remote access failed" },
266
#endif
267
#ifdef ETIMEDOUT
268
	{ ETIMEDOUT,	ALL,	"remote access failed" },
269
#endif
270
#ifdef ELOOP
271
	{ ELOOP,	ALL,	"symbolic link loop" },
272
#endif
273
	{ E2BIG,	E_EXEC,	"argument list too long" },
274
#ifdef ELIBACC
275
	{ ELIBACC,	E_EXEC,	"shared library missing" },
276
#endif
193
#endif
277
	{ 0,		0,	NULL },
194
	{ 0,		0,	NULL },
278
};
195
};
Lines 290-301 Link Here
290
	int action;
207
	int action;
291
{
208
{
292
	struct errname const *ep;
209
	struct errname const *ep;
293
	static char buf[12];
294
210
295
	for (ep = errormsg ; ep->errcode ; ep++) {
211
	for (ep = errormsg ; ep->errcode ; ep++) {
296
		if (ep->errcode == e && (ep->action & action) != 0)
212
		if (ep->errcode == e && (ep->action & action) != 0)
297
			return ep->msg;
213
			return ep->msg;
298
	}
214
	}
299
	fmtstr(buf, sizeof buf, "error %d", e);
215
	return strerror(e);
300
	return buf;
216
}
217
218
219
#ifdef REALLY_SMALL
220
void
221
__inton() {
222
	if (--suppressint == 0 && intpending) {
223
		onint();
224
	}
225
}
226
#endif
227
228
229
230
/*
231
 * Print an error message for the current command.
232
 */
233
static void vwarn(const char *const msg, va_list ap) {
234
	struct output *errs;
235
	const char *name;
236
	const char *fmt;
237
238
	errs = out2;
239
	name = arg0;
240
	fmt = "%s: ";
241
	if (commandname) {
242
		name = commandname;
243
		fmt = "%s: %d: ";
244
	}
245
	outfmt(errs, fmt, name, startlinno);
246
	doformat(errs, msg, ap);
247
#if FLUSHERR
248
	outc('\n', errs);
249
#else
250
	outcslow('\n', errs);
251
#endif
252
}
253
254
255
void warnx(const char *msg, ...) {
256
	va_list ap;
257
258
	va_start(ap, msg);
259
	vwarn(msg, ap);
260
	va_end(ap);
301
}
261
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/error.h (-8 / +43 lines)
Lines 38-43 Link Here
38
 *	@(#)error.h	8.2 (Berkeley) 5/4/95
38
 *	@(#)error.h	8.2 (Berkeley) 5/4/95
39
 */
39
 */
40
40
41
#include <setjmp.h>
42
#include <signal.h>
43
41
/*
44
/*
42
 * Types of operations (passed to the errmsg routine).
45
 * Types of operations (passed to the errmsg routine).
43
 */
46
 */
Lines 57-64 Link Here
57
 * inner scope, and restore handler on exit from the scope.
60
 * inner scope, and restore handler on exit from the scope.
58
 */
61
 */
59
62
60
#include <setjmp.h>
61
62
struct jmploc {
63
struct jmploc {
63
	jmp_buf loc;
64
	jmp_buf loc;
64
};
65
};
Lines 71-76 Link Here
71
#define EXERROR 1	/* a generic error */
72
#define EXERROR 1	/* a generic error */
72
#define EXSHELLPROC 2	/* execute a shell procedure */
73
#define EXSHELLPROC 2	/* execute a shell procedure */
73
#define EXEXEC 3	/* command execution failed */
74
#define EXEXEC 3	/* command execution failed */
75
#define EXEXIT 4	/* exit the shell */
74
76
75
77
76
/*
78
/*
Lines 80-99 Link Here
80
 * more fun than worrying about efficiency and portability. :-))
82
 * more fun than worrying about efficiency and portability. :-))
81
 */
83
 */
82
84
83
extern volatile int suppressint;
85
extern int suppressint;
84
extern volatile int intpending;
86
extern volatile sig_atomic_t intpending;
85
87
86
#define INTOFF suppressint++
88
#define barrier() ({ __asm__ __volatile__ ("": : :"memory"); })
87
#define INTON { if (--suppressint == 0 && intpending) onint(); }
89
#define INTOFF \
88
#define FORCEINTON {suppressint = 0; if (intpending) onint();}
90
	({ \
91
		suppressint++; \
92
		barrier(); \
93
		0; \
94
	})
95
#ifdef REALLY_SMALL
96
void __inton __P((void));
97
#define INTON __inton()
98
#else
99
#define INTON \
100
	({ \
101
		barrier(); \
102
		if (--suppressint == 0 && intpending) onint(); \
103
		0; \
104
	})
105
#endif
106
#define FORCEINTON \
107
	({ \
108
		barrier(); \
109
		suppressint = 0; \
110
		if (intpending) onint(); \
111
		0; \
112
	})
113
#define SAVEINT(v) ((v) = suppressint)
114
#define RESTOREINT(v) \
115
	({ \
116
		barrier(); \
117
		if ((suppressint = (v)) == 0 && intpending) onint(); \
118
	})
89
#define CLEAR_PENDING_INT intpending = 0
119
#define CLEAR_PENDING_INT intpending = 0
90
#define int_pending() intpending
120
#define int_pending() intpending
91
121
92
void exraise __P((int)) __attribute__((__noreturn__));
122
void exraise __P((int)) __attribute__((__noreturn__));
123
#ifdef USE_NORETURN
124
void onint __P((void)) __attribute__((__noreturn__));
125
#else
93
void onint __P((void));
126
void onint __P((void));
127
#endif
94
void error __P((const char *, ...)) __attribute__((__noreturn__));
128
void error __P((const char *, ...)) __attribute__((__noreturn__));
95
void exerror __P((int, const char *, ...)) __attribute__((__noreturn__));
129
void exerror __P((int, const char *, ...)) __attribute__((__noreturn__));
96
const char *errmsg __P((int, int));
130
const char *errmsg __P((int, int));
131
void warnx __P((const char *, ...));
97
132
98
133
99
/*
134
/*
Lines 101-107 Link Here
101
 * so we use _setjmp instead.
136
 * so we use _setjmp instead.
102
 */
137
 */
103
138
104
#if defined(BSD) && !defined(__SVR4)
139
#if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__)
105
#define setjmp(jmploc)	_setjmp(jmploc)
140
#define setjmp(jmploc)	_setjmp(jmploc)
106
#define longjmp(jmploc, val)	_longjmp(jmploc, val)
141
#define longjmp(jmploc, val)	_longjmp(jmploc, val)
107
#endif
142
#endif
(-)bin_NetBSD-1.6release.orig/src/bin/sh/eval.c (-211 / +354 lines)
Lines 45-52 Link Here
45
#endif
45
#endif
46
#endif /* not lint */
46
#endif /* not lint */
47
47
48
#include <sys/types.h>
48
#include <signal.h>
49
#include <signal.h>
50
#include <malloc.h>
49
#include <unistd.h>
51
#include <unistd.h>
52
#include <errno.h>
50
53
51
/*
54
/*
52
 * Evaluate a command.
55
 * Evaluate a command.
Lines 98-106 Link Here
98
STATIC void evalcase __P((union node *, int));
101
STATIC void evalcase __P((union node *, int));
99
STATIC void evalsubshell __P((union node *, int));
102
STATIC void evalsubshell __P((union node *, int));
100
STATIC void expredir __P((union node *));
103
STATIC void expredir __P((union node *));
101
STATIC void evalpipe __P((union node *));
104
STATIC void evalpipe __P((union node *, int));
105
#ifdef notyet
102
STATIC void evalcommand __P((union node *, int, struct backcmd *));
106
STATIC void evalcommand __P((union node *, int, struct backcmd *));
107
#else
108
STATIC void evalcommand __P((union node *, int));
109
#endif
103
STATIC void prehash __P((union node *));
110
STATIC void prehash __P((union node *));
111
STATIC void eprintlist __P((struct strlist *));
112
#if !defined(__alpha__) || !defined(GCC_BROKEN_NG)
113
STATIC
114
#endif
115
void evaltreenr __P((union node *, int)) __attribute__ ((noreturn));
104
116
105
117
106
/*
118
/*
Lines 115-124 Link Here
115
	loopnest = 0;
127
	loopnest = 0;
116
	funcnest = 0;
128
	funcnest = 0;
117
}
129
}
118
119
SHELLPROC {
120
	exitstatus = 0;
121
}
122
#endif
130
#endif
123
131
124
132
Lines 142-149 Link Here
142
                        STARTSTACKSTR(concat);
150
                        STARTSTACKSTR(concat);
143
                        ap = argv + 2;
151
                        ap = argv + 2;
144
                        for (;;) {
152
                        for (;;) {
145
                                while (*p)
153
                        	concat = stputs(p, concat);
146
                                        STPUTC(*p++, concat);
147
                                if ((p = *ap++) == NULL)
154
                                if ((p = *ap++) == NULL)
148
                                        break;
155
                                        break;
149
                                STPUTC(' ', concat);
156
                                STPUTC(' ', concat);
Lines 170-179 Link Here
170
	struct stackmark smark;
177
	struct stackmark smark;
171
178
172
	setstackmark(&smark);
179
	setstackmark(&smark);
173
	setinputstring(s, 1);
180
	setinputstring(s);
174
	while ((n = parsecmd(0)) != NEOF) {
181
	while ((n = parsecmd(0)) != NEOF) {
175
		evaltree(n, flag);
182
		evaltree(n, flag);
176
		popstackmark(&smark);
183
		popstackmark(&smark);
184
		if (evalskip)
185
			break;
177
	}
186
	}
178
	popfile();
187
	popfile();
179
	popstackmark(&smark);
188
	popstackmark(&smark);
Lines 191-199 Link Here
191
	union node *n;
200
	union node *n;
192
	int flags;
201
	int flags;
193
{
202
{
203
	int checkexit = 0;
204
	void (*evalfn)(union node *, int);
205
	unsigned isor;
206
	int status;
194
	if (n == NULL) {
207
	if (n == NULL) {
195
		TRACE(("evaltree(NULL) called\n"));
208
		TRACE(("evaltree(NULL) called\n"));
196
		exitstatus = 0;
197
		goto out;
209
		goto out;
198
	}
210
	}
199
#ifndef SMALL
211
#ifndef SMALL
Lines 201-289 Link Here
201
#endif
213
#endif
202
	TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
214
	TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
203
	switch (n->type) {
215
	switch (n->type) {
204
	case NSEMI:
216
	default:
205
		evaltree(n->nbinary.ch1, flags & EV_TESTED);
217
#ifdef DEBUG
206
		if (evalskip)
218
		out1fmt("Node type = %d\n", n->type);
207
			goto out;
219
#ifndef USE_GLIBC_STDIO
208
		evaltree(n->nbinary.ch2, flags);
220
		flushout(out1);
209
		break;
221
#endif
210
	case NAND:
211
		evaltree(n->nbinary.ch1, EV_TESTED);
212
		if (evalskip || exitstatus != 0) {
213
			/* don't bomb out on "set -e; false && true" */
214
			flags |= EV_TESTED;
215
			goto out;
216
		}
217
		evaltree(n->nbinary.ch2, flags | EV_TESTED);
218
		break;
219
	case NOR:
220
		evaltree(n->nbinary.ch1, EV_TESTED);
221
		if (evalskip || exitstatus == 0)
222
			goto out;
223
		evaltree(n->nbinary.ch2, flags | EV_TESTED);
224
		break;
222
		break;
223
#endif
224
	case NNOT:
225
		evaltree(n->nnot.com, EV_TESTED);
226
		status = !exitstatus;
227
		goto setstatus;
225
	case NREDIR:
228
	case NREDIR:
226
		expredir(n->nredir.redirect);
229
		expredir(n->nredir.redirect);
227
		redirect(n->nredir.redirect, REDIR_PUSH);
230
		status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
228
		evaltree(n->nredir.n, flags);
231
		if (!status) {
229
		popredir();
232
			evaltree(n->nredir.n, flags & EV_TESTED);
233
			status = exitstatus;
234
		}
235
		popredir(0);
236
		goto setstatus;
237
	case NCMD:
238
#ifdef notyet
239
		if (eflag && !(flags & EV_TESTED))
240
			checkexit = ~0;
241
		evalcommand(n, flags, (struct backcmd *)NULL);
230
		break;
242
		break;
243
#else
244
		evalfn = evalcommand;
245
checkexit:
246
		if (eflag && !(flags & EV_TESTED))
247
			checkexit = ~0;
248
		goto calleval;
249
#endif
250
	case NFOR:
251
		evalfn = evalfor;
252
		goto calleval;
253
	case NWHILE:
254
	case NUNTIL:
255
		evalfn = evalloop;
256
		goto calleval;
231
	case NSUBSHELL:
257
	case NSUBSHELL:
232
		evalsubshell(n, flags);
233
		break;
234
	case NBACKGND:
258
	case NBACKGND:
235
		evalsubshell(n, flags);
259
		evalfn = evalsubshell;
260
		goto calleval;
261
	case NPIPE:
262
		evalfn = evalpipe;
263
#ifdef notyet
264
		if (eflag && !(flags & EV_TESTED))
265
			checkexit = ~0;
266
		goto calleval;
267
#else
268
		goto checkexit;
269
#endif
270
	case NCASE:
271
		evalfn = evalcase;
272
		goto calleval;
273
	case NAND:
274
	case NOR:
275
	case NSEMI:
276
#if NAND + 1 != NOR
277
#error NAND + 1 != NOR
278
#endif
279
#if NOR + 1 != NSEMI
280
#error NOR + 1 != NSEMI
281
#endif
282
		isor = n->type - NAND;
283
		evaltree(
284
			n->nbinary.ch1,
285
			(flags | ((isor >> 1) - 1)) & EV_TESTED
286
		);
287
		if (!exitstatus == isor)
236
		break;
288
		break;
237
	case NIF: {
289
		if (!evalskip) {
238
		evaltree(n->nif.test, EV_TESTED);
290
			n = n->nbinary.ch2;
239
		if (evalskip)
291
evaln:
240
			goto out;
292
			evalfn = evaltree;
241
		if (exitstatus == 0)
293
calleval:
242
			evaltree(n->nif.ifpart, flags);
294
			evalfn(n, flags);
243
		else if (n->nif.elsepart)
244
			evaltree(n->nif.elsepart, flags);
245
		else
246
			exitstatus = 0;
247
		break;
295
		break;
248
	}
296
	}
249
	case NWHILE:
250
	case NUNTIL:
251
		evalloop(n, flags);
252
		break;
297
		break;
253
	case NFOR:
298
	case NIF:
254
		evalfor(n, flags);
299
		evaltree(n->nif.test, EV_TESTED);
255
		break;
300
		if (evalskip)
256
	case NCASE:
257
		evalcase(n, flags);
258
		break;
301
		break;
302
		if (exitstatus == 0) {
303
			n = n->nif.ifpart;
304
			goto evaln;
305
		} else if (n->nif.elsepart) {
306
			n = n->nif.elsepart;
307
			goto evaln;
308
		}
309
		goto success;
259
	case NDEFUN:
310
	case NDEFUN:
260
		defun(n->narg.text, n->narg.next);
311
		defun(n->narg.text, n->narg.next);
261
		exitstatus = 0;
312
success:
262
		break;
313
		status = 0;
263
	case NNOT:
314
setstatus:
264
		evaltree(n->nnot.com, EV_TESTED);
315
		exitstatus = status;
265
		exitstatus = !exitstatus;
266
		break;
267
268
	case NPIPE:
269
		evalpipe(n);
270
		break;
271
	case NCMD:
272
		evalcommand(n, flags, (struct backcmd *)NULL);
273
		break;
274
	default:
275
		out1fmt("Node type = %d\n", n->type);
276
		flushout(&output);
277
		break;
316
		break;
278
	}
317
	}
279
out:
318
out:
280
	if (pendingsigs)
319
	if (pendingsigs)
281
		dotrap();
320
		dotrap();
282
	if ((flags & EV_EXIT) != 0)
321
	if (flags & EV_EXIT || checkexit & exitstatus)
283
		exitshell(exitstatus);
322
		exraise(EXEXIT);
284
}
323
}
285
324
286
325
326
#if !defined(__alpha__) || !defined(GCC_BROKEN_NG)
327
STATIC
328
#endif
329
void evaltreenr(union node *, int) __attribute__ ((alias("evaltree")));
330
331
287
STATIC void
332
STATIC void
288
evalloop(n, flags)
333
evalloop(n, flags)
289
	union node *n;
334
	union node *n;
Lines 293-298 Link Here
293
338
294
	loopnest++;
339
	loopnest++;
295
	status = 0;
340
	status = 0;
341
	flags &= EV_TESTED;
296
	for (;;) {
342
	for (;;) {
297
		evaltree(n->nbinary.ch1, EV_TESTED);
343
		evaltree(n->nbinary.ch1, EV_TESTED);
298
		if (evalskip) {
344
		if (evalskip) {
Lines 311-317 Link Here
311
			if (exitstatus == 0)
357
			if (exitstatus == 0)
312
				break;
358
				break;
313
		}
359
		}
314
		evaltree(n->nbinary.ch2, flags & EV_TESTED);
360
		evaltree(n->nbinary.ch2, flags);
315
		status = exitstatus;
361
		status = exitstatus;
316
		if (evalskip)
362
		if (evalskip)
317
			goto skipping;
363
			goto skipping;
Lines 344-352 Link Here
344
390
345
	exitstatus = 0;
391
	exitstatus = 0;
346
	loopnest++;
392
	loopnest++;
393
	flags &= EV_TESTED;
347
	for (sp = arglist.list ; sp ; sp = sp->next) {
394
	for (sp = arglist.list ; sp ; sp = sp->next) {
348
		setvar(n->nfor.var, sp->text, 0);
395
		setvar(n->nfor.var, sp->text, 0);
349
		evaltree(n->nfor.body, flags & EV_TESTED);
396
		evaltree(n->nfor.body, flags);
350
		if (evalskip) {
397
		if (evalskip) {
351
			if (evalskip == SKIPCONT && --skipcount <= 0) {
398
			if (evalskip == SKIPCONT && --skipcount <= 0) {
352
				evalskip = 0;
399
				evalskip = 0;
Lines 377-382 Link Here
377
	setstackmark(&smark);
424
	setstackmark(&smark);
378
	arglist.lastp = &arglist.list;
425
	arglist.lastp = &arglist.list;
379
	oexitstatus = exitstatus;
426
	oexitstatus = exitstatus;
427
	exitstatus = 0;
380
	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
428
	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
381
	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
429
	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
382
		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
430
		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
Lines 405-424 Link Here
405
{
453
{
406
	struct job *jp;
454
	struct job *jp;
407
	int backgnd = (n->type == NBACKGND);
455
	int backgnd = (n->type == NBACKGND);
456
	int status;
408
457
409
	expredir(n->nredir.redirect);
458
	expredir(n->nredir.redirect);
459
	if (!backgnd && flags & EV_EXIT && !trap[0])
460
		goto nofork;
461
	INTOFF;
410
	jp = makejob(n, 1);
462
	jp = makejob(n, 1);
411
	if (forkshell(jp, n, backgnd) == 0) {
463
	if (forkshell(jp, n, backgnd) == 0) {
464
		INTON;
465
		flags |= EV_EXIT;
412
		if (backgnd)
466
		if (backgnd)
413
			flags &=~ EV_TESTED;
467
			flags &=~ EV_TESTED;
468
nofork:
414
		redirect(n->nredir.redirect, 0);
469
		redirect(n->nredir.redirect, 0);
415
		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
470
		evaltreenr(n->nredir.n, flags);
471
		/* never returns */
416
	}
472
	}
417
	if (! backgnd) {
473
	status = 0;
418
		INTOFF;
474
	if (!backgnd)
419
		exitstatus = waitforjob(jp);
475
		status = waitforjob(jp);
476
	exitstatus = status;
420
		INTON;
477
		INTON;
421
	}
422
}
478
}
423
479
424
480
Lines 467-474 Link Here
467
 */
523
 */
468
524
469
STATIC void
525
STATIC void
470
evalpipe(n)
526
evalpipe(n, flags)
471
	union node *n;
527
	union node *n;
528
	int flags;
472
{
529
{
473
	struct job *jp;
530
	struct job *jp;
474
	struct nodelist *lp;
531
	struct nodelist *lp;
Lines 480-485 Link Here
480
	pipelen = 0;
537
	pipelen = 0;
481
	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
538
	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
482
		pipelen++;
539
		pipelen++;
540
	flags |= EV_EXIT;
483
	INTOFF;
541
	INTOFF;
484
	jp = makejob(n, pipelen);
542
	jp = makejob(n, pipelen);
485
	prevfd = -1;
543
	prevfd = -1;
Lines 494-526 Link Here
494
		}
552
		}
495
		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
553
		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
496
			INTON;
554
			INTON;
555
			if (pip[1] >= 0) {
556
				close(pip[0]);
557
			}
497
			if (prevfd > 0) {
558
			if (prevfd > 0) {
498
				close(0);
559
				dup2(prevfd, 0);
499
				copyfd(prevfd, 0);
500
				close(prevfd);
560
				close(prevfd);
501
			}
561
			}
502
			if (pip[1] >= 0) {
562
			if (pip[1] > 1) {
503
				close(pip[0]);
563
				dup2(pip[1], 1);
504
				if (pip[1] != 1) {
505
					close(1);
506
					copyfd(pip[1], 1);
507
					close(pip[1]);
564
					close(pip[1]);
508
				}
565
				}
509
			}
566
			evaltree(lp->n, flags);
510
			evaltree(lp->n, EV_EXIT);
511
		}
567
		}
512
		if (prevfd >= 0)
568
		if (prevfd >= 0)
513
			close(prevfd);
569
			close(prevfd);
514
		prevfd = pip[0];
570
		prevfd = pip[0];
515
		close(pip[1]);
571
		close(pip[1]);
516
	}
572
	}
517
	INTON;
518
	if (n->npipe.backgnd == 0) {
573
	if (n->npipe.backgnd == 0) {
519
		INTOFF;
520
		exitstatus = waitforjob(jp);
574
		exitstatus = waitforjob(jp);
521
		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
575
		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
522
		INTON;
523
	}
576
	}
577
	INTON;
524
}
578
}
525
579
526
580
Lines 595-604 Link Here
595
 */
649
 */
596
650
597
STATIC void
651
STATIC void
652
#ifdef notyet
598
evalcommand(cmd, flags, backcmd)
653
evalcommand(cmd, flags, backcmd)
599
	union node *cmd;
654
	union node *cmd;
600
	int flags;
655
	int flags;
601
	struct backcmd *backcmd;
656
	struct backcmd *backcmd;
657
#else
658
evalcommand(cmd, flags)
659
	union node *cmd;
660
	int flags;
661
#endif
602
{
662
{
603
	struct stackmark smark;
663
	struct stackmark smark;
604
	union node *argp;
664
	union node *argp;
Lines 607-631 Link Here
607
	char **argv;
667
	char **argv;
608
	int argc;
668
	int argc;
609
	char **envp;
669
	char **envp;
610
	int varflag;
611
	struct strlist *sp;
670
	struct strlist *sp;
612
	int mode;
671
	int mode;
672
#ifdef notyet
613
	int pip[2];
673
	int pip[2];
674
#endif
614
	struct cmdentry cmdentry;
675
	struct cmdentry cmdentry;
615
	struct job *jp;
676
	struct job *jp;
616
	struct jmploc jmploc;
617
	struct jmploc *volatile savehandler;
618
	char *volatile savecmdname;
677
	char *volatile savecmdname;
619
	volatile struct shparam saveparam;
678
	volatile struct shparam saveparam;
620
	struct localvar *volatile savelocalvars;
679
	struct localvar *volatile savelocalvars;
621
	volatile int e;
622
	char *lastarg;
680
	char *lastarg;
681
	const char *path;
682
	int spclbltin;
683
	int redir;
684
	struct jmploc *volatile savehandler;
685
	struct jmploc jmploc;
623
#if __GNUC__
686
#if __GNUC__
624
	/* Avoid longjmp clobbering */
687
	/* Avoid longjmp clobbering */
625
	(void) &argv;
688
	(void) &argv;
626
	(void) &argc;
689
	(void) &argc;
627
	(void) &lastarg;
690
	(void) &lastarg;
628
	(void) &flags;
691
	(void) &flags;
692
	(void) &spclbltin;
693
	(void) &redir;
629
#endif
694
#endif
630
695
631
	/* First expand the arguments. */
696
	/* First expand the arguments. */
Lines 633-654 Link Here
633
	setstackmark(&smark);
698
	setstackmark(&smark);
634
	arglist.lastp = &arglist.list;
699
	arglist.lastp = &arglist.list;
635
	varlist.lastp = &varlist.list;
700
	varlist.lastp = &varlist.list;
636
	varflag = 1;
701
	arglist.list = 0;
637
	oexitstatus = exitstatus;
702
	oexitstatus = exitstatus;
638
	exitstatus = 0;
703
	exitstatus = 0;
639
	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
704
	path = pathval();
640
		char *p = argp->narg.text;
705
	for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
641
		if (varflag && is_name(*p)) {
642
			do {
643
				p++;
644
			} while (is_in_name(*p));
645
			if (*p == '=') {
646
				expandarg(argp, &varlist, EXP_VARTILDE);
706
				expandarg(argp, &varlist, EXP_VARTILDE);
647
				continue;
648
			}
649
		}
707
		}
708
	for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
650
		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
709
		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
651
		varflag = 0;
652
	}
710
	}
653
	*arglist.lastp = NULL;
711
	*arglist.lastp = NULL;
654
	*varlist.lastp = NULL;
712
	*varlist.lastp = NULL;
Lines 670-746 Link Here
670
728
671
	/* Print the command if xflag is set. */
729
	/* Print the command if xflag is set. */
672
	if (xflag) {
730
	if (xflag) {
731
#ifdef FLUSHERR
673
		outc('+', &errout);
732
		outc('+', &errout);
674
		for (sp = varlist.list ; sp ; sp = sp->next) {
733
#else
675
			outc(' ', &errout);
734
		outcslow('+', &errout);
676
			out2str(sp->text);
735
#endif
677
		}
736
		eprintlist(varlist.list);
678
		for (sp = arglist.list ; sp ; sp = sp->next) {
737
		eprintlist(arglist.list);
679
			outc(' ', &errout);
738
#ifdef FLUSHERR
680
			out2str(sp->text);
681
		}
682
		outc('\n', &errout);
739
		outc('\n', &errout);
683
		flushout(&errout);
740
		flushout(&errout);
741
#else
742
		outcslow('\n', &errout);
743
#endif
684
	}
744
	}
685
745
746
	redir = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH);
747
686
	/* Now locate the command. */
748
	/* Now locate the command. */
687
	if (argc == 0) {
749
	if (argc == 0) {
688
		cmdentry.cmdtype = CMDBUILTIN;
750
		cmdentry.cmdtype = CMDBUILTIN;
689
		cmdentry.u.index = BLTINCMD;
751
		cmdentry.u.cmd = BLTINCMD;
752
		spclbltin = 1;
690
	} else {
753
	} else {
691
		static const char PATH[] = "PATH=";
754
		const char *oldpath;
692
		const char *path = pathval();
755
		int findflag = DO_ERR;
756
		int oldfindflag;
693
757
694
		/*
758
		/*
695
		 * Modify the command lookup path, if a PATH= assignment
759
		 * Modify the command lookup path, if a PATH= assignment
696
		 * is present
760
		 * is present
697
		 */
761
		 */
698
		for (sp = varlist.list ; sp ; sp = sp->next)
762
		for (sp = varlist.list ; sp ; sp = sp->next)
699
			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
763
			if (varequal(sp->text, defpathvar)) {
700
				path = sp->text + sizeof(PATH) - 1;
764
				path = sp->text + 5;
701
765
				findflag |= DO_BRUTE;
702
		find_command(argv[0], &cmdentry, DO_ERR, path);
766
			}
767
		oldpath = path;
768
		oldfindflag = findflag;
769
		spclbltin = -1;
770
		for(;;) {
771
			find_command(argv[0], &cmdentry, findflag, path);
703
		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
772
		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
704
			exitstatus = 127;
773
				goto notfound;
705
			flushout(&errout);
706
			return;
707
		}
774
		}
708
		/* implement the bltin builtin here */
775
			/* implement bltin and command here */
709
		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
776
			if (cmdentry.cmdtype != CMDBUILTIN) {
710
			for (;;) {
777
				break;
778
			}
779
			if (spclbltin < 0) {
780
				spclbltin =
781
					!!(
782
						cmdentry.u.cmd->flags &
783
						BUILTIN_SPECIAL
784
					) * 2
785
				;
786
			}
787
			if (cmdentry.u.cmd == BLTINCMD) {
788
				for(;;) {
789
					struct builtincmd *bcmd;
790
711
				argv++;
791
				argv++;
712
				if (--argc == 0)
792
				if (--argc == 0)
713
					break;
793
						goto found;
714
				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
794
					if (!(bcmd = find_builtin(*argv))) {
715
					outfmt(&errout, "%s: not found\n", *argv);
795
					outfmt(&errout, "%s: not found\n", *argv);
796
notfound:
716
					exitstatus = 127;
797
					exitstatus = 127;
798
#ifdef FLUSHERR
717
					flushout(&errout);
799
					flushout(&errout);
718
					return;
800
#endif
801
						goto out;
719
				}
802
				}
720
				if (cmdentry.u.index != BLTINCMD)
803
					cmdentry.u.cmd = bcmd;
804
					if (bcmd != BLTINCMD)
721
					break;
805
					break;
722
			}
806
			}
723
		}
807
		}
808
			if (cmdentry.u.cmd == COMMANDCMD) {
809
				argv++;
810
				if (--argc == 0) {
811
					goto found;
812
				}
813
				if (*argv[0] == '-') {
814
					if (!equal(argv[0], "-p")) {
815
						argv--;
816
						argc++;
817
						break;
818
					}
819
					argv++;
820
					if (--argc == 0) {
821
						goto found;
822
					}
823
					path = defpath;
824
					findflag |= DO_BRUTE;
825
				} else {
826
					path = oldpath;
827
					findflag = oldfindflag;
828
				}
829
				findflag |= DO_NOFUN;
830
				continue;
831
			}
832
found:
833
			break;
834
		}
724
	}
835
	}
725
836
726
	/* Fork off a child process if necessary. */
837
	/* Fork off a child process if necessary. */
727
	if (cmd->ncmd.backgnd
838
	if (
728
	 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
839
		(
840
			cmdentry.cmdtype == CMDNORMAL &&
841
			(!(flags & EV_EXIT) || trap[0])
842
		)
843
#ifdef notyet
729
	 || ((flags & EV_BACKCMD) != 0
844
	 || ((flags & EV_BACKCMD) != 0
730
	    && (cmdentry.cmdtype != CMDBUILTIN
845
	    && (cmdentry.cmdtype != CMDBUILTIN
731
		 || cmdentry.u.index == DOTCMD
846
		 || cmdentry.u.bcmd == DOTCMD
732
		 || cmdentry.u.index == EVALCMD))) {
847
		 || cmdentry.u.bcmd == EVALCMD))
848
#endif
849
	) {
850
		INTOFF;
733
		jp = makejob(cmd, 1);
851
		jp = makejob(cmd, 1);
734
		mode = cmd->ncmd.backgnd;
852
		mode = FORK_FG;
853
#ifdef notyet
735
		if (flags & EV_BACKCMD) {
854
		if (flags & EV_BACKCMD) {
736
			mode = FORK_NOJOB;
855
			mode = FORK_NOJOB;
737
			if (pipe(pip) < 0)
856
			if (pipe(pip) < 0)
738
				error("Pipe call failed");
857
				error("Pipe call failed");
739
		}
858
		}
859
#endif
740
		if (forkshell(jp, cmd, mode) != 0)
860
		if (forkshell(jp, cmd, mode) != 0)
741
			goto parent;	/* at end of routine */
861
			goto parent;	/* at end of routine */
742
		if (flags & EV_BACKCMD) {
743
			FORCEINTON;
862
			FORCEINTON;
863
#ifdef notyet
864
		if (flags & EV_BACKCMD) {
744
			close(pip[0]);
865
			close(pip[0]);
745
			if (pip[1] != 1) {
866
			if (pip[1] != 1) {
746
				close(1);
867
				close(1);
Lines 748-895 Link Here
748
				close(pip[1]);
869
				close(pip[1]);
749
			}
870
			}
750
		}
871
		}
872
#endif
751
		flags |= EV_EXIT;
873
		flags |= EV_EXIT;
874
	} else {
875
		flags &= ~EV_EXIT;
752
	}
876
	}
753
877
754
	/* This is the child process if a fork occurred. */
878
	/* This is the child process if a fork occurred. */
755
	/* Execute the command. */
879
	/* Execute the command. */
756
	if (cmdentry.cmdtype == CMDFUNCTION) {
880
	if (redir) {
881
		/* We have a redirection error. */
882
		exitstatus = redir;
883
		if (spclbltin == 2)
884
			exraise(EXERROR);
885
	} else if (cmdentry.cmdtype == CMDFUNCTION) {
757
#ifdef DEBUG
886
#ifdef DEBUG
758
		trputs("Shell function:  ");  trargs(argv);
887
		trputs("Shell function:  ");  trargs(argv);
759
#endif
888
#endif
760
		redirect(cmd->ncmd.redirect, REDIR_PUSH);
889
		exitstatus = oexitstatus;
761
		saveparam = shellparam;
890
		saveparam = shellparam;
762
		shellparam.malloc = 0;
763
		shellparam.reset = 1;
764
		shellparam.nparam = argc - 1;
765
		shellparam.p = argv + 1;
766
		shellparam.optnext = NULL;
767
		INTOFF;
768
		savelocalvars = localvars;
891
		savelocalvars = localvars;
769
		localvars = NULL;
892
		exception = -1;
770
		INTON;
771
		if (setjmp(jmploc.loc)) {
893
		if (setjmp(jmploc.loc)) {
772
			if (exception == EXSHELLPROC) {
894
			goto funcdone;
773
				freeparam((volatile struct shparam *)
774
				    &saveparam);
775
			} else {
776
				freeparam(&shellparam);
777
				shellparam = saveparam;
778
			}
779
			poplocalvars();
780
			localvars = savelocalvars;
781
			handler = savehandler;
782
			longjmp(handler->loc, 1);
783
		}
895
		}
896
		INTOFF;
784
		savehandler = handler;
897
		savehandler = handler;
785
		handler = &jmploc;
898
		handler = &jmploc;
786
		for (sp = varlist.list ; sp ; sp = sp->next)
899
		localvars = NULL;
787
			mklocal(sp->text);
900
		shellparam.malloc = 0;
901
		cmdentry.u.func->count++;
902
		INTON;
903
		shellparam.nparam = argc - 1;
904
		shellparam.p = argv + 1;
905
		shellparam.optind = 1;
906
		shellparam.optoff = -1;
907
		listsetvar(varlist.list, 0);
788
		funcnest++;
908
		funcnest++;
789
		evaltree(cmdentry.u.func, flags & EV_TESTED);
909
		evaltree(&cmdentry.u.func->n, flags & EV_TESTED);
790
		funcnest--;
910
		funcnest--;
911
funcdone:
791
		INTOFF;
912
		INTOFF;
913
		freefunc(cmdentry.u.func);
792
		poplocalvars();
914
		poplocalvars();
793
		localvars = savelocalvars;
915
		localvars = savelocalvars;
794
		freeparam(&shellparam);
916
		freeparam(&shellparam);
795
		shellparam = saveparam;
917
		shellparam = saveparam;
796
		handler = savehandler;
918
		handler = savehandler;
797
		popredir();
798
		INTON;
919
		INTON;
920
		if (exception >= 0) {
921
			longjmp(handler->loc, 1);
922
		}
799
		if (evalskip == SKIPFUNC) {
923
		if (evalskip == SKIPFUNC) {
800
			evalskip = 0;
924
			evalskip = 0;
801
			skipcount = 0;
925
			skipcount = 0;
802
		}
926
		}
803
		if (flags & EV_EXIT)
804
			exitshell(exitstatus);
805
	} else if (cmdentry.cmdtype == CMDBUILTIN) {
927
	} else if (cmdentry.cmdtype == CMDBUILTIN) {
806
#ifdef DEBUG
928
#ifdef DEBUG
807
		trputs("builtin command:  ");  trargs(argv);
929
		trputs("builtin command:  ");  trargs(argv);
808
#endif
930
#endif
809
		mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
931
		if (spclbltin) {
810
		if (flags == EV_BACKCMD) {
932
			int f = 0;
811
			memout.nleft = 0;
933
			if (cmdentry.u.cmd == EXECCMD) {
812
			memout.nextc = memout.buf;
934
				redir++;
813
			memout.bufsize = 64;
935
				if (argc > 1)
814
			mode |= REDIR_BACKQ;
936
					f = VEXPORT;
937
			}
938
			listsetvar(varlist.list, f);
815
		}
939
		}
816
		redirect(cmd->ncmd.redirect, mode);
817
		savecmdname = commandname;
940
		savecmdname = commandname;
818
		cmdenviron = varlist.list;
941
		cmdenviron = varlist.list;
819
		e = -1;
942
		exception = -1;
820
		if (setjmp(jmploc.loc)) {
943
		if (setjmp(jmploc.loc)) {
821
			e = exception;
822
			exitstatus = (e == EXINT)? SIGINT+128 : 2;
823
			goto cmddone;
944
			goto cmddone;
824
		}
945
		}
825
		savehandler = handler;
946
		savehandler = handler;
826
		handler = &jmploc;
947
		handler = &jmploc;
948
#ifdef notyet
949
		if (flags == EV_BACKCMD) {
950
#ifdef USE_GLIBC_STDIO
951
			openmemout();
952
#else
953
			memout.nleft = 0;
954
			memout.nextc = memout.buf;
955
			memout.bufsize = 64;
956
#endif
957
		}
958
#endif
827
		commandname = argv[0];
959
		commandname = argv[0];
828
		argptr = argv + 1;
960
		argptr = argv + 1;
829
		optptr = NULL;			/* initialize nextopt */
961
		optptr = NULL;			/* initialize nextopt */
830
		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
962
		exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
831
		flushall();
963
		flushall();
832
cmddone:
964
cmddone:
965
		exitstatus |= outerr(out1);
966
#ifdef notyet
833
		out1 = &output;
967
		out1 = &output;
834
		out2 = &errout;
968
		out2 = &errout;
969
#endif
835
		freestdout();
970
		freestdout();
836
		cmdenviron = NULL;
971
		cmdenviron = NULL;
837
		if (e != EXSHELLPROC) {
838
			commandname = savecmdname;
972
			commandname = savecmdname;
839
			if (flags & EV_EXIT)
840
				exitshell(exitstatus);
841
		}
842
		handler = savehandler;
973
		handler = savehandler;
843
		if (e != -1) {
974
		if (exception >= 0) {
844
			if ((e != EXERROR && e != EXEXEC)
975
			int f = exception;
845
			   || cmdentry.u.index == BLTINCMD
976
			if (f != EXEXIT) {
846
			   || cmdentry.u.index == DOTCMD
977
				int status = (f == EXINT) ? SIGINT + 128 : 2;
847
			   || cmdentry.u.index == EVALCMD
978
				exitstatus = status;
848
#ifndef SMALL
979
			}
849
			   || cmdentry.u.index == HISTCMD
980
			if (f == EXINT || spclbltin & 2) {
850
#endif
981
				exraise(f);
851
			   || cmdentry.u.index == EXECCMD)
982
			}
852
				exraise(e);
853
			FORCEINTON;
983
			FORCEINTON;
854
		}
984
		}
855
		if (cmdentry.u.index != EXECCMD)
985
#ifdef notyet
856
			popredir();
857
		if (flags == EV_BACKCMD) {
986
		if (flags == EV_BACKCMD) {
987
#ifdef USE_GLIBC_STDIO
988
			if (__closememout()) {
989
				error(
990
					"__closememout() failed: %s",
991
					strerror(errno)
992
				);
993
			}
994
#endif
858
			backcmd->buf = memout.buf;
995
			backcmd->buf = memout.buf;
996
#ifdef USE_GLIBC_STDIO
997
			backcmd->nleft = memout.bufsize;
998
#else
859
			backcmd->nleft = memout.nextc - memout.buf;
999
			backcmd->nleft = memout.nextc - memout.buf;
1000
#endif
860
			memout.buf = NULL;
1001
			memout.buf = NULL;
861
		}
1002
		}
1003
#endif
862
	} else {
1004
	} else {
863
#ifdef DEBUG
1005
#ifdef DEBUG
864
		trputs("normal command:  ");  trargs(argv);
1006
		trputs("normal command:  ");  trargs(argv);
865
#endif
1007
#endif
866
		clearredir();
867
		redirect(cmd->ncmd.redirect, 0);
868
		for (sp = varlist.list ; sp ; sp = sp->next)
1008
		for (sp = varlist.list ; sp ; sp = sp->next)
869
			setvareq(sp->text, VEXPORT|VSTACK);
1009
			setvareq(sp->text, VEXPORT|VSTACK);
870
		envp = environment();
1010
		envp = environment();
871
		shellexec(argv, envp, pathval(), cmdentry.u.index);
1011
		shellexec(argv, envp, path, cmdentry.u.index);
872
	}
1012
	}
1013
	if (flags & EV_EXIT)
1014
		exraise(EXEXIT);
873
	goto out;
1015
	goto out;
874
1016
875
parent:	/* parent process gets here (if we forked) */
1017
parent:	/* parent process gets here (if we forked) */
876
	if (mode == 0) {	/* argument to fork */
1018
	if (mode == FORK_FG) {	/* argument to fork */
877
		INTOFF;
878
		exitstatus = waitforjob(jp);
1019
		exitstatus = waitforjob(jp);
879
		INTON;
1020
#ifdef notyet
880
	} else if (mode == 2) {
1021
	} else if (mode == FORK_NOJOB) {
881
		backcmd->fd = pip[0];
1022
		backcmd->fd = pip[0];
882
		close(pip[1]);
1023
		close(pip[1]);
883
		backcmd->jp = jp;
1024
		backcmd->jp = jp;
1025
#endif
884
	}
1026
	}
1027
	INTON;
885
1028
886
out:
1029
out:
1030
	popredir(redir);
887
	if (lastarg)
1031
	if (lastarg)
888
		setvar("_", lastarg, 0);
1032
		setvar("_", lastarg, 0);
889
	popstackmark(&smark);
1033
	popstackmark(&smark);
890
891
	if (eflag && exitstatus && !(flags & EV_TESTED))
892
	    exitshell(exitstatus);
893
}
1034
}
894
1035
895
1036
Lines 897-904 Link Here
897
/*
1038
/*
898
 * Search for a command.  This is called before we fork so that the
1039
 * Search for a command.  This is called before we fork so that the
899
 * location of the command will be available in the parent as well as
1040
 * location of the command will be available in the parent as well as
900
 * the child.  The check for "goodname" is an overly conservative
1041
 * the child.
901
 * check that the name will not be subject to expansion.
902
 */
1042
 */
903
1043
904
STATIC void
1044
STATIC void
Lines 908-916 Link Here
908
	struct cmdentry entry;
1048
	struct cmdentry entry;
909
1049
910
	if (n->type == NCMD && n->ncmd.args)
1050
	if (n->type == NCMD && n->ncmd.args)
911
		if (goodname(n->ncmd.args->narg.text))
1051
		find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
912
			find_command(n->ncmd.args->narg.text, &entry, 0,
913
				     pathval());
914
}
1052
}
915
1053
916
1054
Lines 930-936 Link Here
930
	int argc;
1068
	int argc;
931
	char **argv;
1069
	char **argv;
932
{
1070
{
933
	listsetvar(cmdenviron);
934
	/*
1071
	/*
935
	 * Preserve exitstatus of a previous possible redirection
1072
	 * Preserve exitstatus of a previous possible redirection
936
	 * as POSIX mandates
1073
	 * as POSIX mandates
Lines 957-962 Link Here
957
{
1094
{
958
	int n = argc > 1 ? number(argv[1]) : 1;
1095
	int n = argc > 1 ? number(argv[1]) : 1;
959
1096
1097
	if (n <= 0)
1098
		error(illnum, argv[1]);
960
	if (n > loopnest)
1099
	if (n > loopnest)
961
		n = loopnest;
1100
		n = loopnest;
962
	if (n > 0) {
1101
	if (n > 0) {
Lines 1016-1029 Link Here
1016
	char **argv;
1155
	char **argv;
1017
{
1156
{
1018
	if (argc > 1) {
1157
	if (argc > 1) {
1019
		struct strlist *sp;
1020
1021
		iflag = 0;		/* exit on error */
1158
		iflag = 0;		/* exit on error */
1022
		mflag = 0;
1159
		mflag = 0;
1023
		optschanged();
1160
		optschanged();
1024
		for (sp = cmdenviron; sp ; sp = sp->next)
1025
			setvareq(sp->text, VEXPORT|VSTACK);
1026
		shellexec(argv + 1, environment(), pathval(), 0);
1161
		shellexec(argv + 1, environment(), pathval(), 0);
1027
	}
1162
	}
1028
	return 0;
1163
	return 0;
1029
}
1164
}
1165
1166
STATIC void
1167
eprintlist(struct strlist *sp)
1168
{
1169
	for (; sp; sp = sp->next) {
1170
		outfmt(&errout, " %s",sp->text);
1171
	}
1172
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/exec.c (-243 / +277 lines)
Lines 51-56 Link Here
51
#include <fcntl.h>
51
#include <fcntl.h>
52
#include <errno.h>
52
#include <errno.h>
53
#include <stdlib.h>
53
#include <stdlib.h>
54
#include <sysexits.h>
55
#include <stdbool.h>
56
#include <paths.h>
54
57
55
/*
58
/*
56
 * When commands are first encountered, they are entered in a hash table.
59
 * When commands are first encountered, they are entered in a hash table.
Lines 99-117 Link Here
99
102
100
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
103
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
101
STATIC int builtinloc = -1;		/* index in path of %builtin, or -1 */
104
STATIC int builtinloc = -1;		/* index in path of %builtin, or -1 */
102
int exerrno = 0;			/* Last exec error */
105
int exerrno;				/* Last exec error */
103
106
104
107
105
STATIC void tryexec __P((char *, char **, char **));
108
STATIC void tryexec __P((char *, char **, char **));
109
#if !defined(BSD) && !defined(linux)
106
STATIC void execinterp __P((char **, char **));
110
STATIC void execinterp __P((char **, char **));
111
#endif
107
STATIC void printentry __P((struct tblentry *, int));
112
STATIC void printentry __P((struct tblentry *, int));
108
STATIC void clearcmdentry __P((int));
113
STATIC void clearcmdentry __P((int));
109
STATIC struct tblentry *cmdlookup __P((char *, int));
114
STATIC struct tblentry *cmdlookup __P((char *, int));
110
STATIC void delete_cmd_entry __P((void));
115
STATIC void delete_cmd_entry __P((void));
116
STATIC int describe_command __P((struct output *, char *, int));
117
STATIC int path_change __P((const char *, int *));
111
118
112
119
113
extern char *const parsekwd[];
114
115
/*
120
/*
116
 * Exec a program.  Never returns.  If you change this routine, you may
121
 * Exec a program.  Never returns.  If you change this routine, you may
117
 * have to change the find_command routine as well.
122
 * have to change the find_command routine as well.
Lines 126-131 Link Here
126
	char *cmdname;
131
	char *cmdname;
127
	int e;
132
	int e;
128
133
134
	clearredir(1);
129
	if (strchr(argv[0], '/') != NULL) {
135
	if (strchr(argv[0], '/') != NULL) {
130
		tryexec(argv[0], argv, envp);
136
		tryexec(argv[0], argv, envp);
131
		e = errno;
137
		e = errno;
Lines 164-174 Link Here
164
	char **argv;
170
	char **argv;
165
	char **envp;
171
	char **envp;
166
	{
172
	{
167
	int e;
173
	int repeated = 0;
168
#ifndef BSD
174
#if !defined(BSD) && !defined(linux)
169
	char *p;
175
	char *p;
170
#endif
176
#endif
171
177
178
repeat:
172
#ifdef SYSV
179
#ifdef SYSV
173
	do {
180
	do {
174
		execve(cmd, argv, envp);
181
		execve(cmd, argv, envp);
Lines 176-278 Link Here
176
#else
183
#else
177
	execve(cmd, argv, envp);
184
	execve(cmd, argv, envp);
178
#endif
185
#endif
179
	e = errno;
186
	if (repeated++) {
180
	if (e == ENOEXEC) {
187
		ckfree(argv);
181
		initshellproc();
188
	} else if (errno == ENOEXEC) {
182
		setinputfile(cmd, 0);
183
		commandname = arg0 = savestr(argv[0]);
184
#ifndef BSD
185
		pgetc(); pungetc();		/* fill up input buffer */
186
		p = parsenextc;
187
		if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
188
			argv[0] = cmd;
189
			execinterp(argv, envp);
190
		}
191
#endif
192
		setparam(argv + 1);
193
		exraise(EXSHELLPROC);
194
	}
195
	errno = e;
196
}
197
198
199
#ifndef BSD
200
/*
201
 * Execute an interpreter introduced by "#!", for systems where this
202
 * feature has not been built into the kernel.  If the interpreter is
203
 * the shell, return (effectively ignoring the "#!").  If the execution
204
 * of the interpreter fails, exit.
205
 *
206
 * This code peeks inside the input buffer in order to avoid actually
207
 * reading any input.  It would benefit from a rewrite.
208
 */
209
210
#define NEWARGS 5
211
212
STATIC void
213
execinterp(argv, envp)
214
	char **argv, **envp;
215
	{
216
	int n;
217
	char *inp;
218
	char *outp;
219
	char c;
220
	char *p;
221
	char **ap;
189
	char **ap;
222
	char *newargs[NEWARGS];
223
	int i;
224
	char **ap2;
225
	char **new;
190
	char **new;
226
191
227
	n = parsenleft - 2;
192
		for (ap = argv; *ap; ap++)
228
	inp = parsenextc + 2;
193
			;
229
	ap = newargs;
194
		ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
230
	for (;;) {
195
		*ap++ = cmd = _PATH_BSHELL;
231
		while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
196
		while ((*ap++ = *argv++))
232
			inp++;
197
			;
233
		if (n < 0)
198
		argv = new;
234
			goto bad;
199
		goto repeat;
235
		if ((c = *inp++) == '\n')
236
			break;
237
		if (ap == &newargs[NEWARGS])
238
bad:		  error("Bad #! line");
239
		STARTSTACKSTR(outp);
240
		do {
241
			STPUTC(c, outp);
242
		} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
243
		STPUTC('\0', outp);
244
		n++, inp--;
245
		*ap++ = grabstackstr(outp);
246
	}
247
	if (ap == newargs + 1) {	/* if no args, maybe no exec is needed */
248
		p = newargs[0];
249
		for (;;) {
250
			if (equal(p, "sh") || equal(p, "ash")) {
251
				return;
252
			}
253
			while (*p != '/') {
254
				if (*p == '\0')
255
					goto break2;
256
				p++;
257
			}
258
			p++;
259
		}
260
break2:;
261
	}
200
	}
262
	i = (char *)ap - (char *)newargs;		/* size in bytes */
263
	if (i == 0)
264
		error("Bad #! line");
265
	for (ap2 = argv ; *ap2++ != NULL ; );
266
	new = ckmalloc(i + ((char *)ap2 - (char *)argv));
267
	ap = newargs, ap2 = new;
268
	while ((i -= sizeof (char **)) >= 0)
269
		*ap2++ = *ap++;
270
	ap = argv;
271
	while (*ap2++ = *ap++);
272
	shellexec(new, envp, pathval(), 0);
273
	/* NOTREACHED */
274
}
201
}
275
#endif
276
202
277
203
278
204
Lines 296-302 Link Here
296
	const char *p;
222
	const char *p;
297
	char *q;
223
	char *q;
298
	const char *start;
224
	const char *start;
299
	int len;
225
	size_t len;
300
226
301
	if (*path == NULL)
227
	if (*path == NULL)
302
		return NULL;
228
		return NULL;
Lines 345-350 Link Here
345
	while ((c = nextopt("rv")) != '\0') {
271
	while ((c = nextopt("rv")) != '\0') {
346
		if (c == 'r') {
272
		if (c == 'r') {
347
			clearcmdentry(0);
273
			clearcmdentry(0);
274
			return 0;
348
		} else if (c == 'v') {
275
		} else if (c == 'v') {
349
			verbose++;
276
			verbose++;
350
		}
277
		}
Lines 352-378 Link Here
352
	if (*argptr == NULL) {
279
	if (*argptr == NULL) {
353
		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
280
		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
354
			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
281
			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
282
				if (cmdp->cmdtype != CMDBUILTIN) {
355
				printentry(cmdp, verbose);
283
				printentry(cmdp, verbose);
356
			}
284
			}
357
		}
285
		}
286
		}
358
		return 0;
287
		return 0;
359
	}
288
	}
289
	c = 0;
360
	while ((name = *argptr) != NULL) {
290
	while ((name = *argptr) != NULL) {
361
		if ((cmdp = cmdlookup(name, 0)) != NULL
291
		if ((cmdp = cmdlookup(name, 0)) != NULL
362
		 && (cmdp->cmdtype == CMDNORMAL
292
		 && (cmdp->cmdtype == CMDNORMAL
363
		     || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
293
		     || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
364
			delete_cmd_entry();
294
			delete_cmd_entry();
365
		find_command(name, &entry, DO_ERR, pathval());
295
		find_command(name, &entry, DO_ERR, pathval());
366
		if (verbose) {
296
		if (entry.cmdtype == CMDUNKNOWN) c = 1;
367
			if (entry.cmdtype != CMDUNKNOWN) {	/* if no error msg */
297
		else if (verbose) {
368
				cmdp = cmdlookup(name, 0);
298
				cmdp = cmdlookup(name, 0);
369
				printentry(cmdp, verbose);
299
			if (cmdp) printentry(cmdp, verbose);
370
			}
371
			flushall();
300
			flushall();
372
		}
301
		}
373
		argptr++;
302
		argptr++;
374
	}
303
	}
375
	return 0;
304
	return c;
376
}
305
}
377
306
378
307
Lines 399-407 Link Here
399
		out1fmt("function %s", cmdp->cmdname);
328
		out1fmt("function %s", cmdp->cmdname);
400
		if (verbose) {
329
		if (verbose) {
401
			INTOFF;
330
			INTOFF;
402
			name = commandtext(cmdp->param.func);
331
			name = commandtext(&cmdp->param.func->n);
403
			out1c(' ');
332
			out1fmt(" %s", name);
404
			out1str(name);
405
			ckfree(name);
333
			ckfree(name);
406
			INTON;
334
			INTON;
407
		}
335
		}
Lines 410-418 Link Here
410
		error("internal error: cmdtype %d", cmdp->cmdtype);
338
		error("internal error: cmdtype %d", cmdp->cmdtype);
411
#endif
339
#endif
412
	}
340
	}
413
	if (cmdp->rehash)
341
	out1fmt(snlfmt, cmdp->rehash ? "*" : nullstr);
414
		out1c('*');
415
	out1c('\n');
416
}
342
}
417
343
418
344
Lines 433-446 Link Here
433
	int idx;
359
	int idx;
434
	int prev;
360
	int prev;
435
	char *fullname;
361
	char *fullname;
436
	struct stat statb;
362
	struct stat64 statb;
437
	int e;
363
	int e;
438
	int i;
364
	int bltin;
365
	int firstchange;
366
	int updatetbl;
367
	bool regular;
368
	struct builtincmd *bcmd;
439
369
440
	/* If name contains a slash, don't use the hash table */
370
	/* If name contains a slash, don't use the hash table */
441
	if (strchr(name, '/') != NULL) {
371
	if (strchr(name, '/') != NULL) {
442
		if (act & DO_ABS) {
372
		if (act & DO_ABS) {
443
			while (stat(name, &statb) < 0) {
373
			while (stat64(name, &statb) < 0) {
444
	#ifdef SYSV
374
	#ifdef SYSV
445
				if (errno == EINTR)
375
				if (errno == EINTR)
446
					continue;
376
					continue;
Lines 460-482 Link Here
460
		return;
390
		return;
461
	}
391
	}
462
392
393
	updatetbl = 1;
394
	if (act & DO_BRUTE) {
395
		firstchange = path_change(path, &bltin);
396
	} else {
397
		bltin = builtinloc;
398
		firstchange = 9999;
399
	}
400
463
	/* If name is in the table, and not invalidated by cd, we're done */
401
	/* If name is in the table, and not invalidated by cd, we're done */
464
	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
402
	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
403
		if (cmdp->cmdtype == CMDFUNCTION) {
404
			if (act & DO_NOFUN) {
405
				updatetbl = 0;
406
			} else {
407
				goto success;
408
			}
409
		} else if (act & DO_BRUTE) {
410
			if ((cmdp->cmdtype == CMDNORMAL &&
411
			     cmdp->param.index >= firstchange) ||
412
			    (cmdp->cmdtype == CMDBUILTIN &&
413
			     ((builtinloc < 0 && bltin >= 0) ?
414
			      bltin : builtinloc) >= firstchange)) {
415
				/* need to recompute the entry */
416
			} else {
417
				goto success;
418
			}
419
		} else {
420
			goto success;
421
		}
422
	}
423
424
	bcmd = find_builtin(name);
425
	regular = bcmd && bcmd->flags & BUILTIN_REGULAR;
426
427
	if (regular) {
428
		if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
465
		goto success;
429
		goto success;
430
		}
431
	} else if (act & DO_BRUTE) {
432
		if (firstchange == 0) {
433
			updatetbl = 0;
434
		}
435
	}
466
436
467
	/* If %builtin not in path, check for builtin next */
437
	/* If %builtin not in path, check for builtin next */
468
	if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
438
	if (regular || (bltin < 0 && bcmd)) {
439
builtin:
440
		if (!updatetbl) {
441
			entry->cmdtype = CMDBUILTIN;
442
			entry->u.cmd = bcmd;
443
			return;
444
		}
469
		INTOFF;
445
		INTOFF;
470
		cmdp = cmdlookup(name, 1);
446
		cmdp = cmdlookup(name, 1);
471
		cmdp->cmdtype = CMDBUILTIN;
447
		cmdp->cmdtype = CMDBUILTIN;
472
		cmdp->param.index = i;
448
		cmdp->param.cmd = bcmd;
473
		INTON;
449
		INTON;
474
		goto success;
450
		goto success;
475
	}
451
	}
476
452
477
	/* We have to search path. */
453
	/* We have to search path. */
478
	prev = -1;		/* where to start */
454
	prev = -1;		/* where to start */
479
	if (cmdp) {		/* doing a rehash */
455
	if (cmdp && cmdp->rehash) {	/* doing a rehash */
480
		if (cmdp->cmdtype == CMDBUILTIN)
456
		if (cmdp->cmdtype == CMDBUILTIN)
481
			prev = builtinloc;
457
			prev = builtinloc;
482
		else
458
		else
Lines 489-518 Link Here
489
	while ((fullname = padvance(&path, name)) != NULL) {
465
	while ((fullname = padvance(&path, name)) != NULL) {
490
		stunalloc(fullname);
466
		stunalloc(fullname);
491
		idx++;
467
		idx++;
468
		if (idx >= firstchange) {
469
			updatetbl = 0;
470
		}
492
		if (pathopt) {
471
		if (pathopt) {
493
			if (prefix("builtin", pathopt)) {
472
			if (prefix("builtin", pathopt)) {
494
				if ((i = find_builtin(name)) < 0)
473
				if ((bcmd = find_builtin(name))) {
495
					goto loop;
474
					goto builtin;
496
				INTOFF;
475
				}
497
				cmdp = cmdlookup(name, 1);
476
				continue;
498
				cmdp->cmdtype = CMDBUILTIN;
477
			} else if (!(act & DO_NOFUN) &&
499
				cmdp->param.index = i;
478
				   prefix("func", pathopt)) {
500
				INTON;
501
				goto success;
502
			} else if (prefix("func", pathopt)) {
503
				/* handled below */
479
				/* handled below */
504
			} else {
480
			} else {
505
				goto loop;	/* ignore unimplemented options */
481
				continue;	/* ignore unimplemented options */
506
			}
482
			}
507
		}
483
		}
508
		/* if rehash, don't redo absolute path names */
484
		/* if rehash, don't redo absolute path names */
509
		if (fullname[0] == '/' && idx <= prev) {
485
		if (fullname[0] == '/' && idx <= prev &&
486
		    idx < firstchange) {
510
			if (idx < prev)
487
			if (idx < prev)
511
				goto loop;
488
				continue;
512
			TRACE(("searchexec \"%s\": no change\n", name));
489
			TRACE(("searchexec \"%s\": no change\n", name));
513
			goto success;
490
			goto success;
514
		}
491
		}
515
		while (stat(fullname, &statb) < 0) {
492
		while (stat64(fullname, &statb) < 0) {
516
#ifdef SYSV
493
#ifdef SYSV
517
			if (errno == EINTR)
494
			if (errno == EINTR)
518
				continue;
495
				continue;
Lines 523-529 Link Here
523
		}
500
		}
524
		e = EACCES;	/* if we fail, this will be the error */
501
		e = EACCES;	/* if we fail, this will be the error */
525
		if (!S_ISREG(statb.st_mode))
502
		if (!S_ISREG(statb.st_mode))
526
			goto loop;
503
			continue;
527
		if (pathopt) {		/* this is a %func directory */
504
		if (pathopt) {		/* this is a %func directory */
528
			stalloc(strlen(fullname) + 1);
505
			stalloc(strlen(fullname) + 1);
529
			readcmdfile(fullname);
506
			readcmdfile(fullname);
Lines 545-550 Link Here
545
		}
522
		}
546
#endif
523
#endif
547
		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
524
		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
525
		/* If we aren't called with DO_BRUTE and cmdp is set, it must
526
		   be a function and we're being called with DO_NOFUN */
527
		if (!updatetbl) {
528
			entry->cmdtype = CMDNORMAL;
529
			entry->u.index = idx;
530
			return;
531
		}
548
		INTOFF;
532
		INTOFF;
549
		cmdp = cmdlookup(name, 1);
533
		cmdp = cmdlookup(name, 1);
550
		cmdp->cmdtype = CMDNORMAL;
534
		cmdp->cmdtype = CMDNORMAL;
Lines 554-563 Link Here
554
	}
538
	}
555
539
556
	/* We failed.  If there was an entry for this command, delete it */
540
	/* We failed.  If there was an entry for this command, delete it */
557
	if (cmdp)
541
	if (cmdp && updatetbl)
558
		delete_cmd_entry();
542
		delete_cmd_entry();
559
	if (act & DO_ERR)
543
	if (act & DO_ERR)
560
		outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
544
		warnx("%s: %s", name, errmsg(e, E_EXEC));
561
	entry->cmdtype = CMDUNKNOWN;
545
	entry->cmdtype = CMDUNKNOWN;
562
	return;
546
	return;
563
547
Lines 573-589 Link Here
573
 * Search the table of builtin commands.
557
 * Search the table of builtin commands.
574
 */
558
 */
575
559
576
int
560
struct builtincmd *
577
find_builtin(name)
561
find_builtin(const char *name)
578
	char *name;
579
{
562
{
580
	const struct builtincmd *bp;
563
	struct builtincmd *bp;
581
564
582
	for (bp = builtincmd ; bp->name ; bp++) {
565
	bp = bsearch(
583
		if (*bp->name == *name && equal(bp->name, name))
566
		&name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
584
			return bp->code;
567
		pstrcmp
585
	}
568
	);
586
	return -1;
569
	return bp;
587
}
570
}
588
571
589
572
Lines 619-655 Link Here
619
changepath(newval)
602
changepath(newval)
620
	const char *newval;
603
	const char *newval;
621
{
604
{
622
	const char *old, *new;
623
	int idx;
624
	int firstchange;
605
	int firstchange;
625
	int bltin;
606
	int bltin;
626
607
627
	old = pathval();
608
	firstchange = path_change(newval, &bltin);
628
	new = newval;
629
	firstchange = 9999;	/* assume no change */
630
	idx = 0;
631
	bltin = -1;
632
	for (;;) {
633
		if (*old != *new) {
634
			firstchange = idx;
635
			if ((*old == '\0' && *new == ':')
636
			 || (*old == ':' && *new == '\0'))
637
				firstchange++;
638
			old = new;	/* ignore subsequent differences */
639
		}
640
		if (*new == '\0')
641
			break;
642
		if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
643
			bltin = idx;
644
		if (*new == ':') {
645
			idx++;
646
		}
647
		new++, old++;
648
	}
649
	if (builtinloc < 0 && bltin >= 0)
609
	if (builtinloc < 0 && bltin >= 0)
650
		builtinloc = bltin;		/* zap builtins */
610
		builtinloc = bltin;		/* zap builtins */
651
	if (builtinloc >= 0 && bltin < 0)
652
		firstchange = 0;
653
	clearcmdentry(firstchange);
611
	clearcmdentry(firstchange);
654
	builtinloc = bltin;
612
	builtinloc = bltin;
655
}
613
}
Lines 687-727 Link Here
687
}
645
}
688
646
689
647
690
/*
691
 * Delete all functions.
692
 */
693
694
#ifdef mkinit
695
MKINIT void deletefuncs __P((void));
696
697
SHELLPROC {
698
	deletefuncs();
699
}
700
#endif
701
702
void
703
deletefuncs() {
704
	struct tblentry **tblp;
705
	struct tblentry **pp;
706
	struct tblentry *cmdp;
707
708
	INTOFF;
709
	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
710
		pp = tblp;
711
		while ((cmdp = *pp) != NULL) {
712
			if (cmdp->cmdtype == CMDFUNCTION) {
713
				*pp = cmdp->next;
714
				freefunc(cmdp->param.func);
715
				ckfree(cmdp);
716
			} else {
717
				pp = &cmdp->next;
718
			}
719
		}
720
	}
721
	INTON;
722
}
723
724
725
648
726
/*
649
/*
727
 * Locate a command in the command hash table.  If "add" is nonzero,
650
 * Locate a command in the command hash table.  If "add" is nonzero,
Lines 780-785 Link Here
780
	INTOFF;
703
	INTOFF;
781
	cmdp = *lastcmdentry;
704
	cmdp = *lastcmdentry;
782
	*lastcmdentry = cmdp->next;
705
	*lastcmdentry = cmdp->next;
706
	if (cmdp->cmdtype == CMDFUNCTION)
707
		freefunc(cmdp->param.func);
783
	ckfree(cmdp);
708
	ckfree(cmdp);
784
	INTON;
709
	INTON;
785
}
710
}
Lines 851-868 Link Here
851
 * Delete a function if it exists.
776
 * Delete a function if it exists.
852
 */
777
 */
853
778
854
int
779
void
855
unsetfunc(name)
780
unsetfunc(name)
856
	char *name;
781
	char *name;
857
	{
782
	{
858
	struct tblentry *cmdp;
783
	struct tblentry *cmdp;
859
784
860
	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
785
	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION)
861
		freefunc(cmdp->param.func);
862
		delete_cmd_entry();
786
		delete_cmd_entry();
863
		return (0);
864
	}
865
	return (1);
866
}
787
}
867
788
868
/*
789
/*
Lines 874-947 Link Here
874
	int argc;
795
	int argc;
875
	char **argv;
796
	char **argv;
876
{
797
{
877
	struct cmdentry entry;
878
	struct tblentry *cmdp;
879
	char * const *pp;
880
	struct alias *ap;
881
	int i;
798
	int i;
882
	int err = 0;
799
	int err = 0;
883
800
884
	for (i = 1; i < argc; i++) {
801
	for (i = 1; i < argc; i++) {
885
		out1str(argv[i]);
802
		err |= describe_command(out1, argv[i], 1);
886
		/* First look at the keywords */
803
	}
887
		for (pp = parsekwd; *pp; pp++)
804
	return err;
888
			if (**pp == *argv[i] && equal(*pp, argv[i]))
805
}
889
				break;
890
806
891
		if (*pp) {
807
STATIC int
892
			out1str(" is a shell keyword\n");
808
describe_command(out, command, verbose)
893
			continue;
809
	struct output *out;
810
	char *command;
811
	int verbose;
812
{
813
	struct cmdentry entry;
814
	struct tblentry *cmdp;
815
	const struct alias *ap;
816
	const char *path = pathval();
817
818
	if (verbose) {
819
		outstr(command, out);
820
	}
821
822
	/* First look at the keywords */
823
	if (findkwd(command)) {
824
		outstr(verbose ? " is a shell keyword" : command, out);
825
		goto out;
894
		}
826
		}
895
827
896
		/* Then look at the aliases */
828
		/* Then look at the aliases */
897
		if ((ap = lookupalias(argv[i], 1)) != NULL) {
829
	if ((ap = lookupalias(command, 0)) != NULL) {
898
			out1fmt(" is an alias for %s\n", ap->val);
830
		if (verbose) {
899
			continue;
831
			outfmt(out, " is an alias for %s", ap->val);
832
		} else {
833
			outstr("alias ", out);
834
			printalias(ap);
835
			return 0;
836
		}
837
		goto out;
900
		}
838
		}
901
839
902
		/* Then check if it is a tracked alias */
840
		/* Then check if it is a tracked alias */
903
		if ((cmdp = cmdlookup(argv[i], 0)) != NULL) {
841
	if ((cmdp = cmdlookup(command, 0)) != NULL) {
904
			entry.cmdtype = cmdp->cmdtype;
842
			entry.cmdtype = cmdp->cmdtype;
905
			entry.u = cmdp->param;
843
			entry.u = cmdp->param;
906
		}
844
	} else {
907
		else {
908
			/* Finally use brute force */
845
			/* Finally use brute force */
909
			find_command(argv[i], &entry, DO_ABS, pathval());
846
		find_command(command, &entry, DO_ABS, path);
910
		}
847
		}
911
848
912
		switch (entry.cmdtype) {
849
		switch (entry.cmdtype) {
913
		case CMDNORMAL: {
850
		case CMDNORMAL: {
914
			if (strchr(argv[i], '/') == NULL) {
915
				const char *path = pathval();
916
				char *name;
917
				int j = entry.u.index;
851
				int j = entry.u.index;
852
		char *p;
853
		if (j == -1) {
854
			p = command;
855
		} else {
918
				do {
856
				do {
919
					name = padvance(&path, argv[i]);
857
				p = padvance(&path, command);
920
					stunalloc(name);
858
				stunalloc(p);
921
				} while (--j >= 0);
859
				} while (--j >= 0);
922
				out1fmt(" is%s %s\n",
860
		}
923
				    cmdp ? " a tracked alias for" : "", name);
861
		if (verbose) {
862
			outfmt(
863
				out, " is%s %s",
864
				cmdp ? " a tracked alias for" : nullstr, p
865
			);
924
			} else {
866
			} else {
925
				if (access(argv[i], X_OK) == 0)
867
			outstr(p, out);
926
					out1fmt(" is %s\n", argv[i]);
927
				else
928
					out1fmt(": %s\n", strerror(errno));
929
			}
868
			}
930
 			break;
869
 			break;
931
		}
870
		}
871
932
		case CMDFUNCTION:
872
		case CMDFUNCTION:
933
			out1str(" is a shell function\n");
873
		if (verbose) {
874
			outstr(" is a shell function", out);
875
		} else {
876
			outstr(command, out);
877
		}
934
			break;
878
			break;
935
879
936
		case CMDBUILTIN:
880
		case CMDBUILTIN:
937
			out1str(" is a shell builtin\n");
881
		if (verbose) {
882
			outfmt(
883
				out, " is a %sshell builtin",
884
				entry.u.cmd->flags & BUILTIN_SPECIAL ?
885
					"special " : nullstr
886
			);
887
		} else {
888
			outstr(command, out);
889
		}
938
			break;
890
			break;
939
891
940
		default:
892
		default:
941
			out1str(": not found\n");
893
		if (verbose) {
942
			err |= 127;
894
			outstr(": not found\n", out);
895
		}
896
		return 127;
897
	}
898
899
out:
900
	outc('\n', out);
901
	return 0;
902
}
903
904
int
905
commandcmd(argc, argv)
906
	int argc;
907
	char **argv;
908
{
909
	int c;
910
	int default_path = 0;
911
	int verify_only = 0;
912
	int verbose_verify_only = 0;
913
914
	while ((c = nextopt("pvV")) != '\0')
915
		switch (c) {
916
		case 'p':
917
			default_path = 1;
943
			break;
918
			break;
919
		case 'v':
920
			verify_only = 1;
921
			break;
922
		case 'V':
923
			verbose_verify_only = 1;
924
			break;
925
		default:
926
			outfmt(out2,
927
"command: nextopt returned character code 0%o\n", c);
928
			return EX_SOFTWARE;
944
		}
929
		}
930
931
	if (default_path + verify_only + verbose_verify_only > 1 ||
932
	    !*argptr) {
933
			outfmt(out2,
934
"command [-p] command [arg ...]\n");
935
			outfmt(out2,
936
"command {-v|-V} command\n");
937
			return EX_USAGE;
945
	}
938
	}
946
	return err;
939
940
	if (verify_only || verbose_verify_only) {
941
		return describe_command(out1, *argptr, verbose_verify_only);
942
	}
943
944
	return 0;
945
}
946
947
STATIC int
948
path_change(newval, bltin)
949
	const char *newval;
950
	int *bltin;
951
{
952
	const char *old, *new;
953
	int idx;
954
	int firstchange;
955
956
	old = pathval();
957
	new = newval;
958
	firstchange = 9999;	/* assume no change */
959
	idx = 0;
960
	*bltin = -1;
961
	for (;;) {
962
		if (*old != *new) {
963
			firstchange = idx;
964
			if ((*old == '\0' && *new == ':')
965
			 || (*old == ':' && *new == '\0'))
966
				firstchange++;
967
			old = new;	/* ignore subsequent differences */
968
		}
969
		if (*new == '\0')
970
			break;
971
		if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
972
			*bltin = idx;
973
		if (*new == ':') {
974
			idx++;
975
		}
976
		new++, old++;
977
	}
978
	if (builtinloc >= 0 && *bltin < 0)
979
		firstchange = 0;
980
	return firstchange;
947
}
981
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/exec.h (-4 / +7 lines)
Lines 49-61 Link Here
49
	int cmdtype;
49
	int cmdtype;
50
	union param {
50
	union param {
51
		int index;
51
		int index;
52
		union node *func;
52
		struct funcnode *func;
53
		const struct builtincmd *cmd;
53
	} u;
54
	} u;
54
};
55
};
55
56
56
57
57
#define DO_ERR	1		/* find_command prints errors */
58
#define DO_ERR	1		/* find_command prints errors */
58
#define DO_ABS	2		/* find_command checks absolute paths */
59
#define DO_ABS	2		/* find_command checks absolute paths */
60
#define DO_NOFUN	4	/* find_command ignores functions */
61
#define DO_BRUTE	8	/* find_command ignores hash table */
59
62
60
extern const char *pathopt;	/* set by padvance */
63
extern const char *pathopt;	/* set by padvance */
61
extern int exerrno;		/* last exec error */
64
extern int exerrno;		/* last exec error */
Lines 65-76 Link Here
65
char *padvance __P((const char **, const char *));
68
char *padvance __P((const char **, const char *));
66
int hashcmd __P((int, char **));
69
int hashcmd __P((int, char **));
67
void find_command __P((char *, struct cmdentry *, int, const char *));
70
void find_command __P((char *, struct cmdentry *, int, const char *));
68
int find_builtin __P((char *));
71
struct builtincmd *find_builtin __P((const char *));
69
void hashcd __P((void));
72
void hashcd __P((void));
70
void changepath __P((const char *));
73
void changepath __P((const char *));
71
void deletefuncs __P((void));
72
void getcmdentry __P((char *, struct cmdentry *));
74
void getcmdentry __P((char *, struct cmdentry *));
73
void addcmdentry __P((char *, struct cmdentry *));
75
void addcmdentry __P((char *, struct cmdentry *));
74
void defun __P((char *, union node *));
76
void defun __P((char *, union node *));
75
int unsetfunc __P((char *));
77
void unsetfunc __P((char *));
76
int typecmd __P((int, char **));
78
int typecmd __P((int, char **));
79
int commandcmd __P((int, char **));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/expand.c (-484 / +718 lines)
Lines 54-59 Link Here
54
#include <pwd.h>
54
#include <pwd.h>
55
#include <stdlib.h>
55
#include <stdlib.h>
56
#include <stdio.h>
56
#include <stdio.h>
57
#include <limits.h>
58
#if defined(__GLIBC__)
59
#if !defined(FNMATCH_BROKEN)
60
#include <fnmatch.h>
61
#if !defined(GLOB_BROKEN)
62
#include <glob.h>
63
#endif
64
#endif
65
#endif
57
66
58
/*
67
/*
59
 * Routines to expand arguments to commands.  We have to deal with
68
 * Routines to expand arguments to commands.  We have to deal with
Lines 78-83 Link Here
78
#include "show.h"
87
#include "show.h"
79
88
80
/*
89
/*
90
 * _rmescape() flags
91
 */
92
#define RMESCAPE_ALLOC	0x1	/* Allocate a new string */
93
#define RMESCAPE_GLOB	0x2	/* Add backslashes for glob */
94
#define RMESCAPE_QUOTED	0x4	/* Remove CTLESC unless in quotes */
95
#define RMESCAPE_GROW	0x8	/* Grow strings instead of stalloc */
96
#define RMESCAPE_HEAP	0x10	/* Malloc strings instead of stalloc */
97
98
/*
81
 * Structure specifying which parts of the string should be searched
99
 * Structure specifying which parts of the string should be searched
82
 * for IFS characters.
100
 * for IFS characters.
83
 */
101
 */
Lines 89-122 Link Here
89
	int nulonly;		/* search for nul bytes only */
107
	int nulonly;		/* search for nul bytes only */
90
};
108
};
91
109
92
110
/* output of current string */
93
char *expdest;			/* output of current string */
111
static char *expdest;
94
struct nodelist *argbackq;	/* list of back quote expressions */
112
/* list of back quote expressions */
95
struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
113
static struct nodelist *argbackq;
96
struct ifsregion *ifslastp;	/* last struct in list */
114
/* first struct in list of ifs regions */
97
struct arglist exparg;		/* holds expanded arg list */
115
static struct ifsregion ifsfirst;
116
/* last struct in list */
117
static struct ifsregion *ifslastp;
118
/* holds expanded arg list */
119
static struct arglist exparg;
98
120
99
STATIC void argstr __P((char *, int));
121
STATIC void argstr __P((char *, int));
100
STATIC char *exptilde __P((char *, int));
122
STATIC char *exptilde __P((char *, int));
101
STATIC void expbackq __P((union node *, int, int));
123
STATIC void expbackq __P((union node *, int, int));
102
STATIC int subevalvar __P((char *, char *, int, int, int, int));
124
STATIC const char *subevalvar __P((char *, char *, int, int, int, int, int));
103
STATIC char *evalvar __P((char *, int));
125
STATIC char *evalvar __P((char *, int));
104
STATIC int varisset __P((char *, int));
126
STATIC int varisset __P((char *, int));
127
STATIC void strtodest __P((const char *, const char *, int));
128
STATIC void memtodest __P((const char *, size_t, const char *, int));
105
STATIC void varvalue __P((char *, int, int));
129
STATIC void varvalue __P((char *, int, int));
106
STATIC void recordregion __P((int, int, int));
130
STATIC void recordregion __P((int, int, int));
107
STATIC void removerecordregions __P((int)); 
131
STATIC void removerecordregions __P((int)); 
108
STATIC void ifsbreakup __P((char *, struct arglist *));
132
STATIC void ifsbreakup __P((char *, struct arglist *));
109
STATIC void ifsfree __P((void));
133
STATIC void ifsfree __P((void));
110
STATIC void expandmeta __P((struct strlist *, int));
134
STATIC void expandmeta __P((struct strlist *, int));
135
#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
136
STATIC void addglob __P((const glob_t *));
137
#else
111
STATIC void expmeta __P((char *, char *));
138
STATIC void expmeta __P((char *, char *));
139
#endif
112
STATIC void addfname __P((char *));
140
STATIC void addfname __P((char *));
141
#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
113
STATIC struct strlist *expsort __P((struct strlist *));
142
STATIC struct strlist *expsort __P((struct strlist *));
114
STATIC struct strlist *msort __P((struct strlist *, int));
143
STATIC struct strlist *msort __P((struct strlist *, int));
115
STATIC int pmatch __P((char *, char *, int));
144
#endif
116
STATIC char *cvtnum __P((int, char *));
145
STATIC int patmatch __P((char *, const char *));
146
#if !defined(__GLIBC__) || defined(FNMATCH_BROKEN)
147
STATIC int pmatch __P((const char *, const char *));
148
#else
149
#define pmatch(a, b) !fnmatch((a), (b), 0)
150
#endif
151
STATIC int cvtnum __P((long));
152
STATIC size_t esclen __P((const char *, const char *));
153
STATIC char *scanleft __P((char *, char *, char *, char *, int, int));
154
STATIC char *scanright __P((char *, char *, char *, char *, int, int));
155
static void varunset(const char *, const char *, const char *, int)
156
	__attribute__((__noreturn__));
117
157
118
extern int oexitstatus;
158
extern int oexitstatus;
119
159
160
161
/*
162
 * Prepare a pattern for a glob(3) call.
163
 *
164
 * Returns an stalloced string.
165
 */
166
167
STATIC inline char *
168
preglob(const char *pattern, int quoted, int flag) {
169
	flag |= RMESCAPE_GLOB;
170
	if (quoted) {
171
		flag |= RMESCAPE_QUOTED;
172
	}
173
	return _rmescapes((char *)pattern, flag);
174
}
175
176
177
STATIC size_t
178
esclen(const char *start, const char *p) {
179
	size_t esc = 0;
180
181
	while (p > start && *--p == CTLESC) {
182
		esc++;
183
	}
184
	return esc;
185
}
186
187
120
/*
188
/*
121
 * Expand shell variables and backquotes inside a here document.
189
 * Expand shell variables and backquotes inside a here document.
122
 */
190
 */
Lines 196-259 Link Here
196
	char *p;
264
	char *p;
197
	int flag;
265
	int flag;
198
{
266
{
199
	char c;
267
	static const char spclchars[] = {
268
		'=',
269
		':',
270
		CTLQUOTEMARK,
271
		CTLENDVAR,
272
		CTLESC,
273
		CTLVAR,
274
		CTLBACKQ,
275
		CTLBACKQ | CTLQUOTE,
276
		CTLENDARI,
277
		0
278
	};
279
	const char *reject = spclchars;
280
	int c;
200
	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
281
	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
201
	int firsteq = 1;
282
	int breakall = flag & EXP_WORD;
283
	int inquotes;
284
	size_t length;
285
	int startloc;
202
286
203
	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
287
	if (!(flag & EXP_VARTILDE)) {
288
		reject += 2;
289
	} else if (flag & EXP_VARTILDE2) {
290
		reject++;
291
	}
292
	inquotes = 0;
293
	length = 0;
294
	if (flag & EXP_TILDE) {
295
		flag &= ~EXP_TILDE;
296
tilde:
204
		p = exptilde(p, flag);
297
		p = exptilde(p, flag);
298
	}
299
start:
300
	startloc = expdest - stackblock();
205
	for (;;) {
301
	for (;;) {
206
		switch (c = *p++) {
302
		length += strcspn(p + length, reject);
303
		c = p[length];
304
		if ((c && !(c & 0x80)) || c == CTLENDARI) {
305
			/* c == '=' || c == ':' || c == CTLENDARI */
306
			length++;
307
		}
308
		if (length > 0) {
309
			int newloc;
310
			expdest = stnputs(p, length, expdest);
311
			newloc = expdest - stackblock();
312
			if (breakall && !inquotes && newloc > startloc) {
313
				recordregion(startloc, newloc, 0);
314
			}
315
			startloc = newloc;
316
		}
317
		p += length + 1;
318
		length = 0;
319
320
		switch (c) {
207
		case '\0':
321
		case '\0':
322
			goto breakloop;
323
		case '=':
324
			if (flag & EXP_VARTILDE2) {
325
				p--;
326
				continue;
327
			}
328
			flag |= EXP_VARTILDE2;
329
			reject++;
330
			/* fall through */
331
		case ':':
332
			/*
333
			 * sort of a hack - expand tildes in variable
334
			 * assignments (after the first '=' and after ':'s).
335
			 */
336
			if (*--p == '~') {
337
				goto tilde;
338
			}
339
			continue;
340
		}
341
342
		switch (c) {
208
		case CTLENDVAR: /* ??? */
343
		case CTLENDVAR: /* ??? */
209
			goto breakloop;
344
			goto breakloop;
210
		case CTLQUOTEMARK:
345
		case CTLQUOTEMARK:
211
			/* "$@" syntax adherence hack */
346
			/* "$@" syntax adherence hack */
212
			if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
347
			if (
213
				break;
348
				!inquotes &&
214
			if ((flag & EXP_FULL) != 0)
349
				!memcmp(p, dolatstr, DOLATSTRLEN) &&
215
				STPUTC(c, expdest);
350
				(p[4] == CTLQUOTEMARK || (
351
					p[4] == CTLENDVAR &&
352
					p[5] == CTLQUOTEMARK
353
				))
354
			) {
355
				p = evalvar(p + 1, flag) + 1;
356
				goto start;
357
			}
358
			inquotes = !inquotes;
359
addquote:
360
			if (quotes) {
361
				p--;
362
				length++;
363
				startloc++;
364
			}
216
			break;
365
			break;
217
		case CTLESC:
366
		case CTLESC:
218
			if (quotes)
367
			startloc++;
219
				STPUTC(c, expdest);
368
			length++;
220
			c = *p++;
369
			goto addquote;
221
			STPUTC(c, expdest);
222
			break;
223
		case CTLVAR:
370
		case CTLVAR:
224
			p = evalvar(p, flag);
371
			p = evalvar(p, flag);
225
			break;
372
			goto start;
226
		case CTLBACKQ:
373
		case CTLBACKQ:
374
			c = 0;
227
		case CTLBACKQ|CTLQUOTE:
375
		case CTLBACKQ|CTLQUOTE:
228
			expbackq(argbackq->n, c & CTLQUOTE, flag);
376
			expbackq(argbackq->n, c, quotes);
229
			argbackq = argbackq->next;
377
			argbackq = argbackq->next;
230
			break;
378
			goto start;
231
		case CTLENDARI:
379
		case CTLENDARI:
232
			expari(flag);
380
			p--;
233
			break;
381
			expari(quotes);
234
		case ':':
382
			goto start;
235
		case '=':
236
			/*
237
			 * sort of a hack - expand tildes in variable
238
			 * assignments (after the first '=' and after ':'s).
239
			 */
240
			STPUTC(c, expdest);
241
			if (flag & EXP_VARTILDE && *p == '~') {
242
				if (c == '=') {
243
					if (firsteq)
244
						firsteq = 0;
245
					else
246
						break;
247
				}
248
				p = exptilde(p, flag);
249
			}
250
			break;
251
		default:
252
			STPUTC(c, expdest);
253
		}
383
		}
254
	}
384
	}
255
breakloop:;
385
breakloop:
256
	return;
386
	;
257
}
387
}
258
388
259
STATIC char *
389
STATIC char *
Lines 262-272 Link Here
262
	int flag;
392
	int flag;
263
{
393
{
264
	char c, *startp = p;
394
	char c, *startp = p;
395
	char *name;
265
	struct passwd *pw;
396
	struct passwd *pw;
266
	const char *home;
397
	const char *home;
267
	int quotes = flag & (EXP_FULL | EXP_CASE);
398
	int quotes = flag & (EXP_FULL | EXP_CASE);
399
	int startloc;
268
400
269
	while ((c = *p) != '\0') {
401
	if (*p == CTLESC && (flag & EXP_QWORD)) {
402
		p++;
403
	}
404
	if (*p != '~') {
405
		return startp;
406
	}
407
	name = p + 1;
408
409
	while ((c = *++p) != '\0') {
270
		switch(c) {
410
		switch(c) {
271
		case CTLESC:
411
		case CTLESC:
272
			return (startp);
412
			return (startp);
Lines 277-304 Link Here
277
				goto done;
417
				goto done;
278
			break;
418
			break;
279
		case '/':
419
		case '/':
420
		case CTLENDVAR:
280
			goto done;
421
			goto done;
281
		}
422
		}
282
		p++;
283
	}
423
	}
284
done:
424
done:
285
	*p = '\0';
425
	*p = '\0';
286
	if (*(startp+1) == '\0') {
426
	if (*name == '\0') {
287
		if ((home = lookupvar("HOME")) == NULL)
427
		if ((home = lookupvar(homestr)) == NULL)
288
			goto lose;
428
			goto lose;
289
	} else {
429
	} else {
290
		if ((pw = getpwnam(startp+1)) == NULL)
430
		if ((pw = getpwnam(name)) == NULL)
291
			goto lose;
431
			goto lose;
292
		home = pw->pw_dir;
432
		home = pw->pw_dir;
293
	}
433
	}
294
	if (*home == '\0')
434
	if (*home == '\0')
295
		goto lose;
435
		goto lose;
296
	*p = c;
436
	*p = c;
297
	while ((c = *home++) != '\0') {
437
	startloc = expdest - stackblock();
298
		if (quotes && SQSYNTAX[(int)c] == CCTL)
438
	strtodest(home, SQSYNTAX, quotes);
299
			STPUTC(CTLESC, expdest);
439
	recordregion(startloc, expdest - stackblock(), 0);
300
		STPUTC(c, expdest);
301
	}
302
	return (p);
440
	return (p);
303
lose:
441
lose:
304
	*p = c;
442
	*p = c;
Lines 352-412 Link Here
352
 * evaluate, place result in (backed up) result, adjust string position.
490
 * evaluate, place result in (backed up) result, adjust string position.
353
 */
491
 */
354
void
492
void
355
expari(flag)
493
expari(quotes)
356
	int flag;
494
	int quotes;
357
{
495
{
358
	char *p, *start;
496
	char *p, *start;
359
	int result;
360
	int begoff;
497
	int begoff;
361
	int quotes = flag & (EXP_FULL | EXP_CASE);
498
	int flag;
362
	int quoted;
499
	int len;
363
500
364
	/*	ifsfree(); */
501
	/*	ifsfree(); */
365
502
366
	/*
503
	/*
367
	 * This routine is slightly over-complicated for
504
	 * This routine is slightly over-complicated for
368
	 * efficiency.  First we make sure there is
505
	 * efficiency.  Next we scan backwards looking for the
369
	 * enough space for the result, which may be bigger
506
	 * start of arithmetic.
370
	 * than the expression if we add exponentation.  Next we
371
	 * scan backwards looking for the start of arithmetic.  If the
372
	 * next previous character is a CTLESC character, then we
373
	 * have to rescan starting from the beginning since CTLESC
374
	 * characters have to be processed left to right.
375
	 */
507
	 */
376
#if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10
377
#error "integers with more than 10 digits are not supported"
378
#endif
379
	CHECKSTRSPACE(12 - 2, expdest);
380
	USTPUTC('\0', expdest);
381
	start = stackblock();
508
	start = stackblock();
382
	p = expdest - 1;
509
	p = expdest - 1;
383
	while (*p != CTLARI && p >= start)
510
	*p = '\0';
384
		--p;
511
	p--;
385
	if (*p != CTLARI)
512
	do {
513
		int esc;
514
515
		while (*p != CTLARI) {
516
			p--;
517
#ifdef DEBUG
518
			if (p < start) {
386
		error("missing CTLARI (shouldn't happen)");
519
		error("missing CTLARI (shouldn't happen)");
387
	if (p > start && *(p-1) == CTLESC)
520
			}
388
		for (p = start; *p != CTLARI; p++)
521
#endif
389
			if (*p == CTLESC)
522
		}
390
				p++;
523
524
		esc = esclen(start, p);
525
		if (!(esc % 2)) {
526
			break;
527
		}
528
529
		p -= esc + 1;
530
	} while (1);
391
531
392
	if (p[1] == '"')
393
		quoted=1;
394
	else
395
		quoted=0;
396
	begoff = p - start;
532
	begoff = p - start;
533
397
	removerecordregions(begoff);
534
	removerecordregions(begoff);
535
536
	flag = p[1];
537
538
	expdest = p;
539
398
	if (quotes)
540
	if (quotes)
399
		rmescapes(p+2);
541
		rmescapes(p + 2);
400
	result = arith(p+2);
401
	fmtstr(p, 12, "%d", result);
402
542
403
	while (*p++)
543
	len = cvtnum(arith(p + 2));
404
		;
405
544
406
	if (quoted == 0)
545
	if (flag != '"')
407
		recordregion(begoff, p - 1 - start, 0);
546
		recordregion(begoff, begoff + len, 0);
408
	result = expdest - p + 1;
409
	STADJUST(-result, expdest);
410
}
547
}
411
548
412
549
Lines 415-456 Link Here
415
 */
552
 */
416
553
417
STATIC void
554
STATIC void
418
expbackq(cmd, quoted, flag)
555
expbackq(cmd, quoted, quotes)
419
	union node *cmd;
556
	union node *cmd;
420
	int quoted;
557
	int quoted;
421
	int flag;
558
	int quotes;
422
{
559
{
423
	struct backcmd in;
560
	struct backcmd in;
424
	int i;
561
	int i;
425
	char buf[128];
562
	char buf[128];
426
	char *p;
563
	char *p;
427
	char *dest = expdest;
564
	char *dest = expdest;
428
	struct ifsregion saveifs, *savelastp;
565
	struct ifsregion saveifs;
566
	struct ifsregion *savelastp;
429
	struct nodelist *saveargbackq;
567
	struct nodelist *saveargbackq;
430
	char lastc;
431
	int startloc = dest - stackblock();
568
	int startloc = dest - stackblock();
432
	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
569
	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
433
	int saveherefd;
570
	int saveherefd;
434
	int quotes = flag & (EXP_FULL | EXP_CASE);
435
571
436
	INTOFF;
572
	in.fd = -1;
573
	in.buf = 0;
574
	in.jp = 0;
575
437
	saveifs = ifsfirst;
576
	saveifs = ifsfirst;
438
	savelastp = ifslastp;
577
	savelastp = ifslastp;
439
	saveargbackq = argbackq;
578
	saveargbackq = argbackq;
440
	saveherefd = herefd;
579
	saveherefd = herefd;
441
	herefd = -1;
580
	herefd = -1;
442
	p = grabstackstr(dest);
581
443
	evalbackcmd(cmd, &in);
582
	INTOFF;
444
	ungrabstackstr(p, dest);
583
	evalbackcmd(cmd, (struct backcmd *) &in);
445
	ifsfirst = saveifs;
584
	ifsfirst = saveifs;
446
	ifslastp = savelastp;
585
	ifslastp = savelastp;
447
	argbackq = saveargbackq;
586
	argbackq = saveargbackq;
448
	herefd = saveherefd;
587
	herefd = saveherefd;
449
588
450
	p = in.buf;
589
	p = in.buf;
451
	lastc = '\0';
590
	i = in.nleft;
591
	if (i == 0)
592
		goto read;
452
	for (;;) {
593
	for (;;) {
453
		if (--in.nleft < 0) {
594
		memtodest(p, i, syntax, quotes);
595
read:
454
			if (in.fd < 0)
596
			if (in.fd < 0)
455
				break;
597
				break;
456
			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
598
			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
Lines 458-475 Link Here
458
			if (i <= 0)
600
			if (i <= 0)
459
				break;
601
				break;
460
			p = buf;
602
			p = buf;
461
			in.nleft = i - 1;
462
		}
463
		lastc = *p++;
464
		if (lastc != '\0') {
465
			if (quotes && syntax[(int)lastc] == CCTL)
466
				STPUTC(CTLESC, dest);
467
			STPUTC(lastc, dest);
468
		}
469
	}
603
	}
470
604
605
	dest = expdest;
606
471
	/* Eat all trailing newlines */
607
	/* Eat all trailing newlines */
472
	for (p--; lastc == '\n'; lastc = *--p)
608
	for (; dest > stackblock() && dest[-1] == '\n';)
473
		STUNPUTC(dest);
609
		STUNPUTC(dest);
474
610
475
	if (in.fd >= 0)
611
	if (in.fd >= 0)
Lines 478-483 Link Here
478
		ckfree(in.buf);
614
		ckfree(in.buf);
479
	if (in.jp)
615
	if (in.jp)
480
		exitstatus = waitforjob(in.jp);
616
		exitstatus = waitforjob(in.jp);
617
	INTON;
481
	if (quoted == 0)
618
	if (quoted == 0)
482
		recordregion(startloc, dest - stackblock(), 0);
619
		recordregion(startloc, dest - stackblock(), 0);
483
	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
620
	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
Lines 485-615 Link Here
485
		(dest - stackblock()) - startloc,
622
		(dest - stackblock()) - startloc,
486
		stackblock() + startloc));
623
		stackblock() + startloc));
487
	expdest = dest;
624
	expdest = dest;
488
	INTON;
489
}
625
}
490
626
491
627
628
STATIC char *
629
scanleft(
630
	char *startp, char *rmesc, char *rmescend, char *str, int quotes,
631
	int zero
632
) {
633
	char *loc;
634
	char *loc2;
635
	char c;
636
637
	loc = startp;
638
	loc2 = rmesc;
639
	do {
640
		int match;
641
		const char *s = loc2;
642
		c = *loc2;
643
		if (zero) {
644
			*loc2 = '\0';
645
			s = rmesc;
646
		}
647
		match = pmatch(str, s);
648
		*loc2 = c;
649
		if (match)
650
			return loc;
651
		if (quotes && *loc == CTLESC)
652
			loc++;
653
		loc++;
654
		loc2++;
655
	} while (c);
656
	return 0;
657
}
658
659
660
STATIC char *
661
scanright(
662
	char *startp, char *rmesc, char *rmescend, char *str, int quotes,
663
	int zero
664
) {
665
	int esc = 0;
666
	char *loc;
667
	char *loc2;
492
668
493
STATIC int
669
	for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
494
subevalvar(p, str, strloc, subtype, startloc, varflags)
670
		int match;
671
		char c = *loc2;
672
		const char *s = loc2;
673
		if (zero) {
674
			*loc2 = '\0';
675
			s = rmesc;
676
		}
677
		match = pmatch(str, s);
678
		*loc2 = c;
679
		if (match)
680
			return loc;
681
		loc--;
682
		if (quotes) {
683
			if (--esc < 0) {
684
				esc = esclen(startp, loc);
685
			}
686
			if (esc % 2) {
687
				esc--;
688
				loc--;
689
			}
690
		}
691
	}
692
	return 0;
693
}
694
695
STATIC const char *
696
subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
495
	char *p;
697
	char *p;
496
	char *str;
698
	char *str;
497
	int strloc;
699
	int strloc;
498
	int subtype;
700
	int subtype;
499
	int startloc;
701
	int startloc;
500
	int varflags;
702
	int varflags;
703
	int quotes;
501
{
704
{
502
	char *startp;
705
	char *startp;
503
	char *loc = NULL;
706
	char *loc;
504
	char *q;
505
	int c = 0;
506
	int saveherefd = herefd;
707
	int saveherefd = herefd;
507
	struct nodelist *saveargbackq = argbackq;
708
	struct nodelist *saveargbackq = argbackq;
508
	int amount;
709
	int amount;
710
	char *rmesc, *rmescend;
711
	int zero;
712
	char *(*scan)(char *, char *, char *, char *, int , int);
509
713
510
	herefd = -1;
714
	herefd = -1;
511
	argstr(p, 0);
715
	argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
512
	STACKSTRNUL(expdest);
716
	STPUTC('\0', expdest);
513
	herefd = saveherefd;
717
	herefd = saveherefd;
514
	argbackq = saveargbackq;
718
	argbackq = saveargbackq;
515
	startp = stackblock() + startloc;
719
	startp = stackblock() + startloc;
516
	if (str == NULL)
517
	    str = stackblock() + strloc;
518
720
519
	switch (subtype) {
721
	switch (subtype) {
520
	case VSASSIGN:
722
	case VSASSIGN:
521
		setvar(str, startp, 0);
723
		setvar(str, startp, 0);
522
		amount = startp - expdest;
724
		amount = startp - expdest;
523
		STADJUST(amount, expdest);
725
		STADJUST(amount, expdest);
524
		varflags &= ~VSNUL;
726
		return startp;
525
		if (c != 0)
526
			*loc = c;
527
		return 1;
528
727
529
	case VSQUESTION:
728
	case VSQUESTION:
530
		if (*p != CTLENDVAR) {
729
		varunset(p, str, startp, varflags);
531
			outfmt(&errout, "%s\n", startp);
532
			error((char *)NULL);
533
		}
534
		error("%.*s: parameter %snot set", p - str - 1,
535
		      str, (varflags & VSNUL) ? "null or "
536
					      : nullstr);
537
		/* NOTREACHED */
730
		/* NOTREACHED */
538
539
	case VSTRIMLEFT:
540
		for (loc = startp; loc < str; loc++) {
541
			c = *loc;
542
			*loc = '\0';
543
			if (patmatch(str, startp, varflags & VSQUOTE))
544
				goto recordleft;
545
			*loc = c;
546
			if ((varflags & VSQUOTE) && *loc == CTLESC)
547
			        loc++;
548
		}
731
		}
549
		return 0;
550
732
551
	case VSTRIMLEFTMAX:
733
	subtype -= VSTRIMRIGHT;
552
		for (loc = str - 1; loc >= startp;) {
734
#ifdef DEBUG
553
			c = *loc;
735
	if (subtype < 0 || subtype > 3)
554
			*loc = '\0';
736
		abort();
555
			if (patmatch(str, startp, varflags & VSQUOTE))
737
#endif
556
				goto recordleft;
557
			*loc = c;
558
			loc--;
559
			if ((varflags & VSQUOTE) && loc > startp &&
560
			    *(loc - 1) == CTLESC) {
561
				for (q = startp; q < loc; q++)
562
					if (*q == CTLESC)
563
						q++;
564
				if (q > loc)
565
					loc--;
566
			}
567
		}
568
		return 0;
569
738
570
	case VSTRIMRIGHT:
739
	rmesc = startp;
571
	        for (loc = str - 1; loc >= startp;) {
740
	rmescend = stackblock() + strloc;
572
			if (patmatch(str, loc, varflags & VSQUOTE))
741
	if (quotes) {
573
				goto recordright;
742
		rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
574
			loc--;
743
		if (rmesc != startp) {
575
			if ((varflags & VSQUOTE) && loc > startp &&
744
			rmescend = expdest;
576
			    *(loc - 1) == CTLESC) { 
745
			startp = stackblock() + startloc;
577
				for (q = startp; q < loc; q++)
578
					if (*q == CTLESC)
579
						q++;
580
				if (q > loc)
581
					loc--;
582
			}
746
			}
583
		}
747
		}
584
		return 0;
748
	rmescend--;
749
	str = stackblock() + strloc;
750
	preglob(str, varflags & VSQUOTE, 0);
585
751
586
	case VSTRIMRIGHTMAX:
752
	/* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
587
		for (loc = startp; loc < str - 1; loc++) {
753
	zero = subtype >> 1;
588
			if (patmatch(str, loc, varflags & VSQUOTE))
754
	/* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
589
				goto recordright;
755
	scan = (subtype & 1) ^ zero ? scanleft : scanright;
590
			if ((varflags & VSQUOTE) && *loc == CTLESC)
591
			        loc++;
592
		}
593
		return 0;
594
756
595
	default:
757
	loc = scan(startp, rmesc, rmescend, str, quotes, zero);
596
		abort();
758
	if (loc) {
759
		if (zero) {
760
			memmove(startp, loc, str - loc);
761
			loc = startp + (str - loc) - 1;
597
	}
762
	}
598
763
		*loc = '\0';
599
recordleft:
600
	*loc = c;
601
	amount = ((str - 1) - (loc - startp)) - expdest;
602
	STADJUST(amount, expdest);
603
	while (loc != str - 1)
604
		*startp++ = *loc++;
605
	return 1;
606
607
recordright:
608
	amount = loc - expdest;
764
	amount = loc - expdest;
609
	STADJUST(amount, expdest);
765
	STADJUST(amount, expdest);
610
	STPUTC('\0', expdest);
766
	}
611
	STADJUST(-1, expdest);
767
	return loc;
612
	return 1;
613
}
768
}
614
769
615
770
Lines 617-736 Link Here
617
 * Expand a variable, and return a pointer to the next character in the
772
 * Expand a variable, and return a pointer to the next character in the
618
 * input string.
773
 * input string.
619
 */
774
 */
620
621
STATIC char *
775
STATIC char *
622
evalvar(p, flag)
776
evalvar(p, flag)
623
	char *p;
777
	char *p;
624
	int flag;
778
	const int flag;
625
{
779
{
626
	int subtype;
780
	int subtype;
627
	int varflags;
781
	int varflags;
628
	char *var;
782
	char *var;
629
	char *val;
630
	int patloc;
783
	int patloc;
631
	int c;
784
	int c;
632
	int set;
785
	int set;
633
	int special;
634
	int startloc;
786
	int startloc;
635
	int varlen;
787
	size_t varlen;
636
	int easy;
788
	int easy;
637
	int quotes = flag & (EXP_FULL | EXP_CASE);
789
	int quotes;
790
	int quoted;
638
791
792
	quotes = flag & (EXP_FULL | EXP_CASE);
639
	varflags = *p++;
793
	varflags = *p++;
640
	subtype = varflags & VSTYPE;
794
	subtype = varflags & VSTYPE;
795
	quoted = varflags & VSQUOTE;
641
	var = p;
796
	var = p;
642
	special = 0;
797
	easy = (!quoted || (*var == '@' && shellparam.nparam));
643
	if (! is_name(*p))
644
		special = 1;
645
	p = strchr(p, '=') + 1;
646
again: /* jump here after setting a variable with ${var=text} */
647
	if (special) {
648
		set = varisset(var, varflags & VSNUL);
649
		val = NULL;
650
	} else {
651
		val = lookupvar(var);
652
		if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
653
			val = NULL;
654
			set = 0;
655
		} else
656
			set = 1;
657
	}
658
	varlen = 0;
798
	varlen = 0;
659
	startloc = expdest - stackblock();
799
	startloc = expdest - stackblock();
660
	if (!set && uflag)
800
	p = strchr(p, '=') + 1;
661
		switch (subtype) {
801
662
		case VSNORMAL:
802
	if (!is_name(*var)) {
663
		case VSTRIMLEFT:
803
		set = varisset(var, varflags & VSNUL);
664
		case VSTRIMLEFTMAX:
804
		set--;
665
		case VSTRIMRIGHT:
805
		if (subtype == VSPLUS)
666
		case VSTRIMRIGHTMAX:
806
			goto vsplus;
667
		case VSLENGTH:
807
		if (++set) {
668
			error("%.*s: parameter not set", p - var - 1, var);
808
			varvalue(var, quoted, flag);
669
			/* NOTREACHED */
670
		}
671
	if (set && subtype != VSPLUS) {
672
		/* insert the value of the variable */
673
		if (special) {
674
			varvalue(var, varflags & VSQUOTE, flag & EXP_FULL);
675
			if (subtype == VSLENGTH) {
809
			if (subtype == VSLENGTH) {
676
				varlen = expdest - stackblock() - startloc;
810
				varlen = expdest - stackblock() - startloc;
677
				STADJUST(-varlen, expdest);
811
				STADJUST(-varlen, expdest);
812
				goto vslen;
813
			}
678
			}
814
			}
679
		} else {
815
		} else {
680
			char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
816
		const char *val;
681
								  : BASESYNTAX;
817
again:
818
		/* jump here after setting a variable with ${var=text} */
819
		val = lookupvar(var);
820
		set = !val || ((varflags & VSNUL) && !*val);
821
		if (subtype == VSPLUS)
822
			goto vsplus;
823
		if (--set) {
824
			varlen = strlen(val);
825
			if (subtype == VSLENGTH)
826
				goto vslen;
827
			memtodest(
828
				val, varlen, quoted ? DQSYNTAX : BASESYNTAX,
829
				quotes
830
			);
831
		}
832
	}
682
833
683
			if (subtype == VSLENGTH) {
834
684
				for (;*val; val++)
835
	if (subtype == VSMINUS) {
685
					varlen++;
836
vsplus:
837
		if (!set) {
838
			argstr(
839
				p, flag | EXP_TILDE |
840
					(quoted ?  EXP_QWORD : EXP_WORD)
841
			);
842
			goto end;
686
			}
843
			}
687
			else {
844
		if (easy)
688
				while (*val) {
845
			goto record;
689
					if (quotes && syntax[(int)*val] == CCTL)
846
		goto end;
690
						STPUTC(CTLESC, expdest);
691
					STPUTC(*val++, expdest);
692
				}
847
				}
693
848
849
	if (subtype == VSASSIGN || subtype == VSQUESTION) {
850
		if (!set) {
851
			if (subevalvar(p, var, 0, subtype, startloc,
852
				       varflags, 0)) {
853
				varflags &= ~VSNUL;
854
				/* 
855
				 * Remove any recorded regions beyond 
856
				 * start of variable 
857
				 */
858
				removerecordregions(startloc);
859
				goto again;
694
			}
860
			}
861
			goto end;
695
		}
862
		}
863
		if (easy)
864
			goto record;
865
		goto end;
696
	}
866
	}
697
867
698
	if (subtype == VSPLUS)
868
	if (!set && uflag)
699
		set = ! set;
869
		varunset(p, var, 0, 0);
700
701
	easy = ((varflags & VSQUOTE) == 0 ||
702
		(*var == '@' && shellparam.nparam != 1));
703
704
870
705
	switch (subtype) {
871
	if (subtype == VSLENGTH) {
706
	case VSLENGTH:
872
vslen:
707
		expdest = cvtnum(varlen, expdest);
873
		cvtnum(varlen);
708
		goto record;
874
		goto record;
875
	}
709
876
710
	case VSNORMAL:
877
	if (subtype == VSNORMAL) {
711
		if (!easy)
878
		if (!easy)
712
			break;
879
			goto end;
713
record:
880
record:
714
		recordregion(startloc, expdest - stackblock(),
881
		recordregion(startloc, expdest - stackblock(), quoted);
715
			     varflags & VSQUOTE);
882
		goto end;
716
		break;
717
718
	case VSPLUS:
719
	case VSMINUS:
720
		if (!set) {
721
		        argstr(p, flag);
722
			break;
723
		}
883
		}
724
		if (easy)
725
			goto record;
726
		break;
727
884
885
#ifdef DEBUG
886
	switch (subtype) {
728
	case VSTRIMLEFT:
887
	case VSTRIMLEFT:
729
	case VSTRIMLEFTMAX:
888
	case VSTRIMLEFTMAX:
730
	case VSTRIMRIGHT:
889
	case VSTRIMRIGHT:
731
	case VSTRIMRIGHTMAX:
890
	case VSTRIMRIGHTMAX:
732
		if (!set)
733
			break;
891
			break;
892
	default:
893
		abort();
894
	}
895
#endif
896
897
	if (set) {
734
		/*
898
		/*
735
		 * Terminate the string and start recording the pattern
899
		 * Terminate the string and start recording the pattern
736
		 * right after it
900
		 * right after it
Lines 738-774 Link Here
738
		STPUTC('\0', expdest);
902
		STPUTC('\0', expdest);
739
		patloc = expdest - stackblock();
903
		patloc = expdest - stackblock();
740
		if (subevalvar(p, NULL, patloc, subtype,
904
		if (subevalvar(p, NULL, patloc, subtype,
741
			       startloc, varflags) == 0) {
905
			       startloc, varflags, quotes) == 0) {
742
			int amount = (expdest - stackblock() - patloc) + 1;
906
			int amount = expdest - (stackblock() + patloc - 1);
743
			STADJUST(-amount, expdest);
907
			STADJUST(-amount, expdest);
744
		}
908
		}
745
		/* Remove any recorded regions beyond start of variable */
909
		/* Remove any recorded regions beyond start of variable */
746
		removerecordregions(startloc);
910
		removerecordregions(startloc);
747
		goto record;
911
		goto record;
748
749
	case VSASSIGN:
750
	case VSQUESTION:
751
		if (!set) {
752
			if (subevalvar(p, var, 0, subtype, startloc,
753
				       varflags)) {
754
				varflags &= ~VSNUL;
755
				/* 
756
				 * Remove any recorded regions beyond 
757
				 * start of variable 
758
				 */
759
				removerecordregions(startloc);
760
				goto again;
761
			}
762
			break;
763
		}
764
		if (easy)
765
			goto record;
766
		break;
767
768
	default:
769
		abort();
770
	}
912
	}
771
913
914
end:
772
	if (subtype != VSNORMAL) {	/* skip to end of alternative */
915
	if (subtype != VSNORMAL) {	/* skip to end of alternative */
773
		int nesting = 1;
916
		int nesting = 1;
774
		for (;;) {
917
		for (;;) {
Lines 801-807 Link Here
801
	int nulok;
944
	int nulok;
802
{
945
{
803
	if (*name == '!')
946
	if (*name == '!')
804
		return backgndpid != -1;
947
		return backgndpid != 0;
805
	else if (*name == '@' || *name == '*') {
948
	else if (*name == '@' || *name == '*') {
806
		if (*shellparam.p == NULL)
949
		if (*shellparam.p == NULL)
807
			return 0;
950
			return 0;
Lines 835-871 Link Here
835
978
836
979
837
/*
980
/*
981
 * Put a string on the stack.
982
 */
983
984
STATIC void
985
memtodest(const char *p, size_t len, const char *syntax, int quotes) {
986
	char *q = expdest;
987
988
	q = makestrspace(len * 2, q);
989
990
	while (len--) {
991
		int c = *p++;
992
		if (!c)
993
			continue;
994
		if (quotes && (syntax[c] == CCTL || syntax[c] == CBACK))
995
			USTPUTC(CTLESC, q);
996
		USTPUTC(c, q);
997
	}
998
999
	expdest = q;
1000
}
1001
1002
1003
STATIC void
1004
strtodest(p, syntax, quotes)
1005
	const char *p;
1006
	const char *syntax;
1007
	int quotes;
1008
{
1009
	memtodest(p, strlen(p), syntax, quotes);
1010
}
1011
1012
1013
1014
/*
838
 * Add the value of a specialized variable to the stack string.
1015
 * Add the value of a specialized variable to the stack string.
839
 */
1016
 */
840
1017
841
STATIC void
1018
STATIC void
842
varvalue(name, quoted, allow_split)
1019
varvalue(name, quoted, flags)
843
	char *name;
1020
	char *name;
844
	int quoted;
1021
	int quoted;
845
	int allow_split;
1022
	int flags;
846
{
1023
{
847
	int num;
1024
	int num;
848
	char *p;
1025
	char *p;
849
	int i;
1026
	int i;
850
	char sep;
1027
	int sep;
1028
	int sepq = 0;
851
	char **ap;
1029
	char **ap;
852
	char const *syntax;
1030
	char const *syntax;
1031
	int allow_split = flags & EXP_FULL;
1032
	int quotes = flags & (EXP_FULL | EXP_CASE);
853
1033
854
#define STRTODEST(p) \
1034
	syntax = quoted ? DQSYNTAX : BASESYNTAX;
855
	do {\
856
	if (allow_split) { \
857
		syntax = quoted? DQSYNTAX : BASESYNTAX; \
858
		while (*p) { \
859
			if (syntax[(int)*p] == CCTL) \
860
				STPUTC(CTLESC, expdest); \
861
			STPUTC(*p++, expdest); \
862
		} \
863
	} else \
864
		while (*p) \
865
			STPUTC(*p++, expdest); \
866
	} while (0)
867
868
869
	switch (*name) {
1035
	switch (*name) {
870
	case '$':
1036
	case '$':
871
		num = rootpid;
1037
		num = rootpid;
Lines 879-924 Link Here
879
	case '!':
1045
	case '!':
880
		num = backgndpid;
1046
		num = backgndpid;
881
numvar:
1047
numvar:
882
		expdest = cvtnum(num, expdest);
1048
		cvtnum(num);
883
		break;
1049
		break;
884
	case '-':
1050
	case '-':
885
		for (i = 0 ; i < NOPTS ; i++) {
1051
		for (i = 0 ; i < NOPTS ; i++) {
886
			if (optlist[i].val)
1052
			if (optlist[i])
887
				STPUTC(optlist[i].letter, expdest);
1053
				STPUTC(optletters[i], expdest);
888
		}
1054
		}
889
		break;
1055
		break;
890
	case '@':
1056
	case '@':
891
		if (allow_split && quoted) {
1057
		if (allow_split && quoted) {
892
			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
1058
			sep = 1 << CHAR_BIT;
893
				STRTODEST(p);
1059
			goto param;
894
				if (*ap)
895
					STPUTC('\0', expdest);
896
			}
897
			break;
898
		}
1060
		}
899
		/* fall through */
1061
		/* fall through */
900
	case '*':
1062
	case '*':
901
		if (ifsset() != 0)
1063
		sep = ifsset() ? ifsval()[0] : ' ';
902
			sep = ifsval()[0];
1064
		if (quotes) {
903
		else
1065
			sepq = (syntax[sep] == CCTL) || (syntax[sep] == CBACK);
904
			sep = ' ';
1066
		}
1067
param:
905
		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
1068
		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
906
			STRTODEST(p);
1069
			strtodest(p, syntax, quotes);
907
			if (*ap && sep)
1070
			if (*ap && sep) {
908
				STPUTC(sep, expdest);
1071
				p = expdest;
1072
				if (sepq)
1073
					STPUTC(CTLESC, p);
1074
				STPUTC(sep, p);
1075
				expdest = p;
1076
			}
909
		}
1077
		}
910
		break;
1078
		break;
911
	case '0':
1079
	case '0':
912
		p = arg0;
1080
		strtodest(arg0, syntax, quotes);
913
		STRTODEST(p);
914
		break;
1081
		break;
915
	default:
1082
	default:
916
		if (is_digit(*name)) {
917
			num = atoi(name);
1083
			num = atoi(name);
918
			if (num > 0 && num <= shellparam.nparam) {
1084
			if (num > 0 && num <= shellparam.nparam) {
919
				p = shellparam.p[num - 1];
1085
			strtodest(shellparam.p[num - 1], syntax, quotes);
920
				STRTODEST(p);
921
			}
922
		}
1086
		}
923
		break;
1087
		break;
924
	}
1088
	}
Lines 942-952 Link Here
942
	if (ifslastp == NULL) {
1106
	if (ifslastp == NULL) {
943
		ifsp = &ifsfirst;
1107
		ifsp = &ifsfirst;
944
	} else {
1108
	} else {
1109
		INTOFF;
945
		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
1110
		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
1111
		ifsp->next = NULL;
946
		ifslastp->next = ifsp;
1112
		ifslastp->next = ifsp;
1113
		INTON;
947
	}
1114
	}
948
	ifslastp = ifsp;
1115
	ifslastp = ifsp;
949
	ifslastp->next = NULL;
950
	ifslastp->begoff = start;
1116
	ifslastp->begoff = start;
951
	ifslastp->endoff = end;
1117
	ifslastp->endoff = end;
952
	ifslastp->nulonly = nulonly;
1118
	ifslastp->nulonly = nulonly;
Lines 969-975 Link Here
969
	char *start;
1135
	char *start;
970
	char *p;
1136
	char *p;
971
	char *q;
1137
	char *q;
972
	const char *ifs;
1138
	const char *ifs, *realifs;
973
	int ifsspc;
1139
	int ifsspc;
974
	int nulonly;
1140
	int nulonly;
975
1141
Lines 977-989 Link Here
977
	start = string;
1143
	start = string;
978
	ifsspc = 0;
1144
	ifsspc = 0;
979
	nulonly = 0;
1145
	nulonly = 0;
1146
	realifs = ifsset() ? ifsval() : defifs;
980
	if (ifslastp != NULL) {
1147
	if (ifslastp != NULL) {
981
		ifsp = &ifsfirst;
1148
		ifsp = &ifsfirst;
982
		do {
1149
		do {
983
			p = string + ifsp->begoff;
1150
			p = string + ifsp->begoff;
984
			nulonly = ifsp->nulonly;
1151
			nulonly = ifsp->nulonly;
985
			ifs = nulonly ? nullstr : 
1152
			ifs = nulonly ? nullstr : realifs;
986
				( ifsset() ? ifsval() : " \t\n" );
987
			ifsspc = 0;
1153
			ifsspc = 0;
988
			while (p < string + ifsp->endoff) {
1154
			while (p < string + ifsp->endoff) {
989
				q = p;
1155
				q = p;
Lines 991-997 Link Here
991
					p++;
1157
					p++;
992
				if (strchr(ifs, *p)) {
1158
				if (strchr(ifs, *p)) {
993
					if (!nulonly)
1159
					if (!nulonly)
994
						ifsspc = (strchr(" \t\n", *p) != NULL);
1160
						ifsspc = (strchr(defifs, *p) != NULL);
995
					/* Ignore IFS whitespace at start */
1161
					/* Ignore IFS whitespace at start */
996
					if (q == start && ifsspc) {
1162
					if (q == start && ifsspc) {
997
						p++;
1163
						p++;
Lines 1015-1021 Link Here
1015
							if (strchr(ifs, *p) == NULL ) {
1181
							if (strchr(ifs, *p) == NULL ) {
1016
								p = q;
1182
								p = q;
1017
								break;
1183
								break;
1018
							} else if (strchr(" \t\n",*p) == NULL) {
1184
							} else if (strchr(defifs, *p) == NULL) {
1019
								if (ifsspc) {
1185
								if (ifsspc) {
1020
									p++;
1186
									p++;
1021
									ifsspc = 0;
1187
									ifsspc = 0;
Lines 1032-1050 Link Here
1032
					p++;
1198
					p++;
1033
			}
1199
			}
1034
		} while ((ifsp = ifsp->next) != NULL);
1200
		} while ((ifsp = ifsp->next) != NULL);
1035
		if (*start || (!ifsspc && start > string && 
1201
		if (nulonly)
1036
			(nulonly || 1))) {
1202
			goto add;
1037
			sp = (struct strlist *)stalloc(sizeof *sp);
1038
			sp->text = start;
1039
			*arglist->lastp = sp;
1040
			arglist->lastp = &sp->next;
1041
		}
1203
		}
1042
	} else {
1204
1205
	if (!*start)
1206
		return;
1207
1208
add:
1043
		sp = (struct strlist *)stalloc(sizeof *sp);
1209
		sp = (struct strlist *)stalloc(sizeof *sp);
1044
		sp->text = start;
1210
		sp->text = start;
1045
		*arglist->lastp = sp;
1211
		*arglist->lastp = sp;
1046
		arglist->lastp = &sp->next;
1212
		arglist->lastp = &sp->next;
1047
	}
1048
}
1213
}
1049
1214
1050
STATIC void
1215
STATIC void
Lines 1069-1075 Link Here
1069
 * should be escapes.  The results are stored in the list exparg.
1234
 * should be escapes.  The results are stored in the list exparg.
1070
 */
1235
 */
1071
1236
1072
char *expdir;
1237
#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
1238
STATIC void
1239
expandmeta(str, flag)
1240
	struct strlist *str;
1241
	int flag;
1242
{
1243
	/* TODO - EXP_REDIR */
1244
1245
	while (str) {
1246
		const char *p;
1247
		glob_t pglob;
1248
		int i;
1249
1250
		if (fflag)
1251
			goto nometa;
1252
		INTOFF;
1253
		p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
1254
		i = glob(p, GLOB_NOMAGIC, 0, &pglob);
1255
		if (p != str->text)
1256
			ckfree(p);
1257
		switch (i) {
1258
		case 0:
1259
			if (!(pglob.gl_flags & GLOB_MAGCHAR))
1260
				goto nometa2;
1261
			addglob(&pglob);
1262
			globfree(&pglob);
1263
			INTON;
1264
			break;
1265
		case GLOB_NOMATCH:
1266
nometa2:
1267
			globfree(&pglob);
1268
			INTON;
1269
nometa:
1270
			*exparg.lastp = str;
1271
			rmescapes(str->text);
1272
			exparg.lastp = &str->next;
1273
			break;
1274
		default:	/* GLOB_NOSPACE */
1275
			error("Out of space");
1276
		}
1277
		str = str->next;
1278
	}
1279
}
1280
1281
1282
/*
1283
 * Add the result of glob(3) to the list.
1284
 */
1285
1286
STATIC void
1287
addglob(pglob)
1288
	const glob_t *pglob;
1289
{
1290
	char **p = pglob->gl_pathv;
1291
1292
	do {
1293
		addfname(*p);
1294
	} while (*++p);
1295
}
1296
1297
1298
#else	/* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
1299
STATIC char *expdir;
1073
1300
1074
1301
1075
STATIC void
1302
STATIC void
Lines 1077-1108 Link Here
1077
	struct strlist *str;
1304
	struct strlist *str;
1078
	int flag;
1305
	int flag;
1079
{
1306
{
1080
	char *p;
1307
	static const char metachars[] = {
1081
	struct strlist **savelastp;
1308
		'*', '?', '[', 0
1082
	struct strlist *sp;
1309
	};
1083
	char c;
1084
	/* TODO - EXP_REDIR */
1310
	/* TODO - EXP_REDIR */
1085
1311
1086
	while (str) {
1312
	while (str) {
1313
		struct strlist **savelastp;
1314
		struct strlist *sp;
1315
		char *p;
1316
1087
		if (fflag)
1317
		if (fflag)
1088
			goto nometa;
1318
			goto nometa;
1089
		p = str->text;
1319
		if (!strpbrk(str->text, metachars))
1090
		for (;;) {			/* fast check for meta chars */
1091
			if ((c = *p++) == '\0')
1092
				goto nometa;
1320
				goto nometa;
1093
			if (c == '*' || c == '?' || c == '[' || c == '!')
1094
				break;
1095
		}
1096
		savelastp = exparg.lastp;
1321
		savelastp = exparg.lastp;
1322
1097
		INTOFF;
1323
		INTOFF;
1098
		if (expdir == NULL) {
1324
		p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
1325
		{
1099
			int i = strlen(str->text);
1326
			int i = strlen(str->text);
1100
			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
1327
			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
1101
		}
1328
		}
1102
1329
1103
		expmeta(expdir, str->text);
1330
		expmeta(expdir, p);
1104
		ckfree(expdir);
1331
		ckfree(expdir);
1105
		expdir = NULL;
1332
		if (p != str->text)
1333
			ckfree(p);
1106
		INTON;
1334
		INTON;
1107
		if (exparg.lastp == savelastp) {
1335
		if (exparg.lastp == savelastp) {
1108
			/*
1336
			/*
Lines 1135-1145 Link Here
1135
	{
1363
	{
1136
	char *p;
1364
	char *p;
1137
	const char *cp;
1365
	const char *cp;
1138
	char *q;
1139
	char *start;
1366
	char *start;
1140
	char *endname;
1367
	char *endname;
1141
	int metaflag;
1368
	int metaflag;
1142
	struct stat statb;
1369
	struct stat64 statb;
1143
	DIR *dirp;
1370
	DIR *dirp;
1144
	struct dirent *dp;
1371
	struct dirent *dp;
1145
	int atend;
1372
	int atend;
Lines 1147-1163 Link Here
1147
1374
1148
	metaflag = 0;
1375
	metaflag = 0;
1149
	start = name;
1376
	start = name;
1150
	for (p = name ; ; p++) {
1377
	for (p = name; *p; p++) {
1151
		if (*p == '*' || *p == '?')
1378
		if (*p == '*' || *p == '?')
1152
			metaflag = 1;
1379
			metaflag = 1;
1153
		else if (*p == '[') {
1380
		else if (*p == '[') {
1154
			q = p + 1;
1381
			char *q = p + 1;
1155
			if (*q == '!')
1382
			if (*q == '!')
1156
				q++;
1383
				q++;
1157
			for (;;) {
1384
			for (;;) {
1158
				while (*q == CTLQUOTEMARK)
1385
				if (*q == '\\')
1159
					q++;
1160
				if (*q == CTLESC)
1161
					q++;
1386
					q++;
1162
				if (*q == '/' || *q == '\0')
1387
				if (*q == '/' || *q == '\0')
1163
					break;
1388
					break;
Lines 1166-1211 Link Here
1166
					break;
1391
					break;
1167
				}
1392
				}
1168
			}
1393
			}
1169
		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {
1394
		} else if (*p == '\\')
1170
			metaflag = 1;
1171
		} else if (*p == '\0')
1172
			break;
1173
		else if (*p == CTLQUOTEMARK)
1174
			continue;
1175
		else if (*p == CTLESC)
1176
			p++;
1395
			p++;
1177
		if (*p == '/') {
1396
		else if (*p == '/') {
1178
			if (metaflag)
1397
			if (metaflag)
1179
				break;
1398
				goto out;
1180
			start = p + 1;
1399
			start = p + 1;
1181
		}
1400
		}
1182
	}
1401
	}
1402
out:
1183
	if (metaflag == 0) {	/* we've reached the end of the file name */
1403
	if (metaflag == 0) {	/* we've reached the end of the file name */
1184
		if (enddir != expdir)
1404
		if (enddir != expdir)
1185
			metaflag++;
1405
			metaflag++;
1186
		for (p = name ; ; p++) {
1406
		p = name;
1187
			if (*p == CTLQUOTEMARK)
1407
		do {
1188
				continue;
1408
			if (*p == '\\')
1189
			if (*p == CTLESC)
1190
				p++;
1409
				p++;
1191
			*enddir++ = *p;
1410
			*enddir++ = *p;
1192
			if (*p == '\0')
1411
		} while (*p++);
1193
				break;
1412
		if (metaflag == 0 || lstat64(expdir, &statb) >= 0)
1194
		}
1195
		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
1196
			addfname(expdir);
1413
			addfname(expdir);
1197
		return;
1414
		return;
1198
	}
1415
	}
1199
	endname = p;
1416
	endname = p;
1200
	if (start != name) {
1417
	if (name < start) {
1201
		p = name;
1418
		p = name;
1202
		while (p < start) {
1419
		do {
1203
			while (*p == CTLQUOTEMARK)
1420
			if (*p == '\\')
1204
				p++;
1205
			if (*p == CTLESC)
1206
				p++;
1421
				p++;
1207
			*enddir++ = *p++;
1422
			*enddir++ = *p++;
1208
		}
1423
		} while (p < start);
1209
	}
1424
	}
1210
	if (enddir == expdir) {
1425
	if (enddir == expdir) {
1211
		cp = ".";
1426
		cp = ".";
Lines 1227-1242 Link Here
1227
	}
1442
	}
1228
	matchdot = 0;
1443
	matchdot = 0;
1229
	p = start;
1444
	p = start;
1230
	while (*p == CTLQUOTEMARK)
1445
	if (*p == '\\')
1231
		p++;
1232
	if (*p == CTLESC)
1233
		p++;
1446
		p++;
1234
	if (*p == '.')
1447
	if (*p == '.')
1235
		matchdot++;
1448
		matchdot++;
1236
	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
1449
	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
1237
		if (dp->d_name[0] == '.' && ! matchdot)
1450
		if (dp->d_name[0] == '.' && ! matchdot)
1238
			continue;
1451
			continue;
1239
		if (patmatch(start, dp->d_name, 0)) {
1452
		if (pmatch(start, dp->d_name)) {
1240
			if (atend) {
1453
			if (atend) {
1241
				scopy(dp->d_name, enddir);
1454
				scopy(dp->d_name, enddir);
1242
				addfname(expdir);
1455
				addfname(expdir);
Lines 1253-1258 Link Here
1253
	if (! atend)
1466
	if (! atend)
1254
		endname[-1] = '/';
1467
		endname[-1] = '/';
1255
}
1468
}
1469
#endif	/* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
1256
1470
1257
1471
1258
/*
1472
/*
Lines 1263-1280 Link Here
1263
addfname(name)
1477
addfname(name)
1264
	char *name;
1478
	char *name;
1265
	{
1479
	{
1266
	char *p;
1267
	struct strlist *sp;
1480
	struct strlist *sp;
1268
1481
1269
	p = stalloc(strlen(name) + 1);
1270
	scopy(name, p);
1271
	sp = (struct strlist *)stalloc(sizeof *sp);
1482
	sp = (struct strlist *)stalloc(sizeof *sp);
1272
	sp->text = p;
1483
	sp->text = sstrdup(name);
1273
	*exparg.lastp = sp;
1484
	*exparg.lastp = sp;
1274
	exparg.lastp = &sp->next;
1485
	exparg.lastp = &sp->next;
1275
}
1486
}
1276
1487
1277
1488
1489
#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
1278
/*
1490
/*
1279
 * Sort the results of file name expansion.  It calculates the number of
1491
 * Sort the results of file name expansion.  It calculates the number of
1280
 * strings to sort and then calls msort (short for merge sort) to do the
1492
 * strings to sort and then calls msort (short for merge sort) to do the
Lines 1336-1370 Link Here
1336
	}
1548
	}
1337
	return list;
1549
	return list;
1338
}
1550
}
1339
1551
#endif
1340
1552
1341
1553
1342
/*
1554
/*
1343
 * Returns true if the pattern matches the string.
1555
 * Returns true if the pattern matches the string.
1344
 */
1556
 */
1345
1557
1346
int
1558
STATIC inline int
1347
patmatch(pattern, string, squoted)
1559
patmatch(pattern, string)
1348
	char *pattern;
1560
	char *pattern;
1349
	char *string;
1561
	const char *string;
1350
	int squoted;	/* string might have quote chars */
1351
	{
1562
	{
1352
#ifdef notdef
1563
	return pmatch(preglob(pattern, 0, 0), string);
1353
	if (pattern[0] == '!' && pattern[1] == '!')
1354
		return 1 - pmatch(pattern + 2, string);
1355
	else
1356
#endif
1357
		return pmatch(pattern, string, squoted);
1358
}
1564
}
1359
1565
1360
1566
1567
#if !defined(__GLIBC__) || defined(FNMATCH_BROKEN)
1361
STATIC int
1568
STATIC int
1362
pmatch(pattern, string, squoted)
1569
pmatch(pattern, string)
1363
	char *pattern;
1570
	const char *pattern;
1364
	char *string;
1571
	const char *string;
1365
	int squoted;
1366
	{
1572
	{
1367
	char *p, *q;
1573
	const char *p, *q;
1368
	char c;
1574
	char c;
1369
1575
1370
	p = pattern;
1576
	p = pattern;
Lines 1373-1418 Link Here
1373
		switch (c = *p++) {
1579
		switch (c = *p++) {
1374
		case '\0':
1580
		case '\0':
1375
			goto breakloop;
1581
			goto breakloop;
1376
		case CTLESC:
1582
		case '\\':
1377
			if (squoted && *q == CTLESC)
1583
			if (*p) {
1378
				q++;
1584
				c = *p++;
1379
			if (*q++ != *p++)
1585
			}
1380
				return 0;
1586
			goto dft;
1381
			break;
1382
		case CTLQUOTEMARK:
1383
			continue;
1384
		case '?':
1587
		case '?':
1385
			if (squoted && *q == CTLESC)
1386
				q++;
1387
			if (*q++ == '\0')
1588
			if (*q++ == '\0')
1388
				return 0;
1589
				return 0;
1389
			break;
1590
			break;
1390
		case '*':
1591
		case '*':
1391
			c = *p;
1592
			c = *p;
1392
			while (c == CTLQUOTEMARK || c == '*')
1593
			while (c == '*')
1393
				c = *++p;
1594
				c = *++p;
1394
			if (c != CTLESC &&  c != CTLQUOTEMARK &&
1595
			if (c != '\\' && c != '?' && c != '*' && c != '[') {
1395
			    c != '?' && c != '*' && c != '[') {
1396
				while (*q != c) {
1596
				while (*q != c) {
1397
					if (squoted && *q == CTLESC &&
1398
					    q[1] == c)
1399
						break;
1400
					if (*q == '\0')
1597
					if (*q == '\0')
1401
						return 0;
1598
						return 0;
1402
					if (squoted && *q == CTLESC)
1403
						q++;
1404
					q++;
1599
					q++;
1405
				}
1600
				}
1406
			}
1601
			}
1407
			do {
1602
			do {
1408
				if (pmatch(p, q, squoted))
1603
				if (pmatch(p, q))
1409
					return 1;
1604
					return 1;
1410
				if (squoted && *q == CTLESC)
1411
					q++;
1412
			} while (*q++ != '\0');
1605
			} while (*q++ != '\0');
1413
			return 0;
1606
			return 0;
1414
		case '[': {
1607
		case '[': {
1415
			char *endp;
1608
			const char *endp;
1416
			int invert, found;
1609
			int invert, found;
1417
			char chr;
1610
			char chr;
1418
1611
Lines 1420-1430 Link Here
1420
			if (*endp == '!')
1613
			if (*endp == '!')
1421
				endp++;
1614
				endp++;
1422
			for (;;) {
1615
			for (;;) {
1423
				while (*endp == CTLQUOTEMARK)
1424
					endp++;
1425
				if (*endp == '\0')
1616
				if (*endp == '\0')
1426
					goto dft;		/* no matching ] */
1617
					goto dft;		/* no matching ] */
1427
				if (*endp == CTLESC)
1618
				if (*endp == '\\')
1428
					endp++;
1619
					endp++;
1429
				if (*++endp == ']')
1620
				if (*++endp == ']')
1430
					break;
1621
					break;
Lines 1436-1456 Link Here
1436
			}
1627
			}
1437
			found = 0;
1628
			found = 0;
1438
			chr = *q++;
1629
			chr = *q++;
1439
			if (squoted && chr == CTLESC)
1440
				chr = *q++;
1441
			if (chr == '\0')
1630
			if (chr == '\0')
1442
				return 0;
1631
				return 0;
1443
			c = *p++;
1632
			c = *p++;
1444
			do {
1633
			do {
1445
				if (c == CTLQUOTEMARK)
1634
				if (c == '\\')
1446
					continue;
1447
				if (c == CTLESC)
1448
					c = *p++;
1635
					c = *p++;
1449
				if (*p == '-' && p[1] != ']') {
1636
				if (*p == '-' && p[1] != ']') {
1450
					p++;
1637
					p++;
1451
					while (*p == CTLQUOTEMARK)
1638
					if (*p == '\\')
1452
						p++;
1453
					if (*p == CTLESC)
1454
						p++;
1639
						p++;
1455
					if (chr >= c && chr <= *p)
1640
					if (chr >= c && chr <= *p)
1456
						found = 1;
1641
						found = 1;
Lines 1465-1472 Link Here
1465
			break;
1650
			break;
1466
		}
1651
		}
1467
dft:	        default:
1652
dft:	        default:
1468
			if (squoted && *q == CTLESC)
1469
				q++;
1470
			if (*q++ != c)
1653
			if (*q++ != c)
1471
				return 0;
1654
				return 0;
1472
			break;
1655
			break;
Lines 1477-1482 Link Here
1477
		return 0;
1660
		return 0;
1478
	return 1;
1661
	return 1;
1479
}
1662
}
1663
#endif
1480
1664
1481
1665
1482
1666
Lines 1484-1511 Link Here
1484
 * Remove any CTLESC characters from a string.
1668
 * Remove any CTLESC characters from a string.
1485
 */
1669
 */
1486
1670
1487
void
1671
char *
1488
rmescapes(str)
1672
_rmescapes(str, flag)
1489
	char *str;
1673
	char *str;
1674
	int flag;
1490
{
1675
{
1491
	char *p, *q;
1676
	char *p, *q, *r;
1677
	static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
1678
	unsigned inquotes;
1679
	int notescaped;
1680
	int globbing;
1492
1681
1493
	p = str;
1682
	p = strpbrk(str, qchars);
1494
	while (*p != CTLESC && *p != CTLQUOTEMARK) {
1683
	if (!p) {
1495
		if (*p++ == '\0')
1684
		return str;
1496
			return;
1497
	}
1685
	}
1498
	q = p;
1686
	q = p;
1687
	r = str;
1688
	if (flag & RMESCAPE_ALLOC) {
1689
		size_t len = p - str;
1690
		size_t fulllen = len + strlen(p) + 1;
1691
1692
		if (flag & RMESCAPE_GROW) {
1693
			r = makestrspace(fulllen, expdest);
1694
		} else if (flag & RMESCAPE_HEAP) {
1695
			r = ckmalloc(fulllen);
1696
		} else {
1697
			r = stalloc(fulllen);
1698
		}
1699
		q = r;
1700
		if (len > 0) {
1701
#ifdef _GNU_SOURCE
1702
			q = mempcpy(q, str, len);
1703
#else
1704
			memcpy(q, str, len);
1705
			q += len;
1706
#endif
1707
		}
1708
	}
1709
	inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
1710
	globbing = flag & RMESCAPE_GLOB;
1711
	notescaped = globbing;
1499
	while (*p) {
1712
	while (*p) {
1500
		if (*p == CTLQUOTEMARK) {
1713
		if (*p == CTLQUOTEMARK) {
1714
			inquotes = ~inquotes;
1501
			p++;
1715
			p++;
1716
			notescaped = globbing;
1502
			continue;
1717
			continue;
1503
		}
1718
		}
1504
		if (*p == CTLESC)
1719
		if (*p == '\\') {
1720
			/* naked back slash */
1721
			notescaped = 0;
1722
			goto copy;
1723
		}
1724
		if (*p == CTLESC) {
1505
			p++;
1725
			p++;
1726
			if (notescaped && inquotes && *p != '/') {
1727
				*q++ = '\\';
1728
			}
1729
		}
1730
		notescaped = globbing;
1731
copy:
1506
		*q++ = *p++;
1732
		*q++ = *p++;
1507
	}
1733
	}
1508
	*q = '\0';
1734
	*q = '\0';
1735
	if (flag & RMESCAPE_GROW) {
1736
		expdest = r;
1737
		STADJUST(q - r + 1, expdest);
1738
	}
1739
	return r;
1509
}
1740
}
1510
1741
1511
1742
Lines 1521-1536 Link Here
1521
	{
1752
	{
1522
	struct stackmark smark;
1753
	struct stackmark smark;
1523
	int result;
1754
	int result;
1524
	char *p;
1525
1755
1526
	setstackmark(&smark);
1756
	setstackmark(&smark);
1527
	argbackq = pattern->narg.backquote;
1757
	argbackq = pattern->narg.backquote;
1528
	STARTSTACKSTR(expdest);
1758
	STARTSTACKSTR(expdest);
1529
	ifslastp = NULL;
1759
	ifslastp = NULL;
1530
	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
1760
	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
1531
	STPUTC('\0', expdest);
1761
	STACKSTRNUL(expdest);
1532
	p = grabstackstr(expdest);
1762
	result = patmatch(stackblock(), val);
1533
	result = patmatch(p, val, 0);
1534
	popstackmark(&smark);
1763
	popstackmark(&smark);
1535
	return result;
1764
	return result;
1536
}
1765
}
Lines 1539-1563 Link Here
1539
 * Our own itoa().
1768
 * Our own itoa().
1540
 */
1769
 */
1541
1770
1542
STATIC char *
1771
STATIC int
1543
cvtnum(num, buf)
1772
cvtnum(long num) {
1544
	int num;
1773
	int len;
1545
	char *buf;
1546
	{
1547
	char temp[32];
1548
	int neg = num < 0;
1549
	char *p = temp + 31;
1550
1551
	temp[31] = '\0';
1552
1774
1553
	do {
1775
	expdest = makestrspace(32, expdest);
1554
		*--p = num % 10 + '0';
1776
	len = fmtstr(expdest, 32, "%ld", num);
1555
	} while ((num /= 10) != 0);
1777
	STADJUST(len, expdest);
1778
	return len;
1779
}
1556
1780
1557
	if (neg)
1781
static void
1558
		*--p = '-';
1782
varunset(const char *end, const char *var, const char *umsg, int varflags)
1783
{
1784
	const char *msg;
1785
	const char *tail;
1559
1786
1560
	while (*p)
1787
	tail = nullstr;
1561
		STPUTC(*p++, buf);
1788
	msg = "parameter not set";
1562
	return buf;
1789
	if (umsg) {
1790
		if (*end == CTLENDVAR) {
1791
			if (varflags & VSNUL)
1792
				tail = " or null";
1793
		} else
1794
			msg = umsg;
1795
	}
1796
	error("%.*s: %s%s", end - var - 1, var, msg, tail);
1563
}
1797
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/expand.h (-2 / +9 lines)
Lines 58-75 Link Here
58
#define	EXP_REDIR	0x8	/* file glob for a redirection (1 match only) */
58
#define	EXP_REDIR	0x8	/* file glob for a redirection (1 match only) */
59
#define EXP_CASE	0x10	/* keeps quotes around for CASE pattern */
59
#define EXP_CASE	0x10	/* keeps quotes around for CASE pattern */
60
#define EXP_RECORD	0x20	/* need to record arguments for ifs breakup */
60
#define EXP_RECORD	0x20	/* need to record arguments for ifs breakup */
61
#define EXP_VARTILDE2	0x40	/* expand tildes after colons only */
62
#define EXP_WORD	0x80	/* expand word in parameter expansion */
63
#define EXP_QWORD	0x100	/* expand word in quoted parameter expansion */
61
64
62
65
63
union node;
66
union node;
64
void expandhere __P((union node *, int));
67
void expandhere __P((union node *, int));
65
void expandarg __P((union node *, struct arglist *, int));
68
void expandarg __P((union node *, struct arglist *, int));
66
void expari __P((int));
69
void expari __P((int));
67
int patmatch __P((char *, char *, int));
70
#define rmescapes(p) _rmescapes((p), 0)
68
void rmescapes __P((char *));
71
char *_rmescapes __P((char *, int));
69
int casematch __P((union node *, char *));
72
int casematch __P((union node *, char *));
70
73
71
/* From arith.y */
74
/* From arith.y */
72
int arith __P((const char *));
75
int arith __P((const char *));
73
int expcmd __P((int , char **));
76
int expcmd __P((int , char **));
77
#ifdef USE_LEX
74
void arith_lex_reset __P((void));
78
void arith_lex_reset __P((void));
79
#else
80
#define arith_lex_reset()
81
#endif
75
int yylex __P((void));
82
int yylex __P((void));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/hetio.c (+397 lines)
Line 0 Link Here
1
/*
2
 * Termios command line History and Editting for NetBSD sh (ash)
3
 * Copyright (c) 1999
4
 *	Main code:	Adam Rogoyski <rogoyski@cs.utexas.edu>
5
 *	Etc:		Dave Cinege <dcinege@psychosis.com>
6
 *
7
 * You may use this code as you wish, so long as the original author(s)
8
 * are attributed in any redistributions of the source code.
9
 * This code is 'as is' with no warranty.
10
 * This code may safely be consumed by a BSD or GPL license.
11
 *
12
 * v 0.5  19990328	Initial release
13
 *
14
 * Future plans: Simple file and path name completion. (like BASH)
15
 *
16
 */
17
18
/*
19
Usage and Known bugs:
20
	Terminal key codes are not extensive, and more will probably
21
	need to be added. This version was created on Debian GNU/Linux 2.x.
22
	Delete, Backspace, Home, End, and the arrow keys were tested
23
	to work in an Xterm and console. Ctrl-A also works as Home.
24
	Ctrl-E also works as End. Ctrl-D and Ctrl-U perform their respective
25
	functions. The binary size increase is <3K.
26
27
	Editting will not display correctly for lines greater then the
28
	terminal width. (more then one line.) However, history will.
29
*/
30
31
#include <stdio.h>
32
#include <unistd.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <termios.h>
36
#include <ctype.h>
37
#include <sys/ioctl.h>
38
39
#include "input.h"
40
#include "output.h"
41
42
#include "hetio.h"
43
44
45
#define  MAX_HISTORY   15			/* Maximum length of the linked list for the command line history */
46
47
#define ESC	27
48
#define DEL	127
49
50
static struct history *his_front = NULL;	/* First element in command line list */
51
static struct history *his_end = NULL;		/* Last element in command line list */
52
static struct termios old_term, new_term;	/* Current termio and the previous termio before starting ash */
53
54
static int history_counter = 0;			/* Number of commands in history list */
55
static int reset_term = 0;			/* Set to true if the terminal needs to be reset upon exit */
56
static int hetio_inter = 0;
57
58
struct history
59
{
60
   char *s;
61
   struct history *p;
62
   struct history *n;
63
};
64
65
66
void input_delete    (int);
67
void input_home      (int *);
68
void input_end       (int *, int);
69
void input_backspace (int *, int *);
70
71
72
73
void hetio_init(void)
74
{
75
	hetio_inter = 1;
76
}
77
78
79
void hetio_reset_term(void)
80
{
81
	if (reset_term)
82
		tcsetattr(1, TCSANOW, &old_term);
83
}
84
85
86
void setIO(struct termios *new, struct termios *old)	/* Set terminal IO to canonical mode, and save old term settings. */
87
{
88
	tcgetattr(0, old);
89
	memcpy(new, old, sizeof(*new));
90
	new->c_cc[VMIN] = 1;
91
	new->c_cc[VTIME] = 0;
92
	new->c_lflag &= ~ICANON; /* unbuffered input */
93
	new->c_lflag &= ~ECHO;
94
	tcsetattr(0, TCSANOW, new);
95
}
96
97
void input_home(int *cursor)				/* Command line input routines */
98
{
99
 	while (*cursor > 0) {
100
		out1c('\b');
101
		--*cursor;
102
	}
103
	flushout(out1);
104
}
105
106
107
void input_delete(int cursor)
108
{
109
	int j = 0;
110
111
	memmove(parsenextc + cursor, parsenextc + cursor + 1,
112
		BUFSIZ - cursor - 1);
113
	for (j = cursor; j < (BUFSIZ - 1); j++) {
114
		if (!*(parsenextc + j))
115
			break;
116
		else
117
			out1c(*(parsenextc + j));
118
	}
119
120
	out1str(" \b");
121
122
	while (j-- > cursor)
123
		out1c('\b');
124
	flushout(out1);
125
}
126
127
128
void input_end(int *cursor, int len)
129
{
130
	while (*cursor < len) {
131
		out1str("\033[C");
132
		++*cursor;
133
	}
134
	flushout(out1);
135
}
136
137
138
void
139
input_backspace(int *cursor, int *len)
140
{
141
	int j = 0;
142
143
	if (*cursor > 0) {
144
		out1str("\b \b");
145
		--*cursor;
146
		memmove(parsenextc + *cursor, parsenextc + *cursor + 1,
147
			BUFSIZ - *cursor + 1);
148
149
		for (j = *cursor; j < (BUFSIZ - 1); j++) {
150
			if (!*(parsenextc + j))
151
				break;
152
			else
153
				out1c(*(parsenextc + j));
154
		}
155
156
		out1str(" \b");
157
158
		while (j-- > *cursor)
159
			out1c('\b');
160
161
		--*len;
162
		flushout(out1);
163
	}
164
}
165
166
int hetio_read_input(int fd)
167
{
168
	int nr = 0;
169
170
	/* Are we an interactive shell? */
171
	if (!hetio_inter || fd) {
172
		return -255;
173
	} else {
174
		int len = 0;
175
		int j = 0;
176
		int cursor = 0;
177
		int break_out = 0;
178
		int ret = 0;
179
		char c = 0;
180
		struct history *hp = his_end;
181
182
		if (!reset_term) {
183
			setIO(&new_term, &old_term);
184
			reset_term = 1;
185
		} else {
186
			tcsetattr(0, TCSANOW, &new_term);
187
		}
188
189
		memset(parsenextc, 0, BUFSIZ);
190
191
		while (1) {
192
			if ((ret = read(fd, &c, 1)) < 1)
193
				return ret;
194
195
			switch (c) {
196
   				case 1:		/* Control-A Beginning of line */
197
   					input_home(&cursor);
198
					break;
199
				case 5:		/* Control-E EOL */
200
					input_end(&cursor, len);
201
					break;
202
				case 4:		/* Control-D */
203
					if (!len)
204
						exitshell(0);
205
					break;
206
				case 21: 	/* Control-U */
207
					/* Return to begining of line. */
208
					for (; cursor > 0; cursor--)
209
						out1c('\b');
210
					/* Erase old command. */
211
					for (j = 0; j < len; j++) {
212
						/*
213
						 * Clear buffer while we're at
214
						 * it.
215
						 */
216
						parsenextc[j] = 0;
217
						out1c(' ');
218
					}
219
					/* return to begining of line */
220
					for (; len > 0; len--)
221
						out1c('\b');
222
					flushout(out1);
223
					break;
224
				case '\b':	/* Backspace */
225
				case DEL:
226
					input_backspace(&cursor, &len);
227
					break;
228
				case '\n':	/* Enter */
229
					*(parsenextc + len++ + 1) = c;
230
					out1c(c);
231
					flushout(out1);
232
					break_out = 1;
233
					break;
234
				case ESC:	/* escape sequence follows */
235
					if ((ret = read(fd, &c, 1)) < 1)
236
						return ret;
237
238
					if (c == '[' ) {    /* 91 */
239
						if ((ret = read(fd, &c, 1)) < 1)
240
							return ret;
241
242
						switch (c) {
243
							case 'A':
244
								if (hp && hp->p) {		/* Up */
245
									hp = hp->p;
246
									goto hop;
247
								}
248
								break;
249
							case 'B':
250
								if (hp && hp->n && hp->n->s) {	/* Down */
251
									hp = hp->n;
252
									goto hop;
253
								}
254
								break;
255
256
hop:						/* hop */
257
								len = strlen(parsenextc);
258
259
								for (; cursor > 0; cursor--)		/* return to begining of line */
260
									out1c('\b');
261
262
		   						for (j = 0; j < len; j++)		/* erase old command */
263
									out1c(' ');
264
265
								for (; j > 0; j--)		/* return to begining of line */
266
									out1c('\b');
267
268
								strcpy (parsenextc, hp->s);		/* write new command */
269
								len = strlen (hp->s);
270
								out1str(parsenextc);
271
								flushout(out1);
272
								cursor = len;
273
								break;
274
							case 'C':		/* Right */
275
								if (cursor < len) {
276
									out1str("\033[C");
277
									cursor++;
278
									flushout(out1);
279
						 		}
280
								break;
281
							case 'D':		/* Left */
282
								if (cursor > 0) {
283
									out1str("\033[D");
284
									cursor--;
285
									flushout(out1);
286
								}
287
								break;
288
							case '3':		/* Delete */
289
								if (cursor != len) {
290
									input_delete(cursor);
291
									len--;
292
								}
293
								break;
294
							case '1':		/* Home (Ctrl-A) */
295
								input_home(&cursor);
296
								break;
297
							case '4':		/* End (Ctrl-E) */
298
								input_end(&cursor, len);
299
								break;
300
						}
301
						if (c == '1' || c == '3' || c == '4')
302
							if ((ret = read(fd, &c, 1)) < 1)
303
								return ret;  /* read 126 (~) */
304
					}
305
306
					if (c == 'O') {	/* 79 */
307
						if ((ret = read(fd, &c, 1)) < 1)
308
							return ret;
309
						switch (c) {
310
							case 'H':		/* Home (xterm) */
311
      								input_home(&cursor);
312
								break;
313
							case 'F':		/* End (xterm_ */
314
								input_end(&cursor, len);
315
								break;
316
						}
317
					}
318
319
					c = 0;
320
					break;
321
322
				default:				/* If it's regular input, do the normal thing */
323
					if (!isprint(c))		/* Skip non-printable characters */
324
						break;
325
326
	       				if (len >= (BUFSIZ - 2))	/* Need to leave space for enter */
327
		  				break;
328
329
					len++;
330
331
					if (cursor == (len - 1)) {	/* Append if at the end of the line */
332
						*(parsenextc + cursor) = c;
333
					} else {			/* Insert otherwise */
334
						memmove(parsenextc + cursor + 1, parsenextc + cursor,
335
							len - cursor - 1);
336
337
						*(parsenextc + cursor) = c;
338
339
						for (j = cursor; j < len; j++)
340
							out1c(*(parsenextc + j));
341
						for (; j > cursor; j--)
342
							out1str("\033[D");
343
					}
344
345
					cursor++;
346
					out1c(c);
347
					flushout(out1);
348
					break;
349
			}
350
351
			if (break_out)		/* Enter is the command terminator, no more input. */
352
				break;
353
		}
354
355
		nr = len + 1;
356
		tcsetattr(0, TCSANOW, &old_term);
357
358
		if (*(parsenextc)) {		/* Handle command history log */
359
			struct history *h = his_end;
360
361
			if (!h) {       /* No previous history */
362
				h = his_front = malloc(sizeof (struct history));
363
				h->n = malloc(sizeof (struct history));
364
				h->p = NULL;
365
				h->s = strdup(parsenextc);
366
367
				h->n->p = h;
368
				h->n->n = NULL;
369
				h->n->s = NULL;
370
				his_end = h->n;
371
				history_counter++;
372
			} else {	/* Add a new history command */
373
374
				h->n = malloc(sizeof (struct history));
375
376
				h->n->p = h;
377
				h->n->n = NULL;
378
				h->n->s = NULL;
379
				h->s = strdup(parsenextc);
380
				his_end = h->n;
381
382
				if (history_counter >= MAX_HISTORY) {	/* After max history, remove the last known command */
383
					struct history *p = his_front->n;
384
385
					p->p = NULL;
386
					free(his_front->s);
387
					free(his_front);
388
					his_front = p;
389
				} else {
390
					history_counter++;
391
				}
392
			}
393
		}
394
	}
395
396
	return nr;
397
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/hetio.h (+22 lines)
Line 0 Link Here
1
/*
2
 * Termios command line History and Editting for NetBSD sh (ash)
3
 * Copyright (c) 1999
4
 *	Main code:	Adam Rogoyski <rogoyski@cs.utexas.edu> 
5
 *	Etc:		Dave Cinege <dcinege@psychosis.com>
6
 *
7
 * You may use this code as you wish, so long as the original author(s)
8
 * are attributed in any redistributions of the source code.
9
 * This code is 'as is' with no warranty.
10
 * This code may safely be consumed by a BSD or GPL license.
11
 *
12
 * v 0.5  19990328	Initial release 
13
 *
14
 * Future plans: Simple file and path name completion. (like BASH)
15
 *
16
 */
17
18
void hetio_init(void);
19
int hetio_read_input(int fd);
20
void hetio_reset_term(void);
21
22
extern int hetio_inter;
(-)bin_NetBSD-1.6release.orig/src/bin/sh/histedit.c (-3 / +7 lines)
Lines 60-68 Link Here
60
#include "main.h"
60
#include "main.h"
61
#include "output.h"
61
#include "output.h"
62
#include "mystring.h"
62
#include "mystring.h"
63
#include "myhistedit.h"
64
#include "error.h"
63
#include "error.h"
65
#ifndef SMALL
64
#ifndef SMALL
65
#include "myhistedit.h"
66
#include "eval.h"
66
#include "eval.h"
67
#include "memalloc.h"
67
#include "memalloc.h"
68
68
Lines 219-225 Link Here
219
	if (argc == 1)
219
	if (argc == 1)
220
		error("missing history argument");
220
		error("missing history argument");
221
221
222
#ifdef __GLIBC__
223
	optind = 0;
224
#else
222
	optreset = 1; optind = 1; /* initialize getopt */
225
	optreset = 1; optind = 1; /* initialize getopt */
226
#endif
223
	while (not_fcnumber(argv[optind]) &&
227
	while (not_fcnumber(argv[optind]) &&
224
	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
228
	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
225
		switch ((char)ch) {
229
		switch ((char)ch) {
Lines 277-284 Link Here
277
		 */
281
		 */
278
		if (sflg == 0) {
282
		if (sflg == 0) {
279
			if (editor == NULL &&
283
			if (editor == NULL &&
280
			    (editor = bltinlookup("FCEDIT", 1)) == NULL &&
284
			    (editor = bltinlookup("FCEDIT")) == NULL &&
281
			    (editor = bltinlookup("EDITOR", 1)) == NULL)
285
			    (editor = bltinlookup("EDITOR")) == NULL)
282
				editor = DEFEDITOR;
286
				editor = DEFEDITOR;
283
			if (editor[0] == '-' && editor[1] == '\0') {
287
			if (editor[0] == '-' && editor[1] == '\0') {
284
				sflg = 1;	/* no edit */
288
				sflg = 1;	/* no edit */
(-)bin_NetBSD-1.6release.orig/src/bin/sh/input.c (-33 / +80 lines)
Lines 66-82 Link Here
66
#include "error.h"
66
#include "error.h"
67
#include "alias.h"
67
#include "alias.h"
68
#include "parser.h"
68
#include "parser.h"
69
#ifndef SMALL
69
#include "myhistedit.h"
70
#include "myhistedit.h"
71
#endif
72
73
#ifdef HETIO
74
#include "hetio.h"
75
#endif
70
76
71
#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
77
#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
78
#define IBUFSIZ (BUFSIZ + 1)
72
79
73
MKINIT
80
MKINIT
74
struct strpush {
81
struct strpush {
75
	struct strpush *prev;	/* preceding string on stack */
82
	struct strpush *prev;	/* preceding string on stack */
76
	char *prevstring;
83
	char *prevstring;
77
	int prevnleft;
84
	int prevnleft;
78
	int prevlleft;
79
	struct alias *ap;	/* if push was associated with an alias */
85
	struct alias *ap;	/* if push was associated with an alias */
86
	char *string;		/* remember the string since it may change */
80
};
87
};
81
88
82
/*
89
/*
Lines 103-114 Link Here
103
MKINIT int parselleft;		/* copy of parsefile->lleft */
110
MKINIT int parselleft;		/* copy of parsefile->lleft */
104
char *parsenextc;		/* copy of parsefile->nextc */
111
char *parsenextc;		/* copy of parsefile->nextc */
105
MKINIT struct parsefile basepf;	/* top level input file */
112
MKINIT struct parsefile basepf;	/* top level input file */
106
MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
113
MKINIT char basebuf[IBUFSIZ];	/* buffer for top level input file */
107
struct parsefile *parsefile = &basepf;	/* current input file */
114
struct parsefile *parsefile = &basepf;	/* current input file */
108
int init_editline = 0;		/* editline library initialized? */
109
int whichprompt;		/* 1 == PS1, 2 == PS2 */
115
int whichprompt;		/* 1 == PS1, 2 == PS2 */
110
116
117
#ifndef SMALL
111
EditLine *el;			/* cookie for editline package */
118
EditLine *el;			/* cookie for editline package */
119
#endif
112
120
113
STATIC void pushfile __P((void));
121
STATIC void pushfile __P((void));
114
static int preadfd __P((void));
122
static int preadfd __P((void));
Lines 123-136 Link Here
123
}
131
}
124
132
125
RESET {
133
RESET {
126
	if (exception != EXSHELLPROC)
127
		parselleft = parsenleft = 0;	/* clear input buffer */
134
		parselleft = parsenleft = 0;	/* clear input buffer */
128
	popallfiles();
135
	popallfiles();
129
}
136
}
130
131
SHELLPROC {
132
	popallfiles();
133
}
134
#endif
137
#endif
135
138
136
139
Lines 148-154 Link Here
148
	int c;
151
	int c;
149
152
150
	while (--nleft > 0) {
153
	while (--nleft > 0) {
151
		c = pgetc_macro();
154
		c = pgetc2();
152
		if (c == PEOF) {
155
		if (c == PEOF) {
153
			if (p == line)
156
			if (p == line)
154
				return NULL;
157
				return NULL;
Lines 163-169 Link Here
163
}
166
}
164
167
165
168
166
167
/*
169
/*
168
 * Read a character from the script, returning PEOF on end of file.
170
 * Read a character from the script, returning PEOF on end of file.
169
 * Nul characters in the input are silently discarded.
171
 * Nul characters in the input are silently discarded.
Lines 176-181 Link Here
176
}
178
}
177
179
178
180
181
/*
182
 * Same as pgetc(), but ignores PEOA.
183
 */
184
185
int
186
pgetc2()
187
{
188
	int c;
189
	do {
190
		c = pgetc_macro();
191
	} while (c == PEOA);
192
	return c;
193
}
194
195
179
static int
196
static int
180
preadfd()
197
preadfd()
181
{
198
{
Lines 197-206 Link Here
197
		}
214
		}
198
	} else
215
	} else
199
#endif
216
#endif
200
		nr = read(parsefile->fd, buf, BUFSIZ - 1);
217
218
#ifdef HETIO
219
		nr = hetio_read_input(parsefile->fd);
220
		if (nr == -255)
221
#endif
222
		nr = read(parsefile->fd, buf, IBUFSIZ - 1);
201
223
202
224
203
	if (nr <= 0) {
204
                if (nr < 0) {
225
                if (nr < 0) {
205
                        if (errno == EINTR)
226
                        if (errno == EINTR)
206
                                goto retry;
227
                                goto retry;
Lines 215-222 Link Here
215
                                }
236
                                }
216
                        }
237
                        }
217
                }
238
                }
218
                nr = -1;
219
	}
220
	return nr;
239
	return nr;
221
}
240
}
222
241
Lines 235-244 Link Here
235
{
254
{
236
	char *p, *q;
255
	char *p, *q;
237
	int more;
256
	int more;
257
#ifndef SMALL
238
	int something;
258
	int something;
259
#endif
239
	char savec;
260
	char savec;
240
261
241
	if (parsefile->strpush) {
262
	while (parsefile->strpush) {
263
		if (
264
			parsenleft == -1 && parsefile->strpush->ap &&
265
			parsenextc[-1] != ' ' && parsenextc[-1] != '\t'
266
		) {
267
			return PEOA;
268
		}
242
		popstring();
269
		popstring();
243
		if (--parsenleft >= 0)
270
		if (--parsenleft >= 0)
244
			return (*parsenextc++);
271
			return (*parsenextc++);
Lines 246-256 Link Here
246
	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
273
	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
247
		return PEOF;
274
		return PEOF;
248
	flushout(&output);
275
	flushout(&output);
276
#ifdef FLUSHERR
249
	flushout(&errout);
277
	flushout(&errout);
278
#endif
250
279
251
again:
280
again:
252
	if (parselleft <= 0) {
281
	if (parselleft <= 0) {
253
		if ((parselleft = preadfd()) == -1) {
282
		if ((parselleft = preadfd()) <= 0) {
254
			parselleft = parsenleft = EOF_NLEFT;
283
			parselleft = parsenleft = EOF_NLEFT;
255
			return PEOF;
284
			return PEOF;
256
		}
285
		}
Lines 259-292 Link Here
259
	q = p = parsenextc;
288
	q = p = parsenextc;
260
289
261
	/* delete nul characters */
290
	/* delete nul characters */
291
#ifndef SMALL
262
	something = 0;
292
	something = 0;
293
#endif
263
	for (more = 1; more;) {
294
	for (more = 1; more;) {
264
		switch (*p) {
295
		switch (*p) {
265
		case '\0':
296
		case '\0':
266
			p++;	/* Skip nul */
297
			p++;	/* Skip nul */
267
			goto check;
298
			goto check;
268
299
300
#ifndef SMALL
269
		case '\t':
301
		case '\t':
270
		case ' ':
302
		case ' ':
271
			break;
303
			break;
304
#endif
272
305
273
		case '\n':
306
		case '\n':
274
			parsenleft = q - parsenextc;
307
			parsenleft = q - parsenextc;
275
			more = 0; /* Stop processing here */
308
			more = 0; /* Stop processing here */
276
			break;
309
			break;
277
310
311
#ifndef SMALL
278
		default:
312
		default:
279
			something = 1;
313
			something = 1;
280
			break;
314
			break;
315
#endif
281
		}
316
		}
282
317
283
		*q++ = *p++;
318
		*q++ = *p++;
284
check:
319
check:
285
		if (--parselleft <= 0) {
320
		if (--parselleft <= 0 && more) {
286
			parsenleft = q - parsenextc - 1;
321
			parsenleft = q - parsenextc - 1;
287
			if (parsenleft < 0)
322
			if (parsenleft < 0)
288
				goto again;
323
				goto again;
289
			*q = '\0';
290
			more = 0;
324
			more = 0;
291
		}
325
		}
292
	}
326
	}
Lines 306-312 Link Here
306
340
307
	if (vflag) {
341
	if (vflag) {
308
		out2str(parsenextc);
342
		out2str(parsenextc);
343
#ifdef FLUSHERR
309
		flushout(out2);
344
		flushout(out2);
345
#endif
310
	}
346
	}
311
347
312
	*q = savec;
348
	*q = savec;
Lines 330-342 Link Here
330
 * We handle aliases this way.
366
 * We handle aliases this way.
331
 */
367
 */
332
void
368
void
333
pushstring(s, len, ap)
369
pushstring(s, ap)
334
	char *s;
370
	char *s;
335
	int len;
336
	void *ap;
371
	void *ap;
337
	{
372
	{
338
	struct strpush *sp;
373
	struct strpush *sp;
374
	size_t len;
339
375
376
	len = strlen(s);
340
	INTOFF;
377
	INTOFF;
341
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
378
/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
342
	if (parsefile->strpush) {
379
	if (parsefile->strpush) {
Lines 347-356 Link Here
347
		sp = parsefile->strpush = &(parsefile->basestrpush);
384
		sp = parsefile->strpush = &(parsefile->basestrpush);
348
	sp->prevstring = parsenextc;
385
	sp->prevstring = parsenextc;
349
	sp->prevnleft = parsenleft;
386
	sp->prevnleft = parsenleft;
350
	sp->prevlleft = parselleft;
351
	sp->ap = (struct alias *)ap;
387
	sp->ap = (struct alias *)ap;
352
	if (ap)
388
	if (ap) {
353
		((struct alias *)ap)->flag |= ALIASINUSE;
389
		((struct alias *)ap)->flag |= ALIASINUSE;
390
		sp->string = s;
391
	}
354
	parsenextc = s;
392
	parsenextc = s;
355
	parsenleft = len;
393
	parsenleft = len;
356
	INTON;
394
	INTON;
Lines 362-373 Link Here
362
	struct strpush *sp = parsefile->strpush;
400
	struct strpush *sp = parsefile->strpush;
363
401
364
	INTOFF;
402
	INTOFF;
403
	if (sp->ap) {
404
		if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
405
			checkkwd |= CHKALIAS;
406
		}
407
		if (sp->string != sp->ap->val) {
408
			ckfree(sp->string);
409
		}
410
		sp->ap->flag &= ~ALIASINUSE;
411
		if (sp->ap->flag & ALIASDEAD) {
412
			unalias(sp->ap->name);
413
		}
414
	}
365
	parsenextc = sp->prevstring;
415
	parsenextc = sp->prevstring;
366
	parsenleft = sp->prevnleft;
416
	parsenleft = sp->prevnleft;
367
	parselleft = sp->prevlleft;
368
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
417
/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
369
	if (sp->ap)
370
		sp->ap->flag &= ~ALIASINUSE;
371
	parsefile->strpush = sp->prev;
418
	parsefile->strpush = sp->prev;
372
	if (sp != &(parsefile->basestrpush))
419
	if (sp != &(parsefile->basestrpush))
373
		ckfree(sp);
420
		ckfree(sp);
Lines 414-426 Link Here
414
	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
461
	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
415
	if (push) {
462
	if (push) {
416
		pushfile();
463
		pushfile();
417
		parsefile->buf = ckmalloc(BUFSIZ);
464
		parsefile->buf = 0;
465
	} else {
466
		closescript();
467
		while (parsefile->strpush)
468
			popstring();
418
	}
469
	}
419
	if (parsefile->fd > 0)
420
		close(parsefile->fd);
421
	parsefile->fd = fd;
470
	parsefile->fd = fd;
422
	if (parsefile->buf == NULL)
471
	if (parsefile->buf == NULL)
423
		parsefile->buf = ckmalloc(BUFSIZ);
472
		parsefile->buf = ckmalloc(IBUFSIZ);
424
	parselleft = parsenleft = 0;
473
	parselleft = parsenleft = 0;
425
	plinno = 1;
474
	plinno = 1;
426
}
475
}
Lines 431-445 Link Here
431
 */
480
 */
432
481
433
void
482
void
434
setinputstring(string, push)
483
setinputstring(string)
435
	char *string;
484
	char *string;
436
	int push;
437
	{
485
	{
438
	INTOFF;
486
	INTOFF;
439
	if (push)
440
		pushfile();
487
		pushfile();
441
	parsenextc = string;
488
	parsenextc = string;
442
	parselleft = parsenleft = strlen(string);
489
	parsenleft = strlen(string);
443
	parsefile->buf = NULL;
490
	parsefile->buf = NULL;
444
	plinno = 1;
491
	plinno = 1;
445
	INTON;
492
	INTON;
(-)bin_NetBSD-1.6release.orig/src/bin/sh/input.h (-3 / +3 lines)
Lines 48-64 Link Here
48
extern int plinno;
48
extern int plinno;
49
extern int parsenleft;		/* number of characters left in input buffer */
49
extern int parsenleft;		/* number of characters left in input buffer */
50
extern char *parsenextc;	/* next character in input buffer */
50
extern char *parsenextc;	/* next character in input buffer */
51
extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
52
51
53
char *pfgets __P((char *, int));
52
char *pfgets __P((char *, int));
54
int pgetc __P((void));
53
int pgetc __P((void));
54
int pgetc2 __P((void));
55
int preadbuffer __P((void));
55
int preadbuffer __P((void));
56
void pungetc __P((void));
56
void pungetc __P((void));
57
void pushstring __P((char *, int, void *));
57
void pushstring __P((char *, void *));
58
void popstring __P((void));
58
void popstring __P((void));
59
void setinputfile __P((const char *, int));
59
void setinputfile __P((const char *, int));
60
void setinputfd __P((int, int));
60
void setinputfd __P((int, int));
61
void setinputstring __P((char *, int));
61
void setinputstring __P((char *));
62
void popfile __P((void));
62
void popfile __P((void));
63
void popallfiles __P((void));
63
void popallfiles __P((void));
64
void closescript __P((void));
64
void closescript __P((void));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/jobs.c (-133 / +242 lines)
Lines 85-105 Link Here
85
#include "mystring.h"
85
#include "mystring.h"
86
86
87
87
88
struct job *jobtab;		/* array of jobs */
88
/* array of jobs */
89
int njobs;			/* size of array */
89
STATIC struct job *jobtab;
90
MKINIT short backgndpid = -1;	/* pid of last background process */
90
/* size of array */
91
STATIC int njobs;
92
/* pid of last background process */
93
MKINIT pid_t backgndpid;
91
#if JOBS
94
#if JOBS
92
int initialpgrp;		/* pgrp of shell on invocation */
95
/* pgrp of shell on invocation */
93
short curjob;			/* current job */
96
STATIC int initialpgrp;
97
/* current job */
98
STATIC struct job *curjob;
94
#endif
99
#endif
95
static int ttyfd = -1;
100
STATIC int ttyfd = -1;
101
/* number of presumed living untracked jobs */
102
STATIC int jobless;
96
103
97
STATIC void restartjob __P((struct job *));
104
STATIC void restartjob __P((struct job *));
98
STATIC void freejob __P((struct job *));
105
STATIC void freejob __P((struct job *));
99
STATIC struct job *getjob __P((char *));
106
STATIC struct job *getjob __P((char *));
100
STATIC int dowait __P((int, struct job *));
107
STATIC int dowait __P((int, struct job *));
108
#ifdef SYSV
101
STATIC int onsigchild __P((void));
109
STATIC int onsigchild __P((void));
102
STATIC int waitproc __P((int, struct job *, int *));
110
#endif
111
STATIC int waitproc __P((int, int *));
103
STATIC void cmdtxt __P((union node *));
112
STATIC void cmdtxt __P((union node *));
104
STATIC void cmdputs __P((const char *));
113
STATIC void cmdputs __P((const char *));
105
114
Lines 127-138 Link Here
127
}
136
}
128
#endif
137
#endif
129
138
139
#if JOBS
130
/*
140
/*
131
 * Turn job control on and off.
141
 * Turn job control on and off.
132
 *
142
 *
133
 * Note:  This code assumes that the third arg to ioctl is a character
143
 * Note:  This code assumes that the third arg to ioctl is a character
134
 * pointer, which is true on Berkeley systems but not System V.  Since
144
 * pointer, which is true on Berkeley systems but not System V.  Since
135
 * System V doesn't have job control yet, this isn't a problem now.
145
 * System V doesn't have job control yet, this isn't a problem now.
146
 *
147
 * Called with interrupts off.
136
 */
148
 */
137
149
138
MKINIT int jobctl;
150
MKINIT int jobctl;
Lines 144-236 Link Here
144
#ifdef OLD_TTY_DRIVER
156
#ifdef OLD_TTY_DRIVER
145
	int ldisc;
157
	int ldisc;
146
#endif
158
#endif
159
	int fd;
160
	int pgrp;
147
161
148
	if (on == jobctl || rootshell == 0)
162
	if (on == jobctl || rootshell == 0)
149
		return;
163
		return;
150
	if (on) {
164
	if (on) {
151
#if defined(FIOCLEX) || defined(FD_CLOEXEC)
165
#if defined(FIOCLEX) || defined(FD_CLOEXEC)
152
		int err;
166
		int ofd;
153
		if (ttyfd != -1)
167
		ofd = fd = open(_PATH_TTY, O_RDWR);
154
			close(ttyfd);
168
		if (fd < 0) {
155
		if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) {
169
			fd += 3;
156
			int i;
170
			while (!isatty(fd) && --fd >= 0)
157
			for (i = 0; i < 3; i++) {
171
				;
158
				if (isatty(i) && (ttyfd = dup(i)) != -1)
159
					break;
160
			}
172
			}
161
			if (i == 3)
173
		fd = fcntl(fd, F_DUPFD, 10);
174
		close(ofd);
175
		if (fd < 0)
162
				goto out;
176
				goto out;
163
		}
177
#ifdef linux
164
#ifdef FIOCLEX
178
		fcntl(fd, F_SETFD, FD_CLOEXEC);
165
		err = ioctl(ttyfd, FIOCLEX, 0);
179
#elif defined(FIOCLEX)
166
#elif FD_CLOEXEC
180
		ioctl(fd, FIOCLEX, 0);
167
		err = fcntl(ttyfd, FD_CLOEXEC, 1);
181
#elif defined(FD_CLOEXEC)
182
		fcntl(fd, FD_CLOEXEC, 1);
168
#endif
183
#endif
169
		if (err == -1) {
170
			close(ttyfd);
171
			ttyfd = -1;
172
			goto out;
173
		}
174
#else
184
#else
175
		out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control");
185
		warnx("Need FIOCLEX or FD_CLOEXEC to support job control");
176
		goto out;
186
		mflag = 0;
187
		return;
177
#endif
188
#endif
178
		do { /* while we are in the background */
189
		do { /* while we are in the background */
179
			if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) {
190
			if ((pgrp = tcgetpgrp(fd)) < 0) {
180
out:
191
out:
181
				out2str("sh: can't access tty; job control turned off\n");
192
				warnx("can't access tty; job control turned off");
182
				mflag = 0;
193
				mflag = on = 0;
183
				return;
194
				goto close;
184
			}
195
			}
185
			if (initialpgrp == -1)
196
			if (pgrp == getpgrp())
186
				initialpgrp = getpgrp();
197
				break;
187
			else if (initialpgrp != getpgrp()) {
188
				killpg(0, SIGTTIN);
198
				killpg(0, SIGTTIN);
189
				continue;
199
		} while (1);
190
			}
200
		initialpgrp = pgrp;
191
		} while (0);
192
201
193
#ifdef OLD_TTY_DRIVER
202
#ifdef OLD_TTY_DRIVER
194
		if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0
203
		if (ioctl(fd, TIOCGETD, (char *)&ldisc) < 0
195
		    || ldisc != NTTYDISC) {
204
		    || ldisc != NTTYDISC) {
196
			out2str("sh: need new tty driver to run job control; job control turned off\n");
205
			warnx("need new tty driver to run job control; job control turned off");
197
			mflag = 0;
206
			mflag = on = 0;
198
			return;
207
			goto close;
199
		}
208
		}
200
#endif
209
#endif
201
		setsignal(SIGTSTP);
210
		setsignal(SIGTSTP);
202
		setsignal(SIGTTOU);
211
		setsignal(SIGTTOU);
203
		setsignal(SIGTTIN);
212
		setsignal(SIGTTIN);
204
		setpgid(0, rootpid);
213
		pgrp = rootpid;
205
		tcsetpgrp(ttyfd, rootpid);
214
		setpgid(0, pgrp);
206
	} else { /* turning job control off */
215
		tcsetpgrp(fd, pgrp);
207
		setpgid(0, initialpgrp);
216
	} else {
208
		tcsetpgrp(ttyfd, initialpgrp);
217
		/* turning job control off */
209
		close(ttyfd);
218
		fd = ttyfd;
210
		ttyfd = -1;
219
		pgrp = initialpgrp;
220
		tcsetpgrp(fd, pgrp);
221
		setpgid(0, pgrp);
211
		setsignal(SIGTSTP);
222
		setsignal(SIGTSTP);
212
		setsignal(SIGTTOU);
223
		setsignal(SIGTTOU);
213
		setsignal(SIGTTIN);
224
		setsignal(SIGTTIN);
225
close:
226
		close(fd);
227
		fd = -1;
214
	}
228
	}
229
	ttyfd = fd;
215
	jobctl = on;
230
	jobctl = on;
216
}
231
}
232
#endif
217
233
218
234
219
#ifdef mkinit
220
INCLUDE <stdlib.h>
221
235
222
SHELLPROC {
223
	backgndpid = -1;
224
#if JOBS
236
#if JOBS
225
	jobctl = 0;
237
int
226
#endif
238
killcmd(argc, argv)
227
}
239
	int argc;
240
	char **argv;
241
{
242
	extern char *signal_names[];
243
	int signo = -1;
244
	int list = 0;
245
	int i;
246
	pid_t pid;
247
	struct job *jp;
248
249
	if (argc <= 1) {
250
usage:
251
		error(
252
"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
253
"kill -l [exitstatus]"
254
		);
255
	}
256
257
	if (*argv[1] == '-') {
258
		signo = decode_signal(argv[1] + 1, 1);
259
		if (signo < 0) {
260
			int c;
228
261
262
			while ((c = nextopt("ls:")) != '\0')
263
				switch (c) {
264
				case 'l':
265
					list = 1;
266
					break;
267
				case 's':
268
					signo = decode_signal(optionarg, 1);
269
					if (signo < 0) {
270
						error(
271
							"invalid signal number or name: %s",
272
							optionarg
273
						);
274
					}
275
		                        break;
276
#ifdef DEBUG
277
				default:
278
					error(
279
	"nextopt returned character code 0%o", c);
229
#endif
280
#endif
281
			}
282
		} else
283
			argptr++;
284
	}
230
285
286
	if (!list && signo < 0)
287
		signo = SIGTERM;
231
288
289
	if ((signo < 0 || !*argptr) ^ list) {
290
		goto usage;
291
	}
292
293
	if (list) {
294
		if (!*argptr) {
295
			out1str("0\n");
296
			for (i = 1; i < NSIG; i++) {
297
				out1fmt(snlfmt, signal_names[i]);
298
			}
299
			return 0;
300
		}
301
		signo = atoi(*argptr);
302
		if (signo > 128)
303
			signo -= 128;
304
		if (0 < signo && signo < NSIG)
305
			out1fmt(snlfmt, signal_names[signo]);
306
		else
307
			error("invalid signal number or exit status: %s",
308
			      *argptr);
309
		return 0;
310
	}
311
312
	i = 0;
313
	do {
314
		if (**argptr == '%') {
315
			jp = getjob(*argptr);
316
			if (jp->jobctl == 0) {
317
				outfmt(
318
					out2,
319
					"job %s not created "
320
						"under job control\n",
321
					*argptr
322
				);
323
				i = 1;
324
				continue;
325
			}
326
			pid = -jp->ps[0].pid;
327
		} else
328
			pid = atoi(*argptr);
329
		if (kill(pid, signo) != 0) {
330
			outfmt(out2, "%s: %s\n", *argptr, strerror(errno));
331
			i = 1;
332
		}
333
	} while (*++argptr);
334
335
	return i;
336
}
232
337
233
#if JOBS
234
int
338
int
235
fgcmd(argc, argv)
339
fgcmd(argc, argv)
236
	int argc;
340
	int argc;
Lines 246-254 Link Here
246
	pgrp = jp->ps[0].pid;
350
	pgrp = jp->ps[0].pid;
247
	tcsetpgrp(ttyfd, pgrp);
351
	tcsetpgrp(ttyfd, pgrp);
248
	restartjob(jp);
352
	restartjob(jp);
249
	INTOFF;
250
	status = waitforjob(jp);
353
	status = waitforjob(jp);
251
	INTON;
252
	return status;
354
	return status;
253
}
355
}
254
356
Lines 366-377 Link Here
366
			}
468
			}
367
			out1str(s);
469
			out1str(s);
368
			col += strlen(s);
470
			col += strlen(s);
369
			do {
471
			out1fmt(
370
				out1c(' ');
472
				"%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
371
				col++;
473
				ps->cmd
372
			} while (col < 30);
474
			);
373
			out1str(ps->cmd);
374
			out1c('\n');
375
			if (--procno <= 0)
475
			if (--procno <= 0)
376
				break;
476
				break;
377
		}
477
		}
Lines 399-412 Link Here
399
		if (ps->cmd != nullstr)
499
		if (ps->cmd != nullstr)
400
			ckfree(ps->cmd);
500
			ckfree(ps->cmd);
401
	}
501
	}
402
	if (jp->ps != &jp->ps0) {
502
	if (jp->ps != &jp->ps0)
403
		ckfree(jp->ps);
503
		ckfree(jp->ps);
404
		jp->ps = &jp->ps0;
405
	}
406
	jp->nprocs = 0;
407
	jp->used = 0;
504
	jp->used = 0;
408
#if JOBS
505
#if JOBS
409
	if (curjob == jp - jobtab + 1)
506
	if (curjob == jp)
410
		curjob = 0;
507
		curjob = 0;
411
#endif
508
#endif
412
	INTON;
509
	INTON;
Lines 423-430 Link Here
423
	int status, retval;
520
	int status, retval;
424
	struct job *jp;
521
	struct job *jp;
425
522
426
	if (argc > 1) {
523
	if (--argc > 0) {
427
		job = getjob(argv[1]);
524
start:
525
		job = getjob(*++argv);
428
	} else {
526
	} else {
429
		job = NULL;
527
		job = NULL;
430
	}
528
	}
Lines 432-437 Link Here
432
		if (job != NULL) {
530
		if (job != NULL) {
433
			if (job->state) {
531
			if (job->state) {
434
				status = job->ps[job->nprocs - 1].status;
532
				status = job->ps[job->nprocs - 1].status;
533
				if (! iflag)
534
					freejob(job);
535
				if (--argc) {
536
					goto start;
537
				}
435
				if (WIFEXITED(status))
538
				if (WIFEXITED(status))
436
					retval = WEXITSTATUS(status);
539
					retval = WEXITSTATUS(status);
437
#if JOBS
540
#if JOBS
Lines 442-467 Link Here
442
					/* XXX: limits number of signals */
545
					/* XXX: limits number of signals */
443
					retval = WTERMSIG(status) + 128;
546
					retval = WTERMSIG(status) + 128;
444
				}
547
				}
445
				if (! iflag)
446
					freejob(job);
447
				return retval;
548
				return retval;
448
			}
549
			}
449
		} else {
550
		} else {
551
			struct job *end = jobtab + njobs;
450
			for (jp = jobtab ; ; jp++) {
552
			for (jp = jobtab ; ; jp++) {
451
				if (jp >= jobtab + njobs) {	/* no running procs */
553
				if (jp >= end) {
554
					/* no running procs */
452
					return 0;
555
					return 0;
453
				}
556
				}
454
				if (jp->used && jp->state == 0)
557
				if (jp->used && jp->state == 0)
455
					break;
558
					break;
456
			}
559
			}
457
		}
560
		}
458
		if (dowait(1, (struct job *)NULL) == -1)
561
		dowait(2, 0);
459
		       return 128 + SIGINT;
562
		if (pendingsigs)
563
			return 128 + pendingsigs;
460
	}
564
	}
461
}
565
}
462
566
463
567
464
568
569
#if 0
465
int
570
int
466
jobidcmd(argc, argv)
571
jobidcmd(argc, argv)
467
	int argc;
572
	int argc;
Lines 472-482 Link Here
472
577
473
	jp = getjob(argv[1]);
578
	jp = getjob(argv[1]);
474
	for (i = 0 ; i < jp->nprocs ; ) {
579
	for (i = 0 ; i < jp->nprocs ; ) {
475
		out1fmt("%ld", (long)jp->ps[i].pid);
580
		out1fmt(
476
		out1c(++i < jp->nprocs? ' ' : '\n');
581
			"%ld%c", (long)jp->ps[i].pid,
582
			++i < jp->nprocs? ' ' : '\n'
583
		);
477
	}
584
	}
478
	return 0;
585
	return 0;
479
}
586
}
587
#endif
480
588
481
589
482
590
Lines 496-504 Link Here
496
	if (name == NULL) {
604
	if (name == NULL) {
497
#if JOBS
605
#if JOBS
498
currentjob:
606
currentjob:
499
		if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
607
		if (!curjob || !curjob->used)
500
			error("No current job");
608
			error("No current job");
501
		return &jobtab[jobno - 1];
609
		return curjob;
502
#else
610
#else
503
		error("No current job");
611
		error("No current job");
504
#endif
612
#endif
Lines 575-587 Link Here
575
			break;
683
			break;
576
	}
684
	}
577
	INTOFF;
685
	INTOFF;
578
	jp->state = 0;
579
	jp->used = 1;
580
	jp->changed = 0;
581
	jp->nprocs = 0;
686
	jp->nprocs = 0;
687
	jp->state = 0;
582
#if JOBS
688
#if JOBS
583
	jp->jobctl = jobctl;
689
	jp->jobctl = jobctl;
584
#endif
690
#endif
691
	jp->changed = 0;
692
	jp->used = 1;
585
	if (nprocs > 1) {
693
	if (nprocs > 1) {
586
		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
694
		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
587
	} else {
695
	} else {
Lines 636-658 Link Here
636
		TRACE(("Child shell %d\n", getpid()));
744
		TRACE(("Child shell %d\n", getpid()));
637
		wasroot = rootshell;
745
		wasroot = rootshell;
638
		rootshell = 0;
746
		rootshell = 0;
639
		for (i = njobs, p = jobtab ; --i >= 0 ; p++) {
640
			if (p == jp)
641
				continue;	/* don't free current job */
642
			if (p->used)
643
				freejob(p);
644
		}
645
		closescript();
747
		closescript();
646
		INTON;
748
		INTON;
647
		clear_traps();
749
		clear_traps();
648
#if JOBS
750
#if JOBS
649
		jobctl = 0;		/* do job control only in root shell */
751
		jobctl = pid;		/* do job control only in root shell */
650
		if (wasroot && mode != FORK_NOJOB && mflag) {
752
		if (wasroot && mode != FORK_NOJOB && mflag) {
651
			if (jp == NULL || jp->nprocs == 0)
753
			if (jp == NULL || jp->nprocs == 0)
652
				pgrp = getpid();
754
				pgrp = getpid();
653
			else
755
			else
654
				pgrp = jp->ps[0].pid;
756
				pgrp = jp->ps[0].pid;
655
			setpgid(0, pgrp);
757
			setpgid(pid, pgrp);
656
			if (mode == FORK_FG) {
758
			if (mode == FORK_FG) {
657
				/*** this causes superfluous TIOCSPGRPS ***/
759
				/*** this causes superfluous TIOCSPGRPS ***/
658
				if (tcsetpgrp(ttyfd, pgrp) < 0)
760
				if (tcsetpgrp(ttyfd, pgrp) < 0)
Lines 661-692 Link Here
661
			setsignal(SIGTSTP);
763
			setsignal(SIGTSTP);
662
			setsignal(SIGTTOU);
764
			setsignal(SIGTTOU);
663
		} else if (mode == FORK_BG) {
765
		} else if (mode == FORK_BG) {
664
			ignoresig(SIGINT);
665
			ignoresig(SIGQUIT);
666
			if ((jp == NULL || jp->nprocs == 0) &&
667
			    ! fd0_redirected_p ()) {
668
				close(0);
669
				if (open(devnull, O_RDONLY) != 0)
670
					error(nullerr, devnull);
671
			}
672
		}
673
#else
766
#else
674
		if (mode == FORK_BG) {
767
		if (mode == FORK_BG) {
768
#endif
675
			ignoresig(SIGINT);
769
			ignoresig(SIGINT);
676
			ignoresig(SIGQUIT);
770
			ignoresig(SIGQUIT);
677
			if ((jp == NULL || jp->nprocs == 0) &&
771
			if ((jp == NULL || jp->nprocs == 0)) {
678
			    ! fd0_redirected_p ()) {
772
				close(pid);
679
				close(0);
680
				if (open(devnull, O_RDONLY) != 0)
773
				if (open(devnull, O_RDONLY) != 0)
681
					error(nullerr, devnull);
774
					error(nullerr, devnull);
682
			}
775
			}
683
		}
776
		}
684
#endif
777
		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
778
			if (p->used)
779
				freejob(p);
685
		if (wasroot && iflag) {
780
		if (wasroot && iflag) {
686
			setsignal(SIGINT);
781
			setsignal(SIGINT);
687
			setsignal(SIGQUIT);
782
			setsignal(SIGQUIT);
688
			setsignal(SIGTERM);
783
			setsignal(SIGTERM);
689
		}
784
		}
785
		jobless = pid;
690
		return pid;
786
		return pid;
691
	}
787
	}
692
	if (rootshell && mode != FORK_NOJOB && mflag) {
788
	if (rootshell && mode != FORK_NOJOB && mflag) {
Lines 705-710 Link Here
705
		ps->cmd = nullstr;
801
		ps->cmd = nullstr;
706
		if (iflag && rootshell && n)
802
		if (iflag && rootshell && n)
707
			ps->cmd = commandtext(n);
803
			ps->cmd = commandtext(n);
804
	} else {
805
		while (jobless && dowait(0, 0) > 0);
806
		jobless++;
708
	}
807
	}
709
	INTON;
808
	INTON;
710
	TRACE(("In parent shell:  child = %d\n", pid));
809
	TRACE(("In parent shell:  child = %d\n", pid));
Lines 753-759 Link Here
753
			error("tcsetpgrp failed, errno=%d\n", errno);
852
			error("tcsetpgrp failed, errno=%d\n", errno);
754
	}
853
	}
755
	if (jp->state == JOBSTOPPED)
854
	if (jp->state == JOBSTOPPED)
756
		curjob = jp - jobtab + 1;
855
		curjob = jp;
757
#endif
856
#endif
758
	status = jp->ps[jp->nprocs - 1].status;
857
	status = jp->ps[jp->nprocs - 1].status;
759
	/* convert to 8 bits */
858
	/* convert to 8 bits */
Lines 798-826 Link Here
798
{
897
{
799
	int pid;
898
	int pid;
800
	int status;
899
	int status;
801
	struct procstat *sp;
802
	struct job *jp;
900
	struct job *jp;
901
	struct job *end;
803
	struct job *thisjob;
902
	struct job *thisjob;
804
	int done;
805
	int stopped;
806
	int core;
903
	int core;
807
	int sig;
904
	int sig;
808
	extern volatile char gotsig[];
905
	int state;
809
906
810
	TRACE(("dowait(%d) called\n", block));
907
	TRACE(("dowait(%d) called\n", block));
811
	do {
908
	do {
812
		pid = waitproc(block, job, &status);
909
		pid = waitproc(block, &status);
813
		TRACE(("wait returns %d, status=%d\n", pid, status));
910
		TRACE(("wait returns %d, status=%d\n", pid, status));
814
	} while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0);
911
	} while (!(block & 2) && pid == -1 && errno == EINTR);
815
	if (pid <= 0)
912
	if (pid <= 0)
816
		return pid;
913
		return pid;
817
	INTOFF;
914
	INTOFF;
818
	thisjob = NULL;
915
	thisjob = NULL;
819
	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
916
	end = jobtab + njobs;
820
		if (jp->used) {
917
	for (jp = jobtab; jp < end; jp++) {
821
			done = 1;
918
		struct procstat *sp;
822
			stopped = 1;
919
		struct procstat *spend;
823
			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
920
		if (!jp->used)
921
			continue;
922
		state = JOBDONE;
923
		spend = jp->ps + jp->nprocs;
924
		for (sp = jp->ps; sp < spend; sp++) {
824
				if (sp->pid == -1)
925
				if (sp->pid == -1)
825
					continue;
926
					continue;
826
				if (sp->pid == pid) {
927
				if (sp->pid == pid) {
Lines 829-851 Link Here
829
					thisjob = jp;
930
					thisjob = jp;
830
				}
931
				}
831
				if (sp->status == -1)
932
				if (sp->status == -1)
832
					stopped = 0;
933
				state = 0;
833
				else if (WIFSTOPPED(sp->status))
934
				else if (WIFSTOPPED(sp->status))
834
					done = 0;
935
				state = JOBSTOPPED;
835
			}
936
			}
836
			if (stopped) {		/* stopped or done */
937
		if (!thisjob)
837
				int state = done? JOBDONE : JOBSTOPPED;
938
			continue;
838
				if (jp->state != state) {
939
		if (state) {
839
					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
940
			/* stopped or done */
840
					jp->state = state;
941
			if (thisjob->state != state) {
942
				TRACE(("Job %d: changing state from %d to %d\n", thisjob - jobtab + 1, thisjob->state, state));
943
				thisjob->state = state;
841
#if JOBS
944
#if JOBS
842
					if (done && curjob == jp - jobtab + 1)
945
				if (state == JOBDONE && curjob == thisjob) {
843
						curjob = 0;		/* no current job */
946
					/* no current job */
844
#endif
947
					curjob = 0;
845
				}
948
				}
949
#endif
846
			}
950
			}
847
		}
951
		}
952
		goto gotjob;
848
	}
953
	}
954
	if (!WIFSTOPPED(status))
955
		jobless--;
956
gotjob:
849
	INTON;
957
	INTON;
850
	if (! rootshell || ! iflag || (job && thisjob == job)) {
958
	if (! rootshell || ! iflag || (job && thisjob == job)) {
851
		core = WCOREDUMP(status);
959
		core = WCOREDUMP(status);
Lines 871-877 Link Here
871
			if (core)
979
			if (core)
872
				out2str(" - core dumped");
980
				out2str(" - core dumped");
873
			out2c('\n');
981
			out2c('\n');
982
#ifdef FLUSHERR
874
			flushout(&errout);
983
			flushout(&errout);
984
#endif
875
		} else {
985
		} else {
876
			TRACE(("Not printing status: status=%d, sig=%d\n", 
986
			TRACE(("Not printing status: status=%d, sig=%d\n", 
877
			       status, sig));
987
			       status, sig));
Lines 925-940 Link Here
925
1035
926
1036
927
STATIC int
1037
STATIC int
928
waitproc(block, jp, status)
1038
waitproc(block, status)
929
	int block;
1039
	int block;
930
	struct job *jp;
931
	int *status;
1040
	int *status;
932
{
1041
{
933
#ifdef BSD
1042
#ifdef BSD
934
	int flags = 0;
1043
	int flags = 0;
935
1044
936
#if JOBS
1045
#if JOBS
937
	if (jp != NULL && jp->jobctl)
1046
	if (jobctl)
938
		flags |= WUNTRACED;
1047
		flags |= WUNTRACED;
939
#endif
1048
#endif
940
	if (block == 0)
1049
	if (block == 0)
Lines 963-969 Link Here
963
/*
1072
/*
964
 * return 1 if there are stopped jobs, otherwise 0
1073
 * return 1 if there are stopped jobs, otherwise 0
965
 */
1074
 */
966
int job_warning = 0;
1075
int job_warning;
967
int
1076
int
968
stoppedjobs()
1077
stoppedjobs()
969
{
1078
{
Lines 1088-1097 Link Here
1088
		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1197
		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1089
			cmdtxt(np);
1198
			cmdtxt(np);
1090
			if (np->narg.next)
1199
			if (np->narg.next)
1091
				cmdputs(" ");
1200
				cmdputs(spcstr);
1092
		}
1201
		}
1093
		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1202
		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1094
			cmdputs(" ");
1203
			cmdputs(spcstr);
1095
			cmdtxt(np);
1204
			cmdtxt(np);
1096
		}
1205
		}
1097
		break;
1206
		break;
(-)bin_NetBSD-1.6release.orig/src/bin/sh/jobs.h (-7 / +12 lines)
Lines 38-43 Link Here
38
 *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
38
 *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
39
 */
39
 */
40
40
41
#include <stdint.h>
42
#include <sys/types.h>
43
41
/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
44
/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
42
#define FORK_FG 0
45
#define FORK_FG 0
43
#define FORK_BG 1
46
#define FORK_BG 1
Lines 66-85 Link Here
66
struct job {
69
struct job {
67
	struct procstat ps0;	/* status of process */
70
	struct procstat ps0;	/* status of process */
68
	struct procstat *ps;	/* status or processes when more than one */
71
	struct procstat *ps;	/* status or processes when more than one */
69
	short nprocs;		/* number of processes */
72
	pid_t pgrp;		/* process group of this job */
70
	short pgrp;		/* process group of this job */
73
	uint32_t
71
	char state;		/* true if job is finished */
74
		nprocs: 16,	/* number of processes */
72
	char used;		/* true if this entry is in used */
75
		state: 8,	/* true if job is finished */
73
	char changed;		/* true if status has changed */
74
#if JOBS
76
#if JOBS
75
	char jobctl;		/* job running under job control */
77
		jobctl: 1,	/* job running under job control */
76
#endif
78
#endif
79
		used: 1,	/* true if this entry is in used */
80
		changed: 1;	/* true if status has changed */
77
};
81
};
78
82
79
extern short backgndpid;	/* pid of last background process */
83
extern pid_t backgndpid;	/* pid of last background process */
80
extern int job_warning;		/* user was warned about stopped jobs */
84
extern int job_warning;		/* user was warned about stopped jobs */
81
85
82
void setjobctl __P((int));
86
void setjobctl __P((int));
87
int killcmd __P((int, char **));
83
int fgcmd __P((int, char **));
88
int fgcmd __P((int, char **));
84
int bgcmd __P((int, char **));
89
int bgcmd __P((int, char **));
85
int jobscmd __P((int, char **));
90
int jobscmd __P((int, char **));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mail.c (-31 / +31 lines)
Lines 53-125 Link Here
53
#include <stdlib.h>
53
#include <stdlib.h>
54
54
55
#include "shell.h"
55
#include "shell.h"
56
#include "nodes.h"
56
#include "exec.h"	/* defines padvance() */
57
#include "exec.h"	/* defines padvance() */
57
#include "var.h"
58
#include "var.h"
58
#include "output.h"
59
#include "output.h"
59
#include "memalloc.h"
60
#include "memalloc.h"
60
#include "error.h"
61
#include "error.h"
61
#include "mail.h"
62
#include "mail.h"
63
#include "mystring.h"
62
64
63
65
64
#define MAXMBOXES 10
66
#define MAXMBOXES 10
65
67
66
68
/* times of mailboxes */
67
STATIC int nmboxes;			/* number of mailboxes */
69
static time_t mailtime[MAXMBOXES];
68
STATIC time_t mailtime[MAXMBOXES];	/* times of mailboxes */
70
/* Set if MAIL or MAILPATH is changed. */
71
static int changed;
69
72
70
73
71
74
72
/*
75
/*
73
 * Print appropriate message(s) if mail has arrived.  If the argument is
76
 * Print appropriate message(s) if mail has arrived.  If changed is set,
74
 * nozero, then the value of MAIL has changed, so we just update the
77
 * then the value of MAIL has changed, so we just update the values.
75
 * values.
76
 */
78
 */
77
79
78
void
80
void
79
chkmail(silent)
81
chkmail()
80
	int silent;
81
{
82
{
82
	int i;
83
	const char *mpath;
83
	const char *mpath;
84
	char *p;
84
	char *p;
85
	char *q;
85
	char *q;
86
	time_t *mtp;
86
	struct stackmark smark;
87
	struct stackmark smark;
87
	struct stat statb;
88
	struct stat64 statb;
88
89
89
	if (silent)
90
		nmboxes = 10;
91
	if (nmboxes == 0)
92
		return;
93
	setstackmark(&smark);
90
	setstackmark(&smark);
94
	mpath = mpathset()? mpathval() : mailval();
91
	mpath = mpathset()? mpathval() : mailval();
95
	for (i = 0 ; i < nmboxes ; i++) {
92
	for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
96
		p = padvance(&mpath, nullstr);
93
		p = padvance(&mpath, nullstr);
97
		if (p == NULL)
94
		if (p == NULL)
98
			break;
95
			break;
99
		if (*p == '\0')
96
		if (*p == '\0')
100
			continue;
97
			continue;
101
		for (q = p ; *q ; q++);
98
		for (q = p ; *q ; q++);
99
#ifdef DEBUG
102
		if (q[-1] != '/')
100
		if (q[-1] != '/')
103
			abort();
101
			abort();
102
#endif
104
		q[-1] = '\0';			/* delete trailing '/' */
103
		q[-1] = '\0';			/* delete trailing '/' */
105
#ifdef notdef /* this is what the System V shell claims to do (it lies) */
104
		if (stat64(p, &statb) < 0) {
106
		if (stat(p, &statb) < 0)
105
			*mtp = 0;
107
			statb.st_mtime = 0;
106
			continue;
108
		if (statb.st_mtime > mailtime[i] && ! silent) {
109
			out2str(pathopt? pathopt : "you have mail");
110
			out2c('\n');
111
		}
107
		}
112
		mailtime[i] = statb.st_mtime;
108
		if (!changed && statb.st_mtime != *mtp) {
113
#else /* this is what it should do */
109
			outfmt(
114
		if (stat(p, &statb) < 0)
110
				&errout, snlfmt,
115
			statb.st_size = 0;
111
				pathopt? pathopt : "you have mail"
116
		if (statb.st_size > mailtime[i] && ! silent) {
112
			);
117
			out2str(pathopt? pathopt : "you have mail");
118
			out2c('\n');
119
		}
113
		}
120
		mailtime[i] = statb.st_size;
114
		*mtp = statb.st_mtime;
121
#endif
122
	}
115
	}
123
	nmboxes = i;
116
	changed = 0;
124
	popstackmark(&smark);
117
	popstackmark(&smark);
125
}
118
}
119
120
121
void
122
changemail(const char *val)
123
{
124
	changed++;
125
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mail.h (-1 / +2 lines)
Lines 38-41 Link Here
38
 *	@(#)mail.h	8.2 (Berkeley) 5/4/95
38
 *	@(#)mail.h	8.2 (Berkeley) 5/4/95
39
 */
39
 */
40
40
41
void chkmail __P((int));
41
void chkmail __P((void));
42
void changemail __P((const char *));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/main.c (-52 / +41 lines)
Lines 79-90 Link Here
79
#include "exec.h"
79
#include "exec.h"
80
#include "cd.h"
80
#include "cd.h"
81
81
82
#ifdef HETIO
83
#include "hetio.h"
84
#endif
85
82
#define PROFILE 0
86
#define PROFILE 0
83
87
84
int rootpid;
88
int rootpid;
85
int rootshell;
89
int rootshell;
86
STATIC union node *curcmd;
87
STATIC union node *prevcmd;
88
#if PROFILE
90
#if PROFILE
89
short profile_buf[16384];
91
short profile_buf[16384];
90
extern int etext();
92
extern int etext();
Lines 108-160 Link Here
108
	int argc;
110
	int argc;
109
	char **argv;
111
	char **argv;
110
{
112
{
113
	char *shinit;
114
	volatile int state;
111
	struct jmploc jmploc;
115
	struct jmploc jmploc;
112
	struct stackmark smark;
116
	struct stackmark smark;
113
	volatile int state;
114
	char *shinit;
115
117
116
#if PROFILE
118
#if PROFILE
117
	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
119
	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
118
#endif
120
#endif
119
	state = 0;
121
	state = 0;
120
	if (setjmp(jmploc.loc)) {
122
	if (setjmp(jmploc.loc)) {
121
		/*
123
		int status;
122
		 * When a shell procedure is executed, we raise the
124
		int e;
123
		 * exception EXSHELLPROC to clean up before executing
124
		 * the shell procedure.
125
		 */
126
		switch (exception) {
127
		case EXSHELLPROC:
128
			rootpid = getpid();
129
			rootshell = 1;
130
			minusc = NULL;
131
			state = 3;
132
			break;
133
125
126
		reset();
127
128
		e = exception;
129
		switch (exception) {
134
		case EXEXEC:
130
		case EXEXEC:
135
			exitstatus = exerrno;
131
			status = exerrno;
136
			break;
132
			break;
137
133
138
		case EXERROR:
134
		case EXERROR:
139
			exitstatus = 2;
135
			status = 2;
140
			break;
136
			break;
141
137
142
		default:
138
		default:
139
			status = exitstatus;
143
			break;
140
			break;
144
		}
141
		}
142
		exitstatus = status;
145
143
146
		if (exception != EXSHELLPROC) {
144
		if (e == EXEXIT || state == 0 || iflag == 0 || ! rootshell)
147
		    if (state == 0 || iflag == 0 || ! rootshell)
145
			exitshell();
148
			    exitshell(exitstatus);
146
149
		}
147
		if (e == EXINT
150
		reset();
151
		if (exception == EXINT
152
#if ATTY
148
#if ATTY
153
		 && (! attyset() || equal(termval(), "emacs"))
149
		 && (! attyset() || equal(termval(), "emacs"))
154
#endif
150
#endif
155
		 ) {
151
		 ) {
156
			out2c('\n');
152
			out2c('\n');
157
			flushout(&errout);
153
#ifdef FLUSHERR
154
			flushout(out2);
155
#endif
158
		}
156
		}
159
		popstackmark(&smark);
157
		popstackmark(&smark);
160
		FORCEINTON;				/* enable interrupts */
158
		FORCEINTON;				/* enable interrupts */
Lines 186-214 Link Here
186
	}
184
	}
187
state2:
185
state2:
188
	state = 3;
186
	state = 3;
189
	if (getuid() == geteuid() && getgid() == getegid()) {
187
	if (
188
#ifndef linux
189
		getuid() == geteuid() && getgid() == getegid() &&
190
#endif
191
		iflag
192
	) {
190
		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
193
		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
191
			state = 3;
192
			read_profile(shinit);
194
			read_profile(shinit);
193
		}
195
		}
194
	}
196
	}
195
state3:
197
state3:
196
	state = 4;
198
	state = 4;
197
	if (sflag == 0 || minusc) {
198
		static int sigs[] =  {
199
		    SIGINT, SIGQUIT, SIGHUP, 
200
#ifdef SIGTSTP
201
		    SIGTSTP,
202
#endif
203
		    SIGPIPE
204
		};
205
#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
206
		int i;
207
208
		for (i = 0; i < SIGSSIZE; i++)
209
		    setsignal(sigs[i]);
210
	}
211
212
	if (minusc)
199
	if (minusc)
213
		evalstring(minusc, 0);
200
		evalstring(minusc, 0);
214
201
Lines 219-225 Link Here
219
#if PROFILE
206
#if PROFILE
220
	monitor(0);
207
	monitor(0);
221
#endif
208
#endif
222
	exitshell(exitstatus);
209
	exitshell();
223
	/* NOTREACHED */
210
	/* NOTREACHED */
224
}
211
}
225
212
Lines 240-245 Link Here
240
227
241
	TRACE(("cmdloop(%d) called\n", top));
228
	TRACE(("cmdloop(%d) called\n", top));
242
	setstackmark(&smark);
229
	setstackmark(&smark);
230
#ifdef HETIO
231
	if(iflag && top)
232
		hetio_init();
233
#endif
243
	for (;;) {
234
	for (;;) {
244
		if (pendingsigs)
235
		if (pendingsigs)
245
			dotrap();
236
			dotrap();
Lines 247-253 Link Here
247
		if (iflag && top) {
238
		if (iflag && top) {
248
			inter++;
239
			inter++;
249
			showjobs(1);
240
			showjobs(1);
250
			chkmail(0);
241
			chkmail();
251
			flushout(&output);
242
			flushout(&output);
252
		}
243
		}
253
		n = parsecmd(inter);
244
		n = parsecmd(inter);
Lines 376-387 Link Here
376
	int argc;
367
	int argc;
377
	char **argv;
368
	char **argv;
378
{
369
{
379
	struct strlist *sp;
380
	exitstatus = 0;
370
	exitstatus = 0;
381
371
382
	for (sp = cmdenviron; sp ; sp = sp->next)
383
		setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
384
385
	if (argc >= 2) {		/* That's what SVR2 does */
372
	if (argc >= 2) {		/* That's what SVR2 does */
386
		char *fullname;
373
		char *fullname;
387
		struct stackmark smark;
374
		struct stackmark smark;
Lines 403-414 Link Here
403
	int argc;
390
	int argc;
404
	char **argv;
391
	char **argv;
405
{
392
{
393
	int status;
394
406
	if (stoppedjobs())
395
	if (stoppedjobs())
407
		return 0;
396
		return 0;
397
	status = oexitstatus;
408
	if (argc > 1)
398
	if (argc > 1)
409
		exitstatus = number(argv[1]);
399
		status = number(argv[1]);
410
	else
400
	exitstatus = status;
411
		exitstatus = oexitstatus;
401
	exraise(EXEXIT);
412
	exitshell(exitstatus);
413
	/* NOTREACHED */
402
	/* NOTREACHED */
414
}
403
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/Makefile (-25 / +16 lines)
Lines 1-40 Link Here
1
#	$NetBSD: Makefile,v 1.57.2.2 2002/12/06 23:29:26 he Exp $
1
#	$NetBSD: Makefile,v 1.59 2002/09/15 00:19:22 thorpej Exp $
2
#	@(#)Makefile	8.4 (Berkeley) 5/5/95
2
#	@(#)Makefile	8.4 (Berkeley) 5/5/95
3
3
4
.include <bsd.own.mk>
4
.include <bsd.own.mk>
5
5
6
YHEADER=1
6
YHEADER=1
7
PROG=	sh
7
PROG=	sh
8
SHSRCS=	alias.c cd.c echo.c error.c eval.c exec.c expand.c \
8
SHSRCS=	alias.c arith_yylex.c cd.c echo.c error.c eval.c exec.c expand.c \
9
	histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
9
	histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
10
	mystring.c options.c parser.c redir.c show.c trap.c output.c var.c \
10
	mystring.c options.c parser.c printf.c redir.c show.c trap.c output.c \
11
	test.c
11
	var.c test.c setmode.c times.c hetio.c
12
GENSRCS=arith.c arith.h arith_lex.c builtins.c builtins.h init.c nodes.c \
12
GENSRCS=arith.c arith.h builtins.c builtins.h init.c nodes.c \
13
	nodes.h syntax.c syntax.h token.h
13
	nodes.h signames.c syntax.c syntax.h token.h
14
SRCS=	${SHSRCS} ${GENSRCS}
14
SRCS=	${SHSRCS} ${GENSRCS}
15
15
16
LDADD+=	-ll -ledit -ltermcap
17
DPADD+=	${LIBL} ${LIBEDIT} ${LIBTERMCAP}
18
19
LFLAGS= -8	# 8-bit lex scanner for arithmetic
20
YFLAGS=	-d
16
YFLAGS=	-d
21
17
22
CPPFLAGS+=-DSHELL -I. -I${.CURDIR}
18
CPPFLAGS+=-DSHELL -I. -I${.CURDIR}
19
CPPFLAGS+=-DSMALL -DHETIO
23
20
24
.ifdef SMALLPROG
21
.PATH:	${.CURDIR}/bltin ${NETBSDSRCDIR}/bin/test
25
CPPFLAGS+=-DSMALL
26
.endif
27
28
.PATH:	${.CURDIR}/bltin ${.CURDIR}/../test
29
22
30
CLEANFILES+= mkinit mknodes mksyntax
23
CLEANFILES+= mkinit mknodes mksyntax
31
CLEANFILES+= ${GENSRCS} y.tab.h
24
CLEANFILES+= ${GENSRCS} y.tab.h
32
25
26
BLTINDEFS=specialbltins.def regularbltins.def assignbltins.def
27
33
token.h: mktokens
28
token.h: mktokens
34
	sh ${.ALLSRC}
29
	sh ${.ALLSRC}
35
30
36
builtins.c builtins.h: mkbuiltins shell.h builtins.def
31
builtins.c builtins.h: mkbuiltins shell.h builtins.def ${BLTINDEFS}
37
	sh ${.ALLSRC} ${.OBJDIR}
32
	sh ${.ALLSRC} ${.OBJDIR} '${CFLAGS}'
38
33
39
init.c: mkinit ${SHSRCS}
34
init.c: mkinit ${SHSRCS}
40
	./${.ALLSRC}
35
	./${.ALLSRC}
Lines 45-66 Link Here
45
syntax.c syntax.h: mksyntax
40
syntax.c syntax.h: mksyntax
46
	./${.ALLSRC}
41
	./${.ALLSRC}
47
42
43
signames.c: mksignames
44
	./${.ALLSRC}
45
48
mkinit: mkinit.c
46
mkinit: mkinit.c
49
	${HOST_LINK.c} -o mkinit ${.IMPSRC}
47
	${HOST_LINK.c} -o mkinit ${.IMPSRC}
50
48
51
mknodes: mknodes.c
49
mknodes: mknodes.c
52
	${HOST_LINK.c} -o mknodes ${.IMPSRC}
50
	${HOST_LINK.c} -o mknodes ${.IMPSRC}
53
51
54
.if	(${MACHINE_ARCH} == "powerpc") || \
55
	(${MACHINE_CPU} == "arm")
56
TARGET_CHARFLAG= -DTARGET_CHAR="unsigned char"
57
.else
58
TARGET_CHARFLAG= -DTARGET_CHAR="signed char"
59
.endif
60
61
mksyntax: mksyntax.c
52
mksyntax: mksyntax.c
62
	${HOST_LINK.c} ${TARGET_CHARFLAG} -o mksyntax ${.IMPSRC}
53
	${HOST_LINK.c} ${TARGET_CHARFLAG} -o mksyntax ${.IMPSRC}
63
54
64
.include <bsd.prog.mk>
55
.include <bsd.prog.mk>
65
56
66
${OBJS}: builtins.h nodes.h syntax.h token.h
57
${OBJS}: arith.h builtins.h nodes.h syntax.h token.h
(-)bin_NetBSD-1.6release.orig/src/bin/sh/memalloc.c (-51 / +70 lines)
Lines 60-74 Link Here
60
 */
60
 */
61
61
62
pointer
62
pointer
63
ckmalloc(nbytes)
63
ckmalloc(size_t nbytes)
64
	int nbytes;
65
{
64
{
66
	pointer p;
65
	pointer p;
67
66
68
	INTOFF;
67
	if ((p = malloc(nbytes)) == NULL)
69
	p = malloc(nbytes);
70
	INTON;
71
	if (p == NULL)
72
		error("Out of space");
68
		error("Out of space");
73
	return p;
69
	return p;
74
}
70
}
Lines 79-87 Link Here
79
 */
75
 */
80
76
81
pointer
77
pointer
82
ckrealloc(p, nbytes)
78
ckrealloc(pointer p, size_t nbytes)
83
	pointer p;
84
	int nbytes;
85
{
79
{
86
80
87
	if ((p = realloc(p, nbytes)) == NULL)
81
	if ((p = realloc(p, nbytes)) == NULL)
Lines 96-107 Link Here
96
90
97
char *
91
char *
98
savestr(s)
92
savestr(s)
99
	char *s;
93
	const char *s;
100
	{
94
	{
101
	char *p;
95
	char *p = strdup(s);
102
96
	if (!p)
103
	p = ckmalloc(strlen(s) + 1);
97
		error("Out of space");
104
	scopy(s, p);
105
	return p;
98
	return p;
106
}
99
}
107
100
Lines 115-121 Link Here
115
 * well.
108
 * well.
116
 */
109
 */
117
110
118
#define MINSIZE 504		/* minimum size of a block */
111
#define MINSIZE ALIGN(504)		/* minimum size of a block */
119
112
120
113
121
struct stack_block {
114
struct stack_block {
Lines 127-163 Link Here
127
struct stack_block *stackp = &stackbase;
120
struct stack_block *stackp = &stackbase;
128
struct stackmark *markp;
121
struct stackmark *markp;
129
char *stacknxt = stackbase.space;
122
char *stacknxt = stackbase.space;
130
int stacknleft = MINSIZE;
123
size_t stacknleft = MINSIZE;
131
int sstrnleft;
124
char *sstrend = stackbase.space + MINSIZE;
132
int herefd = -1;
125
int herefd = -1;
133
126
134
127
135
128
136
pointer
129
pointer
137
stalloc(nbytes)
130
stalloc(size_t nbytes)
138
	int nbytes;
139
{
131
{
140
	char *p;
132
	char *p;
133
	size_t aligned;
141
134
142
	nbytes = ALIGN(nbytes);
135
	aligned = ALIGN(nbytes);
143
	if (nbytes > stacknleft) {
136
	if (nbytes > stacknleft) {
144
		int blocksize;
137
		size_t len;
138
		size_t blocksize;
145
		struct stack_block *sp;
139
		struct stack_block *sp;
146
140
147
		blocksize = nbytes;
141
		blocksize = aligned;
148
		if (blocksize < MINSIZE)
142
		if (blocksize < MINSIZE)
149
			blocksize = MINSIZE;
143
			blocksize = MINSIZE;
144
		len = sizeof(struct stack_block) - MINSIZE + blocksize;
145
		if (len < blocksize)
146
			error("Out of space");
150
		INTOFF;
147
		INTOFF;
151
		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
148
		sp = ckmalloc(len);
152
		sp->prev = stackp;
149
		sp->prev = stackp;
153
		stacknxt = sp->space;
150
		stacknxt = sp->space;
154
		stacknleft = blocksize;
151
		stacknleft = blocksize;
152
		sstrend = stacknxt + blocksize;
155
		stackp = sp;
153
		stackp = sp;
156
		INTON;
154
		INTON;
157
	}
155
	}
158
	p = stacknxt;
156
	p = stacknxt;
159
	stacknxt += nbytes;
157
	stacknxt += aligned;
160
	stacknleft -= nbytes;
158
	stacknleft -= aligned;
161
	return p;
159
	return p;
162
}
160
}
163
161
Lines 166-175 Link Here
166
stunalloc(p)
164
stunalloc(p)
167
	pointer p;
165
	pointer p;
168
	{
166
	{
169
	if (p == NULL) {		/*DEBUG */
167
#ifdef DEBUG
168
	if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
170
		write(2, "stunalloc\n", 10);
169
		write(2, "stunalloc\n", 10);
171
		abort();
170
		abort();
172
	}
171
	}
172
#endif
173
	stacknleft += stacknxt - (char *)p;
173
	stacknleft += stacknxt - (char *)p;
174
	stacknxt = p;
174
	stacknxt = p;
175
}
175
}
Lines 203-208 Link Here
203
	}
203
	}
204
	stacknxt = mark->stacknxt;
204
	stacknxt = mark->stacknxt;
205
	stacknleft = mark->stacknleft;
205
	stacknleft = mark->stacknleft;
206
	sstrend = mark->stacknxt + mark->stacknleft;
206
	INTON;
207
	INTON;
207
}
208
}
208
209
Lines 220-241 Link Here
220
void
221
void
221
growstackblock() {
222
growstackblock() {
222
	char *p;
223
	char *p;
223
	int newlen = ALIGN(stacknleft * 2 + 100);
224
	size_t newlen, grosslen;
224
	char *oldspace = stacknxt;
225
	char *oldspace = stacknxt;
225
	int oldlen = stacknleft;
226
	size_t oldlen = stacknleft;
226
	struct stack_block *sp;
227
	struct stack_block *sp;
227
	struct stack_block *oldstackp;
228
	struct stack_block *oldstackp;
229
	struct stack_block *prevstackp;
230
231
 	grosslen = stacknleft * 2;
232
	if (grosslen < stacknleft)
233
		error("Out of space");
234
	if (grosslen < 128)
235
		grosslen += 128 + sizeof(struct stack_block) - MINSIZE;
236
	newlen = grosslen - (sizeof(struct stack_block) - MINSIZE);
228
237
229
	if (stacknxt == stackp->space && stackp != &stackbase) {
238
	if (stacknxt == stackp->space && stackp != &stackbase) {
230
		INTOFF;
239
		INTOFF;
231
		oldstackp = stackp;
240
		oldstackp = stackp;
232
		sp = stackp;
241
		sp = stackp;
233
		stackp = sp->prev;
242
		prevstackp = sp->prev;
234
		sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
243
		sp = ckrealloc((pointer)sp, grosslen);
235
		sp->prev = stackp;
244
		sp->prev = prevstackp;
236
		stackp = sp;
245
		stackp = sp;
237
		stacknxt = sp->space;
246
		stacknxt = sp->space;
238
		stacknleft = newlen;
247
		stacknleft = newlen;
248
		sstrend = sp->space + newlen;
239
		{
249
		{
240
		  /* Stack marks pointing to the start of the old block
250
		  /* Stack marks pointing to the start of the old block
241
		   * must be relocated to point to the new block 
251
		   * must be relocated to point to the new block 
Lines 252-268 Link Here
252
		INTON;
262
		INTON;
253
	} else {
263
	} else {
254
		p = stalloc(newlen);
264
		p = stalloc(newlen);
255
		memcpy(p, oldspace, oldlen);
265
		/* free the space we just allocated */
256
		stacknxt = p;			/* free the space */
266
		stacknxt = memcpy(p, oldspace, oldlen);
257
		stacknleft += newlen;		/* we just allocated */
267
		stacknleft += newlen;
258
	}
268
	}
259
}
269
}
260
270
261
271
262
272
263
void
273
void
264
grabstackblock(len)
274
grabstackblock(size_t len)
265
	int len;
266
{
275
{
267
	len = ALIGN(len);
276
	len = ALIGN(len);
268
	stacknxt += len;
277
	stacknxt += len;
Lines 290-305 Link Here
290
 */
299
 */
291
300
292
301
293
char *
302
void *
294
growstackstr() {
303
growstackstr() {
295
	int len = stackblocksize();
304
	size_t len = stackblocksize();
296
	if (herefd >= 0 && len >= 1024) {
305
	if (herefd >= 0 && len >= 1024) {
297
		xwrite(herefd, stackblock(), len);
306
		xwrite(herefd, stackblock(), len);
298
		sstrnleft = len - 1;
299
		return stackblock();
307
		return stackblock();
300
	}
308
	}
301
	growstackblock();
309
	growstackblock();
302
	sstrnleft = stackblocksize() - len - 1;
303
	return stackblock() + len;
310
	return stackblock() + len;
304
}
311
}
305
312
Lines 309-329 Link Here
309
 */
316
 */
310
317
311
char *
318
char *
312
makestrspace() {
319
makestrspace(size_t newlen, char *p) {
313
	int len = stackblocksize() - sstrnleft;
320
	size_t len = p - stackblock();
321
	size_t size = stackblocksize();
322
323
	for (;;) {
324
		size_t nleft;
325
326
		size = stackblocksize();
327
		nleft = size - len;
328
		if (nleft >= newlen)
329
			break;
314
	growstackblock();
330
	growstackblock();
315
	sstrnleft = stackblocksize() - len;
331
	}
316
	return stackblock() + len;
332
	return stackblock() + len;
317
}
333
}
318
334
319
335
320
336
321
void
337
char *
322
ungrabstackstr(s, p)
338
stnputs(const char *s, size_t n, char *p) {
323
	char *s;
339
	p = makestrspace(n, p);
324
	char *p;
340
	p = mempcpy(p, s, n);
325
	{
341
	return p;
326
	stacknleft += stacknxt - s;
342
}
327
	stacknxt = s;
343
328
	sstrnleft = stacknleft - (p - s);
344
345
char *
346
stputs(const char *s, char *p) {
347
	return stnputs(s, strlen(s), p);
329
}
348
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/memalloc.h (-19 / +37 lines)
Lines 38-81 Link Here
38
 *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
38
 *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
39
 */
39
 */
40
40
41
#include <stddef.h>
42
41
struct stackmark {
43
struct stackmark {
42
	struct stack_block *stackp;
44
	struct stack_block *stackp;
43
	char *stacknxt;
45
	char *stacknxt;
44
	int stacknleft;
46
	size_t stacknleft;
45
	struct stackmark *marknext;
47
	struct stackmark *marknext;
46
};
48
};
47
49
48
50
49
extern char *stacknxt;
51
extern char *stacknxt;
50
extern int stacknleft;
52
extern size_t stacknleft;
51
extern int sstrnleft;
53
extern char *sstrend;
52
extern int herefd;
54
extern int herefd;
53
55
54
pointer ckmalloc __P((int));
56
pointer ckmalloc __P((size_t));
55
pointer ckrealloc __P((pointer, int));
57
pointer ckrealloc __P((pointer, size_t));
56
char *savestr __P((char *));
58
char *savestr __P((const char *));
57
pointer stalloc __P((int));
59
pointer stalloc __P((size_t));
58
void stunalloc __P((pointer));
60
void stunalloc __P((pointer));
59
void setstackmark __P((struct stackmark *));
61
void setstackmark __P((struct stackmark *));
60
void popstackmark __P((struct stackmark *));
62
void popstackmark __P((struct stackmark *));
61
void growstackblock __P((void));
63
void growstackblock __P((void));
62
void grabstackblock __P((int));
64
void grabstackblock __P((size_t));
63
char *growstackstr __P((void));
65
void *growstackstr __P((void));
64
char *makestrspace __P((void));
66
char *makestrspace __P((size_t, char *));
65
void ungrabstackstr __P((char *, char *));
67
char *stnputs __P((const char *, size_t, char *));
68
char *stputs __P((const char *, char *));
66
69
67
70
71
static inline char *_STPUTC(char c, char *p) {
72
	if (p == sstrend)
73
		p = growstackstr();
74
	*p++ = c;
75
	return p;
76
}
68
77
69
#define stackblock() stacknxt
78
#define stackblock() stacknxt
70
#define stackblocksize() stacknleft
79
#define stackblocksize() stacknleft
71
#define STARTSTACKSTR(p)	p = stackblock(), sstrnleft = stackblocksize()
80
#define STARTSTACKSTR(p) (p) = ((void *) stackblock())
72
#define STPUTC(c, p)	(--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
81
#define STPUTC(c, p) (p) = _STPUTC(c, p)
73
#define CHECKSTRSPACE(n, p)	{ if (sstrnleft < n) p = makestrspace(); }
82
#define CHECKSTRSPACE(n, p) \
74
#define USTPUTC(c, p)	(--sstrnleft, *p++ = (c))
83
	({ \
75
#define STACKSTRNUL(p)	(sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
84
		char *q = (p); \
76
#define STUNPUTC(p)	(++sstrnleft, --p)
85
		size_t l = (n); \
86
		size_t m = sstrend - q; \
87
		if (l > m) \
88
			(p) = makestrspace(l, q); \
89
		0; \
90
	})
91
#define USTPUTC(c, p)	(*p++ = (c))
92
#define STACKSTRNUL(p)	((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
93
#define STUNPUTC(p)	(--p)
77
#define STTOPC(p)	p[-1]
94
#define STTOPC(p)	p[-1]
78
#define STADJUST(amount, p)	(p += (amount), sstrnleft -= (amount))
95
#define STADJUST(amount, p)	(p += (amount))
79
#define grabstackstr(p)	stalloc(stackblocksize() - sstrnleft)
96
#define grabstackstr(p)	stalloc(((char *) (p)) - stackblock())
97
#define ungrabstackstr(s, p) stunalloc((s))
80
98
81
#define ckfree(p)	free((pointer)(p))
99
#define ckfree(p)	free((pointer)(p))
(-)bin_NetBSD-1.6release.orig/src/bin/sh/miscbltin.c (-12 / +18 lines)
Lines 70-75 Link Here
70
70
71
#undef rflag
71
#undef rflag
72
72
73
#ifdef __GLIBC__
74
mode_t getmode(const void *, mode_t);
75
void *setmode(const char *);
76
77
#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
78
typedef enum __rlimit_resource rlim_t;
79
#endif
80
#endif
81
73
82
74
83
75
/*
84
/*
Lines 89-95 Link Here
89
	char c;
98
	char c;
90
	int rflag;
99
	int rflag;
91
	char *prompt;
100
	char *prompt;
92
	char *ifs;
101
	const char *ifs;
93
	char *p;
102
	char *p;
94
	int startword;
103
	int startword;
95
	int status;
104
	int status;
Lines 105-116 Link Here
105
	}
114
	}
106
	if (prompt && isatty(0)) {
115
	if (prompt && isatty(0)) {
107
		out2str(prompt);
116
		out2str(prompt);
117
#ifdef FLUSHERR
108
		flushall();
118
		flushall();
119
#endif
109
	}
120
	}
110
	if (*(ap = argptr) == NULL)
121
	if (*(ap = argptr) == NULL)
111
		error("arg count");
122
		error("arg count");
112
	if ((ifs = bltinlookup("IFS", 1)) == NULL)
123
	if ((ifs = bltinlookup("IFS")) == NULL)
113
		ifs = nullstr;
124
		ifs = defifs;
114
	status = 0;
125
	status = 0;
115
	startword = 1;
126
	startword = 1;
116
	backslash = 0;
127
	backslash = 0;
Lines 125-131 Link Here
125
		if (backslash) {
136
		if (backslash) {
126
			backslash = 0;
137
			backslash = 0;
127
			if (c != '\n')
138
			if (c != '\n')
128
				STPUTC(c, p);
139
				goto put;
129
			continue;
140
			continue;
130
		}
141
		}
131
		if (!rflag && c == '\\') {
142
		if (!rflag && c == '\\') {
Lines 138-156 Link Here
138
			continue;
149
			continue;
139
		}
150
		}
140
		startword = 0;
151
		startword = 0;
141
		if (backslash && c == '\\') {
152
		if (ap[1] != NULL && strchr(ifs, c) != NULL) {
142
			if (read(0, &c, 1) != 1) {
143
				status = 1;
144
				break;
145
			}
146
			STPUTC(c, p);
147
		} else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
148
			STACKSTRNUL(p);
153
			STACKSTRNUL(p);
149
			setvar(*ap, stackblock(), 0);
154
			setvar(*ap, stackblock(), 0);
150
			ap++;
155
			ap++;
151
			startword = 1;
156
			startword = 1;
152
			STARTSTACKSTR(p);
157
			STARTSTACKSTR(p);
153
		} else {
158
		} else {
159
put:
154
			STPUTC(c, p);
160
			STPUTC(c, p);
155
		}
161
		}
156
	}
162
	}
Lines 225-231 Link Here
225
			mask = 0;
231
			mask = 0;
226
			do {
232
			do {
227
				if (*ap >= '8' || *ap < '0')
233
				if (*ap >= '8' || *ap < '0')
228
					error("Illegal number: %s", argv[1]);
234
					error(illnum, argv[1]);
229
				mask = (mask << 3) + (*ap - '0');
235
				mask = (mask << 3) + (*ap - '0');
230
			} while (*++ap != '\0');
236
			} while (*++ap != '\0');
231
			umask(mask);
237
			umask(mask);
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mkbuiltins (-24 / +33 lines)
Lines 37-57 Link Here
37
#
37
#
38
#	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
38
#	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
39
39
40
temp=/tmp/ka$$
40
trap 'rm -f $temp $temp2' EXIT
41
temp=$(tempfile)
42
temp2=$(tempfile)
43
44
shell=$1
45
builtins=$2
46
specialbltins=$3
47
regularbltins=$4
48
assignbltins=$5
49
objdir=$6
41
50
42
havehist=1
51
havehist=1
43
if [ "X$1" = "X-h" ]; then
52
if [ -z "${7##*-DSMALL*}" ]; then
44
	havehist=0
53
	havehist=0
45
	shift
46
fi
54
fi
47
shell=$1
48
builtins=$2
49
objdir=$3
50
55
51
havejobs=0
56
havejobs=1
52
if grep '^#define JOBS[	 ]*1' ${shell} > /dev/null
57
if [ -z "${7##*-DJOBS=0*}" ]; then
53
then
58
	havejobs=0
54
	havejobs=1
55
fi
59
fi
56
60
57
exec > ${objdir}/builtins.c
61
exec > ${objdir}/builtins.c
Lines 65-83 Link Here
65
69
66
!
70
!
67
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
71
awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \
68
    print $0}' ${builtins} | sed 's/-j//' > $temp
72
    print $0}' ${builtins} | sed 's/-[hj]//' > $temp
69
awk '{	printf "int %s __P((int, char **));\n", $1}' $temp
73
awk '{	printf "int %s __P((int, char **));\n", $1}' $temp
70
echo '
74
echo '
71
int (*const builtinfunc[]) __P((int, char **)) = {'
72
awk '/^[^#]/ {	printf "\t%s,\n", $1}' $temp
73
echo '};
74
75
const struct builtincmd builtincmd[] = {'
75
const struct builtincmd builtincmd[] = {'
76
awk '{	for (i = 2 ; i <= NF ; i++) {
76
awk '{	for (i = 2 ; i <= NF ; i++) {
77
		printf "\t{ \"%s\", %d },\n",  $i, NR-1
77
		print $i "\t" $1
78
	}}' $temp
78
	}}' $temp | sort -k 1,1 | tee $temp2 |
79
echo '	{ NULL, 0 }
79
	join -a 1 -e 0 -o 1.1,1.2,2.1 - $specialbltins |
80
};'
80
	join -a 1 -e 0 -o 1.1,1.2,1.3,2.1 - $regularbltins |
81
	join -a 1 -e 0 -o 1.1,1.2,1.3,1.4,2.1 - $assignbltins |
82
	awk '{  printf "\t{ \"%s\", %s, %d },\n", $1, $2,
83
		!!$3 + (!!$4 * 2) + (!!$5 * 4)}'
84
echo '};'
81
85
82
exec > ${objdir}/builtins.h
86
exec > ${objdir}/builtins.h
83
cat <<\!
87
cat <<\!
Lines 87-100 Link Here
87
91
88
#include <sys/cdefs.h>
92
#include <sys/cdefs.h>
89
!
93
!
90
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
94
nl -v 0 $temp2 | sort -u -k 3,3 |
91
	awk '{	printf "#define %s %d\n", $1, NR-1}'
95
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ |
96
	awk '{	printf "#define %s (builtincmd + %d)\n", $3, $1}'
97
printf '\n#define NUMBUILTINS %d\n' $(wc -l < $temp2)
92
echo '
98
echo '
99
#define BUILTIN_SPECIAL 0x1
100
#define BUILTIN_REGULAR 0x2
101
#define BUILTIN_ASSIGN 0x4
102
93
struct builtincmd {
103
struct builtincmd {
94
      const char *name;
104
      const char *name;
95
      int code;
105
	int (*const builtinfunc) __P((int, char **));
106
	unsigned flags;
96
};
107
};
97
108
98
extern int (*const builtinfunc[]) __P((int, char **));
99
extern const struct builtincmd builtincmd[];'
109
extern const struct builtincmd builtincmd[];'
100
rm -f $temp
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mkinit.c (-8 lines)
Lines 131-146 Link Here
131
 * interactive shell and control is returned to the main command loop.\n\
131
 * interactive shell and control is returned to the main command loop.\n\
132
 */\n";
132
 */\n";
133
133
134
char shellproc[] = "\
135
/*\n\
136
 * This routine is called to initialize the shell to run a shell procedure.\n\
137
 */\n";
138
139
134
140
struct event event[] = {
135
struct event event[] = {
141
	{"INIT", "init", init},
136
	{"INIT", "init", init},
142
	{"RESET", "reset", reset},
137
	{"RESET", "reset", reset},
143
	{"SHELLPROC", "initshellproc", shellproc},
144
	{NULL, NULL}
138
	{NULL, NULL}
145
};
139
};
146
140
Lines 218-225 Link Here
218
			doinclude(line);
212
			doinclude(line);
219
		if (line[0] == 'M' && match("MKINIT", line))
213
		if (line[0] == 'M' && match("MKINIT", line))
220
			dodecl(line, fp);
214
			dodecl(line, fp);
221
		if (line[0] == '#' && gooddefine(line))
222
			addstr(line, &defines);
223
		if (line[0] == '#' && gooddefine(line)) {
215
		if (line[0] == '#' && gooddefine(line)) {
224
		        char *cp;
216
		        char *cp;
225
			char line2[1024];
217
			char line2[1024];
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mknodes.c (-25 / +9 lines)
Lines 1-4 Link Here
1
/*	$NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $	*/
1
/*	$NetBSD: mknodes.c,v 1.19 2002/05/25 23:09:06 wiz Exp $	*/
2
2
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
Lines 47-53 Link Here
47
static char sccsid[] = "@(#)mknodes.c	8.2 (Berkeley) 5/4/95";
47
static char sccsid[] = "@(#)mknodes.c	8.2 (Berkeley) 5/4/95";
48
#else
48
#else
49
static const char rcsid[] =
49
static const char rcsid[] =
50
    "$NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $";
50
    "$NetBSD: mknodes.c,v 1.19 2002/05/25 23:09:06 wiz Exp $";
51
#endif
51
#endif
52
#endif /* not lint */
52
#endif /* not lint */
53
53
Lines 59-70 Link Here
59
#include <stdio.h>
59
#include <stdio.h>
60
#include <stdlib.h>
60
#include <stdlib.h>
61
#include <string.h>
61
#include <string.h>
62
#ifdef __STDC__
63
#include <stdarg.h>
62
#include <stdarg.h>
64
#else
65
#include <varargs.h>
66
#endif
67
68
63
69
#define MAXTYPES 50		/* max number of node types */
64
#define MAXTYPES 50		/* max number of node types */
70
#define MAXFIELDS 20		/* max fields in a structure */
65
#define MAXFIELDS 20		/* max fields in a structure */
Lines 270-282 Link Here
270
	fputs("\tstruct nodelist *next;\n", hfile);
265
	fputs("\tstruct nodelist *next;\n", hfile);
271
	fputs("\tunion node *n;\n", hfile);
266
	fputs("\tunion node *n;\n", hfile);
272
	fputs("};\n\n\n", hfile);
267
	fputs("};\n\n\n", hfile);
273
	fputs("#ifdef __STDC__\n", hfile);
268
	fputs("struct funcnode {\n", hfile);
274
	fputs("union node *copyfunc(union node *);\n", hfile);
269
	fputs("\tint count;\n", hfile);
275
	fputs("void freefunc(union node *);\n", hfile);
270
	fputs("\tunion node n;\n", hfile);
276
	fputs("#else\n", hfile);
271
	fputs("};\n\n\n", hfile);
277
	fputs("union node *copyfunc();\n", hfile);
272
	fputs("struct funcnode *copyfunc(union node *);\n", hfile);
278
	fputs("void freefunc();\n", hfile);
273
	fputs("void freefunc(struct funcnode *);\n", hfile);
279
	fputs("#endif\n", hfile);
280
274
281
	fputs(writer, cfile);
275
	fputs(writer, cfile);
282
	while (fgets(line, sizeof line, patfile) != NULL) {
276
	while (fgets(line, sizeof line, patfile) != NULL) {
Lines 451-471 Link Here
451
445
452
446
453
static void
447
static void
454
#ifdef __STDC__
455
error(const char *msg, ...)
448
error(const char *msg, ...)
456
#else
457
error(va_alist)
458
	va_dcl
459
#endif
460
{
449
{
461
	va_list va;
450
	va_list va;
462
#ifdef __STDC__
451
463
	va_start(va, msg);
452
	va_start(va, msg);
464
#else
465
	char *msg;
466
	va_start(va);
467
	msg = va_arg(va, char *);
468
#endif
469
453
470
	(void) fprintf(stderr, "line %d: ", linno);
454
	(void) fprintf(stderr, "line %d: ", linno);
471
	(void) vfprintf(stderr, msg, va);
455
	(void) vfprintf(stderr, msg, va);
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mksignames.c (+419 lines)
Line 0 Link Here
1
/* signames.c -- Create and write `signames.c', which contains an array of
2
   signal names. */
3
4
/* Copyright (C) 1992 Free Software Foundation, Inc.
5
6
   This file is part of GNU Bash, the Bourne Again SHell.
7
8
   Bash is free software; you can redistribute it and/or modify it under
9
   the terms of the GNU General Public License as published by the Free
10
   Software Foundation; either version 2, or (at your option) any later
11
   version.
12
13
   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
   for more details.
17
18
   You should have received a copy of the GNU General Public License along
19
   with Bash; see the file COPYING.  If not, write to the Free Software
20
   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21
22
#include <stdio.h>
23
#include <sys/types.h>
24
#include <signal.h>
25
#include <stdlib.h>
26
27
#if !defined (NSIG)
28
#  define NSIG 64
29
#endif
30
31
/*
32
 * Special traps:
33
 *	EXIT == 0
34
 */
35
#define LASTSIG NSIG-1
36
37
char *signal_names[2 * NSIG + 3];
38
39
#define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0]))
40
41
char *progname;
42
43
/* AIX 4.3 defines SIGRTMIN and SIGRTMAX as 888 and 999 respectively.
44
   I don't want to allocate so much unused space for the intervening signal
45
   numbers, so we just punt if SIGRTMAX is past the bounds of the
46
   signal_names array (handled in configure). */
47
#if defined (SIGRTMAX) && defined (UNUSABLE_RT_SIGNALS)
48
#  undef SIGRTMAX
49
#  undef SIGRTMIN
50
#endif
51
52
#if defined (SIGRTMAX) || defined (SIGRTMIN)
53
#  define RTLEN 14
54
#  define RTLIM 256
55
#endif
56
57
void
58
initialize_signames ()
59
{
60
  register int i;
61
#if defined (SIGRTMAX) || defined (SIGRTMIN)
62
  int rtmin, rtmax, rtcnt;
63
#endif
64
65
  for (i = 1; i < signal_names_size; i++)
66
    signal_names[i] = (char *)NULL;
67
68
  /* `signal' 0 is what we do on exit. */
69
  signal_names[0] = "EXIT";
70
71
  /* Place signal names which can be aliases for more common signal
72
     names first.  This allows (for example) SIGABRT to overwrite SIGLOST. */
73
74
  /* POSIX 1003.1b-1993 real time signals, but take care of incomplete
75
     implementations. Acoording to the standard, both, SIGRTMIN and
76
     SIGRTMAX must be defined, SIGRTMIN must be stricly less than
77
     SIGRTMAX, and the difference must be at least 7, that is, there
78
     must be at least eight distinct real time signals. */
79
80
  /* The generated signal names are SIGRTMIN, SIGRTMIN+1, ...,
81
     SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number
82
     of RT signals is odd, there is an extra SIGRTMIN+(x+1).
83
     These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */
84
85
#if defined (SIGRTMIN)
86
  rtmin = SIGRTMIN;
87
  signal_names[rtmin] = "RTMIN";
88
#endif
89
90
#if defined (SIGRTMAX)
91
  rtmax = SIGRTMAX;
92
  signal_names[rtmax] = "RTMAX";
93
#endif
94
95
#if defined (SIGRTMAX) && defined (SIGRTMIN)
96
  if (rtmax > rtmin)
97
    {
98
      rtcnt = (rtmax - rtmin - 1) / 2;
99
      /* croak if there are too many RT signals */
100
      if (rtcnt >= RTLIM/2)
101
	{
102
	  rtcnt = RTLIM/2-1;
103
	  fprintf(stderr, "%s: error: more than %i real time signals, fix `%s'\n",
104
		  progname, RTLIM, progname);
105
	}
106
107
      for (i = 1; i <= rtcnt; i++)
108
	{
109
	  signal_names[rtmin+i] = (char *)malloc(RTLEN);
110
	  if (signal_names[rtmin+i])
111
	    sprintf (signal_names[rtmin+i], "RTMIN+%d", i);
112
	  signal_names[rtmax-i] = (char *)malloc(RTLEN);
113
	  if (signal_names[rtmax-i])
114
	    sprintf (signal_names[rtmax-i], "RTMAX-%d", i);
115
	}
116
117
      if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
118
	{
119
	  /* Need an extra RTMIN signal */
120
	  signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
121
	  if (signal_names[rtmin+rtcnt+1])
122
	    sprintf (signal_names[rtmin+rtcnt+1], "RTMIN+%d", rtcnt+1);
123
	}
124
    }
125
#endif /* SIGRTMIN && SIGRTMAX */
126
127
/* AIX */
128
#if defined (SIGLOST)	/* resource lost (eg, record-lock lost) */
129
  signal_names[SIGLOST] = "LOST";
130
#endif
131
132
#if defined (SIGMSG)	/* HFT input data pending */
133
  signal_names[SIGMSG] = "MSG";
134
#endif
135
136
#if defined (SIGDANGER)	/* system crash imminent */
137
  signal_names[SIGDANGER] = "DANGER";
138
#endif
139
140
#if defined (SIGMIGRATE) /* migrate process to another CPU */
141
  signal_names[SIGMIGRATE] = "MIGRATE";
142
#endif
143
144
#if defined (SIGPRE)	/* programming error */
145
  signal_names[SIGPRE] = "PRE";
146
#endif
147
148
#if defined (SIGVIRT)	/* AIX virtual time alarm */
149
  signal_names[SIGVIRT] = "VIRT";
150
#endif
151
152
#if defined (SIGALRM1)	/* m:n condition variables */
153
  signal_names[SIGALRM1] = "ALRM1";
154
#endif
155
156
#if defined (SIGWAITING)	/* m:n scheduling */
157
  signal_names[SIGWAITING] = "WAITING";
158
#endif
159
160
#if defined (SIGGRANT)	/* HFT monitor mode granted */
161
  signal_names[SIGGRANT] = "GRANT";
162
#endif
163
164
#if defined (SIGKAP)	/* keep alive poll from native keyboard */
165
  signal_names[SIGKAP] = "KAP";
166
#endif
167
168
#if defined (SIGRETRACT) /* HFT monitor mode retracted */
169
  signal_names[SIGRETRACT] = "RETRACT";
170
#endif
171
172
#if defined (SIGSOUND)	/* HFT sound sequence has completed */
173
  signal_names[SIGSOUND] = "SOUND";
174
#endif
175
176
#if defined (SIGSAK)	/* Secure Attention Key */
177
  signal_names[SIGSAK] = "SAK";
178
#endif
179
180
/* SunOS5 */
181
#if defined (SIGLWP)	/* special signal used by thread library */
182
  signal_names[SIGLWP] = "LWP";
183
#endif
184
185
#if defined (SIGFREEZE)	/* special signal used by CPR */
186
  signal_names[SIGFREEZE] = "FREEZE";
187
#endif
188
189
#if defined (SIGTHAW)	/* special signal used by CPR */
190
  signal_names[SIGTHAW] = "THAW";
191
#endif
192
193
#if defined (SIGCANCEL)	/* thread cancellation signal used by libthread */
194
  signal_names[SIGCANCEL] = "CANCEL";
195
#endif
196
197
/* HP-UX */
198
#if defined (SIGDIL)	/* DIL signal (?) */
199
  signal_names[SIGDIL] = "DIL";
200
#endif
201
202
/* System V */
203
#if defined (SIGCLD)	/* Like SIGCHLD.  */
204
  signal_names[SIGCLD] = "CLD";
205
#endif
206
207
#if defined (SIGPWR)	/* power state indication */
208
  signal_names[SIGPWR] = "PWR";
209
#endif
210
211
#if defined (SIGPOLL)	/* Pollable event (for streams)  */
212
  signal_names[SIGPOLL] = "POLL";
213
#endif
214
215
/* Unknown */
216
#if defined (SIGWINDOW)
217
  signal_names[SIGWINDOW] = "WINDOW";
218
#endif
219
220
/* Common */
221
#if defined (SIGHUP)	/* hangup */
222
  signal_names[SIGHUP] = "HUP";
223
#endif
224
225
#if defined (SIGINT)	/* interrupt */
226
  signal_names[SIGINT] = "INT";
227
#endif
228
229
#if defined (SIGQUIT)	/* quit */
230
  signal_names[SIGQUIT] = "QUIT";
231
#endif
232
233
#if defined (SIGILL)	/* illegal instruction (not reset when caught) */
234
  signal_names[SIGILL] = "ILL";
235
#endif
236
237
#if defined (SIGTRAP)	/* trace trap (not reset when caught) */
238
  signal_names[SIGTRAP] = "TRAP";
239
#endif
240
241
#if defined (SIGIOT)	/* IOT instruction */
242
  signal_names[SIGIOT] = "IOT";
243
#endif
244
245
#if defined (SIGABRT)	/* Cause current process to dump core. */
246
  signal_names[SIGABRT] = "ABRT";
247
#endif
248
249
#if defined (SIGEMT)	/* EMT instruction */
250
  signal_names[SIGEMT] = "EMT";
251
#endif
252
253
#if defined (SIGFPE)	/* floating point exception */
254
  signal_names[SIGFPE] = "FPE";
255
#endif
256
257
#if defined (SIGKILL)	/* kill (cannot be caught or ignored) */
258
  signal_names[SIGKILL] = "KILL";
259
#endif
260
261
#if defined (SIGBUS)	/* bus error */
262
  signal_names[SIGBUS] = "BUS";
263
#endif
264
265
#if defined (SIGSEGV)	/* segmentation violation */
266
  signal_names[SIGSEGV] = "SEGV";
267
#endif
268
269
#if defined (SIGSYS)	/* bad argument to system call */
270
  signal_names[SIGSYS] = "SYS";
271
#endif
272
273
#if defined (SIGPIPE)	/* write on a pipe with no one to read it */
274
  signal_names[SIGPIPE] = "PIPE";
275
#endif
276
277
#if defined (SIGALRM)	/* alarm clock */
278
  signal_names[SIGALRM] = "ALRM";
279
#endif
280
281
#if defined (SIGTERM)	/* software termination signal from kill */
282
  signal_names[SIGTERM] = "TERM";
283
#endif
284
285
#if defined (SIGURG)	/* urgent condition on IO channel */
286
  signal_names[SIGURG] = "URG";
287
#endif
288
289
#if defined (SIGSTOP)	/* sendable stop signal not from tty */
290
  signal_names[SIGSTOP] = "STOP";
291
#endif
292
293
#if defined (SIGTSTP)	/* stop signal from tty */
294
  signal_names[SIGTSTP] = "TSTP";
295
#endif
296
297
#if defined (SIGCONT)	/* continue a stopped process */
298
  signal_names[SIGCONT] = "CONT";
299
#endif
300
301
#if defined (SIGCHLD)	/* to parent on child stop or exit */
302
  signal_names[SIGCHLD] = "CHLD";
303
#endif
304
305
#if defined (SIGTTIN)	/* to readers pgrp upon background tty read */
306
  signal_names[SIGTTIN] = "TTIN";
307
#endif
308
309
#if defined (SIGTTOU)	/* like TTIN for output if (tp->t_local&LTOSTOP) */
310
  signal_names[SIGTTOU] = "TTOU";
311
#endif
312
313
#if defined (SIGIO)	/* input/output possible signal */
314
  signal_names[SIGIO] = "IO";
315
#endif
316
317
#if defined (SIGXCPU)	/* exceeded CPU time limit */
318
  signal_names[SIGXCPU] = "XCPU";
319
#endif
320
321
#if defined (SIGXFSZ)	/* exceeded file size limit */
322
  signal_names[SIGXFSZ] = "XFSZ";
323
#endif
324
325
#if defined (SIGVTALRM)	/* virtual time alarm */
326
  signal_names[SIGVTALRM] = "VTALRM";
327
#endif
328
329
#if defined (SIGPROF)	/* profiling time alarm */
330
  signal_names[SIGPROF] = "PROF";
331
#endif
332
333
#if defined (SIGWINCH)	/* window changed */
334
  signal_names[SIGWINCH] = "WINCH";
335
#endif
336
337
/* 4.4 BSD */
338
#if defined (SIGINFO) && !defined (_SEQUENT_)	/* information request */
339
  signal_names[SIGINFO] = "INFO";
340
#endif
341
342
#if defined (SIGUSR1)	/* user defined signal 1 */
343
  signal_names[SIGUSR1] = "USR1";
344
#endif
345
346
#if defined (SIGUSR2)	/* user defined signal 2 */
347
  signal_names[SIGUSR2] = "USR2";
348
#endif
349
350
#if defined (SIGKILLTHR)	/* BeOS: Kill Thread */
351
  signal_names[SIGKILLTHR] = "KILLTHR";
352
#endif
353
354
  for (i = 0; i < NSIG; i++)
355
    if (signal_names[i] == (char *)NULL)
356
      {
357
	signal_names[i] = (char *)malloc (18);
358
	if (signal_names[i])
359
	  sprintf (signal_names[i], "%d", i);
360
      }
361
}
362
363
void
364
write_signames (stream)
365
     FILE *stream;
366
{
367
  register int i;
368
369
  fprintf (stream, "/* This file was automatically created by %s.\n",
370
	   progname);
371
  fprintf (stream, "   Do not edit.  Edit support/mksignames.c instead. */\n\n");
372
  fprintf (stream, "#include <signal.h>\n\n");
373
  fprintf (stream,
374
	   "/* A translation list so we can be polite to our users. */\n");
375
  fprintf (stream, "const char *const signal_names[NSIG + 1] = {\n");
376
377
  for (i = 0; i <= LASTSIG; i++)
378
    fprintf (stream, "    \"%s\",\n", signal_names[i]);
379
380
  fprintf (stream, "    (char *)0x0\n");
381
  fprintf (stream, "};\n");
382
}
383
384
int
385
main (argc, argv)
386
     int argc;
387
     char **argv;
388
{
389
  char *stream_name;
390
  FILE *stream;
391
392
  progname = argv[0];
393
394
  if (argc == 1)
395
    {
396
      stream_name = "signames.c";
397
    }
398
  else if (argc == 2)
399
    {
400
      stream_name = argv[1];
401
    }
402
  else
403
    {
404
      fprintf (stderr, "Usage: %s [output-file]\n", progname);
405
      exit (1);
406
    }
407
408
  stream = fopen (stream_name, "w");
409
  if (!stream)
410
    {
411
      fprintf (stderr, "%s: %s: cannot open for writing\n",
412
	       progname, stream_name);
413
      exit (2);
414
    }
415
416
  initialize_signames ();
417
  write_signames (stream);
418
  exit (0);
419
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mksyntax.c (-16 / +20 lines)
Lines 1-4 Link Here
1
/*	$NetBSD: mksyntax.c,v 1.24.4.1 2002/05/31 16:42:05 tv Exp $	*/
1
/*	$NetBSD: mksyntax.c,v 1.25 2002/05/31 16:18:48 christos Exp $	*/
2
2
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
Lines 47-53 Link Here
47
static char sccsid[] = "@(#)mksyntax.c	8.2 (Berkeley) 5/4/95";
47
static char sccsid[] = "@(#)mksyntax.c	8.2 (Berkeley) 5/4/95";
48
#else
48
#else
49
static const char rcsid[] =
49
static const char rcsid[] =
50
    "$NetBSD: mksyntax.c,v 1.24.4.1 2002/05/31 16:42:05 tv Exp $";
50
    "$NetBSD: mksyntax.c,v 1.25 2002/05/31 16:18:48 christos Exp $";
51
#endif
51
#endif
52
#endif /* not lint */
52
#endif /* not lint */
53
53
Lines 73-78 Link Here
73
	{ "CBACK",	"a backslash character" },
73
	{ "CBACK",	"a backslash character" },
74
	{ "CSQUOTE",	"single quote" },
74
	{ "CSQUOTE",	"single quote" },
75
	{ "CDQUOTE",	"double quote" },
75
	{ "CDQUOTE",	"double quote" },
76
	{ "CENDQUOTE",	"a terminating quote" },
76
	{ "CBQUOTE",	"backwards single quote" },
77
	{ "CBQUOTE",	"backwards single quote" },
77
	{ "CVAR",	"a dollar sign" },
78
	{ "CVAR",	"a dollar sign" },
78
	{ "CENDVAR",	"a '}' character" },
79
	{ "CENDVAR",	"a '}' character" },
Lines 81-86 Link Here
81
	{ "CEOF",	"end of file" },
82
	{ "CEOF",	"end of file" },
82
	{ "CCTL",	"like CWORD, except it must be escaped" },
83
	{ "CCTL",	"like CWORD, except it must be escaped" },
83
	{ "CSPCL",	"these terminate a word" },
84
	{ "CSPCL",	"these terminate a word" },
85
	{ "CIGN",	"character should be ignored" },
84
	{ NULL,		NULL }
86
	{ NULL,		NULL }
85
};
87
};
86
88
Lines 168-174 Link Here
168
		exit(2);
170
		exit(2);
169
	}
171
	}
170
	size = (1 << nbits) + 1;
172
	size = (1 << nbits) + 1;
171
	base = 1;
173
	base = 2;
172
	if (sign)
174
	if (sign)
173
		base += 1 << (nbits - 1);
175
		base += 1 << (nbits - 1);
174
	digit_contig = 1;
176
	digit_contig = 1;
Lines 179-184 Link Here
179
181
180
	fputs("#include <sys/cdefs.h>\n", hfile);
182
	fputs("#include <sys/cdefs.h>\n", hfile);
181
	fputs("#include <ctype.h>\n", hfile);
183
	fputs("#include <ctype.h>\n", hfile);
184
	fputs("\n", hfile);
185
	fputs("#ifdef CEOF\n", hfile);
186
	fputs("#undef CEOF\n", hfile);
187
	fputs("#endif\n", hfile);
188
	fputs("\n", hfile);
182
189
183
	/* Generate the #define statements in the header file */
190
	/* Generate the #define statements in the header file */
184
	fputs("/* Syntax classes */\n", hfile);
191
	fputs("/* Syntax classes */\n", hfile);
Lines 201-210 Link Here
201
	putc('\n', hfile);
208
	putc('\n', hfile);
202
	fprintf(hfile, "#define SYNBASE %d\n", base);
209
	fprintf(hfile, "#define SYNBASE %d\n", base);
203
	fprintf(hfile, "#define PEOF %d\n\n", -base);
210
	fprintf(hfile, "#define PEOF %d\n\n", -base);
204
	if (sign)
211
	fprintf(hfile, "#define PEOA %d\n\n", -base + 1);
205
		fprintf(hfile, "#define UPEOF ((char)%d)\n\n", -base);
206
	else
207
		fprintf(hfile, "#define UPEOF ((unsigned char)%d)\n\n", -base);
208
	putc('\n', hfile);
212
	putc('\n', hfile);
209
	fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
213
	fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
210
	fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
214
	fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
Lines 227-258 Link Here
227
	add("$", "CVAR");
231
	add("$", "CVAR");
228
	add("}", "CENDVAR");
232
	add("}", "CENDVAR");
229
	add("<>();&| \t", "CSPCL");
233
	add("<>();&| \t", "CSPCL");
234
	syntax[1] = "CSPCL";
230
	print("basesyntax");
235
	print("basesyntax");
231
	init();
236
	init();
232
	fputs("\n/* syntax table used when in double quotes */\n", cfile);
237
	fputs("\n/* syntax table used when in double quotes */\n", cfile);
233
	add("\n", "CNL");
238
	add("\n", "CNL");
234
	add("\\", "CBACK");
239
	add("\\", "CBACK");
235
	add("\"", "CDQUOTE");
240
	add("\"", "CENDQUOTE");
236
	add("`", "CBQUOTE");
241
	add("`", "CBQUOTE");
237
	add("$", "CVAR");
242
	add("$", "CVAR");
238
	add("}", "CENDVAR");
243
	add("}", "CENDVAR");
239
	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
244
	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
240
	add("!*?[=~:/-", "CCTL");
245
	add("!*?[=~:/-]", "CCTL");
241
	print("dqsyntax");
246
	print("dqsyntax");
242
	init();
247
	init();
243
	fputs("\n/* syntax table used when in single quotes */\n", cfile);
248
	fputs("\n/* syntax table used when in single quotes */\n", cfile);
244
	add("\n", "CNL");
249
	add("\n", "CNL");
245
	add("'", "CSQUOTE");
250
	add("'", "CENDQUOTE");
246
	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
251
	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
247
	add("!*?[=~:/-", "CCTL");
252
	add("!*?[=~:/-]\\", "CCTL");
248
	print("sqsyntax");
253
	print("sqsyntax");
249
	init();
254
	init();
250
	fputs("\n/* syntax table used when in arithmetic */\n", cfile);
255
	fputs("\n/* syntax table used when in arithmetic */\n", cfile);
251
	add("\n", "CNL");
256
	add("\n", "CNL");
252
	add("\\", "CBACK");
257
	add("\\", "CBACK");
253
	add("`", "CBQUOTE");
258
	add("`", "CBQUOTE");
254
	add("'", "CSQUOTE");
255
	add("\"", "CDQUOTE");
256
	add("$", "CVAR");
259
	add("$", "CVAR");
257
	add("}", "CENDVAR");
260
	add("}", "CENDVAR");
258
	add("(", "CLP");
261
	add("(", "CLP");
Lines 298-303 Link Here
298
{
301
{
299
	filltable("CWORD");
302
	filltable("CWORD");
300
	syntax[0] = "CEOF";
303
	syntax[0] = "CEOF";
304
	syntax[1] = "CIGN";
301
#ifdef TARGET_CHAR
305
#ifdef TARGET_CHAR
302
	syntax[base + (TARGET_CHAR)CTLESC] = "CCTL";
306
	syntax[base + (TARGET_CHAR)CTLESC] = "CCTL";
303
	syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL";
307
	syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL";
Lines 374-382 Link Here
374
378
375
static char *macro[] = {
379
static char *macro[] = {
376
	"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
380
	"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
377
	"#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
381
	"#define is_alpha(c)\t(((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
378
	"#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
382
	"#define is_name(c)\t(((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
379
	"#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
383
	"#define is_in_name(c)\t(((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
380
	"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
384
	"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
381
	NULL
385
	NULL
382
};
386
};
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mktokens (-15 / +15 lines)
Lines 55-75 Link Here
55
TENDBQUOTE 1	"`"
55
TENDBQUOTE 1	"`"
56
TREDIR	0	redirection
56
TREDIR	0	redirection
57
TWORD	0	word
57
TWORD	0	word
58
TIF	0	"if"
58
TNOT	0	"!"
59
TTHEN	1	"then"
59
TCASE	0	"case"
60
TELSE	1	"else"
60
TDO	1	"do"
61
TDONE	1	"done"
61
TELIF	1	"elif"
62
TELIF	1	"elif"
63
TELSE	1	"else"
64
TESAC	1	"esac"
62
TFI	1	"fi"
65
TFI	1	"fi"
63
TWHILE	0	"while"
64
TUNTIL	0	"until"
65
TFOR	0	"for"
66
TFOR	0	"for"
66
TDO	1	"do"
67
TIF	0	"if"
67
TDONE	1	"done"
68
TIN	0	"in"
69
TTHEN	1	"then"
70
TUNTIL	0	"until"
71
TWHILE	0	"while"
68
TBEGIN	0	"{"
72
TBEGIN	0	"{"
69
TEND	1	"}"
73
TEND	1	"}"
70
TCASE	0	"case"
71
TESAC	1	"esac"
72
TNOT	0	"!"
73
!
74
!
74
nl=`wc -l /tmp/ka$$`
75
nl=`wc -l /tmp/ka$$`
75
exec > token.h
76
exec > token.h
Lines 87-96 Link Here
87
echo '};
88
echo '};
88
'
89
'
89
sed 's/"//g' /tmp/ka$$ | awk '
90
sed 's/"//g' /tmp/ka$$ | awk '
90
/TIF/{print "#define KWDOFFSET " NR-1; print ""; 
91
/TNOT/{print "#define KWDOFFSET " NR-1; print ""; 
91
      print "const char *const parsekwd[] = {"}
92
      print "STATIC const char *const parsekwd[] = {"}
92
/TIF/,/neverfound/{print "	\"" $3 "\","}'
93
/TNOT/,/neverfound/{if (last) print "	\"" last "\","; last = $3}
93
echo '	0
94
END{print "	\"" last "\"\n};"}'
94
};'
95
95
96
rm /tmp/ka$$
96
rm /tmp/ka$$
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mystring.c (-1 / +85 lines)
Lines 60-68 Link Here
60
#include "syntax.h"
60
#include "syntax.h"
61
#include "error.h"
61
#include "error.h"
62
#include "mystring.h"
62
#include "mystring.h"
63
#include "memalloc.h"
64
#include "parser.h"
63
65
64
66
65
char nullstr[1];		/* zero length string */
67
char nullstr[1];		/* zero length string */
68
const char spcstr[] = " ";
69
const char snlfmt[] = "%s\n";
70
const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
71
const char illnum[] = "Illegal number: %s";
72
const char homestr[] = "HOME";
66
73
67
/*
74
/*
68
 * equal - #defined in mystring.h
75
 * equal - #defined in mystring.h
Lines 73-78 Link Here
73
 */
80
 */
74
81
75
82
83
#if 0
76
/*
84
/*
77
 * scopyn - copy a string from "from" to "to", truncating the string
85
 * scopyn - copy a string from "from" to "to", truncating the string
78
 *		if necessary.  "To" is always nul terminated, even if
86
 *		if necessary.  "To" is always nul terminated, even if
Lines 92-97 Link Here
92
	}
100
	}
93
	*to = '\0';
101
	*to = '\0';
94
}
102
}
103
#endif
95
104
96
105
97
/*
106
/*
Lines 122-128 Link Here
122
	{
131
	{
123
132
124
	if (! is_number(s))
133
	if (! is_number(s))
125
		error("Illegal number: %s", s);
134
		error(illnum, s);
126
	return atoi(s);
135
	return atoi(s);
127
}
136
}
128
137
Lines 142-144 Link Here
142
	} while (*++p != '\0');
151
	} while (*++p != '\0');
143
	return 1;
152
	return 1;
144
}
153
}
154
155
156
/*
157
 * Produce a possibly single quoted string suitable as input to the shell.
158
 * The return string is allocated on the stack.
159
 */
160
161
char *
162
single_quote(const char *s) {
163
	char *p;
164
165
	STARTSTACKSTR(p);
166
167
	do {
168
		char *q;
169
		size_t len;
170
171
		len = strchrnul(s, '\'') - s;
172
173
		q = p = makestrspace(len + 3, p);
174
175
		*q++ = '\'';
176
		q = mempcpy(q, s, len);
177
		*q++ = '\'';
178
		s += len;
179
180
		STADJUST(q - p, p);
181
182
		len = strspn(s, "'");
183
		if (!len)
184
			break;
185
186
		q = p = makestrspace(len + 3, p);
187
188
		*q++ = '"';
189
		q = mempcpy(q, s, len);
190
		*q++ = '"';
191
		s += len;
192
193
		STADJUST(q - p, p);
194
	} while (*s);
195
196
	USTPUTC(0, p);
197
198
	return stackblock();
199
}
200
201
/*
202
 * Like strdup but works with the ash stack.
203
 */
204
205
char *
206
sstrdup(const char *p)
207
{
208
	size_t len = strlen(p) + 1;
209
	return memcpy(stalloc(len), p, len);
210
}
211
212
/*
213
 * Wrapper around strcmp for qsort/bsearch/...
214
 */
215
int
216
pstrcmp(const void *a, const void *b)
217
{
218
	return strcmp(*(const char *const *) a, *(const char *const *) b);
219
}
220
221
/*
222
 * Find a string is in a sorted array.
223
 */
224
const char *const *
225
findstring(const char *s, const char *const *array, size_t nmemb)
226
{
227
	return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp);
228
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/mystring.h (+13 lines)
Lines 40-49 Link Here
40
40
41
#include <string.h>
41
#include <string.h>
42
42
43
extern const char snlfmt[];
44
extern const char spcstr[];
45
extern const char dolatstr[];
46
#define DOLATSTRLEN 4
47
extern const char illnum[];
48
extern const char homestr[];
49
50
#if 0
43
void scopyn __P((const char *, char *, int));
51
void scopyn __P((const char *, char *, int));
52
#endif
44
int prefix __P((const char *, const char *));
53
int prefix __P((const char *, const char *));
45
int number __P((const char *));
54
int number __P((const char *));
46
int is_number __P((const char *));
55
int is_number __P((const char *));
56
char *single_quote __P((const char *));
57
char *sstrdup __P((const char *));
58
int pstrcmp __P((const void *, const void *));
59
const char *const *findstring __P((const char *, const char *const *, size_t));
47
60
48
#define equal(s1, s2)	(strcmp(s1, s2) == 0)
61
#define equal(s1, s2)	(strcmp(s1, s2) == 0)
49
#define scopy(s1, s2)	((void)strcpy(s2, s1))
62
#define scopy(s1, s2)	((void)strcpy(s2, s1))
(-)bin_NetBSD-1.6release.orig/src/bin/sh/nodes.c.pat (-13 / +23 lines)
Lines 70-87 Link Here
70
 * Make a copy of a parse tree.
70
 * Make a copy of a parse tree.
71
 */
71
 */
72
72
73
union node *
73
struct funcnode *
74
copyfunc(n)
74
copyfunc(union node *n)
75
	union node *n;
76
{
75
{
77
	if (n == NULL)
76
	struct funcnode *f;
78
		return NULL;
77
	size_t blocksize;
79
	funcblocksize = 0;
78
79
	funcblocksize = offsetof(struct funcnode, n);
80
	funcstringsize = 0;
80
	funcstringsize = 0;
81
	calcsize(n);
81
	calcsize(n);
82
	funcblock = ckmalloc(funcblocksize + funcstringsize);
82
	blocksize = funcblocksize;
83
	funcstring = (char *) funcblock + funcblocksize;
83
	f = ckmalloc(blocksize + funcstringsize);
84
	return copynode(n);
84
	funcblock = (char *) f + offsetof(struct funcnode, n);
85
	funcstring = (char *) f + blocksize;
86
	copynode(n);
87
	f->count = 0;
88
	return f;
85
}
89
}
86
90
87
91
Lines 144-149 Link Here
144
nodesavestr(s)
148
nodesavestr(s)
145
	char   *s;
149
	char   *s;
146
{
150
{
151
#ifdef _GNU_SOURCE
152
	char   *rtn = funcstring;
153
154
	funcstring = stpcpy(funcstring, s) + 1;
155
	return rtn;
156
#else
147
	register char *p = s;
157
	register char *p = s;
148
	register char *q = funcstring;
158
	register char *q = funcstring;
149
	char   *rtn = funcstring;
159
	char   *rtn = funcstring;
Lines 152-157 Link Here
152
		continue;
162
		continue;
153
	funcstring = q;
163
	funcstring = q;
154
	return rtn;
164
	return rtn;
165
#endif
155
}
166
}
156
167
157
168
Lines 161-169 Link Here
161
 */
172
 */
162
173
163
void
174
void
164
freefunc(n)
175
freefunc(struct funcnode *f)
165
	union node *n;
166
{
176
{
167
	if (n)
177
	if (f && --f->count < 0)
168
		ckfree(n);
178
		ckfree(f);
169
}
179
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/nodetypes (-6 / +6 lines)
Lines 52-65 Link Here
52
# The last two types should be followed by the text of a C declaration for
52
# The last two types should be followed by the text of a C declaration for
53
# the field.
53
# the field.
54
54
55
NSEMI nbinary			# two commands separated by a semicolon
56
	type	  int
57
	ch1	  nodeptr		# the first child
58
	ch2	  nodeptr		# the second child
59
60
NCMD ncmd			# a simple command
55
NCMD ncmd			# a simple command
61
	type	  int
56
	type	  int
62
	backgnd	  int			# set to run command in background
57
	assign    nodeptr		# variable assignments
63
	args	  nodeptr		# the arguments
58
	args	  nodeptr		# the arguments
64
	redirect  nodeptr		# list of file redirections
59
	redirect  nodeptr		# list of file redirections
65
60
Lines 79-84 Link Here
79
NAND nbinary			# the && operator
74
NAND nbinary			# the && operator
80
NOR nbinary			# the || operator
75
NOR nbinary			# the || operator
81
76
77
NSEMI nbinary			# two commands separated by a semicolon
78
	type	  int
79
	ch1	  nodeptr		# the first child
80
	ch2	  nodeptr		# the second child
81
82
NIF nif				# the if statement.  Elif clauses are handled
82
NIF nif				# the if statement.  Elif clauses are handled
83
	type	  int		    # using multiple if nodes.
83
	type	  int		    # using multiple if nodes.
84
	test	  nodeptr		# if test
84
	test	  nodeptr		# if test
(-)bin_NetBSD-1.6release.orig/src/bin/sh/options.c (-69 / +103 lines)
Lines 75-85 Link Here
75
75
76
char *minusc;			/* argument to -c option */
76
char *minusc;			/* argument to -c option */
77
77
78
static const char *const optnames[NOPTS] = {
79
	"errexit",
80
	"noglob",
81
	"ignoreeof",
82
	"interactive",
83
	"monitor",
84
	"noexec",
85
	"stdin",
86
	"xtrace",
87
	"verbose",
88
	"vi",
89
	"emacs",
90
	"noclobber",
91
	"allexport",
92
	"notify",
93
	"nounset",
94
	"quietprofile",
95
};
96
97
const char optletters[NOPTS] = {
98
	'e',
99
	'f',
100
	'I',
101
	'i',
102
	'm',
103
	'n',
104
	's',
105
	'x',
106
	'v',
107
	'V',
108
	'E',
109
	'C',
110
	'a',
111
	'b',
112
	'u',
113
	'q',
114
};
115
116
char optlist[NOPTS];
117
78
118
79
STATIC void options __P((int));
119
STATIC void options __P((int));
80
STATIC void minus_o __P((char *, int));
120
STATIC void minus_o __P((char *, int));
81
STATIC void setoption __P((int, int));
121
STATIC void setoption __P((int, int));
82
STATIC int getopts __P((char *, char *, char **, char ***, char **));
122
STATIC int getopts __P((char *, char *, char **, int *, int *));
83
123
84
124
85
/*
125
/*
Lines 97-103 Link Here
97
	if (argc > 0)
137
	if (argc > 0)
98
		argptr++;
138
		argptr++;
99
	for (i = 0; i < NOPTS; i++)
139
	for (i = 0; i < NOPTS; i++)
100
		optlist[i].val = 2;
140
		optlist[i] = 2;
101
	options(1);
141
	options(1);
102
	if (*argptr == NULL && minusc == NULL)
142
	if (*argptr == NULL && minusc == NULL)
103
		sflag = 1;
143
		sflag = 1;
Lines 106-126 Link Here
106
	if (mflag == 2)
146
	if (mflag == 2)
107
		mflag = iflag;
147
		mflag = iflag;
108
	for (i = 0; i < NOPTS; i++)
148
	for (i = 0; i < NOPTS; i++)
109
		if (optlist[i].val == 2)
149
		if (optlist[i] == 2)
110
			optlist[i].val = 0;
150
			optlist[i] = 0;
111
	arg0 = argv[0];
151
	arg0 = argv[0];
112
	if (sflag == 0 && minusc == NULL) {
113
		commandname = argv[0];
114
		arg0 = *argptr++;
115
		setinputfile(arg0, 0);
116
		commandname = arg0;
117
	}
118
	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
152
	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
119
	if (argptr && minusc && *argptr)
153
	if (*argptr) {
120
	        arg0 = *argptr++;
154
		char *p = *argptr++;
155
		if (!minusc)
156
			setinputfile(p, 0);
157
		arg0 = p;
158
	}
159
	if (!sflag)
160
		commandname = arg0;
121
161
122
	shellparam.p = argptr;
162
	shellparam.p = argptr;
123
	shellparam.reset = 1;
163
	shellparam.optind = 1;
164
	shellparam.optoff = -1;
124
	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
165
	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
125
	while (*argptr) {
166
	while (*argptr) {
126
		shellparam.nparam++;
167
		shellparam.nparam++;
Lines 210-221 Link Here
210
	if (name == NULL) {
251
	if (name == NULL) {
211
		out1str("Current option settings\n");
252
		out1str("Current option settings\n");
212
		for (i = 0; i < NOPTS; i++)
253
		for (i = 0; i < NOPTS; i++)
213
			out1fmt("%-16s%s\n", optlist[i].name,
254
			out1fmt("%-16s%s\n", optnames[i],
214
				optlist[i].val ? "on" : "off");
255
				optlist[i] ? "on" : "off");
215
	} else {
256
	} else {
216
		for (i = 0; i < NOPTS; i++)
257
		for (i = 0; i < NOPTS; i++)
217
			if (equal(name, optlist[i].name)) {
258
			if (equal(name, optnames[i])) {
218
				setoption(optlist[i].letter, val);
259
				setoption(optletters[i], val);
219
				return;
260
				return;
220
			}
261
			}
221
		error("Illegal option -o %s", name);
262
		error("Illegal option -o %s", name);
Lines 231-238 Link Here
231
	int i;
272
	int i;
232
273
233
	for (i = 0; i < NOPTS; i++)
274
	for (i = 0; i < NOPTS; i++)
234
		if (optlist[i].letter == flag) {
275
		if (optletters[i] == flag) {
235
			optlist[i].val = val;
276
			optlist[i] = val;
236
			if (val) {
277
			if (val) {
237
				/* #%$ hack for ksh semantics */
278
				/* #%$ hack for ksh semantics */
238
				if (flag == 'V')
279
				if (flag == 'V')
Lines 248-267 Link Here
248
289
249
290
250
291
251
#ifdef mkinit
252
INCLUDE "options.h"
253
254
SHELLPROC {
255
	int i;
256
257
	for (i = 0; i < NOPTS; i++)
258
		optlist[i].val = 0;
259
	optschanged();
260
261
}
262
#endif
263
264
265
/*
292
/*
266
 * Set the shell parameters.
293
 * Set the shell parameters.
267
 */
294
 */
Lines 284-290 Link Here
284
	shellparam.malloc = 1;
311
	shellparam.malloc = 1;
285
	shellparam.nparam = nparam;
312
	shellparam.nparam = nparam;
286
	shellparam.p = newparam;
313
	shellparam.p = newparam;
287
	shellparam.optnext = NULL;
314
	shellparam.optind = 1;
315
	shellparam.optoff = -1;
288
}
316
}
289
317
290
318
Lines 332-338 Link Here
332
	}
360
	}
333
	ap2 = shellparam.p;
361
	ap2 = shellparam.p;
334
	while ((*ap2++ = *ap1++) != NULL);
362
	while ((*ap2++ = *ap1++) != NULL);
335
	shellparam.optnext = NULL;
363
	shellparam.optind = 1;
364
	shellparam.optoff = -1;
336
	INTON;
365
	INTON;
337
	return 0;
366
	return 0;
338
}
367
}
Lines 365-374 Link Here
365
getoptsreset(value)
394
getoptsreset(value)
366
	const char *value;
395
	const char *value;
367
{
396
{
368
	if (number(value) == 1) {
397
	shellparam.optind = number(value);
369
		shellparam.optnext = NULL;
398
	shellparam.optoff = -1;
370
		shellparam.reset = 1;
371
	}
372
}
399
}
373
400
374
/*
401
/*
Lines 387-436 Link Here
387
414
388
	if (argc < 3)
415
	if (argc < 3)
389
		error("Usage: getopts optstring var [arg]");
416
		error("Usage: getopts optstring var [arg]");
390
	else if (argc == 3)
417
	else if (argc == 3) {
391
		optbase = shellparam.p;
418
		optbase = shellparam.p;
392
	else
419
		if (shellparam.optind > shellparam.nparam + 1) {
420
			shellparam.optind = 1;
421
			shellparam.optoff = -1;
422
		}
423
	}
424
	else {
393
		optbase = &argv[3];
425
		optbase = &argv[3];
394
426
		if (shellparam.optind > argc - 2) {
395
	if (shellparam.reset == 1) {
427
			shellparam.optind = 1;
396
		shellparam.optnext = optbase;
428
			shellparam.optoff = -1;
397
		shellparam.optptr = NULL;
429
		}
398
		shellparam.reset = 0;
399
	}
430
	}
400
431
401
	return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
432
	return getopts(argv[1], argv[2], optbase, &shellparam.optind,
402
		       &shellparam.optptr);
433
		       &shellparam.optoff);
403
}
434
}
404
435
405
STATIC int
436
STATIC int
406
getopts(optstr, optvar, optfirst, optnext, optpptr)
437
getopts(optstr, optvar, optfirst, optind, optoff)
407
	char *optstr;
438
	char *optstr;
408
	char *optvar;
439
	char *optvar;
409
	char **optfirst;
440
	char **optfirst;
410
	char ***optnext;
441
	int *optind;
411
	char **optpptr;
442
	int *optoff;
412
{
443
{
413
	char *p, *q;
444
	char *p, *q;
414
	char c = '?';
445
	char c = '?';
415
	int done = 0;
446
	int done = 0;
416
	int ind = 0;
417
	int err = 0;
447
	int err = 0;
418
	char s[10];
448
	char s[10];
449
	char **optnext = optfirst + *optind - 1;
419
450
420
	if ((p = *optpptr) == NULL || *p == '\0') {
451
	if (*optind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
452
	    strlen(*(optnext - 1)) < *optoff)
453
		p = NULL;
454
	else
455
		p = *(optnext - 1) + *optoff;
456
	if (p == NULL || *p == '\0') {
421
		/* Current word is done, advance */
457
		/* Current word is done, advance */
422
		if (*optnext == NULL)
458
		if (optnext == NULL)
423
			return 1;
459
			return 1;
424
		p = **optnext;
460
		p = *optnext;
425
		if (p == NULL || *p != '-' || *++p == '\0') {
461
		if (p == NULL || *p != '-' || *++p == '\0') {
426
atend:
462
atend:
427
			ind = *optnext - optfirst + 1;
463
			*optind = optnext - optfirst + 1;
428
			*optnext = NULL;
429
			p = NULL;
464
			p = NULL;
430
			done = 1;
465
			done = 1;
431
			goto out;
466
			goto out;
432
		}
467
		}
433
		(*optnext)++;
468
		optnext++;
434
		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
469
		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
435
			goto atend;
470
			goto atend;
436
	}
471
	}
Lines 455-461 Link Here
455
	}
490
	}
456
491
457
	if (*++q == ':') {
492
	if (*++q == ':') {
458
		if (*p == '\0' && (p = **optnext) == NULL) {
493
		if (*p == '\0' && (p = *optnext) == NULL) {
459
			if (optstr[0] == ':') {
494
			if (optstr[0] == ':') {
460
				s[0] = c;
495
				s[0] = c;
461
				s[1] = '\0';
496
				s[1] = '\0';
Lines 470-499 Link Here
470
			goto bad;
505
			goto bad;
471
		}
506
		}
472
507
473
		if (p == **optnext)
508
		if (p == *optnext)
474
			(*optnext)++;
509
			optnext++;
475
		setvarsafe("OPTARG", p, 0);
510
		setvarsafe("OPTARG", p, 0);
476
		p = NULL;
511
		p = NULL;
477
	}
512
	}
478
	else
513
	else
479
		setvarsafe("OPTARG", "", 0);
514
		setvarsafe("OPTARG", nullstr, 0);
480
	ind = *optnext - optfirst + 1;
515
	*optind = optnext - optfirst + 1;
481
	goto out;
516
	goto out;
482
517
483
bad:
518
bad:
484
	ind = 1;
519
	*optind = 1;
485
	*optnext = NULL;
486
	p = NULL;
520
	p = NULL;
487
out:
521
out:
488
	*optpptr = p;
522
	*optoff = p ? p - *(optnext - 1) : -1;
489
	fmtstr(s, sizeof(s), "%d", ind);
523
	fmtstr(s, sizeof(s), "%d", *optind);
490
	err |= setvarsafe("OPTIND", s, VNOFUNC);
524
	err |= setvarsafe("OPTIND", s, VNOFUNC);
491
	s[0] = c;
525
	s[0] = c;
492
	s[1] = '\0';
526
	s[1] = '\0';
493
	err |= setvarsafe(optvar, s, 0);
527
	err |= setvarsafe(optvar, s, 0);
494
	if (err) {
528
	if (err) {
495
		*optnext = NULL;
529
		*optind = 1;
496
		*optpptr = NULL;
530
		*optoff = -1;
497
		flushall();
531
		flushall();
498
		exraise(EXERROR);
532
		exraise(EXERROR);
499
	}
533
	}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/options.h (-47 / +20 lines)
Lines 41-101 Link Here
41
struct shparam {
41
struct shparam {
42
	int nparam;		/* # of positional parameters (without $0) */
42
	int nparam;		/* # of positional parameters (without $0) */
43
	unsigned char malloc;	/* if parameter list dynamically allocated */
43
	unsigned char malloc;	/* if parameter list dynamically allocated */
44
	unsigned char reset;	/* if getopts has been reset */
45
	char **p;		/* parameter list */
44
	char **p;		/* parameter list */
46
	char **optnext;		/* next parameter to be processed by getopts */
45
	int optind;		/* next parameter to be processed by getopts */
47
	char *optptr;		/* used by getopts */
46
	int optoff;		/* used by getopts */
48
};
47
};
49
48
50
49
51
50
52
#define eflag optlist[0].val
51
#define eflag optlist[0]
53
#define fflag optlist[1].val
52
#define fflag optlist[1]
54
#define Iflag optlist[2].val
53
#define Iflag optlist[2]
55
#define iflag optlist[3].val
54
#define iflag optlist[3]
56
#define mflag optlist[4].val
55
#define mflag optlist[4]
57
#define nflag optlist[5].val
56
#define nflag optlist[5]
58
#define sflag optlist[6].val
57
#define sflag optlist[6]
59
#define xflag optlist[7].val
58
#define xflag optlist[7]
60
#define vflag optlist[8].val
59
#define vflag optlist[8]
61
#define Vflag optlist[9].val
60
#define Vflag optlist[9]
62
#define	Eflag optlist[10].val
61
#define	Eflag optlist[10]
63
#define	Cflag optlist[11].val
62
#define	Cflag optlist[11]
64
#define	aflag optlist[12].val
63
#define	aflag optlist[12]
65
#define	bflag optlist[13].val
64
#define	bflag optlist[13]
66
#define	uflag optlist[14].val
65
#define	uflag optlist[14]
67
#define	qflag optlist[15].val
66
#define	qflag optlist[15]
68
67
69
#define NOPTS	16
68
#define NOPTS	16
70
69
71
struct optent {
70
extern const char optletters[NOPTS];
72
	const char *name;
71
extern char optlist[NOPTS];
73
	const char letter;
74
	char val;
75
};
76
77
#ifdef DEFINE_OPTIONS
78
struct optent optlist[NOPTS] = {
79
	{ "errexit",	'e',	0 },
80
	{ "noglob",	'f',	0 },
81
	{ "ignoreeof",	'I',	0 },
82
	{ "interactive",'i',	0 },
83
	{ "monitor",	'm',	0 },
84
	{ "noexec",	'n',	0 },
85
	{ "stdin",	's',	0 },
86
	{ "xtrace",	'x',	0 },
87
	{ "verbose",	'v',	0 },
88
	{ "vi",		'V',	0 },
89
	{ "emacs",	'E',	0 },
90
	{ "noclobber",	'C',	0 },
91
	{ "allexport",	'a',	0 },
92
	{ "notify",	'b',	0 },
93
	{ "nounset",	'u',	0 },
94
	{ "quietprofile", 'q',	0 },
95
};
96
#else
97
extern struct optent optlist[NOPTS];
98
#endif
99
72
100
73
101
extern char *minusc;		/* argument to -c option */
74
extern char *minusc;		/* argument to -c option */
(-)bin_NetBSD-1.6release.orig/src/bin/sh/output.c (-388 / +200 lines)
Lines 1-4 Link Here
1
/*	$NetBSD: output.c,v 1.25 2002/04/09 00:52:05 thorpej Exp $	*/
1
/*	$NetBSD: output.c,v 1.26 2002/05/25 23:09:06 wiz Exp $	*/
2
2
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
Lines 41-47 Link Here
41
#if 0
41
#if 0
42
static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
42
static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
43
#else
43
#else
44
__RCSID("$NetBSD: output.c,v 1.25 2002/04/09 00:52:05 thorpej Exp $");
44
__RCSID("$NetBSD: output.c,v 1.26 2002/05/25 23:09:06 wiz Exp $");
45
#endif
45
#endif
46
#endif /* not lint */
46
#endif /* not lint */
47
47
Lines 65-70 Link Here
65
#include <errno.h>
65
#include <errno.h>
66
#include <unistd.h>
66
#include <unistd.h>
67
#include <stdlib.h>
67
#include <stdlib.h>
68
#ifdef USE_GLIBC_STDIO
69
#include <fcntl.h>
70
#endif
71
#include <limits.h>
68
72
69
#include "shell.h"
73
#include "shell.h"
70
#include "syntax.h"
74
#include "syntax.h"
Lines 74-142 Link Here
74
78
75
79
76
#define OUTBUFSIZ BUFSIZ
80
#define OUTBUFSIZ BUFSIZ
77
#define BLOCK_OUT -2		/* output to a fixed block of memory */
78
#define MEM_OUT -3		/* output to dynamically allocated memory */
81
#define MEM_OUT -3		/* output to dynamically allocated memory */
79
#define OUTPUT_ERR 01		/* error occurred on output */
80
82
81
83
82
struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
84
#ifdef USE_GLIBC_STDIO
83
struct output errout = {NULL, 0, NULL, 100, 2, 0};
85
struct output output = {
84
struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
86
	stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 1, flags: 0
87
};
88
struct output errout = {
89
	stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0
90
}
91
#ifdef notyet
92
struct output memout = {
93
	stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0
94
};
95
#endif
96
#else
97
struct output output = {
98
	nextc: 0, end: 0, buf: 0, bufsize: OUTBUFSIZ, fd: 1, flags: 0
99
};
100
struct output errout = {
101
	nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0
102
};
103
#ifdef notyet
104
struct output memout = {
105
	nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0
106
};
107
#endif
108
#endif
85
struct output *out1 = &output;
109
struct output *out1 = &output;
86
struct output *out2 = &errout;
110
struct output *out2 = &errout;
87
111
88
112
113
#ifndef USE_GLIBC_STDIO
114
static void __outstr(const char *, size_t, struct output *);
115
#endif
116
static int xvsnprintf(char *, size_t, const char *, va_list);
117
89
118
90
#ifdef mkinit
119
#ifdef mkinit
91
120
92
INCLUDE "output.h"
121
INCLUDE "output.h"
93
INCLUDE "memalloc.h"
122
INCLUDE "memalloc.h"
94
123
124
INIT {
125
#ifdef USE_GLIBC_STDIO
126
	initstreams();
127
#endif
128
}
129
95
RESET {
130
RESET {
131
#ifdef notyet
96
	out1 = &output;
132
	out1 = &output;
97
	out2 = &errout;
133
	out2 = &errout;
134
#ifdef USE_GLIBC_STDIO
135
	if (memout.stream != NULL)
136
		__closememout();
137
#endif
98
	if (memout.buf != NULL) {
138
	if (memout.buf != NULL) {
99
		ckfree(memout.buf);
139
		ckfree(memout.buf);
100
		memout.buf = NULL;
140
		memout.buf = NULL;
101
	}
141
	}
142
#endif
102
}
143
}
103
144
104
#endif
145
#endif
105
146
106
147
107
#ifdef notdef	/* no longer used */
148
#ifndef USE_GLIBC_STDIO
108
/*
149
static void
109
 * Set up an output file to write to memory rather than a file.
150
__outstr(const char *p, size_t len, struct output *dest) {
110
 */
151
	size_t bufsize;
111
152
	size_t offset;
112
void
153
	size_t nleft;
113
open_mem(block, length, file)
114
	char *block;
115
	int length;
116
	struct output *file;
117
	{
118
	file->nextc = block;
119
	file->nleft = --length;
120
	file->fd = BLOCK_OUT;
121
	file->flags = 0;
122
}
123
#endif
124
154
155
	nleft = dest->end - dest->nextc;
156
	if (nleft >= len) {
157
buffered:
158
		dest->nextc = mempcpy(dest->nextc, p, len);
159
		return;
160
	}
125
161
126
void
162
	bufsize = dest->bufsize;
127
out1str(p)
163
	if (!bufsize) {
128
	const char *p;
164
		;
129
	{
165
	} else if (dest->buf == NULL) {
130
	outstr(p, out1);
166
		if (dest->fd == MEM_OUT && len > bufsize) {
131
}
167
			bufsize = len;
168
		}
169
		offset = 0;
170
		goto alloc;
171
	} else if (dest->fd == MEM_OUT) {
172
		offset = bufsize;
173
		if (bufsize >= len) {
174
			bufsize <<= 1;
175
		} else {
176
			bufsize += len;
177
		}
178
		if (bufsize < offset)
179
			goto err;
180
alloc:
181
		INTOFF;
182
		dest->buf = ckrealloc(dest->buf, bufsize);
183
		dest->bufsize = bufsize;
184
		dest->end = dest->buf + bufsize;
185
		dest->nextc = dest->buf + offset;
186
		INTON;
187
	} else {
188
		flushout(dest);
189
	}
132
190
191
	nleft = dest->end - dest->nextc;
192
	if (nleft > len)
193
		goto buffered;
133
194
134
void
195
	if ((xwrite(dest->fd, p, len))) {
135
out2str(p)
196
err:
136
	const char *p;
197
		dest->flags |= OUTPUT_ERR;
137
	{
198
	}
138
	outstr(p, out2);
139
}
199
}
200
#endif
140
201
141
202
142
void
203
void
Lines 144-194 Link Here
144
	const char *p;
205
	const char *p;
145
	struct output *file;
206
	struct output *file;
146
	{
207
	{
147
	while (*p)
208
#ifdef USE_GLIBC_STDIO
148
		outc(*p++, file);
209
	INTOFF;
149
	if (file == out2)
210
	fputs(p, file->stream);
150
		flushout(file);
211
	INTON;
212
#else
213
	size_t len;
214
215
	len = strlen(p);
216
	__outstr(p, len, file);
217
#endif
151
}
218
}
152
219
153
220
154
char out_junk[16];
221
#ifndef USE_GLIBC_STDIO
155
222
156
223
157
void
224
void
158
emptyoutbuf(dest)
225
outcslow(char c, struct output *dest)
159
	struct output *dest;
226
{
160
	{
227
	__outstr(&c, 1, dest);
161
	int offset;
162
163
	if (dest->fd == BLOCK_OUT) {
164
		dest->nextc = out_junk;
165
		dest->nleft = sizeof out_junk;
166
		dest->flags |= OUTPUT_ERR;
167
	} else if (dest->buf == NULL) {
168
		INTOFF;
169
		dest->buf = ckmalloc(dest->bufsize);
170
		dest->nextc = dest->buf;
171
		dest->nleft = dest->bufsize;
172
		INTON;
173
	} else if (dest->fd == MEM_OUT) {
174
		offset = dest->bufsize;
175
		INTOFF;
176
		dest->bufsize <<= 1;
177
		dest->buf = ckrealloc(dest->buf, dest->bufsize);
178
		dest->nleft = dest->bufsize - offset;
179
		dest->nextc = dest->buf + offset;
180
		INTON;
181
	} else {
182
		flushout(dest);
183
	}
184
	dest->nleft--;
185
}
228
}
229
#endif
186
230
187
231
188
void
232
void
189
flushall() {
233
flushall() {
190
	flushout(&output);
234
	flushout(&output);
235
#ifdef FLUSHERR
191
	flushout(&errout);
236
	flushout(&errout);
237
#endif
192
}
238
}
193
239
194
240
Lines 196-538 Link Here
196
flushout(dest)
242
flushout(dest)
197
	struct output *dest;
243
	struct output *dest;
198
	{
244
	{
245
#ifdef USE_GLIBC_STDIO
246
	INTOFF;
247
	fflush(dest->stream);
248
	INTON;
249
#else
250
	size_t len;
199
251
200
	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
252
	len = dest->nextc - dest->buf;
253
	if (dest->buf == NULL || !len || dest->fd < 0)
201
		return;
254
		return;
202
	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
203
		dest->flags |= OUTPUT_ERR;
204
	dest->nextc = dest->buf;
255
	dest->nextc = dest->buf;
205
	dest->nleft = dest->bufsize;
256
	if ((xwrite(dest->fd, dest->buf, len)))
206
}
257
		dest->flags |= OUTPUT_ERR;
207
258
#endif
208
209
void
210
freestdout() {
211
	INTOFF;
212
	if (output.buf) {
213
		ckfree(output.buf);
214
		output.buf = NULL;
215
		output.nleft = 0;
216
	}
217
	INTON;
218
}
259
}
219
260
220
261
221
void
262
void
222
#ifdef __STDC__
223
outfmt(struct output *file, const char *fmt, ...)
263
outfmt(struct output *file, const char *fmt, ...)
224
#else
225
void
226
outfmt(va_alist)
227
	va_dcl
228
#endif
229
{
264
{
230
	va_list ap;
265
	va_list ap;
231
#ifndef __STDC__
232
	struct output *file;
233
	const char *fmt;
234
266
235
	va_start(ap);
236
	file = va_arg(ap, struct output *);
237
	fmt = va_arg(ap, const char *);
238
#else
239
	va_start(ap, fmt);
267
	va_start(ap, fmt);
240
#endif
241
	doformat(file, fmt, ap);
268
	doformat(file, fmt, ap);
242
	va_end(ap);
269
	va_end(ap);
243
}
270
}
244
271
245
272
246
void
273
void
247
#ifdef __STDC__
248
out1fmt(const char *fmt, ...)
274
out1fmt(const char *fmt, ...)
249
#else
250
out1fmt(va_alist)
251
	va_dcl
252
#endif
253
{
275
{
254
	va_list ap;
276
	va_list ap;
255
#ifndef __STDC__
256
	const char *fmt;
257
277
258
	va_start(ap);
259
	fmt = va_arg(ap, const char *);
260
#else
261
	va_start(ap, fmt);
278
	va_start(ap, fmt);
262
#endif
263
	doformat(out1, fmt, ap);
279
	doformat(out1, fmt, ap);
264
	va_end(ap);
280
	va_end(ap);
265
}
281
}
266
282
267
void
268
#ifdef __STDC__
269
dprintf(const char *fmt, ...)
270
#else
271
dprintf(va_alist)
272
	va_dcl
273
#endif
274
{
275
	va_list ap;
276
#ifndef __STDC__
277
	const char *fmt;
278
279
	va_start(ap);
280
	fmt = va_arg(ap, const char *);
281
#else
282
	va_start(ap, fmt);
283
#endif
284
	doformat(out2, fmt, ap);
285
	va_end(ap);
286
	flushout(out2);
287
}
288
283
289
void
284
int
290
#ifdef __STDC__
291
fmtstr(char *outbuf, size_t length, const char *fmt, ...)
285
fmtstr(char *outbuf, size_t length, const char *fmt, ...)
292
#else
293
fmtstr(va_alist)
294
	va_dcl
295
#endif
296
{
286
{
297
	va_list ap;
287
	va_list ap;
298
	struct output strout;
288
	int ret;
299
#ifndef __STDC__
300
	char *outbuf;
301
	size_t length;
302
	const char *fmt;
303
289
304
	va_start(ap);
305
	outbuf = va_arg(ap, char *);
306
	length = va_arg(ap, size_t);
307
	fmt = va_arg(ap, const char *);
308
#else
309
	va_start(ap, fmt);
290
	va_start(ap, fmt);
310
#endif
291
	ret = xvsnprintf(outbuf, length, fmt, ap);
311
	strout.nextc = outbuf;
312
	strout.nleft = length;
313
	strout.fd = BLOCK_OUT;
314
	strout.flags = 0;
315
	doformat(&strout, fmt, ap);
316
	outc('\0', &strout);
317
	if (strout.flags & OUTPUT_ERR)
318
		outbuf[length - 1] = '\0';
319
	va_end(ap);
292
	va_end(ap);
293
	return ret;
320
}
294
}
321
295
322
/*
323
 * Formatted output.  This routine handles a subset of the printf formats:
324
 * - Formats supported: d, u, o, p, X, s, and c.
325
 * - The x format is also accepted but is treated like X.
326
 * - The l, ll and q modifiers are accepted.
327
 * - The - and # flags are accepted; # only works with the o format.
328
 * - Width and precision may be specified with any format except c.
329
 * - An * may be given for the width or precision.
330
 * - The obsolete practice of preceding the width with a zero to get
331
 *   zero padding is not supported; use the precision field.
332
 * - A % may be printed by writing %% in the format string.
333
 */
334
335
#define TEMPSIZE 24
336
337
#ifdef BSD4_4
338
#define HAVE_VASPRINTF 1
339
#endif
340
296
297
#ifndef USE_GLIBC_STDIO
341
void
298
void
342
doformat(dest, f, ap)
299
doformat(dest, f, ap)
343
	struct output *dest;
300
	struct output *dest;
344
	const char *f;		/* format string */
301
	const char *f;		/* format string */
345
	va_list ap;
302
	va_list ap;
346
{
303
{
347
#if	HAVE_VASPRINTF
304
	struct stackmark smark;
348
	char *s;
305
	char *s;
306
	int len, ret;
307
	size_t size;
308
	va_list ap2;
349
309
350
	vasprintf(&s, f, ap);
310
	va_copy(ap2, ap);
351
	outstr(s, dest);
311
	size = dest->end - dest->nextc;
352
	free(s);     
312
	len = xvsnprintf(dest->nextc, size, f, ap2);
353
#else	/* !HAVE_VASPRINTF */
313
	va_end(ap2);
354
	static const char digit[] = "0123456789ABCDEF";
314
	if (len < 0) {
355
	char c;
315
		dest->flags |= OUTPUT_ERR;
356
	char temp[TEMPSIZE];
316
		return;
357
	int flushleft;
358
	int sharp;
359
	int width;
360
	int prec;
361
	int islong;
362
	int isquad;
363
	char *p;
364
	int sign;
365
#ifdef BSD4_4
366
	quad_t l;
367
	u_quad_t num;
368
#else
369
	long l;
370
	u_long num;
371
#endif
372
	unsigned base;
373
	int len;
374
	int size;
375
	int pad;
376
377
	while ((c = *f++) != '\0') {
378
		if (c != '%') {
379
			outc(c, dest);
380
			continue;
381
		}
382
		flushleft = 0;
383
		sharp = 0;
384
		width = 0;
385
		prec = -1;
386
		islong = 0;
387
		isquad = 0;
388
		for (;;) {
389
			if (*f == '-')
390
				flushleft++;
391
			else if (*f == '#')
392
				sharp++;
393
			else
394
				break;
395
			f++;
396
		}
397
		if (*f == '*') {
398
			width = va_arg(ap, int);
399
			f++;
400
		} else {
401
			while (is_digit(*f)) {
402
				width = 10 * width + digit_val(*f++);
403
			}
404
		}
405
		if (*f == '.') {
406
			if (*++f == '*') {
407
				prec = va_arg(ap, int);
408
				f++;
409
			} else {
410
				prec = 0;
411
				while (is_digit(*f)) {
412
					prec = 10 * prec + digit_val(*f++);
413
				}
414
			}
415
		}
416
		if (*f == 'l') {
417
			f++;
418
			if (*f == 'l') {
419
				isquad++;
420
				f++;
421
			} else
422
				islong++;
423
		} else if (*f == 'q') {
424
			isquad++;
425
			f++;
426
		}
317
		}
427
		switch (*f) {
318
	if (len < size) {
428
		case 'd':
319
		dest->nextc += len;
429
#ifdef BSD4_4
320
		return;
430
			if (isquad)
431
				l = va_arg(ap, quad_t);
432
			else
433
#endif
434
			if (islong)
435
				l = va_arg(ap, long);
436
			else
437
				l = va_arg(ap, int);
438
			sign = 0;
439
			num = l;
440
			if (l < 0) {
441
				num = -l;
442
				sign = 1;
443
			}
321
			}
444
			base = 10;
322
	setstackmark(&smark);
445
			goto number;
323
	s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1);
446
		case 'u':
324
	ret = xvsnprintf(s, len + 1, f, ap);
447
			base = 10;
325
	if (ret == len)
448
			goto uns_number;
326
		__outstr(s, len, dest);
449
		case 'o':
450
			base = 8;
451
			goto uns_number;
452
		case 'p':
453
			outc('0', dest);
454
			outc('x', dest);
455
			/*FALLTHROUGH*/
456
		case 'x':
457
			/* we don't implement 'x'; treat like 'X' */
458
		case 'X':
459
			base = 16;
460
uns_number:	  /* an unsigned number */
461
			sign = 0;
462
#ifdef BSD4_4
463
			if (isquad)
464
				num = va_arg(ap, u_quad_t);
465
			else
466
#endif
467
			if (islong)
468
				num = va_arg(ap, unsigned long);
469
			else
327
			else
470
				num = va_arg(ap, unsigned int);
328
		dest->flags |= OUTPUT_ERR;
471
number:		  /* process a number */
329
	popstackmark(&smark);
472
			p = temp + TEMPSIZE - 1;
473
			*p = '\0';
474
			while (num) {
475
				*--p = digit[num % base];
476
				num /= base;
477
			}
478
			len = (temp + TEMPSIZE - 1) - p;
479
			if (prec < 0)
480
				prec = 1;
481
			if (sharp && *f == 'o' && prec <= len)
482
				prec = len + 1;
483
			pad = 0;
484
			if (width) {
485
				size = len;
486
				if (size < prec)
487
					size = prec;
488
				size += sign;
489
				pad = width - size;
490
				if (flushleft == 0) {
491
					while (--pad >= 0)
492
						outc(' ', dest);
493
				}
494
			}
495
			if (sign)
496
				outc('-', dest);
497
			prec -= len;
498
			while (--prec >= 0)
499
				outc('0', dest);
500
			while (*p)
501
				outc(*p++, dest);
502
			while (--pad >= 0)
503
				outc(' ', dest);
504
			break;
505
		case 's':
506
			p = va_arg(ap, char *);
507
			pad = 0;
508
			if (width) {
509
				len = strlen(p);
510
				if (prec >= 0 && len > prec)
511
					len = prec;
512
				pad = width - len;
513
				if (flushleft == 0) {
514
					while (--pad >= 0)
515
						outc(' ', dest);
516
				}
517
			}
518
			prec++;
519
			while (--prec != 0 && *p)
520
				outc(*p++, dest);
521
			while (--pad >= 0)
522
				outc(' ', dest);
523
			break;
524
		case 'c':
525
			c = va_arg(ap, int);
526
			outc(c, dest);
527
			break;
528
		default:
529
			outc(*f, dest);
530
			break;
531
		}
532
		f++;
533
	}
534
#endif	/* !HAVE_VASPRINTF */
535
}
330
}
331
#endif
536
332
537
333
538
334
Lines 541-587 Link Here
541
 */
337
 */
542
338
543
int
339
int
544
xwrite(fd, buf, nbytes)
340
xwrite(int fd, const void *p, size_t n)
545
	int fd;
341
{
546
	char *buf;
342
	const char *buf = p;
547
	int nbytes;
548
	{
549
	int ntry;
550
	int i;
551
	int n;
552
343
553
	n = nbytes;
344
	while (n) {
554
	ntry = 0;
345
		ssize_t i;
555
	for (;;) {
346
		size_t m;
556
		i = write(fd, buf, n);
347
557
		if (i > 0) {
348
		m = n;
558
			if ((n -= i) <= 0)
349
		if (m > SSIZE_MAX)
559
				return nbytes;
350
			m = SSIZE_MAX;
560
			buf += i;
351
		do {
561
			ntry = 0;
352
			i = write(fd, buf, m);
562
		} else if (i == 0) {
353
		} while (i < 0 && errno == EINTR);
563
			if (++ntry > 10)
354
		if (i < 0)
564
				return nbytes - n;
565
		} else if (errno != EINTR) {
566
			return -1;
355
			return -1;
356
		buf += i;
357
		n -= i;
567
		}
358
		}
568
	}
359
	return 0;
569
}
360
}
570
361
571
362
572
/*
363
#ifdef notyet
573
 * Version of ioctl that retries after a signal is caught.
364
#ifdef USE_GLIBC_STDIO
574
 * XXX unused function
365
void initstreams() {
575
 */
366
	output.stream = stdout;
367
	errout.stream = stderr;
368
}
369
370
371
void
372
openmemout() {
373
	INTOFF;
374
	memout.stream = open_memstream(&memout.buf, &memout.bufsize);
375
	INTON;
376
}
377
576
378
577
int
379
int
578
xioctl(fd, request, arg)
380
__closememout() {
579
	int fd;
381
	int error;
580
	unsigned long request;
382
	error = fclose(memout.stream);
581
	char * arg;
383
	memout.stream = NULL;
384
	return error;
385
}
386
#endif
387
#endif
388
389
390
static int
391
xvsnprintf(char *outbuf, size_t length, const char *fmt, va_list ap)
582
{
392
{
583
	int i;
393
	int ret;
584
394
585
	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
395
	INTOFF;
586
	return i;
396
	ret = vsnprintf(outbuf, length, fmt, ap);
397
	INTON;
398
	return ret;
587
}
399
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/output.h (-21 / +47 lines)
Lines 1-4 Link Here
1
/*	$NetBSD: output.h,v 1.14 1998/01/31 12:37:55 christos Exp $	*/
1
/*	$NetBSD: output.h,v 1.15 2002/05/25 23:13:26 wiz Exp $	*/
2
2
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
Lines 40-89 Link Here
40
40
41
#ifndef OUTPUT_INCL
41
#ifndef OUTPUT_INCL
42
42
43
#ifdef __STDC__
44
#include <stdarg.h>
43
#include <stdarg.h>
45
#else
44
#ifdef USE_GLIBC_STDIO
46
#include <varargs.h>
45
#include <stdio.h>
47
#endif
46
#endif
47
#include <sys/types.h>
48
48
49
struct output {
49
struct output {
50
#ifdef USE_GLIBC_STDIO
51
	FILE *stream;
52
#endif
50
	char *nextc;
53
	char *nextc;
51
	int nleft;
54
	char *end;
52
	char *buf;
55
	char *buf;
53
	int bufsize;
56
	size_t bufsize;
54
	short fd;
57
	int fd;
55
	short flags;
58
	int flags;
56
};
59
};
57
60
58
extern struct output output;
61
extern struct output output;
59
extern struct output errout;
62
extern struct output errout;
63
#ifdef notyet
60
extern struct output memout;
64
extern struct output memout;
65
#endif
61
extern struct output *out1;
66
extern struct output *out1;
62
extern struct output *out2;
67
extern struct output *out2;
63
68
64
void open_mem __P((char *, int, struct output *));
65
void out1str __P((const char *));
66
void out2str __P((const char *));
67
void outstr __P((const char *, struct output *));
69
void outstr __P((const char *, struct output *));
68
void emptyoutbuf __P((struct output *));
70
#ifndef USE_GLIBC_STDIO
71
void outcslow __P((char, struct output *));
72
#endif
69
void flushall __P((void));
73
void flushall __P((void));
70
void flushout __P((struct output *));
74
void flushout __P((struct output *));
71
void freestdout __P((void));
72
void outfmt __P((struct output *, const char *, ...))
75
void outfmt __P((struct output *, const char *, ...))
73
    __attribute__((__format__(__printf__,2,3)));
76
    __attribute__((__format__(__printf__,2,3)));
74
void out1fmt __P((const char *, ...))
77
void out1fmt __P((const char *, ...))
75
    __attribute__((__format__(__printf__,1,2)));
78
    __attribute__((__format__(__printf__,1,2)));
76
void dprintf __P((const char *, ...))
79
int fmtstr __P((char *, size_t, const char *, ...))
77
    __attribute__((__format__(__printf__,1,2)));
78
void fmtstr __P((char *, size_t, const char *, ...))
79
    __attribute__((__format__(__printf__,3,4)));
80
    __attribute__((__format__(__printf__,3,4)));
81
#ifndef USE_GLIBC_STDIO
80
void doformat __P((struct output *, const char *, va_list));
82
void doformat __P((struct output *, const char *, va_list));
81
int xwrite __P((int, char *, int));
83
#endif
82
int xioctl __P((int, unsigned long, char *));
84
int xwrite __P((int, const void *, size_t));
85
#ifdef notyet
86
#ifdef USE_GLIBC_STDIO
87
void initstreams __P((void));
88
void openmemout __P((void));
89
int __closememout __P((void));
90
#endif
91
#endif
83
92
84
#define outc(c, file)	(--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
93
static inline void
85
#define out1c(c)	outc(c, out1);
94
freestdout()
86
#define out2c(c)	outc(c, out2);
95
{
96
	output.nextc = output.buf;
97
	output.flags = 0;
98
}
99
100
#define OUTPUT_ERR 01		/* error occurred on output */
101
102
#ifdef USE_GLIBC_STDIO
103
#define outc(c, o)	putc((c), (o)->stream)
104
#define doformat(d, f, a)	vfprintf((d)->stream, (f), (a))
105
#else
106
#define outc(c, file)	((file)->nextc == (file)->end ? outcslow((c), (file)) : (*(file)->nextc = (c), (file)->nextc++))
107
#endif
108
#define out1c(c)	outc((c), out1)
109
#define out2c(c)	outc((c), out2)
110
#define out1str(s)	outstr((s), out1)
111
#define out2str(s)	outstr((s), out2)
112
#define outerr(f)	((f)->flags & OUTPUT_ERR)
87
113
88
#define OUTPUT_INCL
114
#define OUTPUT_INCL
89
#endif
115
#endif
(-)bin_NetBSD-1.6release.orig/src/bin/sh/parser.c (-297 / +249 lines)
Lines 53-58 Link Here
53
#include "expand.h"	/* defines rmescapes() */
53
#include "expand.h"	/* defines rmescapes() */
54
#include "eval.h"	/* defines commandname */
54
#include "eval.h"	/* defines commandname */
55
#include "redir.h"	/* defines copyfd() */
55
#include "redir.h"	/* defines copyfd() */
56
#include "exec.h"	/* defines find_builtin() */
56
#include "syntax.h"
57
#include "syntax.h"
57
#include "options.h"
58
#include "options.h"
58
#include "input.h"
59
#include "input.h"
Lines 63-68 Link Here
63
#include "mystring.h"
64
#include "mystring.h"
64
#include "alias.h"
65
#include "alias.h"
65
#include "show.h"
66
#include "show.h"
67
#include "builtins.h"
66
#ifndef SMALL
68
#ifndef SMALL
67
#include "myhistedit.h"
69
#include "myhistedit.h"
68
#endif
70
#endif
Lines 76-83 Link Here
76
/* values returned by readtoken */
78
/* values returned by readtoken */
77
#include "token.h"
79
#include "token.h"
78
80
79
#define OPENBRACE '{'
80
#define CLOSEBRACE '}'
81
81
82
82
83
struct heredoc {
83
struct heredoc {
Lines 89-95 Link Here
89
89
90
90
91
91
92
static int noalias = 0;		/* when set, don't handle aliases */
93
struct heredoc *heredoclist;	/* list of here documents to read */
92
struct heredoc *heredoclist;	/* list of here documents to read */
94
int parsebackquote;		/* nonzero if we are inside backquotes */
93
int parsebackquote;		/* nonzero if we are inside backquotes */
95
int doprompt;			/* if set, prompt the user */
94
int doprompt;			/* if set, prompt the user */
Lines 97-103 Link Here
97
int lasttoken;			/* last token read */
96
int lasttoken;			/* last token read */
98
MKINIT int tokpushback;		/* last token pushed back */
97
MKINIT int tokpushback;		/* last token pushed back */
99
char *wordtext;			/* text of last word returned by readtoken */
98
char *wordtext;			/* text of last word returned by readtoken */
100
MKINIT int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
99
int checkkwd;
101
struct nodelist *backquotelist;
100
struct nodelist *backquotelist;
102
union node *redirnode;
101
union node *redirnode;
103
struct heredoc *heredoc;
102
struct heredoc *heredoc;
Lines 109-115 Link Here
109
STATIC union node *andor __P((void));
108
STATIC union node *andor __P((void));
110
STATIC union node *pipeline __P((void));
109
STATIC union node *pipeline __P((void));
111
STATIC union node *command __P((void));
110
STATIC union node *command __P((void));
112
STATIC union node *simplecmd __P((union node **, union node *));
111
STATIC union node *simplecmd __P((void));
113
STATIC union node *makename __P((void));
112
STATIC union node *makename __P((void));
114
STATIC void parsefname __P((void));
113
STATIC void parsefname __P((void));
115
STATIC void parseheredoc __P((void));
114
STATIC void parseheredoc __P((void));
Lines 123-128 Link Here
123
STATIC void setprompt __P((int));
122
STATIC void setprompt __P((int));
124
123
125
124
125
static inline int
126
goodname(const char *p)
127
{
128
	return !*endofname(p);
129
}
130
131
static inline int
132
isassignment(const char *p)
133
{
134
	const char *q = endofname(p);
135
	if (p == q)
136
		return 0;
137
	return *q == '=';
138
}
139
140
126
/*
141
/*
127
 * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
142
 * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
128
 * valid parse tree indicating a blank line.)
143
 * valid parse tree indicating a blank line.)
Lines 136-144 Link Here
136
	tokpushback = 0;
151
	tokpushback = 0;
137
	doprompt = interact;
152
	doprompt = interact;
138
	if (doprompt)
153
	if (doprompt)
139
		setprompt(1);
154
		setprompt(doprompt);
140
	else
141
		setprompt(0);
142
	needprompt = 0;
155
	needprompt = 0;
143
	t = readtoken();
156
	t = readtoken();
144
	if (t == TEOF)
157
	if (t == TEOF)
Lines 157-181 Link Here
157
	union node *n1, *n2, *n3;
170
	union node *n1, *n2, *n3;
158
	int tok;
171
	int tok;
159
172
160
	checkkwd = 2;
173
	checkkwd = CHKNL | CHKKWD | CHKALIAS;
161
	if (nlflag == 0 && tokendlist[peektoken()])
174
	if (nlflag == 2 && tokendlist[peektoken()])
162
		return NULL;
175
		return NULL;
163
	n1 = NULL;
176
	n1 = NULL;
164
	for (;;) {
177
	for (;;) {
165
		n2 = andor();
178
		n2 = andor();
166
		tok = readtoken();
179
		tok = readtoken();
167
		if (tok == TBACKGND) {
180
		if (tok == TBACKGND) {
168
			if (n2->type == NCMD || n2->type == NPIPE) {
181
			if (n2->type == NPIPE) {
169
				n2->ncmd.backgnd = 1;
182
				n2->npipe.backgnd = 1;
170
			} else if (n2->type == NREDIR) {
171
				n2->type = NBACKGND;
172
			} else {
183
			} else {
173
				n3 = (union node *)stalloc(sizeof (struct nredir));
184
				if (n2->type != NREDIR) {
174
				n3->type = NBACKGND;
185
					n3 = stalloc(sizeof(struct nredir));
175
				n3->nredir.n = n2;
186
				n3->nredir.n = n2;
176
				n3->nredir.redirect = NULL;
187
				n3->nredir.redirect = NULL;
177
				n2 = n3;
188
				n2 = n3;
178
			}
189
			}
190
				n2->type = NBACKGND;
191
			}
179
		}
192
		}
180
		if (n1 == NULL) {
193
		if (n1 == NULL) {
181
			n1 = n2;
194
			n1 = n2;
Lines 195-206 Link Here
195
		case TNL:
208
		case TNL:
196
			if (tok == TNL) {
209
			if (tok == TNL) {
197
				parseheredoc();
210
				parseheredoc();
198
				if (nlflag)
211
				if (nlflag == 1)
199
					return n1;
212
					return n1;
200
			} else {
213
			} else {
201
				tokpushback++;
214
				tokpushback++;
202
			}
215
			}
203
			checkkwd = 2;
216
			checkkwd = CHKNL | CHKKWD | CHKALIAS;
204
			if (tokendlist[peektoken()])
217
			if (tokendlist[peektoken()])
205
				return n1;
218
				return n1;
206
			break;
219
			break;
Lines 211-217 Link Here
211
				pungetc();		/* push back EOF on input */
224
				pungetc();		/* push back EOF on input */
212
			return n1;
225
			return n1;
213
		default:
226
		default:
214
			if (nlflag)
227
			if (nlflag == 1)
215
				synexpect(-1);
228
				synexpect(-1);
216
			tokpushback++;
229
			tokpushback++;
217
			return n1;
230
			return n1;
Lines 236-241 Link Here
236
			tokpushback++;
249
			tokpushback++;
237
			return n1;
250
			return n1;
238
		}
251
		}
252
		checkkwd = CHKNL | CHKKWD | CHKALIAS;
239
		n2 = pipeline();
253
		n2 = pipeline();
240
		n3 = (union node *)stalloc(sizeof (struct nbinary));
254
		n3 = (union node *)stalloc(sizeof (struct nbinary));
241
		n3->type = t;
255
		n3->type = t;
Lines 255-262 Link Here
255
269
256
	negate = 0;
270
	negate = 0;
257
	TRACE(("pipeline: entered\n"));
271
	TRACE(("pipeline: entered\n"));
258
	while (readtoken() == TNOT)
272
	if (readtoken() == TNOT) {
259
		negate = !negate;
273
		negate = !negate;
274
		checkkwd = CHKKWD | CHKALIAS;
275
	} else
260
	tokpushback++;
276
	tokpushback++;
261
	n1 = command();
277
	n1 = command();
262
	if (readtoken() == TPIPE) {
278
	if (readtoken() == TPIPE) {
Lines 269-274 Link Here
269
		do {
285
		do {
270
			prev = lp;
286
			prev = lp;
271
			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
287
			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
288
			checkkwd = CHKNL | CHKKWD | CHKALIAS;
272
			lp->n = command();
289
			lp->n = command();
273
			prev->next = lp;
290
			prev->next = lp;
274
		} while (readtoken() == TPIPE);
291
		} while (readtoken() == TPIPE);
Lines 293-320 Link Here
293
	union node *ap, **app;
310
	union node *ap, **app;
294
	union node *cp, **cpp;
311
	union node *cp, **cpp;
295
	union node *redir, **rpp;
312
	union node *redir, **rpp;
296
	int t, negate = 0;
313
	union node **rpp2;
314
	int t;
297
315
298
	checkkwd = 2;
299
	redir = NULL;
316
	redir = NULL;
300
	n1 = NULL;
317
	rpp2 = &redir;
301
	rpp = &redir;
302
303
	/* Check for redirection which may precede command */
304
	while (readtoken() == TREDIR) {
305
		*rpp = n2 = redirnode;
306
		rpp = &n2->nfile.next;
307
		parsefname();
308
	}
309
	tokpushback++;
310
311
	while (readtoken() == TNOT) {
312
		TRACE(("command: TNOT recognized\n"));
313
		negate = !negate;
314
	}
315
	tokpushback++;
316
318
317
	switch (readtoken()) {
319
	switch (readtoken()) {
320
	default:
321
		synexpect(-1);
322
		/* NOTREACHED */
318
	case TIF:
323
	case TIF:
319
		n1 = (union node *)stalloc(sizeof (struct nif));
324
		n1 = (union node *)stalloc(sizeof (struct nif));
320
		n1->type = NIF;
325
		n1->type = NIF;
Lines 338-346 Link Here
338
			n2->nif.elsepart = NULL;
343
			n2->nif.elsepart = NULL;
339
			tokpushback++;
344
			tokpushback++;
340
		}
345
		}
341
		if (readtoken() != TFI)
346
		t = TFI;
342
			synexpect(TFI);
343
		checkkwd = 1;
344
		break;
347
		break;
345
	case TWHILE:
348
	case TWHILE:
346
	case TUNTIL: {
349
	case TUNTIL: {
Lines 353-361 Link Here
353
			synexpect(TDO);
356
			synexpect(TDO);
354
		}
357
		}
355
		n1->nbinary.ch2 = list(0);
358
		n1->nbinary.ch2 = list(0);
356
		if (readtoken() != TDONE)
359
		t = TDONE;
357
			synexpect(TDONE);
358
		checkkwd = 1;
359
		break;
360
		break;
360
	}
361
	}
361
	case TFOR:
362
	case TFOR:
Lines 364-370 Link Here
364
		n1 = (union node *)stalloc(sizeof (struct nfor));
365
		n1 = (union node *)stalloc(sizeof (struct nfor));
365
		n1->type = NFOR;
366
		n1->type = NFOR;
366
		n1->nfor.var = wordtext;
367
		n1->nfor.var = wordtext;
367
		if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
368
		checkkwd = CHKKWD | CHKALIAS;
369
		if (readtoken() == TIN) {
368
			app = &ap;
370
			app = &ap;
369
			while (readtoken() == TWORD) {
371
			while (readtoken() == TWORD) {
370
				n2 = (union node *)stalloc(sizeof (struct narg));
372
				n2 = (union node *)stalloc(sizeof (struct narg));
Lines 379-389 Link Here
379
			if (lasttoken != TNL && lasttoken != TSEMI)
381
			if (lasttoken != TNL && lasttoken != TSEMI)
380
				synexpect(-1);
382
				synexpect(-1);
381
		} else {
383
		} else {
382
			static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
383
								   '@', '=', '\0'};
384
			n2 = (union node *)stalloc(sizeof (struct narg));
384
			n2 = (union node *)stalloc(sizeof (struct narg));
385
			n2->type = NARG;
385
			n2->type = NARG;
386
			n2->narg.text = argvars;
386
			n2->narg.text = (char *)dolatstr;
387
			n2->narg.backquote = NULL;
387
			n2->narg.backquote = NULL;
388
			n2->narg.next = NULL;
388
			n2->narg.next = NULL;
389
			n1->nfor.args = n2;
389
			n1->nfor.args = n2;
Lines 394-410 Link Here
394
			if (lasttoken != TNL && lasttoken != TSEMI)
394
			if (lasttoken != TNL && lasttoken != TSEMI)
395
				tokpushback++;
395
				tokpushback++;
396
		}
396
		}
397
		checkkwd = 2;
397
		checkkwd = CHKNL | CHKKWD | CHKALIAS;
398
		if ((t = readtoken()) == TDO)
398
		if (readtoken() != TDO)
399
			t = TDONE;
399
			synexpect(TDO);
400
		else if (t == TBEGIN)
401
			t = TEND;
402
		else
403
			synexpect(-1);
404
		n1->nfor.body = list(0);
400
		n1->nfor.body = list(0);
405
		if (readtoken() != t)
401
		t = TDONE;
406
			synexpect(t);
407
		checkkwd = 1;
408
		break;
402
		break;
409
	case TCASE:
403
	case TCASE:
410
		n1 = (union node *)stalloc(sizeof (struct ncase));
404
		n1 = (union node *)stalloc(sizeof (struct ncase));
Lines 416-428 Link Here
416
		n2->narg.text = wordtext;
410
		n2->narg.text = wordtext;
417
		n2->narg.backquote = backquotelist;
411
		n2->narg.backquote = backquotelist;
418
		n2->narg.next = NULL;
412
		n2->narg.next = NULL;
419
		while (readtoken() == TNL);
420
		if (lasttoken != TWORD || ! equal(wordtext, "in"))
421
			synerror("expecting \"in\"");
422
		cpp = &n1->ncase.cases;
423
		noalias = 1;
424
		checkkwd = 2, readtoken();
425
		do {
413
		do {
414
			checkkwd = CHKKWD | CHKALIAS;
415
		} while (readtoken() == TNL);
416
		if (lasttoken != TIN)
417
			synexpect(TIN);
418
		cpp = &n1->ncase.cases;
419
next_case:
420
		checkkwd = CHKNL | CHKKWD;
421
		t = readtoken();
422
		while(t != TESAC) {
423
			if (lasttoken == TLP)
424
				readtoken();
426
			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
425
			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
427
			cp->type = NCLIST;
426
			cp->type = NCLIST;
428
			app = &cp->nclist.pattern;
427
			app = &cp->nclist.pattern;
Lines 431-503 Link Here
431
				ap->type = NARG;
430
				ap->type = NARG;
432
				ap->narg.text = wordtext;
431
				ap->narg.text = wordtext;
433
				ap->narg.backquote = backquotelist;
432
				ap->narg.backquote = backquotelist;
434
				if (checkkwd = 2, readtoken() != TPIPE)
433
				if (readtoken() != TPIPE)
435
					break;
434
					break;
436
				app = &ap->narg.next;
435
				app = &ap->narg.next;
437
				readtoken();
436
				readtoken();
438
			}
437
			}
439
			ap->narg.next = NULL;
438
			ap->narg.next = NULL;
440
			noalias = 0;
439
			if (lasttoken != TRP)
441
			if (lasttoken != TRP) {
442
				synexpect(TRP);
440
				synexpect(TRP);
443
			}
441
			cp->nclist.body = list(2);
444
			cp->nclist.body = list(0);
445
442
446
			checkkwd = 2;
443
			cpp = &cp->nclist.next;
444
445
			checkkwd = CHKNL | CHKKWD;
447
			if ((t = readtoken()) != TESAC) {
446
			if ((t = readtoken()) != TESAC) {
448
				if (t != TENDCASE) {
447
				if (t != TENDCASE)
449
					noalias = 0;
450
					synexpect(TENDCASE);
448
					synexpect(TENDCASE);
451
				} else {
449
				else
452
					noalias = 1;
450
					goto next_case;
453
					checkkwd = 2;
454
					readtoken();
455
				}
451
				}
456
			}
452
			}
457
			cpp = &cp->nclist.next;
458
		} while(lasttoken != TESAC);
459
		noalias = 0;
460
		*cpp = NULL;
453
		*cpp = NULL;
461
		checkkwd = 1;
454
		goto redir;
462
		break;
463
	case TLP:
455
	case TLP:
464
		n1 = (union node *)stalloc(sizeof (struct nredir));
456
		n1 = (union node *)stalloc(sizeof (struct nredir));
465
		n1->type = NSUBSHELL;
457
		n1->type = NSUBSHELL;
466
		n1->nredir.n = list(0);
458
		n1->nredir.n = list(0);
467
		n1->nredir.redirect = NULL;
459
		n1->nredir.redirect = NULL;
468
		if (readtoken() != TRP)
460
		t = TRP;
469
			synexpect(TRP);
470
		checkkwd = 1;
471
		break;
461
		break;
472
	case TBEGIN:
462
	case TBEGIN:
473
		n1 = list(0);
463
		n1 = list(0);
474
		if (readtoken() != TEND)
464
		t = TEND;
475
			synexpect(TEND);
476
		checkkwd = 1;
477
		break;
465
		break;
478
	/* Handle an empty command like other simple commands.  */
479
	case TSEMI:
480
		/*
481
		 * An empty command before a ; doesn't make much sense, and
482
		 * should certainly be disallowed in the case of `if ;'.
483
		 */
484
		if (!redir)
485
			synexpect(-1);
486
	case TAND:
487
	case TOR:
488
	case TNL:
489
	case TEOF:
490
	case TWORD:
466
	case TWORD:
491
	case TRP:
467
	case TREDIR:
492
		tokpushback++;
468
		tokpushback++;
493
		n1 = simplecmd(rpp, redir);
469
		return simplecmd();
494
		goto checkneg;
495
	default:
496
		synexpect(-1);
497
		/* NOTREACHED */
498
	}
470
	}
499
471
472
	if (readtoken() != t)
473
		synexpect(t);
474
475
redir:
500
	/* Now check for redirection which may follow command */
476
	/* Now check for redirection which may follow command */
477
	checkkwd = CHKKWD | CHKALIAS;
478
	rpp = rpp2;
501
	while (readtoken() == TREDIR) {
479
	while (readtoken() == TREDIR) {
502
		*rpp = n2 = redirnode;
480
		*rpp = n2 = redirnode;
503
		rpp = &n2->nfile.next;
481
		rpp = &n2->nfile.next;
Lines 515-606 Link Here
515
		n1->nredir.redirect = redir;
493
		n1->nredir.redirect = redir;
516
	}
494
	}
517
495
518
checkneg:
519
	if (negate) {
520
		n2 = (union node *)stalloc(sizeof (struct nnot));
521
		n2->type = NNOT;
522
		n2->nnot.com = n1;
523
		return n2;
524
	}
525
	else
526
		return n1;
496
		return n1;
527
}
497
}
528
498
529
499
530
STATIC union node *
500
STATIC union node *
531
simplecmd(rpp, redir)
501
simplecmd() {
532
	union node **rpp, *redir;
533
	{
534
	union node *args, **app;
502
	union node *args, **app;
535
	union node **orig_rpp = rpp;
503
	union node *n = NULL;
536
	union node *n = NULL, *n2;
504
	union node *vars, **vpp;
537
	int negate = 0;
505
	union node **rpp, *redir;
538
506
	int savecheckkwd;
539
	/* If we don't have any redirections already, then we must reset */
540
	/* rpp to be the address of the local redir variable.  */
541
	if (redir == 0)
542
		rpp = &redir;
543
507
544
	args = NULL;
508
	args = NULL;
545
	app = &args;
509
	app = &args;
546
	/*
510
	vars = NULL;
547
	 * We save the incoming value, because we need this for shell
511
	vpp = &vars;
548
	 * functions.  There can not be a redirect or an argument between
512
	redir = NULL;
549
	 * the function name and the open parenthesis.
513
	rpp = &redir;
550
	 */
551
	orig_rpp = rpp;
552
553
	while (readtoken() == TNOT) {
554
		TRACE(("command: TNOT recognized\n"));
555
		negate = !negate;
556
	}
557
	tokpushback++;
558
514
515
	savecheckkwd = CHKALIAS;
559
	for (;;) {
516
	for (;;) {
560
		if (readtoken() == TWORD) {
517
		checkkwd = savecheckkwd;
518
		switch (readtoken()) {
519
		case TWORD:
561
			n = (union node *)stalloc(sizeof (struct narg));
520
			n = (union node *)stalloc(sizeof (struct narg));
562
			n->type = NARG;
521
			n->type = NARG;
563
			n->narg.text = wordtext;
522
			n->narg.text = wordtext;
564
			n->narg.backquote = backquotelist;
523
			n->narg.backquote = backquotelist;
524
			if (savecheckkwd && isassignment(wordtext)) {
525
				*vpp = n;
526
				vpp = &n->narg.next;
527
			} else {
565
			*app = n;
528
			*app = n;
566
			app = &n->narg.next;
529
			app = &n->narg.next;
567
		} else if (lasttoken == TREDIR) {
530
				savecheckkwd = 0;
531
			}
532
			break;
533
		case TREDIR:
568
			*rpp = n = redirnode;
534
			*rpp = n = redirnode;
569
			rpp = &n->nfile.next;
535
			rpp = &n->nfile.next;
570
			parsefname();	/* read name of redirection file */
536
			parsefname();	/* read name of redirection file */
571
		} else if (lasttoken == TLP && app == &args->narg.next
537
			break;
572
					    && rpp == orig_rpp) {
538
		case TLP:
539
			if (
540
				args && app == &args->narg.next &&
541
				!vars && !redir
542
			) {
543
				struct builtincmd *bcmd;
544
				const char *name;
545
573
			/* We have a function */
546
			/* We have a function */
574
			if (readtoken() != TRP)
547
			if (readtoken() != TRP)
575
				synexpect(TRP);
548
				synexpect(TRP);
576
#ifdef notdef
549
				name = n->narg.text;
577
			if (! goodname(n->narg.text))
550
				if (
551
					!goodname(name) || (
552
						(bcmd = find_builtin(name)) &&
553
						bcmd->flags & BUILTIN_SPECIAL
554
					)
555
				)
578
				synerror("Bad function name");
556
				synerror("Bad function name");
579
#endif
580
			n->type = NDEFUN;
557
			n->type = NDEFUN;
558
				checkkwd = CHKNL | CHKKWD | CHKALIAS;
581
			n->narg.next = command();
559
			n->narg.next = command();
582
			goto checkneg;
560
				return n;
583
		} else {
561
			}
562
			/* fall through */
563
		default:
584
			tokpushback++;
564
			tokpushback++;
585
			break;
565
			goto out;
586
		}
566
		}
587
	}
567
	}
568
out:
588
	*app = NULL;
569
	*app = NULL;
570
	*vpp = NULL;
589
	*rpp = NULL;
571
	*rpp = NULL;
590
	n = (union node *)stalloc(sizeof (struct ncmd));
572
	n = (union node *)stalloc(sizeof (struct ncmd));
591
	n->type = NCMD;
573
	n->type = NCMD;
592
	n->ncmd.backgnd = 0;
593
	n->ncmd.args = args;
574
	n->ncmd.args = args;
575
	n->ncmd.assign = vars;
594
	n->ncmd.redirect = redir;
576
	n->ncmd.redirect = redir;
595
596
checkneg:
597
	if (negate) {
598
		n2 = (union node *)stalloc(sizeof (struct nnot));
599
		n2->type = NNOT;
600
		n2->nnot.com = n;
601
		return n2;
602
	}
603
	else
604
		return n;
577
		return n;
605
}
578
}
606
579
Lines 682-690 Link Here
682
	struct heredoc *here;
655
	struct heredoc *here;
683
	union node *n;
656
	union node *n;
684
657
685
	while (heredoclist) {
686
		here = heredoclist;
658
		here = heredoclist;
687
		heredoclist = here->next;
659
	heredoclist = 0;
660
661
	while (here) {
688
		if (needprompt) {
662
		if (needprompt) {
689
			setprompt(2);
663
			setprompt(2);
690
			needprompt = 0;
664
			needprompt = 0;
Lines 697-702 Link Here
697
		n->narg.text = wordtext;
671
		n->narg.text = wordtext;
698
		n->narg.backquote = backquotelist;
672
		n->narg.backquote = backquotelist;
699
		here->here->nhere.doc = n;
673
		here->here->nhere.doc = n;
674
		here = here->next;
700
	}
675
	}
701
}
676
}
702
677
Lines 712-764 Link Here
712
STATIC int
687
STATIC int
713
readtoken() {
688
readtoken() {
714
	int t;
689
	int t;
715
	int savecheckkwd = checkkwd;
716
#ifdef DEBUG
690
#ifdef DEBUG
717
	int alreadyseen = tokpushback;
691
	int alreadyseen = tokpushback;
718
#endif
692
#endif
719
	struct alias *ap;
720
693
721
	top:
694
top:
722
	t = xxreadtoken();
695
	t = xxreadtoken();
723
696
724
	if (checkkwd) {
725
		/*
697
		/*
726
		 * eat newlines
698
		 * eat newlines
727
		 */
699
		 */
728
		if (checkkwd == 2) {
700
	if (checkkwd & CHKNL) {
729
			checkkwd = 0;
730
			while (t == TNL) {
701
			while (t == TNL) {
731
				parseheredoc();
702
				parseheredoc();
732
				t = xxreadtoken();
703
				t = xxreadtoken();
733
			}
704
			}
734
		} else
705
	}
735
			checkkwd = 0;
706
707
	if (t != TWORD || quoteflag) {
708
		goto out;
709
	}
710
736
		/*
711
		/*
737
		 * check for keywords and aliases
712
	 * check for keywords
738
		 */
713
		 */
739
		if (t == TWORD && !quoteflag)
714
	if (checkkwd & CHKKWD) {
740
		{
741
			const char *const *pp;
715
			const char *const *pp;
742
716
743
			for (pp = parsekwd; *pp; pp++) {
717
		if ((pp = findkwd(wordtext))) {
744
				if (**pp == *wordtext && equal(*pp, wordtext))
718
			lasttoken = t = pp - parsekwd + KWDOFFSET;
745
				{
746
					lasttoken = t = pp - 
747
					    parsekwd + KWDOFFSET;
748
					TRACE(("keyword %s recognized\n", tokname[t]));
719
					TRACE(("keyword %s recognized\n", tokname[t]));
749
					goto out;
720
					goto out;
750
				}
721
				}
751
			}
722
			}
752
			if(!noalias &&
723
753
			    (ap = lookupalias(wordtext, 1)) != NULL) {
724
	if (checkkwd & CHKALIAS) {
754
				pushstring(ap->val, strlen(ap->val), ap);
725
		struct alias *ap;
755
				checkkwd = savecheckkwd;
726
		if ((ap = lookupalias(wordtext, 1)) != NULL) {
727
			if (*ap->val) {
728
				pushstring(ap->val, ap);
729
			}
756
				goto top;
730
				goto top;
757
			}
731
			}
758
		}
732
		}
759
out:
733
out:
760
		checkkwd = (t == TNOT) ? savecheckkwd : 0;
734
	checkkwd = 0;
761
	}
762
#ifdef DEBUG
735
#ifdef DEBUG
763
	if (!alreadyseen)
736
	if (!alreadyseen)
764
	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
737
	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
Lines 804-813 Link Here
804
	startlinno = plinno;
777
	startlinno = plinno;
805
	for (;;) {	/* until token or start of word found */
778
	for (;;) {	/* until token or start of word found */
806
		c = pgetc_macro();
779
		c = pgetc_macro();
807
		if (c == ' ' || c == '\t')
808
			continue;		/* quick check for white space first */
809
		switch (c) {
780
		switch (c) {
810
		case ' ': case '\t':
781
		case ' ': case '\t':
782
		case PEOA:
811
			continue;
783
			continue;
812
		case '#':
784
		case '#':
813
			while ((c = pgetc()) != '\n' && c != PEOF);
785
			while ((c = pgetc()) != '\n' && c != PEOF);
Lines 818-825 Link Here
818
				startlinno = ++plinno;
790
				startlinno = ++plinno;
819
				if (doprompt)
791
				if (doprompt)
820
					setprompt(2);
792
					setprompt(2);
821
				else
822
					setprompt(0);
823
				continue;
793
				continue;
824
			}
794
			}
825
			pungetc();
795
			pungetc();
Lines 879-906 Link Here
879
#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
849
#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
880
#define	PARSEARITH()	{goto parsearith; parsearith_return:;}
850
#define	PARSEARITH()	{goto parsearith; parsearith_return:;}
881
851
882
/*
883
 * Keep track of nested doublequotes in dblquote and doublequotep.
884
 * We use dblquote for the first 32 levels, and we expand to a malloc'ed
885
 * region for levels above that. Usually we never need to malloc.
886
 * This code assumes that an int is 32 bits. We don't use uint32_t,
887
 * because the rest of the code does not.
888
 */
889
#define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \
890
    (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32))))
891
892
#define SETDBLQUOTE() \
893
    if (varnest < 32) \
894
	dblquote |= (1 << varnest); \
895
    else \
896
	dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32))
897
898
#define CLRDBLQUOTE() \
899
    if (varnest < 32) \
900
	dblquote &= ~(1 << varnest); \
901
    else \
902
	dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32))
903
904
STATIC int
852
STATIC int
905
readtoken1(firstc, syntax, eofmark, striptabs)
853
readtoken1(firstc, syntax, eofmark, striptabs)
906
	int firstc;
854
	int firstc;
Lines 914-937 Link Here
914
	char line[EOFMARKLEN + 1];
862
	char line[EOFMARKLEN + 1];
915
	struct nodelist *bqlist;
863
	struct nodelist *bqlist;
916
	int quotef;
864
	int quotef;
917
	int *dblquotep = NULL;
918
	size_t maxnest = 32;
919
	int dblquote;
865
	int dblquote;
920
	int varnest;	/* levels of variables expansion */
866
	int varnest;	/* levels of variables expansion */
921
	int arinest;	/* levels of arithmetic expansion */
867
	int arinest;	/* levels of arithmetic expansion */
922
	int parenlevel;	/* levels of parens in arithmetic */
868
	int parenlevel;	/* levels of parens in arithmetic */
869
	int dqvarnest;	/* levels of variables expansion within double quotes */
923
	int oldstyle;
870
	int oldstyle;
924
	char const *prevsyntax;	/* syntax before arithmetic */
871
	char const *prevsyntax;	/* syntax before arithmetic */
925
#if __GNUC__
872
#if __GNUC__
926
	/* Avoid longjmp clobbering */
873
	/* Avoid longjmp clobbering */
927
	(void) &maxnest;
928
	(void) &dblquotep;
929
	(void) &out;
874
	(void) &out;
930
	(void) &quotef;
875
	(void) &quotef;
931
	(void) &dblquote;
876
	(void) &dblquote;
932
	(void) &varnest;
877
	(void) &varnest;
933
	(void) &arinest;
878
	(void) &arinest;
934
	(void) &parenlevel;
879
	(void) &parenlevel;
880
	(void) &dqvarnest;
935
	(void) &oldstyle;
881
	(void) &oldstyle;
936
	(void) &prevsyntax;
882
	(void) &prevsyntax;
937
	(void) &syntax;
883
	(void) &syntax;
Lines 939-952 Link Here
939
885
940
	startlinno = plinno;
886
	startlinno = plinno;
941
	dblquote = 0;
887
	dblquote = 0;
942
	varnest = 0;
888
	if (syntax == DQSYNTAX)
943
	if (syntax == DQSYNTAX) {
889
		dblquote = 1;
944
		SETDBLQUOTE();
945
	}
946
	quotef = 0;
890
	quotef = 0;
947
	bqlist = NULL;
891
	bqlist = NULL;
892
	varnest = 0;
948
	arinest = 0;
893
	arinest = 0;
949
	parenlevel = 0;
894
	parenlevel = 0;
895
	dqvarnest = 0;
950
896
951
	STARTSTACKSTR(out);
897
	STARTSTACKSTR(out);
952
	loop: {	/* for each line, until end of word */
898
	loop: {	/* for each line, until end of word */
Lines 962-968 Link Here
962
#endif
908
#endif
963
		CHECKEND();	/* set c to PEOF if at end of here document */
909
		CHECKEND();	/* set c to PEOF if at end of here document */
964
		for (;;) {	/* until end of line or end of word */
910
		for (;;) {	/* until end of line or end of word */
965
			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */
911
			CHECKSTRSPACE(4, out);	/* permit 4 calls to USTPUTC */
966
			switch(syntax[c]) {
912
			switch(syntax[c]) {
967
			case CNL:	/* '\n' */
913
			case CNL:	/* '\n' */
968
				if (syntax == BASESYNTAX)
914
				if (syntax == BASESYNTAX)
Lines 971-1052 Link Here
971
				plinno++;
917
				plinno++;
972
				if (doprompt)
918
				if (doprompt)
973
					setprompt(2);
919
					setprompt(2);
974
				else
975
					setprompt(0);
976
				c = pgetc();
920
				c = pgetc();
977
				goto loop;		/* continue outer loop */
921
				goto loop;		/* continue outer loop */
978
			case CWORD:
922
			case CWORD:
979
				USTPUTC(c, out);
923
				USTPUTC(c, out);
980
				break;
924
				break;
981
			case CCTL:
925
			case CCTL:
982
				if (eofmark == NULL || ISDBLQUOTE())
926
				if (eofmark == NULL || dblquote)
983
					USTPUTC(CTLESC, out);
927
					USTPUTC(CTLESC, out);
984
				USTPUTC(c, out);
928
				USTPUTC(c, out);
985
				break;
929
				break;
986
			case CBACK:	/* backslash */
930
			case CBACK:	/* backslash */
987
				c = pgetc();
931
				c = pgetc2();
988
				if (c == PEOF) {
932
				if (c == PEOF) {
933
					USTPUTC(CTLESC, out);
989
					USTPUTC('\\', out);
934
					USTPUTC('\\', out);
990
					pungetc();
935
					pungetc();
991
				} else if (c == '\n') {
936
				} else if (c == '\n') {
992
					if (doprompt)
937
					if (doprompt)
993
						setprompt(2);
938
						setprompt(2);
994
					else
995
						setprompt(0);
996
				} else {
939
				} else {
997
					if (ISDBLQUOTE() && c != '\\' &&
940
					if (
998
					    c != '`' && c != '$' &&
941
						dblquote &&
999
					    (c != '"' || eofmark != NULL))
942
						c != '\\' && c != '`' &&
943
						c != '$' && (
944
							c != '"' ||
945
							eofmark != NULL
946
						)
947
					) {
948
						USTPUTC(CTLESC, out);
1000
						USTPUTC('\\', out);
949
						USTPUTC('\\', out);
950
					}
1001
					if (SQSYNTAX[c] == CCTL)
951
					if (SQSYNTAX[c] == CCTL)
1002
						USTPUTC(CTLESC, out);
952
						USTPUTC(CTLESC, out);
1003
					else if (eofmark == NULL)
1004
						USTPUTC(CTLQUOTEMARK, out);
1005
					USTPUTC(c, out);
953
					USTPUTC(c, out);
1006
					quotef++;
954
					quotef++;
1007
				}
955
				}
1008
				break;
956
				break;
1009
			case CSQUOTE:
957
			case CSQUOTE:
1010
				if (syntax != SQSYNTAX) {
1011
				    if (eofmark == NULL)
1012
					    USTPUTC(CTLQUOTEMARK, out);
1013
				    syntax = SQSYNTAX;
958
				    syntax = SQSYNTAX;
1014
				    break;
959
quotemark:
960
				if (eofmark == NULL) {
961
					USTPUTC(CTLQUOTEMARK, out);
1015
				}
962
				}
1016
				/* FALLTHROUGH */
963
				break;
1017
			case CDQUOTE:
964
			case CDQUOTE:
965
				syntax = DQSYNTAX;
966
				dblquote = 1;
967
				goto quotemark;
968
			case CENDQUOTE:
1018
				if (eofmark != NULL && arinest == 0 &&
969
				if (eofmark != NULL && arinest == 0 &&
1019
				    varnest == 0) {
970
				    varnest == 0) {
1020
					USTPUTC(c, out);
971
					USTPUTC(c, out);
1021
				} else {
972
				} else {
1022
					if (arinest) {
973
					if (dqvarnest == 0) {
1023
						if (c != '"' || ISDBLQUOTE()) {
1024
							syntax = ARISYNTAX;
1025
							CLRDBLQUOTE();
1026
						} else {
1027
							syntax = DQSYNTAX;
1028
							SETDBLQUOTE();
1029
							USTPUTC(CTLQUOTEMARK, out);
1030
						}
1031
					} else if (eofmark == NULL) {
1032
						if (c != '"' || ISDBLQUOTE()) {
1033
							syntax = BASESYNTAX;
974
							syntax = BASESYNTAX;
1034
							CLRDBLQUOTE();
975
						dblquote = 0;
1035
						} else {
1036
							syntax = DQSYNTAX;
1037
							SETDBLQUOTE();
1038
							USTPUTC(CTLQUOTEMARK, out);
1039
						}
1040
					}
976
					}
1041
					quotef++;
977
					quotef++;
978
					goto quotemark;
1042
				}
979
				}
1043
				break;
980
				break;
1044
			case CVAR:	/* '$' */
981
			case CVAR:	/* '$' */
1045
				PARSESUB();		/* parse substitution */
982
				PARSESUB();		/* parse substitution */
1046
				break;
983
				break;
1047
			case CENDVAR:	/* CLOSEBRACE */
984
			case CENDVAR:	/* '}' */
1048
				if (varnest > 0 && !ISDBLQUOTE()) {
985
				if (varnest > 0) {
1049
					varnest--;
986
					varnest--;
987
					if (dqvarnest > 0) {
988
						dqvarnest--;
989
					}
1050
					USTPUTC(CTLENDVAR, out);
990
					USTPUTC(CTLENDVAR, out);
1051
				} else {
991
				} else {
1052
					USTPUTC(c, out);
992
					USTPUTC(c, out);
Lines 1066-1074 Link Here
1066
							USTPUTC(CTLENDARI, out);
1006
							USTPUTC(CTLENDARI, out);
1067
							syntax = prevsyntax;
1007
							syntax = prevsyntax;
1068
							if (syntax == DQSYNTAX)
1008
							if (syntax == DQSYNTAX)
1069
								SETDBLQUOTE();
1009
								dblquote = 1;
1070
							else
1010
							else
1071
								CLRDBLQUOTE();
1011
								dblquote = 0;
1072
						} else
1012
						} else
1073
							USTPUTC(')', out);
1013
							USTPUTC(')', out);
1074
					} else {
1014
					} else {
Lines 1086-1096 Link Here
1086
				break;
1026
				break;
1087
			case CEOF:
1027
			case CEOF:
1088
				goto endword;		/* exit outer loop */
1028
				goto endword;		/* exit outer loop */
1029
			case CIGN:
1030
				break;
1089
			default:
1031
			default:
1090
				if (varnest == 0)
1032
				if (varnest == 0)
1091
					goto endword;	/* exit outer loop */
1033
					goto endword;	/* exit outer loop */
1034
				if (c != PEOA) {
1092
				USTPUTC(c, out);
1035
				USTPUTC(c, out);
1093
			}
1036
			}
1037
			}
1094
			c = pgetc_macro();
1038
			c = pgetc_macro();
1095
		}
1039
		}
1096
	}
1040
	}
Lines 1122-1129 Link Here
1122
	backquotelist = bqlist;
1066
	backquotelist = bqlist;
1123
	grabstackblock(len);
1067
	grabstackblock(len);
1124
	wordtext = out;
1068
	wordtext = out;
1125
	if (dblquotep != NULL)
1126
	    ckfree(dblquotep);
1127
	return lasttoken = TWORD;
1069
	return lasttoken = TWORD;
1128
/* end of readtoken routine */
1070
/* end of readtoken routine */
1129
1071
Lines 1137-1145 Link Here
1137
1079
1138
checkend: {
1080
checkend: {
1139
	if (eofmark) {
1081
	if (eofmark) {
1082
		if (c == PEOA) {
1083
			c = pgetc2();
1084
		}
1140
		if (striptabs) {
1085
		if (striptabs) {
1141
			while (c == '\t')
1086
			while (c == '\t') {
1142
				c = pgetc();
1087
				c = pgetc2();
1088
			}
1143
		}
1089
		}
1144
		if (c == *eofmark) {
1090
		if (c == *eofmark) {
1145
			if (pfgets(line, sizeof line) != NULL) {
1091
			if (pfgets(line, sizeof line) != NULL) {
Lines 1152-1158 Link Here
1152
					plinno++;
1098
					plinno++;
1153
					needprompt = doprompt;
1099
					needprompt = doprompt;
1154
				} else {
1100
				} else {
1155
					pushstring(line, strlen(line), NULL);
1101
					pushstring(line, NULL);
1156
				}
1102
				}
1157
			}
1103
			}
1158
		}
1104
		}
Lines 1238-1244 Link Here
1238
	static const char types[] = "}-+?=";
1184
	static const char types[] = "}-+?=";
1239
1185
1240
	c = pgetc();
1186
	c = pgetc();
1241
	if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
1187
	if (
1188
		c <= PEOA  ||
1189
		(c != '(' && c != '{' && !is_name(c) && !is_special(c))
1190
	) {
1242
		USTPUTC('$', out);
1191
		USTPUTC('$', out);
1243
		pungetc();
1192
		pungetc();
1244
	} else if (c == '(') {	/* $(command) or $((arith)) */
1193
	} else if (c == '(') {	/* $(command) or $((arith)) */
Lines 1253-1262 Link Here
1253
		typeloc = out - stackblock();
1202
		typeloc = out - stackblock();
1254
		USTPUTC(VSNORMAL, out);
1203
		USTPUTC(VSNORMAL, out);
1255
		subtype = VSNORMAL;
1204
		subtype = VSNORMAL;
1256
		if (c == OPENBRACE) {
1205
		if (c == '{') {
1257
			c = pgetc();
1206
			c = pgetc();
1258
			if (c == '#') {
1207
			if (c == '#') {
1259
				if ((c = pgetc()) == CLOSEBRACE)
1208
				if ((c = pgetc()) == '}')
1260
					c = '#';
1209
					c = '#';
1261
				else
1210
				else
1262
					subtype = VSLENGTH;
1211
					subtype = VSLENGTH;
Lines 1264-1274 Link Here
1264
			else
1213
			else
1265
				subtype = 0;
1214
				subtype = 0;
1266
		}
1215
		}
1267
		if (is_name(c)) {
1216
		if (c > PEOA && is_name(c)) {
1268
			do {
1217
			do {
1269
				STPUTC(c, out);
1218
				STPUTC(c, out);
1270
				c = pgetc();
1219
				c = pgetc();
1271
			} while (is_in_name(c));
1220
			} while (c > PEOA && is_in_name(c));
1272
		} else if (is_digit(c)) {
1221
		} else if (is_digit(c)) {
1273
			do {
1222
			do {
1274
				USTPUTC(c, out);
1223
				USTPUTC(c, out);
Lines 1313-1327 Link Here
1313
		} else {
1262
		} else {
1314
			pungetc();
1263
			pungetc();
1315
		}
1264
		}
1316
		if (ISDBLQUOTE() || arinest)
1265
		if (dblquote || arinest)
1317
			flags |= VSQUOTE;
1266
			flags |= VSQUOTE;
1318
		*(stackblock() + typeloc) = subtype | flags;
1267
		*(stackblock() + typeloc) = subtype | flags;
1319
		if (subtype != VSNORMAL) {
1268
		if (subtype != VSNORMAL) {
1320
			varnest++;
1269
			varnest++;
1321
			if (varnest >= maxnest) {
1270
			if (dblquote || arinest) {
1322
				dblquotep = ckrealloc(dblquotep, maxnest / 8);
1271
				dqvarnest++;
1323
				dblquotep[(maxnest / 32) - 1] = 0;
1324
				maxnest += 32;
1325
			}
1272
			}
1326
		}
1273
		}
1327
	}
1274
	}
Lines 1343-1349 Link Here
1343
	char *volatile str;
1290
	char *volatile str;
1344
	struct jmploc jmploc;
1291
	struct jmploc jmploc;
1345
	struct jmploc *volatile savehandler;
1292
	struct jmploc *volatile savehandler;
1346
	int savelen;
1293
	size_t savelen;
1347
	int saveprompt;
1294
	int saveprompt;
1348
#ifdef __GNUC__
1295
#ifdef __GNUC__
1349
	(void) &saveprompt;
1296
	(void) &saveprompt;
Lines 1373-1379 Link Here
1373
                   reread it as input, interpreting it normally.  */
1320
                   reread it as input, interpreting it normally.  */
1374
                char *pout;
1321
                char *pout;
1375
                int pc;
1322
                int pc;
1376
                int psavelen;
1323
                size_t psavelen;
1377
                char *pstr;
1324
                char *pstr;
1378
1325
1379
1326
Lines 1392-1399 Link Here
1392
					plinno++;
1339
					plinno++;
1393
					if (doprompt)
1340
					if (doprompt)
1394
						setprompt(2);
1341
						setprompt(2);
1395
					else
1396
						setprompt(0);
1397
					/*
1342
					/*
1398
					 * If eating a newline, avoid putting
1343
					 * If eating a newline, avoid putting
1399
					 * the newline into the new character
1344
					 * the newline into the new character
Lines 1403-1420 Link Here
1403
					continue;
1348
					continue;
1404
				}
1349
				}
1405
                                if (pc != '\\' && pc != '`' && pc != '$'
1350
                                if (pc != '\\' && pc != '`' && pc != '$'
1406
                                    && (!ISDBLQUOTE() || pc != '"'))
1351
                                    && (!dblquote || pc != '"'))
1407
                                        STPUTC('\\', pout);
1352
                                        STPUTC('\\', pout);
1353
				if (pc > PEOA) {
1408
				break;
1354
				break;
1409
1355
				}
1410
			case '\n':
1356
				/* fall through */
1411
				plinno++;
1412
				needprompt = doprompt;
1413
				break;
1414
1357
1415
			case PEOF:
1358
			case PEOF:
1359
			case PEOA:
1416
			        startlinno = plinno;
1360
			        startlinno = plinno;
1417
				synerror("EOF in backquote substitution");
1361
				synerror("EOF in backquote substitution");
1362
1363
			case '\n':
1364
				plinno++;
1365
				needprompt = doprompt;
1418
 				break;
1366
 				break;
1419
1367
1420
			default:
1368
			default:
Lines 1427-1433 Link Here
1427
                psavelen = pout - stackblock();
1375
                psavelen = pout - stackblock();
1428
                if (psavelen > 0) {
1376
                if (psavelen > 0) {
1429
			pstr = grabstackstr(pout);
1377
			pstr = grabstackstr(pout);
1430
			setinputstring(pstr, 1);
1378
			setinputstring(pstr);
1431
                }
1379
                }
1432
        }
1380
        }
1433
	nlpp = &bqlist;
1381
	nlpp = &bqlist;
Lines 1442-1448 Link Here
1442
		doprompt = 0;
1390
		doprompt = 0;
1443
	}
1391
	}
1444
1392
1445
	n = list(0);
1393
	n = list(2);
1446
1394
1447
	if (oldstyle)
1395
	if (oldstyle)
1448
		doprompt = saveprompt;
1396
		doprompt = saveprompt;
Lines 1473-1479 Link Here
1473
	}
1421
	}
1474
	parsebackquote = savepbq;
1422
	parsebackquote = savepbq;
1475
	handler = savehandler;
1423
	handler = savehandler;
1476
	if (arinest || ISDBLQUOTE())
1424
	if (arinest || dblquote)
1477
		USTPUTC(CTLBACKQ | CTLQUOTE, out);
1425
		USTPUTC(CTLBACKQ | CTLQUOTE, out);
1478
	else
1426
	else
1479
		USTPUTC(CTLBACKQ, out);
1427
		USTPUTC(CTLBACKQ, out);
Lines 1492-1498 Link Here
1492
		prevsyntax = syntax;
1440
		prevsyntax = syntax;
1493
		syntax = ARISYNTAX;
1441
		syntax = ARISYNTAX;
1494
		USTPUTC(CTLARI, out);
1442
		USTPUTC(CTLARI, out);
1495
		if (ISDBLQUOTE())
1443
		if (dblquote)
1496
			USTPUTC('"',out);
1444
			USTPUTC('"',out);
1497
		else
1445
		else
1498
			USTPUTC(' ',out);
1446
			USTPUTC(' ',out);
Lines 1511-1516 Link Here
1511
1459
1512
1460
1513
#ifdef mkinit
1461
#ifdef mkinit
1462
INCLUDE "parser.h"
1514
RESET {
1463
RESET {
1515
	tokpushback = 0;
1464
	tokpushback = 0;
1516
	checkkwd = 0;
1465
	checkkwd = 0;
Lines 1543-1565 Link Here
1543
1492
1544
1493
1545
/*
1494
/*
1546
 * Return true if the argument is a legal variable name (a letter or
1495
 * Return of a legal variable name (a letter or underscore followed by zero or
1547
 * underscore followed by zero or more letters, underscores, and digits).
1496
 * more letters, underscores, and digits).
1548
 */
1497
 */
1549
1498
1550
int
1499
char *
1551
goodname(char *name)
1500
endofname(const char *name)
1552
	{
1501
	{
1553
	char *p;
1502
	char *p;
1554
1503
1555
	p = name;
1504
	p = (char *) name;
1556
	if (! is_name(*p))
1505
	if (! is_name(*p))
1557
		return 0;
1506
		return p;
1558
	while (*++p) {
1507
	while (*++p) {
1559
		if (! is_in_name(*p))
1508
		if (! is_in_name(*p))
1560
			return 0;
1509
			break;
1561
	}
1510
	}
1562
	return 1;
1511
	return p;
1563
}
1512
}
1564
1513
1565
1514
Lines 1587-1599 Link Here
1587
1536
1588
1537
1589
STATIC void
1538
STATIC void
1590
synerror(msg)
1539
synerror(const char *msg)
1591
	const char *msg;
1540
{
1592
	{
1541
	error("Syntax error: %s", msg);
1593
	if (commandname)
1594
		outfmt(&errout, "%s: %d: ", commandname, startlinno);
1595
	outfmt(&errout, "Syntax error: %s\n", msg);
1596
	error((char *)NULL);
1597
	/* NOTREACHED */
1542
	/* NOTREACHED */
1598
}
1543
}
1599
1544
Lines 1618-1624 Link Here
1618
	{
1563
	{
1619
	switch (whichprompt) {
1564
	switch (whichprompt) {
1620
	case 0:
1565
	case 0:
1621
		return "";
1566
		return nullstr;
1622
	case 1:
1567
	case 1:
1623
		return ps1val();
1568
		return ps1val();
1624
	case 2:
1569
	case 2:
Lines 1627-1629 Link Here
1627
		return "<internal prompt error>";
1572
		return "<internal prompt error>";
1628
	}
1573
	}
1629
}
1574
}
1575
1576
const char *const *
1577
findkwd(const char *s) {
1578
	return findstring(
1579
		s, parsekwd, sizeof(parsekwd) / sizeof(const char *)
1580
	);
1581
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/parser.h (-5 / +13 lines)
Lines 60-71 Link Here
60
#define VSPLUS		0x3		/* ${var+text} */
60
#define VSPLUS		0x3		/* ${var+text} */
61
#define VSQUESTION	0x4		/* ${var?message} */
61
#define VSQUESTION	0x4		/* ${var?message} */
62
#define VSASSIGN	0x5		/* ${var=text} */
62
#define VSASSIGN	0x5		/* ${var=text} */
63
#define VSTRIMLEFT	0x6		/* ${var#pattern} */
63
#define VSTRIMRIGHT	0x6		/* ${var%pattern} */
64
#define VSTRIMLEFTMAX	0x7		/* ${var##pattern} */
64
#define VSTRIMRIGHTMAX 	0x7		/* ${var%%pattern} */
65
#define VSTRIMRIGHT	0x8		/* ${var%pattern} */
65
#define VSTRIMLEFT	0x8		/* ${var#pattern} */
66
#define VSTRIMRIGHTMAX 	0x9		/* ${var%%pattern} */
66
#define VSTRIMLEFTMAX	0x9		/* ${var##pattern} */
67
#define VSLENGTH	0xa		/* ${#var} */
67
#define VSLENGTH	0xa		/* ${#var} */
68
68
69
/* values of checkkwd variable */
70
#define CHKALIAS	0x1
71
#define CHKKWD		0x2
72
#define CHKNL		0x4
73
69
74
70
/*
75
/*
71
 * NEOF is returned by parsecmd when it encounters an end of file.  It
76
 * NEOF is returned by parsecmd when it encounters an end of file.  It
Lines 75-83 Link Here
75
extern int tokpushback;
80
extern int tokpushback;
76
#define NEOF ((union node *)&tokpushback)
81
#define NEOF ((union node *)&tokpushback)
77
extern int whichprompt;		/* 1 == PS1, 2 == PS2 */
82
extern int whichprompt;		/* 1 == PS1, 2 == PS2 */
83
extern int checkkwd;
84
extern int startlinno;		/* line # where last token started */
78
85
79
86
80
union node *parsecmd(int);
87
union node *parsecmd(int);
81
void fixredir(union node *, const char *, int);
88
void fixredir(union node *, const char *, int);
82
int goodname(char *);
83
const char *getprompt(void *);
89
const char *getprompt(void *);
90
const char *const *findkwd(const char *);
91
char *endofname(const char *);
(-)bin_NetBSD-1.6release.orig/src/bin/sh/redir.c (-106 / +216 lines)
Lines 45-50 Link Here
45
#endif
45
#endif
46
#endif /* not lint */
46
#endif /* not lint */
47
47
48
#include <sys/stat.h>
48
#include <sys/types.h>
49
#include <sys/types.h>
49
#include <sys/param.h>	/* PIPE_BUF */
50
#include <sys/param.h>	/* PIPE_BUF */
50
#include <signal.h>
51
#include <signal.h>
Lines 80-100 Link Here
80
MKINIT
81
MKINIT
81
struct redirtab {
82
struct redirtab {
82
	struct redirtab *next;
83
	struct redirtab *next;
83
	short renamed[10];
84
	int renamed[10];
85
	int nullredirs;
84
};
86
};
85
87
86
88
87
MKINIT struct redirtab *redirlist;
89
MKINIT struct redirtab *redirlist;
90
MKINIT int nullredirs;
88
91
89
/*
92
STATIC int openredirect __P((union node *));
90
 * We keep track of whether or not fd0 has been redirected.  This is for
93
#ifdef notyet
91
 * background commands, where we want to redirect fd0 to /dev/null only
94
STATIC void dupredirect __P((union node *, int, char[10 ]));
92
 * if it hasn't already been redirected.
95
#else
93
*/
96
STATIC void dupredirect __P((union node *, int));
94
int fd0_redirected = 0;
97
#endif
95
96
STATIC void openredirect __P((union node *, char[10 ]));
97
STATIC int openhere __P((union node *));
98
STATIC int openhere __P((union node *));
99
STATIC int noclobberopen __P((const char *));
98
100
99
101
100
/*
102
/*
Lines 111-247 Link Here
111
	int flags;
113
	int flags;
112
	{
114
	{
113
	union node *n;
115
	union node *n;
114
	struct redirtab *sv = NULL;
116
	struct redirtab *sv;
115
	int i;
117
	int i;
116
	int fd;
118
	int fd;
117
	int try;
119
	int newfd;
120
	int *p;
121
#if notyet
118
	char memory[10];	/* file descriptors to write to memory */
122
	char memory[10];	/* file descriptors to write to memory */
119
123
120
	for (i = 10 ; --i >= 0 ; )
124
	for (i = 10 ; --i >= 0 ; )
121
		memory[i] = 0;
125
		memory[i] = 0;
122
	memory[1] = flags & REDIR_BACKQ;
126
	memory[1] = flags & REDIR_BACKQ;
127
#endif
128
	if (!redir) {
129
		if (flags & REDIR_PUSH)
130
			nullredirs++;
131
		return;
132
	}
133
	sv = NULL;
134
	INTOFF;
123
	if (flags & REDIR_PUSH) {
135
	if (flags & REDIR_PUSH) {
124
		sv = ckmalloc(sizeof (struct redirtab));
136
		struct redirtab *q;
137
		q = ckmalloc(sizeof (struct redirtab));
138
		q->next = redirlist;
139
		redirlist = q;
140
		q->nullredirs = nullredirs;
125
		for (i = 0 ; i < 10 ; i++)
141
		for (i = 0 ; i < 10 ; i++)
126
			sv->renamed[i] = EMPTY;
142
			q->renamed[i] = EMPTY;
127
		sv->next = redirlist;
143
		nullredirs = 0;
128
		redirlist = sv;
144
		sv = q;
129
	}
145
	}
130
	for (n = redir ; n ; n = n->nfile.next) {
146
	n = redir;
147
	do {
131
		fd = n->nfile.fd;
148
		fd = n->nfile.fd;
132
		try = 0;
133
		if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
149
		if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
134
		    n->ndup.dupfd == fd)
150
		    n->ndup.dupfd == fd)
135
			continue; /* redirect from/to same file descriptor */
151
			continue; /* redirect from/to same file descriptor */
136
152
137
		if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
153
		newfd = openredirect(n);
138
			INTOFF;
154
		if (fd == newfd)
139
again:
155
			continue;
140
			if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
156
		if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
141
				switch (errno) {
157
			int i = fcntl(fd, F_DUPFD, 10);
142
				case EBADF:
158
			if (i == -1) {
143
					if (!try) {
159
				i = errno;
144
						openredirect(n, memory);
160
				if (i != EBADF) {
145
						try++;
161
					const char *m = strerror(i);
146
						goto again;
162
					close(newfd);
147
					}
163
					error("%d: %s", fd, m);
148
					/* FALLTHROUGH*/
149
				default:
150
					INTON;
151
					error("%d: %s", fd, strerror(errno));
152
					/* NOTREACHED */
164
					/* NOTREACHED */
153
				}
165
				}
154
			}
166
			} else {
155
			if (!try) {
167
				*p = i;
156
				sv->renamed[fd] = i;
157
				close(fd);
168
				close(fd);
158
			}
169
			}
159
			INTON;
160
		} else {
170
		} else {
161
			close(fd);
171
			close(fd);
162
		}
172
		}
163
                if (fd == 0)
173
#ifdef notyet
164
                        fd0_redirected++;
174
		dupredirect(n, newfd, memory);
165
		if (!try)
175
#else
166
			openredirect(n, memory);
176
		dupredirect(n, newfd);
167
	}
177
#endif
178
	} while ((n = n->nfile.next));
179
	INTON;
180
#ifdef notyet
168
	if (memory[1])
181
	if (memory[1])
169
		out1 = &memout;
182
		out1 = &memout;
170
	if (memory[2])
183
	if (memory[2])
171
		out2 = &memout;
184
		out2 = &memout;
185
#endif
172
}
186
}
173
187
174
188
175
STATIC void
189
STATIC int
176
openredirect(redir, memory)
190
openredirect(redir)
177
	union node *redir;
191
	union node *redir;
178
	char memory[10];
179
	{
192
	{
180
	int fd = redir->nfile.fd;
181
	char *fname;
193
	char *fname;
182
	int f;
194
	int f;
183
	int flags = O_WRONLY|O_CREAT|O_TRUNC;
184
195
185
	/*
186
	 * We suppress interrupts so that we won't leave open file
187
	 * descriptors around.  This may not be such a good idea because
188
	 * an open of a device or a fifo can block indefinitely.
189
	 */
190
	INTOFF;
191
	memory[fd] = 0;
192
	switch (redir->nfile.type) {
196
	switch (redir->nfile.type) {
193
	case NFROM:
197
	case NFROM:
194
		fname = redir->nfile.expfname;
198
		fname = redir->nfile.expfname;
195
		if ((f = open(fname, O_RDONLY)) < 0)
199
		if ((f = open64(fname, O_RDONLY)) < 0)
196
			goto eopen;
200
			goto eopen;
197
		break;
201
		break;
198
	case NFROMTO:
202
	case NFROMTO:
199
		fname = redir->nfile.expfname;
203
		fname = redir->nfile.expfname;
200
		if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
204
		if ((f = open64(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
201
			goto ecreate;
205
			goto ecreate;
202
		break;
206
		break;
203
	case NTO:
207
	case NTO:
204
		if (Cflag)
208
		/* Take care of noclobber mode. */
205
			flags |= O_EXCL;
209
		if (Cflag) {
210
			fname = redir->nfile.expfname;
211
			if ((f = noclobberopen(fname)) < 0)
212
				goto ecreate;
213
			break;
214
		}
206
		/* FALLTHROUGH */
215
		/* FALLTHROUGH */
207
	case NCLOBBER:
216
	case NCLOBBER:
208
		fname = redir->nfile.expfname;
217
		fname = redir->nfile.expfname;
209
		if ((f = open(fname, flags, 0666)) < 0)
218
		if ((f = open64(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
210
			goto ecreate;
219
			goto ecreate;
211
		break;
220
		break;
212
	case NAPPEND:
221
	case NAPPEND:
213
		fname = redir->nfile.expfname;
222
		fname = redir->nfile.expfname;
214
		if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
223
		if ((f = open64(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
215
			goto ecreate;
224
			goto ecreate;
216
		break;
225
		break;
226
	default:
227
#ifdef DEBUG
228
		abort();
229
#endif
230
		/* Fall through to eliminate warning. */
217
	case NTOFD:
231
	case NTOFD:
218
	case NFROMFD:
232
	case NFROMFD:
233
		f = -1;
234
		break;
235
	case NHERE:
236
	case NXHERE:
237
		f = openhere(redir);
238
		break;
239
	}
240
241
	return f;
242
ecreate:
243
	error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
244
eopen:
245
	error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
246
}
247
248
249
STATIC void
250
#ifdef notyet
251
dupredirect(redir, f, memory)
252
#else
253
dupredirect(redir, f)
254
#endif
255
	union node *redir;
256
	int f;
257
#ifdef notyet
258
	char memory[10];
259
#endif
260
	{
261
	int fd = redir->nfile.fd;
262
263
#ifdef notyet
264
	memory[fd] = 0;
265
#endif
266
	if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
219
		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
267
		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
268
#ifdef notyet
220
			if (memory[redir->ndup.dupfd])
269
			if (memory[redir->ndup.dupfd])
221
				memory[fd] = 1;
270
				memory[fd] = 1;
222
			else
271
			else
272
#endif
223
				copyfd(redir->ndup.dupfd, fd);
273
				copyfd(redir->ndup.dupfd, fd);
224
		}
274
		}
225
		INTON;
226
		return;
275
		return;
227
	case NHERE:
228
	case NXHERE:
229
		f = openhere(redir);
230
		break;
231
	default:
232
		abort();
233
	}
276
	}
234
277
235
	if (f != fd) {
278
	if (f != fd) {
236
		copyfd(f, fd);
279
		copyfd(f, fd);
237
		close(f);
280
		close(f);
238
	}
281
	}
239
	INTON;
240
	return;
282
	return;
241
ecreate:
242
	error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
243
eopen:
244
	error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
245
}
283
}
246
284
247
285
Lines 256-262 Link Here
256
	union node *redir;
294
	union node *redir;
257
	{
295
	{
258
	int pip[2];
296
	int pip[2];
259
	int len = 0;
297
	size_t len = 0;
260
298
261
	if (pipe(pip) < 0)
299
	if (pipe(pip) < 0)
262
		error("Pipe call failed");
300
		error("Pipe call failed");
Lines 294-317 Link Here
294
 */
332
 */
295
333
296
void
334
void
297
popredir() {
335
popredir(int drop) {
298
	struct redirtab *rp = redirlist;
336
	struct redirtab *rp = redirlist;
299
	int i;
337
	int i;
300
338
339
	INTOFF;
340
	if (--nullredirs >= 0)
341
		goto out;
301
	for (i = 0 ; i < 10 ; i++) {
342
	for (i = 0 ; i < 10 ; i++) {
302
		if (rp->renamed[i] != EMPTY) {
343
		if (rp->renamed[i] != EMPTY) {
303
                        if (i == 0)
344
			if (!drop) {
304
                                fd0_redirected--;
305
			close(i);
345
			close(i);
306
			if (rp->renamed[i] >= 0) {
307
				copyfd(rp->renamed[i], i);
346
				copyfd(rp->renamed[i], i);
308
				close(rp->renamed[i]);
309
			}
347
			}
348
			close(rp->renamed[i]);
310
		}
349
		}
311
	}
350
	}
312
	INTOFF;
313
	redirlist = rp->next;
351
	redirlist = rp->next;
352
	nullredirs = rp->nullredirs;
314
	ckfree(rp);
353
	ckfree(rp);
354
out:
315
	INTON;
355
	INTON;
316
}
356
}
317
357
Lines 324-361 Link Here
324
INCLUDE "redir.h"
364
INCLUDE "redir.h"
325
365
326
RESET {
366
RESET {
327
	while (redirlist)
367
	clearredir(0);
328
		popredir();
329
}
330
331
SHELLPROC {
332
	clearredir();
333
}
368
}
334
369
335
#endif
370
#endif
336
371
337
/* Return true if fd 0 has already been redirected at least once.  */
338
int
339
fd0_redirected_p () {
340
        return fd0_redirected != 0;
341
}
342
343
/*
372
/*
344
 * Discard all saved file descriptors.
373
 * Discard all saved file descriptors.
345
 */
374
 */
346
375
347
void
376
void
348
clearredir() {
377
clearredir(int drop) {
349
	struct redirtab *rp;
378
	for (;;) {
350
	int i;
379
		nullredirs = 0;
351
380
		if (!redirlist)
352
	for (rp = redirlist ; rp ; rp = rp->next) {
381
			break;
353
		for (i = 0 ; i < 10 ; i++) {
382
		popredir(drop);
354
			if (rp->renamed[i] >= 0) {
355
				close(rp->renamed[i]);
356
			}
357
			rp->renamed[i] = EMPTY;
358
		}
359
	}
383
	}
360
}
384
}
361
385
Lines 368-385 Link Here
368
 */
392
 */
369
393
370
int
394
int
371
copyfd(from, to)
395
copyfd(int from, int to)
372
	int from;
373
	int to;
374
{
396
{
375
	int newfd;
397
	int newfd;
376
398
377
	newfd = fcntl(from, F_DUPFD, to);
399
	newfd = fcntl(from, F_DUPFD, to);
378
	if (newfd < 0) {
400
	if (newfd < 0) {
379
		if (errno == EMFILE)
401
		int errno2 = errno;
402
		if (errno2 == EMFILE)
380
			return EMPTY;
403
			return EMPTY;
381
		else
404
		else
382
			error("%d: %s", from, strerror(errno));
405
			error("%d: %s", from, strerror(errno2));
383
	}
406
	}
384
	return newfd;
407
	return newfd;
385
}
408
}
409
410
411
/*
412
 * Open a file in noclobber mode.
413
 * The code was copied from bash.
414
 */
415
int
416
noclobberopen(fname)
417
	const char *fname;
418
{
419
	int r, fd;
420
	struct stat64 finfo, finfo2;
421
422
	/*
423
	 * If the file exists and is a regular file, return an error
424
	 * immediately.
425
	 */
426
	r = stat64(fname, &finfo);
427
	if (r == 0 && S_ISREG(finfo.st_mode)) {
428
		errno = EEXIST;
429
		return -1;
430
	}
431
432
	/*
433
	 * If the file was not present (r != 0), make sure we open it
434
	 * exclusively so that if it is created before we open it, our open
435
	 * will fail.  Make sure that we do not truncate an existing file.
436
	 * Note that we don't turn on O_EXCL unless the stat failed -- if the
437
	 * file was not a regular file, we leave O_EXCL off.
438
	 */
439
	if (r != 0)
440
		return open64(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
441
	fd = open64(fname, O_WRONLY|O_CREAT, 0666);
442
443
	/* If the open failed, return the file descriptor right away. */
444
	if (fd < 0)
445
		return fd;
446
447
	/*
448
	 * OK, the open succeeded, but the file may have been changed from a
449
	 * non-regular file to a regular file between the stat and the open.
450
	 * We are assuming that the O_EXCL open handles the case where FILENAME
451
	 * did not exist and is symlinked to an existing file between the stat
452
	 * and open.
453
	 */
454
455
	/*
456
	 * If we can open it and fstat the file descriptor, and neither check
457
	 * revealed that it was a regular file, and the file has not been
458
	 * replaced, return the file descriptor.
459
	 */
460
	 if (fstat64(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
461
	     finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
462
	 	return fd;
463
464
	/* The file has been replaced.  badness. */
465
	close(fd);
466
	errno = EEXIST;
467
	return -1;
468
}
469
470
471
int
472
redirectsafe(union node *redir, int flags)
473
{
474
	int err;
475
	int e;
476
	volatile int saveint;
477
	struct jmploc *volatile savehandler = handler;
478
	struct jmploc jmploc;
479
480
	SAVEINT(saveint);
481
	exception = -1;
482
	if (setjmp(jmploc.loc))
483
		err = 2;
484
	else {
485
		handler = &jmploc;
486
		redirect(redir, flags);
487
		err = 0;
488
	}
489
	handler = savehandler;
490
	e = exception;
491
	if (e >= 0 && e != EXERROR)
492
		longjmp(handler->loc, 1);
493
	RESTOREINT(saveint);
494
	return err;
495
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/redir.h (-3 / +5 lines)
Lines 40-51 Link Here
40
40
41
/* flags passed to redirect */
41
/* flags passed to redirect */
42
#define REDIR_PUSH 01		/* save previous values of file descriptors */
42
#define REDIR_PUSH 01		/* save previous values of file descriptors */
43
#ifdef notyet
43
#define REDIR_BACKQ 02		/* save the command output in memory */
44
#define REDIR_BACKQ 02		/* save the command output in memory */
45
#endif
44
46
45
union node;
47
union node;
46
void redirect __P((union node *, int));
48
void redirect __P((union node *, int));
47
void popredir __P((void));
49
void popredir __P((int));
48
int fd0_redirected_p __P((void));
50
void clearredir __P((int));
49
void clearredir __P((void));
50
int copyfd __P((int, int));
51
int copyfd __P((int, int));
52
int redirectsafe __P((union node *, int));
51
53
(-)bin_NetBSD-1.6release.orig/src/bin/sh/regularbltins.def (+16 lines)
Line 0 Link Here
1
alias
2
bg
3
cd
4
command
5
false
6
fc
7
fg
8
getopts
9
jobs
10
kill
11
newgrp
12
read
13
true
14
umask
15
unalias
16
wait
(-)bin_NetBSD-1.6release.orig/src/bin/sh/setmode.c (+486 lines)
Line 0 Link Here
1
/*	$NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $	*/
2
3
/*
4
 * Copyright (c) 1989, 1993, 1994
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * This code is derived from software contributed to Berkeley by
8
 * Dave Borman at Cray Research, Inc.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. All advertising materials mentioning features or use of this software
19
 *    must display the following acknowledgement:
20
 *	This product includes software developed by the University of
21
 *	California, Berkeley and its contributors.
22
 * 4. Neither the name of the University nor the names of its contributors
23
 *    may be used to endorse or promote products derived from this software
24
 *    without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
 * SUCH DAMAGE.
37
 */
38
39
#include <sys/cdefs.h>
40
#if defined(LIBC_SCCS) && !defined(lint)
41
#if 0
42
static char sccsid[] = "@(#)setmode.c	8.2 (Berkeley) 3/25/94";
43
#else
44
__RCSID("$NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $");
45
#endif
46
#endif /* LIBC_SCCS and not lint */
47
48
#include <sys/types.h>
49
#include <sys/stat.h>
50
51
#include <assert.h>
52
#include <ctype.h>
53
#include <errno.h>
54
#include <signal.h>
55
#include <stdlib.h>
56
#include <unistd.h>
57
58
#ifdef SETMODE_DEBUG
59
#include <stdio.h>
60
#endif
61
62
#ifdef __weak_alias
63
__weak_alias(getmode,_getmode)
64
__weak_alias(setmode,_setmode)
65
#endif
66
67
#ifdef __GLIBC__
68
#define S_ISTXT __S_ISVTX
69
#endif
70
71
#define	SET_LEN	6		/* initial # of bitcmd struct to malloc */
72
#define	SET_LEN_INCR 4		/* # of bitcmd structs to add as needed */
73
74
typedef struct bitcmd {
75
	char	cmd;
76
	char	cmd2;
77
	mode_t	bits;
78
} BITCMD;
79
80
#define	CMD2_CLR	0x01
81
#define	CMD2_SET	0x02
82
#define	CMD2_GBITS	0x04
83
#define	CMD2_OBITS	0x08
84
#define	CMD2_UBITS	0x10
85
86
static BITCMD	*addcmd __P((BITCMD *, int, int, int, u_int));
87
static void	 compress_mode __P((BITCMD *));
88
#ifdef SETMODE_DEBUG
89
static void	 dumpmode __P((BITCMD *));
90
#endif
91
92
/*
93
 * Given the old mode and an array of bitcmd structures, apply the operations
94
 * described in the bitcmd structures to the old mode, and return the new mode.
95
 * Note that there is no '=' command; a strict assignment is just a '-' (clear
96
 * bits) followed by a '+' (set bits).
97
 */
98
mode_t
99
getmode(bbox, omode)
100
	const void *bbox;
101
	mode_t omode;
102
{
103
	const BITCMD *set;
104
	mode_t clrval, newmode, value;
105
106
	_DIAGASSERT(bbox != NULL);
107
108
	set = (const BITCMD *)bbox;
109
	newmode = omode;
110
	for (value = 0;; set++)
111
		switch(set->cmd) {
112
		/*
113
		 * When copying the user, group or other bits around, we "know"
114
		 * where the bits are in the mode so that we can do shifts to
115
		 * copy them around.  If we don't use shifts, it gets real
116
		 * grundgy with lots of single bit checks and bit sets.
117
		 */
118
		case 'u':
119
			value = (newmode & S_IRWXU) >> 6;
120
			goto common;
121
122
		case 'g':
123
			value = (newmode & S_IRWXG) >> 3;
124
			goto common;
125
126
		case 'o':
127
			value = newmode & S_IRWXO;
128
common:			if (set->cmd2 & CMD2_CLR) {
129
				clrval =
130
				    (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
131
				if (set->cmd2 & CMD2_UBITS)
132
					newmode &= ~((clrval<<6) & set->bits);
133
				if (set->cmd2 & CMD2_GBITS)
134
					newmode &= ~((clrval<<3) & set->bits);
135
				if (set->cmd2 & CMD2_OBITS)
136
					newmode &= ~(clrval & set->bits);
137
			}
138
			if (set->cmd2 & CMD2_SET) {
139
				if (set->cmd2 & CMD2_UBITS)
140
					newmode |= (value<<6) & set->bits;
141
				if (set->cmd2 & CMD2_GBITS)
142
					newmode |= (value<<3) & set->bits;
143
				if (set->cmd2 & CMD2_OBITS)
144
					newmode |= value & set->bits;
145
			}
146
			break;
147
148
		case '+':
149
			newmode |= set->bits;
150
			break;
151
152
		case '-':
153
			newmode &= ~set->bits;
154
			break;
155
156
		case 'X':
157
			if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
158
				newmode |= set->bits;
159
			break;
160
161
		case '\0':
162
		default:
163
#ifdef SETMODE_DEBUG
164
			(void)printf("getmode:%04o -> %04o\n", omode, newmode);
165
#endif
166
			return (newmode);
167
		}
168
}
169
170
#define	ADDCMD(a, b, c, d) do {						\
171
	if (set >= endset) {						\
172
		BITCMD *newset;						\
173
		setlen += SET_LEN_INCR;					\
174
		newset = realloc(saveset, sizeof(BITCMD) * setlen);	\
175
		if (newset == NULL) {					\
176
			free(saveset);					\
177
			return (NULL);					\
178
		}							\
179
		set = newset + (set - saveset);				\
180
		saveset = newset;					\
181
		endset = newset + (setlen - 2);				\
182
	}								\
183
	set = addcmd(set, (a), (b), (c), (d));				\
184
} while (/*CONSTCOND*/0)
185
186
#define	STANDARD_BITS	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
187
188
void *
189
setmode(p)
190
	const char *p;
191
{
192
	int perm, who;
193
	char op, *ep;
194
	BITCMD *set, *saveset, *endset;
195
	sigset_t sigset, sigoset;
196
	mode_t mask;
197
	int equalopdone = 0;	/* pacify gcc */
198
	int permXbits, setlen;
199
200
	if (!*p)
201
		return (NULL);
202
203
	/*
204
	 * Get a copy of the mask for the permissions that are mask relative.
205
	 * Flip the bits, we want what's not set.  Since it's possible that
206
	 * the caller is opening files inside a signal handler, protect them
207
	 * as best we can.
208
	 */
209
	sigfillset(&sigset);
210
	(void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
211
	(void)umask(mask = umask(0));
212
	mask = ~mask;
213
	(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
214
215
	setlen = SET_LEN + 2;
216
	
217
	if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
218
		return (NULL);
219
	saveset = set;
220
	endset = set + (setlen - 2);
221
222
	/*
223
	 * If an absolute number, get it and return; disallow non-octal digits
224
	 * or illegal bits.
225
	 */
226
	if (isdigit((unsigned char)*p)) {
227
		perm = (mode_t)strtol(p, &ep, 8);
228
		if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
229
			free(saveset);
230
			return (NULL);
231
		}
232
		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
233
		set->cmd = 0;
234
		return (saveset);
235
	}
236
237
	/*
238
	 * Build list of structures to set/clear/copy bits as described by
239
	 * each clause of the symbolic mode.
240
	 */
241
	for (;;) {
242
		/* First, find out which bits might be modified. */
243
		for (who = 0;; ++p) {
244
			switch (*p) {
245
			case 'a':
246
				who |= STANDARD_BITS;
247
				break;
248
			case 'u':
249
				who |= S_ISUID|S_IRWXU;
250
				break;
251
			case 'g':
252
				who |= S_ISGID|S_IRWXG;
253
				break;
254
			case 'o':
255
				who |= S_IRWXO;
256
				break;
257
			default:
258
				goto getop;
259
			}
260
		}
261
262
getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {
263
			free(saveset);
264
			return (NULL);
265
		}
266
		if (op == '=')
267
			equalopdone = 0;
268
269
		who &= ~S_ISTXT;
270
		for (perm = 0, permXbits = 0;; ++p) {
271
			switch (*p) {
272
			case 'r':
273
				perm |= S_IRUSR|S_IRGRP|S_IROTH;
274
				break;
275
			case 's':
276
				/*
277
				 * If specific bits where requested and 
278
				 * only "other" bits ignore set-id. 
279
				 */
280
				if (who == 0 || (who & ~S_IRWXO))
281
					perm |= S_ISUID|S_ISGID;
282
				break;
283
			case 't':
284
				/*
285
				 * If specific bits where requested and 
286
				 * only "other" bits ignore set-id. 
287
				 */
288
				if (who == 0 || (who & ~S_IRWXO)) {
289
					who |= S_ISTXT;
290
					perm |= S_ISTXT;
291
				}
292
				break;
293
			case 'w':
294
				perm |= S_IWUSR|S_IWGRP|S_IWOTH;
295
				break;
296
			case 'X':
297
				permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
298
				break;
299
			case 'x':
300
				perm |= S_IXUSR|S_IXGRP|S_IXOTH;
301
				break;
302
			case 'u':
303
			case 'g':
304
			case 'o':
305
				/*
306
				 * When ever we hit 'u', 'g', or 'o', we have
307
				 * to flush out any partial mode that we have,
308
				 * and then do the copying of the mode bits.
309
				 */
310
				if (perm) {
311
					ADDCMD(op, who, perm, mask);
312
					perm = 0;
313
				}
314
				if (op == '=')
315
					equalopdone = 1;
316
				if (op == '+' && permXbits) {
317
					ADDCMD('X', who, permXbits, mask);
318
					permXbits = 0;
319
				}
320
				ADDCMD(*p, who, op, mask);
321
				break;
322
323
			default:
324
				/*
325
				 * Add any permissions that we haven't already
326
				 * done.
327
				 */
328
				if (perm || (op == '=' && !equalopdone)) {
329
					if (op == '=')
330
						equalopdone = 1;
331
					ADDCMD(op, who, perm, mask);
332
					perm = 0;
333
				}
334
				if (permXbits) {
335
					ADDCMD('X', who, permXbits, mask);
336
					permXbits = 0;
337
				}
338
				goto apply;
339
			}
340
		}
341
342
apply:		if (!*p)
343
			break;
344
		if (*p != ',')
345
			goto getop;
346
		++p;
347
	}
348
	set->cmd = 0;
349
#ifdef SETMODE_DEBUG
350
	(void)printf("Before compress_mode()\n");
351
	dumpmode(saveset);
352
#endif
353
	compress_mode(saveset);
354
#ifdef SETMODE_DEBUG
355
	(void)printf("After compress_mode()\n");
356
	dumpmode(saveset);
357
#endif
358
	return (saveset);
359
}
360
361
static BITCMD *
362
addcmd(set, op, who, oparg, mask)
363
	BITCMD *set;
364
	int oparg, who;
365
	int op;
366
	u_int mask;
367
{
368
369
	_DIAGASSERT(set != NULL);
370
371
	switch (op) {
372
	case '=':
373
		set->cmd = '-';
374
		set->bits = who ? who : STANDARD_BITS;
375
		set++;
376
377
		op = '+';
378
		/* FALLTHROUGH */
379
	case '+':
380
	case '-':
381
	case 'X':
382
		set->cmd = op;
383
		set->bits = (who ? who : mask) & oparg;
384
		break;
385
386
	case 'u':
387
	case 'g':
388
	case 'o':
389
		set->cmd = op;
390
		if (who) {
391
			set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
392
				    ((who & S_IRGRP) ? CMD2_GBITS : 0) |
393
				    ((who & S_IROTH) ? CMD2_OBITS : 0);
394
			set->bits = (mode_t)~0;
395
		} else {
396
			set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
397
			set->bits = mask;
398
		}
399
	
400
		if (oparg == '+')
401
			set->cmd2 |= CMD2_SET;
402
		else if (oparg == '-')
403
			set->cmd2 |= CMD2_CLR;
404
		else if (oparg == '=')
405
			set->cmd2 |= CMD2_SET|CMD2_CLR;
406
		break;
407
	}
408
	return (set + 1);
409
}
410
411
#ifdef SETMODE_DEBUG
412
static void
413
dumpmode(set)
414
	BITCMD *set;
415
{
416
417
	_DIAGASSERT(set != NULL);
418
419
	for (; set->cmd; ++set)
420
		(void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
421
		    set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
422
		    set->cmd2 & CMD2_CLR ? " CLR" : "",
423
		    set->cmd2 & CMD2_SET ? " SET" : "",
424
		    set->cmd2 & CMD2_UBITS ? " UBITS" : "",
425
		    set->cmd2 & CMD2_GBITS ? " GBITS" : "",
426
		    set->cmd2 & CMD2_OBITS ? " OBITS" : "");
427
}
428
#endif
429
430
/*
431
 * Given an array of bitcmd structures, compress by compacting consecutive
432
 * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
433
 * 'g' and 'o' commands continue to be separate.  They could probably be 
434
 * compacted, but it's not worth the effort.
435
 */
436
static void
437
compress_mode(set)
438
	BITCMD *set;
439
{
440
	BITCMD *nset;
441
	int setbits, clrbits, Xbits, op;
442
443
	_DIAGASSERT(set != NULL);
444
445
	for (nset = set;;) {
446
		/* Copy over any 'u', 'g' and 'o' commands. */
447
		while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
448
			*set++ = *nset++;
449
			if (!op)
450
				return;
451
		}
452
453
		for (setbits = clrbits = Xbits = 0;; nset++) {
454
			if ((op = nset->cmd) == '-') {
455
				clrbits |= nset->bits;
456
				setbits &= ~nset->bits;
457
				Xbits &= ~nset->bits;
458
			} else if (op == '+') {
459
				setbits |= nset->bits;
460
				clrbits &= ~nset->bits;
461
				Xbits &= ~nset->bits;
462
			} else if (op == 'X')
463
				Xbits |= nset->bits & ~setbits;
464
			else
465
				break;
466
		}
467
		if (clrbits) {
468
			set->cmd = '-';
469
			set->cmd2 = 0;
470
			set->bits = clrbits;
471
			set++;
472
		}
473
		if (setbits) {
474
			set->cmd = '+';
475
			set->cmd2 = 0;
476
			set->bits = setbits;
477
			set++;
478
		}
479
		if (Xbits) {
480
			set->cmd = 'X';
481
			set->cmd2 = 0;
482
			set->bits = Xbits;
483
			set++;
484
		}
485
	}
486
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/sh.1 (-49 / +560 lines)
Lines 188-194 Link Here
188
or
188
or
189
.Ic until ;
189
.Ic until ;
190
or if the command is the left hand operand of an
190
or if the command is the left hand operand of an
191
.Dq \*[Am]\*[Am]
191
.Dq &&
192
or
192
or
193
.Dq ||
193
.Dq ||
194
operator.
194
operator.
Lines 256-264 Link Here
256
operators (their meaning is discussed later). Following is a list of operators:
256
operators (their meaning is discussed later). Following is a list of operators:
257
.Bl -ohang -offset indent
257
.Bl -ohang -offset indent
258
.It "Control operators:"
258
.It "Control operators:"
259
.Dl \*[Am]  \*[Am]\*[Am]  \&(  \&)  \&;  ;; | || \*[Lt]newline\*[Gt]
259
.Dl &  &&  \&(  \&)  \&;  ;; | || \*[Lt]newline\*[Gt]
260
.It "Redirection operators:"
260
.It "Redirection operators:"
261
.Dl \*[Lt]  \*[Gt]  \*[Gt]|  \*[Lt]\*[Lt]  \*[Gt]\*[Gt]  \*[Lt]\*[Am]  \*[Gt]\*[Am]  \*[Lt]\*[Lt]-  \*[Lt]\*[Gt]
261
.Dl \*[Lt]  \*[Gt]  \*[Gt]|  \*[Lt]\*[Lt]  \*[Gt]\*[Gt]  \*[Lt]&  \*[Gt]&  \*[Lt]\*[Lt]-  \*[Lt]\*[Gt]
262
.El
262
.El
263
.Ss Quoting
263
.Ss Quoting
264
Quoting is used to remove the special meaning of certain characters or
264
Quoting is used to remove the special meaning of certain characters or
Lines 381-393 Link Here
381
Append standard output (or n) to file.
381
Append standard output (or n) to file.
382
.It [n] Ns \*[Lt] file
382
.It [n] Ns \*[Lt] file
383
Redirect standard input (or n) from file.
383
Redirect standard input (or n) from file.
384
.It [n1] Ns \*[Lt]\*[Am] Ns n2
384
.It [n1] Ns \*[Lt]& Ns n2
385
Duplicate standard input (or n1) from file descriptor n2.
385
Duplicate standard input (or n1) from file descriptor n2.
386
.It [n] Ns \*[Lt]\*[Am]-
386
.It [n] Ns \*[Lt]&-
387
Close standard input (or n).
387
Close standard input (or n).
388
.It [n1] Ns \*[Gt]\*[Am] Ns n2
388
.It [n1] Ns \*[Gt]& Ns n2
389
Duplicate standard output (or n1) from n2.
389
Duplicate standard output (or n1) from n2.
390
.It [n] Ns \*[Gt]\*[Am]-
390
.It [n] Ns \*[Gt]&-
391
Close standard output (or n).
391
Close standard output (or n).
392
.It [n] Ns \*[Lt]\*[Gt] file
392
.It [n] Ns \*[Lt]\*[Gt] file
393
Open file for reading and writing on standard input (or n).
393
Open file for reading and writing on standard input (or n).
Lines 525-551 Link Here
525
takes place before redirection, it can be modified by redirection.  For
525
takes place before redirection, it can be modified by redirection.  For
526
example:
526
example:
527
.Pp
527
.Pp
528
.Dl $ command1 2\*[Gt]\*[Am]1 | command2
528
.Dl $ command1 2\*[Gt]&1 | command2
529
.Pp
529
.Pp
530
sends both the standard output and standard error of command1
530
sends both the standard output and standard error of command1
531
to the standard input of command2.
531
to the standard input of command2.
532
.Pp
532
.Pp
533
A ; or \*[Lt]newline\*[Gt] terminator causes the preceding AND-OR-list (described
533
A ; or \*[Lt]newline\*[Gt] terminator causes the preceding AND-OR-list (described
534
next) to be executed sequentially; a \*[Am] causes asynchronous execution of
534
next) to be executed sequentially; a & causes asynchronous execution of
535
the preceding AND-OR-list.
535
the preceding AND-OR-list.
536
.Pp
536
.Pp
537
Note that unlike some other shells, each process in the pipeline is a
537
Note that unlike some other shells, each process in the pipeline is a
538
child of the invoking shell (unless it is a shell builtin, in which case
538
child of the invoking shell (unless it is a shell builtin, in which case
539
it executes in the current shell -- but any effect it has on the
539
it executes in the current shell -- but any effect it has on the
540
environment is wiped).
540
environment is wiped).
541
.Ss Background Commands -- \*[Am]
541
.Ss Background Commands -- &
542
If a command is terminated by the control operator ampersand (\*[Am]), the
542
If a command is terminated by the control operator ampersand (&), the
543
shell executes the command asynchronously -- that is, the shell does not
543
shell executes the command asynchronously -- that is, the shell does not
544
wait for the command to finish before executing the next command.
544
wait for the command to finish before executing the next command.
545
.Pp
545
.Pp
546
The format for running a command in background is:
546
The format for running a command in background is:
547
.Pp
547
.Pp
548
.Dl command1 \*[Am] [command2 \*[Am] ...]
548
.Dl command1 & [command2 & ...]
549
.Pp
549
.Pp
550
If the shell is not interactive, the standard input of an asynchronous
550
If the shell is not interactive, the standard input of an asynchronous
551
command is set to
551
command is set to
Lines 558-574 Link Here
558
command and immediately proceed onto the next command; otherwise it waits
558
command and immediately proceed onto the next command; otherwise it waits
559
for the command to terminate before proceeding to the next one.
559
for the command to terminate before proceeding to the next one.
560
.Ss Short-Circuit List Operators
560
.Ss Short-Circuit List Operators
561
.Dq \*[Am]\*[Am]
561
.Dq &&
562
and
562
and
563
.Dq ||
563
.Dq ||
564
are AND-OR list operators.
564
are AND-OR list operators.
565
.Dq \*[Am]\*[Am]
565
.Dq &&
566
executes the first command, and then executes the second command iff the
566
executes the first command, and then executes the second command iff the
567
exit status of the first command is zero.
567
exit status of the first command is zero.
568
.Dq ||
568
.Dq ||
569
is similar, but executes the second command iff the exit status of the first
569
is similar, but executes the second command iff the exit status of the first
570
command is nonzero.
570
command is nonzero.
571
.Dq \*[Am]\*[Am]
571
.Dq &&
572
and
572
and
573
.Dq ||
573
.Dq ||
574
both have the same priority.
574
both have the same priority.
Lines 646-652 Link Here
646
they were one program:
646
they were one program:
647
.Pp
647
.Pp
648
.Bd -literal -offset indent
648
.Bd -literal -offset indent
649
{ echo -n \*q hello \*q ; echo \*q world" ; } \*[Gt] greeting
649
{ printf \*q hello \*q ; printf \*q world\\n" ; } \*[Gt] greeting
650
.Ed
650
.Ed
651
.Pp
651
.Pp
652
Note that
652
Note that
Lines 961-971 Link Here
961
.Ss Shell Patterns
961
.Ss Shell Patterns
962
A pattern consists of normal characters, which match themselves,
962
A pattern consists of normal characters, which match themselves,
963
and meta-characters.   The meta-characters are
963
and meta-characters.   The meta-characters are
964
.Dq ! ,
964
.Dq \&! ,
965
.Dq * ,
965
.Dq * ,
966
.Dq ? ,
966
.Dq \&? ,
967
and
967
and
968
.Dq [ .
968
.Dq \&[ .
969
These characters lose their special meanings if they are quoted.  When
969
These characters lose their special meanings if they are quoted.  When
970
command or variable substitution is performed and the dollar sign or back
970
command or variable substitution is performed and the dollar sign or back
971
quotes are not double quoted, the value of the variable or the output of
971
quotes are not double quoted, the value of the variable or the output of
Lines 999-1012 Link Here
999
.Ss Builtins
999
.Ss Builtins
1000
This section lists the builtin commands which are builtin because they
1000
This section lists the builtin commands which are builtin because they
1001
need to perform some operation that can't be performed by a separate
1001
need to perform some operation that can't be performed by a separate
1002
process. In addition to these, there are several other commands that may
1002
process.
1003
be builtin for efficiency (e.g.
1004
.Xr printf 1 ,
1005
.Xr echo 1 ,
1006
.Xr test 1 ,
1007
etc).
1008
.Bl -tag -width 5n
1003
.Bl -tag -width 5n
1009
.It :
1004
.It :
1005
.It true
1010
A null command that returns a 0 (true) exit value.
1006
A null command that returns a 0 (true) exit value.
1011
.It \&. file
1007
.It \&. file
1012
The commands in the specified file are read and executed by the shell.
1008
The commands in the specified file are read and executed by the shell.
Lines 1032-1040 Link Here
1032
.It command Ar command Ar arg ...
1028
.It command Ar command Ar arg ...
1033
Execute the specified builtin command.  (This is useful when you
1029
Execute the specified builtin command.  (This is useful when you
1034
have a shell function with the same name as a builtin command.)
1030
have a shell function with the same name as a builtin command.)
1035
.It cd Op Ar directory
1031
.It cd Ar -
1032
.It Xo cd Op Fl LP
1033
.Op Ar directory
1034
.Xc
1036
Switch to the specified directory (default
1035
Switch to the specified directory (default
1037
.Ev $HOME ) .
1036
.Ev HOME ) .
1038
If an entry for
1037
If an entry for
1039
.Ev CDPATH
1038
.Ev CDPATH
1040
appears in the environment of the
1039
appears in the environment of the
Lines 1048-1060 Link Here
1048
.Ev CDPATH
1047
.Ev CDPATH
1049
is the same as that of
1048
is the same as that of
1050
.Ev PATH .
1049
.Ev PATH .
1051
In an interactive shell, the
1050
If a single dash is specified as the argument, it will be replaced by the
1051
value of
1052
.Ev OLDPWD .
1053
The
1052
.Ic cd
1054
.Ic cd
1053
command will print out the name of the
1055
command will print out the name of the
1054
directory that it actually switched to if this is different from the name
1056
directory that it actually switched to if this is different from the name
1055
that the user gave.  These may be different either because the
1057
that the user gave.  These may be different either because the
1056
.Ev CDPATH
1058
.Ev CDPATH
1057
mechanism was used or because a symbolic link was crossed.
1059
mechanism was used or because the argument is a single dash.
1060
The
1061
.Fl P
1062
option causes the physical directory structure to be used, that is, all
1063
symbolic links are resolved to their repective values.  The
1064
.Fl L
1065
option turns off the effect of any preceding
1066
.Fl P
1067
options.
1068
.It Xo echo Op Fl n
1069
.Ar args... 
1070
.Xc
1071
Print the arguments on the standard output, separated by spaces.
1072
Unless the
1073
.Fl n
1074
option is present, a newline is output following the arguments.
1075
.Pp
1076
If any of the following sequences of characters is encountered during
1077
output, the sequence is not output.  Instead, the specified action is
1078
performed:
1079
.Bl -tag -width indent
1080
.It Li \eb
1081
A backspace character is output.
1082
.It Li \ec
1083
Subsequent output is suppressed.  This is normally used at the end of the
1084
last argument to suppress the trailing newline that
1085
.Ic echo
1086
would otherwise output.
1087
.It Li \ef
1088
Output a form feed.
1089
.It Li \en
1090
Output a newline character.
1091
.It Li \er
1092
Output a carriage return.
1093
.It Li \et
1094
Output a (horizontal) tab character.
1095
.It Li \ev
1096
Output a vertical tab.
1097
.It Li \e0 Ns Ar digits
1098
Output the character whose value is given by zero to three octal digits.
1099
If there are zero digits, a nul character is output.
1100
.It Li \e\e
1101
Output a backslash.
1102
.El
1103
.Pp
1104
All other backslash sequences elicit undefined behaviour.
1058
.It eval Ar string ...
1105
.It eval Ar string ...
1059
Concatenate all the arguments with spaces.  Then re-parse and execute
1106
Concatenate all the arguments with spaces.  Then re-parse and execute
1060
the command.
1107
the command.
Lines 1217-1223 Link Here
1217
will set the variable
1264
will set the variable
1218
.Va var
1265
.Va var
1219
to a
1266
to a
1220
.Dq ? ;
1267
.Dq \&? ;
1221
.Ic getopts
1268
.Ic getopts
1222
will then unset
1269
will then unset
1223
.Ev OPTARG
1270
.Ev OPTARG
Lines 1236-1242 Link Here
1236
otherwise, it will set
1283
otherwise, it will set
1237
.Va var
1284
.Va var
1238
to
1285
to
1239
.Dq ? .
1286
.Dq \&? .
1240
.Pp
1287
.Pp
1241
The following code fragment shows how one might process the arguments
1288
The following code fragment shows how one might process the arguments
1242
for a command that can take the options
1289
for a command that can take the options
Lines 1295-1301 Link Here
1295
.It jobs
1342
.It jobs
1296
This command lists out all the background processes
1343
This command lists out all the background processes
1297
which are children of the current shell process.
1344
which are children of the current shell process.
1298
.It pwd
1345
.It pwd Op Fl LP
1299
Print the current directory.  The builtin command may
1346
Print the current directory.  The builtin command may
1300
differ from the program of the same name because the
1347
differ from the program of the same name because the
1301
builtin command remembers what the current directory
1348
builtin command remembers what the current directory
Lines 1304-1309 Link Here
1304
renamed, the builtin version of
1351
renamed, the builtin version of
1305
.Ic pwd
1352
.Ic pwd
1306
will continue to print the old name for the directory.
1353
will continue to print the old name for the directory.
1354
The
1355
.Fl P
1356
option causes the phyical value of the current working directory to be shown,
1357
that is, all symbolic links are resolved to their repective values.  The
1358
.Fl L
1359
option turns off the effect of any preceding
1360
.Fl P
1361
options.
1307
.It Xo read Op Fl p Ar prompt
1362
.It Xo read Op Fl p Ar prompt
1308
.Op Fl r
1363
.Op Fl r
1309
.Ar variable
1364
.Ar variable
Lines 1314-1320 Link Here
1314
option is specified and the standard input is a terminal.  Then a line is
1369
option is specified and the standard input is a terminal.  Then a line is
1315
read from the standard input.  The trailing newline is deleted from the
1370
read from the standard input.  The trailing newline is deleted from the
1316
line and the line is split as described in the section on word splitting
1371
line and the line is split as described in the section on word splitting
1317
above, and the pieces are assigned to the variables in order. If there are
1372
above, and the pieces are assigned to the variables in order.
1373
At least one variable must be specified.
1374
If there are
1318
more pieces than variables, the remaining pieces (along with the
1375
more pieces than variables, the remaining pieces (along with the
1319
characters in
1376
characters in
1320
.Ev IFS
1377
.Ev IFS
Lines 1346-1351 Link Here
1346
.Fl p
1403
.Fl p
1347
option specified the output will be formatted suitably for non-interactive use.
1404
option specified the output will be formatted suitably for non-interactive use.
1348
.Pp
1405
.Pp
1406
.It Xo printf Ar format
1407
.Op Ar arguments  ...
1408
.Xc
1409
.Ic printf
1410
formats and prints its arguments, after the first, under control
1411
of the
1412
.Ar format  .
1413
The
1414
.Ar format
1415
is a character string which contains three types of objects: plain characters,
1416
which are simply copied to standard output, character escape sequences which
1417
are converted and copied to the standard output, and format specifications,
1418
each of which causes printing of the next successive
1419
.Ar argument  .
1420
.Pp
1421
The
1422
.Ar arguments
1423
after the first are treated as strings if the corresponding format is
1424
either
1425
.Cm b ,
1426
.Cm c
1427
or
1428
.Cm s ;
1429
otherwise it is evaluated as a C constant, with the following extensions:
1430
.Pp
1431
.Bl -bullet -offset indent -compact
1432
.It
1433
A leading plus or minus sign is allowed.
1434
.It
1435
If the leading character is a single or double quote, the value is the
1436
.Tn ASCII
1437
code of the next character.
1438
.El
1439
.Pp
1440
The format string is reused as often as necessary to satisfy the
1441
.Ar arguments  .
1442
Any extra format specifications are evaluated with zero or the null
1443
string.
1444
.Pp
1445
Character escape sequences are in backslash notation as defined in
1446
.St -ansiC .
1447
The characters and their meanings
1448
are as follows:
1449
.Bl -tag -width Ds -offset indent
1450
.It Cm \ee
1451
Write an \*[Lt]escape\*[Gt] character.
1452
.It Cm \ea
1453
Write a \*[Lt]bell\*[Gt] character.
1454
.It Cm \eb
1455
Write a \*[Lt]backspace\*[Gt] character.
1456
.It Cm \ef
1457
Write a \*[Lt]form-feed\*[Gt] character.
1458
.It Cm \en
1459
Write a \*[Lt]new-line\*[Gt] character.
1460
.It Cm \er
1461
Write a \*[Lt]carriage return\*[Gt] character.
1462
.It Cm \et
1463
Write a \*[Lt]tab\*[Gt] character.
1464
.It Cm \ev
1465
Write a \*[Lt]vertical tab\*[Gt] character.
1466
.It Cm \e\'
1467
Write a \*[Lt]single quote\*[Gt] character.
1468
.It Cm \e\e
1469
Write a backslash character.
1470
.It Cm \e Ns Ar num
1471
Write an 8-bit character whose
1472
.Tn ASCII
1473
value is the 1-, 2-, or 3-digit
1474
octal number
1475
.Ar num .
1476
.El
1477
.Pp
1478
Each format specification is introduced by the percent character
1479
(``%'').
1480
The remainder of the format specification includes,
1481
in the following order:
1482
.Bl -tag -width Ds
1483
.It "Zero or more of the following flags:"
1484
.Bl -tag -width Ds
1485
.It Cm #
1486
A `#' character
1487
specifying that the value should be printed in an ``alternative form''.
1488
For
1489
.Cm c  ,
1490
.Cm d ,
1491
and
1492
.Cm s  ,
1493
formats, this option has no effect.  For the
1494
.Cm o
1495
formats the precision of the number is increased to force the first
1496
character of the output string to a zero.  For the
1497
.Cm x
1498
.Pq Cm X
1499
format, a non-zero result has the string
1500
.Li 0x
1501
.Pq Li 0X
1502
prepended to it.  For
1503
.Cm e  ,
1504
.Cm E ,
1505
.Cm f  ,
1506
.Cm g ,
1507
and
1508
.Cm G  ,
1509
formats, the result will always contain a decimal point, even if no
1510
digits follow the point (normally, a decimal point only appears in the
1511
results of those formats if a digit follows the decimal point).  For
1512
.Cm g
1513
and
1514
.Cm G
1515
formats, trailing zeros are not removed from the result as they
1516
would otherwise be;
1517
.It Cm \&\-
1518
A minus sign `\-' which specifies
1519
.Em left adjustment
1520
of the output in the indicated field;
1521
.It Cm \&+
1522
A `+' character specifying that there should always be
1523
a sign placed before the number when using signed formats.
1524
.It Sq \&\ \&
1525
A space specifying that a blank should be left before a positive number
1526
for a signed format.  A `+' overrides a space if both are used;
1527
.It Cm \&0
1528
A zero `0' character indicating that zero-padding should be used
1529
rather than blank-padding.  A `\-' overrides a `0' if both are used;
1530
.El
1531
.It "Field Width:"
1532
An optional digit string specifying a
1533
.Em field width ;
1534
if the output string has fewer characters than the field width it will
1535
be blank-padded on the left (or right, if the left-adjustment indicator
1536
has been given) to make up the field width (note that a leading zero
1537
is a flag, but an embedded zero is part of a field width);
1538
.It Precision :
1539
An optional period,
1540
.Sq Cm \&.\& ,
1541
followed by an optional digit string giving a
1542
.Em precision
1543
which specifies the number of digits to appear after the decimal point,
1544
for
1545
.Cm e
1546
and
1547
.Cm f
1548
formats, or the maximum number of characters to be printed
1549
from a string; if the digit string is missing, the precision is treated
1550
as zero;
1551
.It Format :
1552
A character which indicates the type of format to use (one of
1553
.Cm diouxXfwEgGbcs ) .
1554
.El
1555
.Pp
1556
A field width or precision may be
1557
.Sq Cm \&*
1558
instead of a digit string.
1559
In this case an
1560
.Ar argument
1561
supplies the field width or precision.
1562
.Pp
1563
The format characters and their meanings are:
1564
.Bl -tag -width Fl
1565
.It Cm diouXx
1566
The
1567
.Ar argument
1568
is printed as a signed decimal (d or i), unsigned octal, unsigned decimal,
1569
or unsigned hexadecimal (X or x), respectively.
1570
.It Cm f
1571
The
1572
.Ar argument
1573
is printed in the style
1574
.Sm off
1575
.Pf [\-]ddd Cm \&. No ddd
1576
.Sm on
1577
where the number of d's
1578
after the decimal point is equal to the precision specification for
1579
the argument.
1580
If the precision is missing, 6 digits are given; if the precision
1581
is explicitly 0, no digits and no decimal point are printed.
1582
.It Cm eE
1583
The
1584
.Ar argument
1585
is printed in the style
1586
.Sm off
1587
.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd
1588
.Sm on
1589
where there
1590
is one digit before the decimal point and the number after is equal to
1591
the precision specification for the argument; when the precision is
1592
missing, 6 digits are produced.
1593
An upper-case E is used for an `E' format.
1594
.It Cm gG
1595
The
1596
.Ar argument
1597
is printed in style
1598
.Cm f
1599
or in style
1600
.Cm e
1601
.Pq Cm E
1602
whichever gives full precision in minimum space.
1603
.It Cm b
1604
Characters from the string
1605
.Ar argument
1606
are printed with backslash-escape sequences expanded as in
1607
.Ic echo .
1608
.It Cm c
1609
The first character of
1610
.Ar argument
1611
is printed.
1612
.It Cm s
1613
Characters from the string
1614
.Ar argument
1615
are printed until the end is reached or until the number of characters
1616
indicated by the precision specification is reached; however if the
1617
precision is 0 or missing, all characters in the string are printed.
1618
.It Cm \&%
1619
Print a `%'; no argument is used.
1620
.El
1621
.Pp
1622
In no case does a non-existent or small field width cause truncation of
1623
a field; padding takes place only if the specified field width exceeds
1624
the actual width.
1349
.It Xo set
1625
.It Xo set
1350
.Oo {
1626
.Oo {
1351
.Fl options | Cm +options | Cm -- }
1627
.Fl options | Cm +options | Cm -- }
Lines 1392-1406 Link Here
1392
and so on, decreasing
1668
and so on, decreasing
1393
the value of
1669
the value of
1394
.Va $#
1670
.Va $#
1395
by one. If there are zero positional parameters,
1671
by one. If n is greater than the number of positional parameters,
1396
.Ic shift
1672
.Ic shift
1397
does nothing.
1673
will issue an error message, and exit with return status 2.
1398
.It Xo trap
1674
.It test Ar expression
1399
.Op Fl l
1675
.It \&[ Ar expression Cm ]
1400
.Xc
1676
The
1677
.Ic test
1678
utility evaluates the expression and, if it evaluates
1679
to true, returns a zero (true) exit status; otherwise
1680
it returns 1 (false).
1681
If there is no expression, test also
1682
returns 1 (false).
1683
.Pp
1684
All operators and flags are separate arguments to the
1685
.Ic test
1686
utility.
1687
.Pp
1688
The following primaries are used to construct expression:
1689
.Bl -tag -width Ar
1690
.It Fl b Ar file
1691
True if
1692
.Ar file
1693
exists and is a block special
1694
file.
1695
.It Fl c Ar file
1696
True if
1697
.Ar file
1698
exists and is a character
1699
special file.
1700
.It Fl d Ar file
1701
True if
1702
.Ar file
1703
exists and is a directory.
1704
.It Fl e Ar file
1705
True if
1706
.Ar file
1707
exists (regardless of type).
1708
.It Fl f Ar file
1709
True if
1710
.Ar file
1711
exists and is a regular file.
1712
.It Fl g Ar file
1713
True if
1714
.Ar file
1715
exists and its set group ID flag
1716
is set.
1717
.It Fl h Ar file
1718
True if
1719
.Ar file
1720
exists and is a symbolic link.
1721
.It Fl k Ar file
1722
True if
1723
.Ar file
1724
exists and its sticky bit is set.
1725
.It Fl n Ar string
1726
True if the length of
1727
.Ar string
1728
is nonzero.
1729
.It Fl p Ar file
1730
True if
1731
.Ar file
1732
is a named pipe
1733
.Po Tn FIFO Pc .
1734
.It Fl r Ar file
1735
True if
1736
.Ar file
1737
exists and is readable.
1738
.It Fl s Ar file
1739
True if
1740
.Ar file
1741
exists and has a size greater
1742
than zero.
1743
.It Fl t Ar file_descriptor
1744
True if the file whose file descriptor number
1745
is
1746
.Ar file_descriptor
1747
is open and is associated with a terminal.
1748
.It Fl u Ar file
1749
True if
1750
.Ar file
1751
exists and its set user ID flag
1752
is set.
1753
.It Fl w Ar file
1754
True if
1755
.Ar file
1756
exists and is writable.
1757
True
1758
indicates only that the write flag is on.
1759
The file is not writable on a read-only file
1760
system even if this test indicates true.
1761
.It Fl x Ar file
1762
True if
1763
.Ar file
1764
exists and is executable.
1765
True
1766
indicates only that the execute flag is on.
1767
If
1768
.Ar file
1769
is a directory, true indicates that
1770
.Ar file
1771
can be searched.
1772
.It Fl z Ar string
1773
True if the length of
1774
.Ar string
1775
is zero.
1776
.It Fl L Ar file
1777
True if
1778
.Ar file
1779
exists and is a symbolic link.
1780
This operator is retained for compatibility with previous versions of
1781
this program. Do not rely on its existence; use
1782
.Fl h
1783
instead.
1784
.It Fl O Ar file
1785
True if
1786
.Ar file
1787
exists and its owner matches the effective user id of this process.
1788
.It Fl G Ar file
1789
True if
1790
.Ar file
1791
exists and its group matches the effective group id of this process.
1792
.It Fl S Ar file
1793
True if
1794
.Ar file
1795
exists and is a socket.
1796
.It Ar file1 Fl nt Ar file2
1797
True if
1798
.Ar file1
1799
exists and is newer than
1800
.Ar file2 .
1801
.It Ar file1 Fl ot Ar file2
1802
True if
1803
.Ar file1
1804
exists and is older than
1805
.Ar file2 .
1806
.It Ar file1 Fl ef Ar file2
1807
True if
1808
.Ar file1
1809
and
1810
.Ar file2
1811
exist and refer to the same file.
1812
.It Ar string
1813
True if
1814
.Ar string
1815
is not the null
1816
string.
1817
.It Ar \&s\&1 Cm \&= Ar \&s\&2
1818
True if the strings
1819
.Ar \&s\&1
1820
and
1821
.Ar \&s\&2
1822
are identical.
1823
.It Ar \&s\&1 Cm \&!= Ar \&s\&2
1824
True if the strings
1825
.Ar \&s\&1
1826
and
1827
.Ar \&s\&2
1828
are not identical.
1829
.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2
1830
True if string
1831
.Ar \&s\&1
1832
comes before
1833
.Ar \&s\&2
1834
based on the ASCII value of their characters.
1835
.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2
1836
True if string
1837
.Ar \&s\&1
1838
comes after
1839
.Ar \&s\&2
1840
based on the ASCII value of their characters.
1841
.It Ar \&n\&1 Fl \&eq Ar \&n\&2
1842
True if the integers
1843
.Ar \&n\&1
1844
and
1845
.Ar \&n\&2
1846
are algebraically
1847
equal.
1848
.It Ar \&n\&1 Fl \&ne Ar \&n\&2
1849
True if the integers
1850
.Ar \&n\&1
1851
and
1852
.Ar \&n\&2
1853
are not
1854
algebraically equal.
1855
.It Ar \&n\&1 Fl \&gt Ar \&n\&2
1856
True if the integer
1857
.Ar \&n\&1
1858
is algebraically
1859
greater than the integer
1860
.Ar \&n\&2 .
1861
.It Ar \&n\&1 Fl \&ge Ar \&n\&2
1862
True if the integer
1863
.Ar \&n\&1
1864
is algebraically
1865
greater than or equal to the integer
1866
.Ar \&n\&2 .
1867
.It Ar \&n\&1 Fl \&lt Ar \&n\&2
1868
True if the integer
1869
.Ar \&n\&1
1870
is algebraically less
1871
than the integer
1872
.Ar \&n\&2 .
1873
.It Ar \&n\&1 Fl \&le Ar \&n\&2
1874
True if the integer
1875
.Ar \&n\&1
1876
is algebraically less
1877
than or equal to the integer
1878
.Ar \&n\&2 .
1879
.El
1880
.Pp
1881
These primaries can be combined with the following operators:
1882
.Bl -tag -width Ar
1883
.It Cm \&! Ar expression
1884
True if
1885
.Ar expression
1886
is false.
1887
.It Ar expression1 Fl a Ar expression2
1888
True if both
1889
.Ar expression1
1890
and
1891
.Ar expression2
1892
are true.
1893
.It Ar expression1 Fl o Ar expression2
1894
True if either
1895
.Ar expression1
1896
or
1897
.Ar expression2
1898
are true.
1899
.It Cm \&( Ns Ar expression Ns Cm \&)
1900
True if expression is true.
1901
.El
1902
.Pp
1903
The
1904
.Fl a
1905
operator has higher precedence than the
1906
.Fl o
1907
operator.
1908
.It times
1909
Print the accumulated user and system times for the shell and for processes
1910
run from the shell.  The return status is 0.
1401
.It Xo trap
1911
.It Xo trap
1402
.Op Ar action
1912
.Op Ar action Ar signal ...
1403
.Ar signal ...
1404
.Xc
1913
.Xc
1405
Cause the shell to parse and execute action when any of the specified
1914
Cause the shell to parse and execute action when any of the specified
1406
signals are received. The signals are specified by signal number or as
1915
signals are received. The signals are specified by signal number or as
Lines 1420-1430 Link Here
1420
.Ic trap
1929
.Ic trap
1421
command has no effect on signals that were
1930
command has no effect on signals that were
1422
ignored on entry to the shell.
1931
ignored on entry to the shell.
1423
Issuing
1424
.Ic trap
1425
with option
1426
.Ar -l
1427
will print a list of valid signal names.
1428
.Ic trap
1932
.Ic trap
1429
without any arguments cause it to write a list of signals and their
1933
without any arguments cause it to write a list of signals and their
1430
associated action to the standard output in a format that is suitable
1934
associated action to the standard output in a format that is suitable
Lines 1436-1445 Link Here
1436
.Pp
1940
.Pp
1437
List trapped signals and their corresponding action
1941
List trapped signals and their corresponding action
1438
.Pp
1942
.Pp
1439
.Dl trap -l
1440
.Pp
1441
Print a list of valid signals
1442
.Pp
1443
.Dl trap '' SIGINT QUIT tstp 30
1943
.Dl trap '' SIGINT QUIT tstp 30
1444
.Pp
1944
.Pp
1445
Ignore signals INT QUIT TSTP USR1
1945
Ignore signals INT QUIT TSTP USR1
Lines 1614-1619 Link Here
1614
children of the shell, and is used in the history editing modes.
2114
children of the shell, and is used in the history editing modes.
1615
.It Ev HISTSIZE
2115
.It Ev HISTSIZE
1616
The number of lines in the history buffer for the shell.
2116
The number of lines in the history buffer for the shell.
2117
.It Ev PWD
2118
The logical value of the current working directory.  This is set by the
2119
.Ic cd
2120
command.
2121
.It Ev OLDPWD
2122
The previous logical value of the current working directory.  This is set by
2123
the
2124
.Ic cd
2125
command.
2126
.It Ev PPID
2127
The process ID of the parent process of the shell.
1617
.El
2128
.El
1618
.Sh FILES
2129
.Sh FILES
1619
.Bl -item -width HOMEprofilexxxx
2130
.Bl -item -width HOMEprofilexxxx
(-)bin_NetBSD-1.6release.orig/src/bin/sh/shell.h (-9 / +8 lines)
Lines 1-4 Link Here
1
/*	$NetBSD: shell.h,v 1.13 2000/05/22 10:18:47 elric Exp $	*/
1
/*	$NetBSD: shell.h,v 1.14 2002/05/25 23:09:06 wiz Exp $	*/
2
2
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
Lines 52-74 Link Here
52
 */
52
 */
53
53
54
54
55
#ifndef JOBS
55
#define JOBS 1
56
#define JOBS 1
57
#endif
56
#ifndef BSD
58
#ifndef BSD
57
#define BSD 1
59
#define BSD 1
58
#endif
60
#endif
59
61
60
#ifdef __STDC__
61
typedef void *pointer;
62
typedef void *pointer;
62
#ifndef NULL
63
#ifndef NULL
63
#define NULL (void *)0
64
#define NULL (void *)0
64
#endif
65
#endif
65
#else /* not __STDC__ */
66
#define STATIC static
66
typedef char *pointer;
67
#ifndef NULL
68
#define NULL 0
69
#endif
70
#endif /*  not __STDC__ */
71
#define STATIC	/* empty */
72
#define MKINIT	/* empty */
67
#define MKINIT	/* empty */
73
68
74
#include <sys/cdefs.h>
69
#include <sys/cdefs.h>
Lines 81-83 Link Here
81
#else
76
#else
82
#define TRACE(param)
77
#define TRACE(param)
83
#endif
78
#endif
79
80
#if defined(__GNUC__) && __GNUC__ < 3
81
#define va_copy __va_copy
82
#endif
(-)bin_NetBSD-1.6release.orig/src/bin/sh/show.c (-28 / +4 lines)
Lines 1-4 Link Here
1
/*	$NetBSD: show.c,v 1.21 2002/05/15 16:33:35 christos Exp $	*/
1
/*	$NetBSD: show.c,v 1.22 2002/05/25 23:09:06 wiz Exp $	*/
2
2
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
Lines 41-56 Link Here
41
#if 0
41
#if 0
42
static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
42
static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
43
#else
43
#else
44
__RCSID("$NetBSD: show.c,v 1.21 2002/05/15 16:33:35 christos Exp $");
44
__RCSID("$NetBSD: show.c,v 1.22 2002/05/25 23:09:06 wiz Exp $");
45
#endif
45
#endif
46
#endif /* not lint */
46
#endif /* not lint */
47
47
48
#include <stdio.h>
48
#include <stdio.h>
49
#ifdef __STDC__
50
#include <stdarg.h>
49
#include <stdarg.h>
51
#else
52
#include <varargs.h>
53
#endif
54
50
55
#include "shell.h"
51
#include "shell.h"
56
#include "parser.h"
52
#include "parser.h"
Lines 276-282 Link Here
276
		putc('\t', fp);
272
		putc('\t', fp);
277
	}
273
	}
278
}
274
}
279
#endif
280
275
281
276
282
277
Lines 294-300 Link Here
294
#endif
289
#endif
295
290
296
291
297
#ifdef DEBUG
298
void
292
void
299
trputc(c)
293
trputc(c)
300
	int c;
294
	int c;
Lines 305-340 Link Here
305
	if (c == '\n')
299
	if (c == '\n')
306
		fflush(tracefile);
300
		fflush(tracefile);
307
}
301
}
308
#endif
309
302
310
void
303
void
311
#ifdef __STDC__
312
trace(const char *fmt, ...)
304
trace(const char *fmt, ...)
313
#else
314
trace(va_alist)
315
	va_dcl
316
#endif
317
{
305
{
318
#ifdef DEBUG
319
	va_list va;
306
	va_list va;
320
#ifdef __STDC__
307
321
	va_start(va, fmt);
308
	va_start(va, fmt);
322
#else
323
	char *fmt;
324
	va_start(va);
325
	fmt = va_arg(va, char *);
326
#endif
327
	if (tracefile != NULL) {
309
	if (tracefile != NULL) {
328
		(void) vfprintf(tracefile, fmt, va);
310
		(void) vfprintf(tracefile, fmt, va);
329
		if (strchr(fmt, '\n'))
311
		if (strchr(fmt, '\n'))
330
			(void) fflush(tracefile);
312
			(void) fflush(tracefile);
331
	}
313
	}
332
	va_end(va);
314
	va_end(va);
333
#endif
334
}
315
}
335
316
336
317
337
#ifdef DEBUG
338
void
318
void
339
trputs(s)
319
trputs(s)
340
	const char *s;
320
	const char *s;
Lines 386-399 Link Here
386
	}
366
	}
387
	putc('"', tracefile);
367
	putc('"', tracefile);
388
}
368
}
389
#endif
390
369
391
370
392
void
371
void
393
trargs(ap)
372
trargs(ap)
394
	char **ap;
373
	char **ap;
395
{
374
{
396
#ifdef DEBUG
397
	if (tracefile == NULL)
375
	if (tracefile == NULL)
398
		return;
376
		return;
399
	while (*ap) {
377
	while (*ap) {
Lines 404-414 Link Here
404
			putc('\n', tracefile);
382
			putc('\n', tracefile);
405
	}
383
	}
406
	fflush(tracefile);
384
	fflush(tracefile);
407
#endif
408
}
385
}
409
386
410
387
411
#ifdef DEBUG
412
void
388
void
413
opentrace() {
389
opentrace() {
414
	char s[100];
390
	char s[100];
Lines 421-427 Link Here
421
#ifdef not_this_way
397
#ifdef not_this_way
422
	{
398
	{
423
		char *p;
399
		char *p;
424
		if ((p = getenv("HOME")) == NULL) {
400
		if ((p = getenv(homestr)) == NULL) {
425
			if (geteuid() == 0)
401
			if (geteuid() == 0)
426
				p = "/";
402
				p = "/";
427
			else
403
			else
(-)bin_NetBSD-1.6release.orig/src/bin/sh/specialbltins.def (+16 lines)
Line 0 Link Here
1
.
2
:
3
break
4
builtin
5
continue
6
eval
7
exec
8
exit
9
export
10
readonly
11
return
12
set
13
shift
14
times
15
trap
16
unset
(-)bin_NetBSD-1.6release.orig/src/bin/sh/trap.c (-160 / +98 lines)
Lines 48-53 Link Here
48
#include <signal.h>
48
#include <signal.h>
49
#include <unistd.h>
49
#include <unistd.h>
50
#include <stdlib.h>
50
#include <stdlib.h>
51
#include <string.h>
51
52
52
#include "shell.h"
53
#include "shell.h"
53
#include "main.h"
54
#include "main.h"
Lines 63-68 Link Here
63
#include "trap.h"
64
#include "trap.h"
64
#include "mystring.h"
65
#include "mystring.h"
65
66
67
#ifdef HETIO
68
#include "hetio.h"
69
#endif
66
70
67
/*
71
/*
68
 * Sigmode records the current value of the signal handlers for the various
72
 * Sigmode records the current value of the signal handlers for the various
Lines 77-135 Link Here
77
#define S_RESET 5		/* temporary - to reset a hard ignored sig */
81
#define S_RESET 5		/* temporary - to reset a hard ignored sig */
78
82
79
83
80
char *trap[NSIG+1];		/* trap handler commands */
84
/* trap handler commands */
81
MKINIT char sigmode[NSIG];	/* current value of signal */
85
char *trap[NSIG];
82
char gotsig[NSIG];		/* indicates specified signal received */
86
/* current value of signal */
83
int pendingsigs;			/* indicates some signal received */
87
STATIC char sigmode[NSIG - 1];
84
88
/* indicates specified signal received */
85
static int getsigaction __P((int, sig_t *));
89
STATIC char gotsig[NSIG - 1];
86
static int signame_to_signum __P((const char *));
90
/* last pending signal */
87
void printsignals __P((void));
91
volatile sig_atomic_t pendingsigs;
88
89
/*
90
 * return the signal number described by `p' (as a number or a name)
91
 * or -1 if it isn't one
92
 */
93
94
static int
95
signame_to_signum(p)
96
	const char *p;
97
{
98
	int i;
99
100
	if (is_number(p))
101
		return number(p);
102
103
	if (strcasecmp(p, "exit") == 0 )
104
		return 0;
105
	
92
	
106
	if (strncasecmp(p, "sig", 3) == 0)
93
extern char *signal_names[];
107
		p += 3;
108
94
109
	for (i = 0; i < NSIG; ++i)
95
#ifdef mkinit
110
		if (strcasecmp (p, sys_signame[i]) == 0)
96
INCLUDE <signal.h>
111
			return i;
97
INIT {
112
	return -1;
98
	signal(SIGCHLD, SIG_DFL);
113
}
99
}
100
#endif
114
101
115
/*
116
 * Print a list of valid signal names
117
 */
118
void
119
printsignals(void)
120
{
121
	int n;
122
123
	out1str("EXIT ");
124
125
	for (n = 1; n < NSIG; n++) {
126
		out1fmt("%s", sys_signame[n]);
127
		if ((n == NSIG/2) ||  n == (NSIG - 1))
128
			out1str("\n");
129
		else
130
			out1c(' ');
131
	}
132
}
133
102
134
/*
103
/*
135
 * The trap builtin.
104
 * The trap builtin.
Lines 144-198 Link Here
144
	char **ap;
113
	char **ap;
145
	int signo;
114
	int signo;
146
115
147
	if (argc <= 1) {
116
	nextopt(nullstr);
148
		for (signo = 0 ; signo <= NSIG ; signo++) {
117
	ap = argptr;
149
			if (trap[signo] != NULL)
118
	if (!*ap) {
150
				out1fmt("trap -- '%s' %s\n", trap[signo],
119
		for (signo = 0 ; signo < NSIG ; signo++) {
151
				    (signo) ? sys_signame[signo] : "EXIT");
120
			if (trap[signo] != NULL) {
121
				out1fmt(
122
					"trap -- %s %s\n",
123
					single_quote(trap[signo]),
124
					signal_names[signo]
125
				);
152
		}
126
		}
153
		return 0;
154
	}
127
	}
155
	ap = argv + 1;
156
157
	action = NULL;
158
159
	if (strcmp(*ap, "--") == 0)
160
		if (*++ap == NULL)
161
			return 0;
162
163
	if (signame_to_signum(*ap) == -1) {
164
		if ((*ap)[0] =='-') {
165
			if ((*ap)[1] == NULL)
166
				ap++;
167
			else if ((*ap)[1] == 'l' && (*ap)[2] == NULL) {
168
				printsignals();
169
				return 0;
128
				return 0;
170
			}
129
			}
171
			else
130
	if (!ap[1])
172
				error("bad option %s\n", *ap);
131
		action = NULL;
173
		}
174
		else
132
		else
175
			action = *ap++;
133
			action = *ap++;
176
	}
177
178
	while (*ap) {
134
	while (*ap) {
179
		if (is_number(*ap))
135
		if ((signo = decode_signal(*ap, 0)) < 0)
180
			signo = number(*ap);
181
		else
182
			signo = signame_to_signum(*ap);
183
184
		if (signo < 0 || signo > NSIG)
185
			error("%s: bad trap", *ap);
136
			error("%s: bad trap", *ap);
186
187
		INTOFF;
137
		INTOFF;
188
		if (action)
138
		if (action) {
139
			if (action[0] == '-' && action[1] == '\0')
140
				action = NULL;
141
			else
189
			action = savestr(action);
142
			action = savestr(action);
190
143
		}
191
		if (trap[signo])
144
		if (trap[signo])
192
			ckfree(trap[signo]);
145
			ckfree(trap[signo]);
193
194
		trap[signo] = action;
146
		trap[signo] = action;
195
196
		if (signo != 0)
147
		if (signo != 0)
197
			setsignal(signo);
148
			setsignal(signo);
198
		INTON;
149
		INTON;
Lines 211-217 Link Here
211
clear_traps() {
162
clear_traps() {
212
	char **tp;
163
	char **tp;
213
164
214
	for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
165
	for (tp = trap ; tp < &trap[NSIG] ; tp++) {
215
		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
166
		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
216
			INTOFF;
167
			INTOFF;
217
			ckfree(*tp);
168
			ckfree(*tp);
Lines 230-242 Link Here
230
 * out what it should be set to.
181
 * out what it should be set to.
231
 */
182
 */
232
183
233
long
184
void
234
setsignal(signo)
185
setsignal(signo)
235
	int signo;
186
	int signo;
236
{
187
{
237
	int action;
188
	int action;
238
	sig_t sigact = SIG_DFL;
239
	char *t;
189
	char *t;
190
	struct sigaction act;
240
191
241
	if ((t = trap[signo]) == NULL)
192
	if ((t = trap[signo]) == NULL)
242
		action = S_DFL;
193
		action = S_DFL;
Lines 279-293 Link Here
279
		/*
230
		/*
280
		 * current setting unknown
231
		 * current setting unknown
281
		 */
232
		 */
282
		if (!getsigaction(signo, &sigact)) {
233
		if (sigaction(signo, 0, &act) == -1) {
283
			/*
234
			/*
284
			 * Pretend it worked; maybe we should give a warning
235
			 * Pretend it worked; maybe we should give a warning
285
			 * here, but other shells don't. We don't alter
236
			 * here, but other shells don't. We don't alter
286
			 * sigmode, so that we retry every time.
237
			 * sigmode, so that we retry every time.
287
			 */
238
			 */
288
			return 0;
239
			return;
289
		}
240
		}
290
		if (sigact == SIG_IGN) {
241
		if (act.sa_handler == SIG_IGN) {
291
			if (mflag && (signo == SIGTSTP ||
242
			if (mflag && (signo == SIGTSTP ||
292
			     signo == SIGTTIN || signo == SIGTTOU)) {
243
			     signo == SIGTTIN || signo == SIGTTOU)) {
293
				*t = S_IGN;	/* don't hard ignore these */
244
				*t = S_IGN;	/* don't hard ignore these */
Lines 298-328 Link Here
298
		}
249
		}
299
	}
250
	}
300
	if (*t == S_HARD_IGN || *t == action)
251
	if (*t == S_HARD_IGN || *t == action)
301
		return 0;
252
		return;
302
	switch (action) {
253
	switch (action) {
303
		case S_DFL:	sigact = SIG_DFL;	break;
254
	case S_CATCH:
304
		case S_CATCH:  	sigact = onsig;		break;
255
		act.sa_handler = onsig;
305
		case S_IGN:	sigact = SIG_IGN;	break;
256
		break;
257
	case S_IGN:
258
		act.sa_handler = SIG_IGN;
259
		break;
260
	default:
261
		act.sa_handler = SIG_DFL;
306
	}
262
	}
307
	*t = action;
263
	*t = action;
308
	siginterrupt(signo, 1);
264
	act.sa_flags = 0;
309
	return (long)signal(signo, sigact);
265
	sigfillset(&act.sa_mask);
310
}
266
	sigaction(signo, &act, 0);
311
312
/*
313
 * Return the current setting for sig w/o changing it.
314
 */
315
static int
316
getsigaction(signo, sigact)
317
	int signo;
318
	sig_t *sigact;
319
{
320
	struct sigaction sa;
321
322
	if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
323
		return 0;
324
	*sigact = (sig_t) sa.sa_handler;
325
	return 1;
326
}
267
}
327
268
328
/*
269
/*
Lines 340-361 Link Here
340
}
281
}
341
282
342
283
343
#ifdef mkinit
344
INCLUDE <signal.h>
345
INCLUDE "trap.h"
346
347
SHELLPROC {
348
	char *sm;
349
350
	clear_traps();
351
	for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
352
		if (*sm == S_IGN)
353
			*sm = S_HARD_IGN;
354
	}
355
}
356
#endif
357
358
359
284
360
/*
285
/*
361
 * Signal handler.
286
 * Signal handler.
Lines 365-377 Link Here
365
onsig(signo)
290
onsig(signo)
366
	int signo;
291
	int signo;
367
{
292
{
368
	signal(signo, onsig);
369
	if (signo == SIGINT && trap[SIGINT] == NULL) {
293
	if (signo == SIGINT && trap[SIGINT] == NULL) {
370
		onint();
294
		if (suppressint) {
295
			(*(sig_atomic_t *) &intpending)++;
371
		return;
296
		return;
372
	}
297
	}
298
		onint();
299
	}
373
	gotsig[signo - 1] = 1;
300
	gotsig[signo - 1] = 1;
374
	pendingsigs++;
301
	pendingsigs = signo;
375
}
302
}
376
303
377
304
Lines 383-405 Link Here
383
310
384
void
311
void
385
dotrap() {
312
dotrap() {
386
	int i;
313
	char *p;
387
	int savestatus;
314
	int savestatus;
388
315
389
	for (;;) {
316
	while (pendingsigs = 0, barrier(), (p = memchr(gotsig, 1, NSIG - 1))) {
390
		for (i = 1 ; ; i++) {
317
		*p = 0;
391
			if (gotsig[i - 1])
392
				break;
393
			if (i >= NSIG)
394
				goto done;
395
		}
396
		gotsig[i - 1] = 0;
397
		savestatus=exitstatus;
318
		savestatus=exitstatus;
398
		evalstring(trap[i], 0);
319
		evalstring(trap[p - gotsig + 1], 0);
399
		exitstatus=savestatus;
320
		exitstatus=savestatus;
400
	}
321
	}
401
done:
402
	pendingsigs = 0;
403
}
322
}
404
323
405
324
Lines 415-426 Link Here
415
{
334
{
416
	static int is_interactive;
335
	static int is_interactive;
417
336
418
	if (on == is_interactive)
337
	if (++on == is_interactive)
419
		return;
338
		return;
339
	is_interactive = on;
420
	setsignal(SIGINT);
340
	setsignal(SIGINT);
421
	setsignal(SIGQUIT);
341
	setsignal(SIGQUIT);
422
	setsignal(SIGTERM);
342
	setsignal(SIGTERM);
423
	is_interactive = on;
424
}
343
}
425
344
426
345
Lines 430-458 Link Here
430
 */
349
 */
431
350
432
void
351
void
433
exitshell(status)
352
exitshell(void)
434
	int status;
435
{
353
{
436
	struct jmploc loc1, loc2;
354
	struct jmploc loc;
437
	char *p;
355
	char *p;
356
	int status;
438
357
358
	status = exitstatus;
439
	TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
359
	TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
440
	if (setjmp(loc1.loc)) {
360
#ifdef HETIO
441
		goto l1;
361
	hetio_reset_term();
442
	}
362
#endif
443
	if (setjmp(loc2.loc)) {
363
	if (setjmp(loc.loc)) {
444
		goto l2;
364
		goto out;
445
	}
365
	}
446
	handler = &loc1;
366
	handler = &loc;
447
	if ((p = trap[0]) != NULL && *p != '\0') {
367
	if ((p = trap[0]) != NULL && *p != '\0') {
448
		trap[0] = NULL;
368
		trap[0] = NULL;
449
		evalstring(p, 0);
369
		evalstring(p, 0);
450
	}
370
	}
451
l1:   handler = &loc2;			/* probably unnecessary */
452
	flushall();
371
	flushall();
453
#if JOBS
372
out:
454
	setjobctl(0);
373
	_exit(status);
455
#endif
456
l2:   _exit(status);
457
	/* NOTREACHED */
374
	/* NOTREACHED */
458
}
375
}
376
377
int decode_signal(const char *string, int minsig)
378
{
379
	int signo;
380
381
	if (is_number(string)) {
382
		signo = atoi(string);
383
		if (signo >= NSIG) {
384
			return -1;
385
		}
386
		return signo;
387
	}
388
389
	for (signo = minsig; signo < NSIG; signo++) {
390
		if (!strcasecmp(string, signal_names[signo])) {
391
			return signo;
392
		}
393
	}
394
395
	return -1;
396
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/trap.h (-3 / +7 lines)
Lines 38-50 Link Here
38
 *	@(#)trap.h	8.3 (Berkeley) 6/5/95
38
 *	@(#)trap.h	8.3 (Berkeley) 6/5/95
39
 */
39
 */
40
40
41
extern int pendingsigs;
41
#include <signal.h>
42
43
extern volatile sig_atomic_t pendingsigs;
44
extern char *trap[];
42
45
43
int trapcmd __P((int, char **));
46
int trapcmd __P((int, char **));
44
void clear_traps __P((void));
47
void clear_traps __P((void));
45
long setsignal __P((int));
48
void setsignal __P((int));
46
void ignoresig __P((int));
49
void ignoresig __P((int));
47
void onsig __P((int));
50
void onsig __P((int));
48
void dotrap __P((void));
51
void dotrap __P((void));
49
void setinteractive __P((int));
52
void setinteractive __P((int));
50
void exitshell __P((int)) __attribute__((noreturn));
53
void exitshell __P((void)) __attribute__((noreturn));
54
int decode_signal __P((const char *, int));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/var.c (-241 / +154 lines)
Lines 67-72 Link Here
67
#include "error.h"
67
#include "error.h"
68
#include "mystring.h"
68
#include "mystring.h"
69
#include "parser.h"
69
#include "parser.h"
70
#include "mail.h"
70
#ifndef SMALL
71
#ifndef SMALL
71
#include "myhistedit.h"
72
#include "myhistedit.h"
72
#endif
73
#endif
Lines 75-150 Link Here
75
#define VTABSIZE 39
76
#define VTABSIZE 39
76
77
77
78
78
struct varinit {
79
struct localvar *localvars;
79
	struct var *var;
80
	int flags;
81
	const char *text;
82
	void (*func) __P((const char *));
83
};
84
85
80
86
#if ATTY
81
const char defpathvar[] =
87
struct var vatty;
82
	"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
88
#endif
83
#ifdef IFS_BROKEN
89
#ifndef SMALL
84
const char defifsvar[] = "IFS= \t\n";
90
struct var vhistsize;
85
#else
91
struct var vterm;
86
const char defifs[] = " \t\n";
92
#endif
87
#endif
93
struct var vifs;
94
struct var vmail;
95
struct var vmpath;
96
struct var vpath;
97
struct var vps1;
98
struct var vps2;
99
struct var vvers;
100
struct var voptind;
101
88
102
const struct varinit varinit[] = {
89
struct var varinit[] = {
103
#if ATTY
90
#if ATTY
104
	{ &vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",
91
	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",	0 },
105
	  NULL },
106
#endif
92
#endif
107
#ifndef SMALL
93
#ifdef IFS_BROKEN
108
	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
94
	{ 0,	VSTRFIXED|VTEXTFIXED,		defifsvar,	0 },
109
	  sethistsize },
95
#else
96
	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"IFS=",		0 },
110
#endif
97
#endif
111
	{ &vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",
98
	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL=",	changemail },
112
	  NULL },
99
	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",	changemail },
113
	{ &vmail,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL=",
100
	{ 0,	VSTRFIXED|VTEXTFIXED,		defpathvar,	changepath },
114
	  NULL },
101
	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS1=$ ",	0 },
115
	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
102
	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",	0 },
116
	  NULL },
103
	{ 0,	VSTRFIXED|VTEXTFIXED,		"OPTIND=1",	getoptsreset },
117
	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,
118
	  changepath },
119
	/*
120
	 * vps1 depends on uid
121
	 */
122
	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
123
	  NULL },
124
#ifndef SMALL
104
#ifndef SMALL
125
	{ &vterm,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM=",
105
	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM=",	0 },
126
	  setterm },
106
	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",	sethistsize },
127
#endif
107
#endif
128
	{ &voptind,	VSTRFIXED|VTEXTFIXED,		"OPTIND=1",
129
	  getoptsreset },
130
	{ NULL,	0,				NULL,
131
	  NULL }
132
};
108
};
133
109
134
struct var *vartab[VTABSIZE];
110
STATIC struct var *vartab[VTABSIZE];
135
111
136
STATIC struct var **hashvar __P((const char *));
112
STATIC struct var **hashvar __P((const char *));
137
STATIC int varequal __P((const char *, const char *));
113
STATIC void showvars __P((const char *, int, int));
114
STATIC struct var **findvar __P((struct var **, const char *));
138
115
139
/*
116
/*
140
 * Initialize the varable symbol tables and import the environment
117
 * Initialize the varable symbol tables and import the environment
141
 */
118
 */
142
119
143
#ifdef mkinit
120
#ifdef mkinit
121
INCLUDE <unistd.h>
122
INCLUDE "cd.h"
123
INCLUDE "output.h"
144
INCLUDE "var.h"
124
INCLUDE "var.h"
145
MKINIT char **environ;
125
MKINIT char **environ;
146
INIT {
126
INIT {
147
	char **envp;
127
	char **envp;
128
	static char ppid[32 + 5] = "PPID=";
148
129
149
	initvar();
130
	initvar();
150
	for (envp = environ ; *envp ; envp++) {
131
	for (envp = environ ; *envp ; envp++) {
Lines 152-192 Link Here
152
			setvareq(*envp, VEXPORT|VTEXTFIXED);
133
			setvareq(*envp, VEXPORT|VTEXTFIXED);
153
		}
134
		}
154
	}
135
	}
136
137
	fmtstr(ppid + 5, sizeof(ppid) - 5, "%ld", (long) getppid());
138
	setvareq(ppid, VTEXTFIXED);
139
	setpwd(0, 0);
155
}
140
}
156
#endif
141
#endif
157
142
158
143
159
/*
144
/*
160
 * This routine initializes the builtin variables.  It is called when the
145
 * This routine initializes the builtin variables.  It is called when the
161
 * shell is initialized and again when a shell procedure is spawned.
146
 * shell is initialized.
162
 */
147
 */
163
148
164
void
149
void
165
initvar() {
150
initvar() {
166
	const struct varinit *ip;
167
	struct var *vp;
151
	struct var *vp;
152
	struct var *end;
168
	struct var **vpp;
153
	struct var **vpp;
169
154
170
	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
155
	vp = varinit;
171
		if ((vp->flags & VEXPORT) == 0) {
156
	end = vp + sizeof(varinit) / sizeof(varinit[0]);
172
			vpp = hashvar(ip->text);
157
	do {
158
		vpp = hashvar(vp->text);
173
			vp->next = *vpp;
159
			vp->next = *vpp;
174
			*vpp = vp;
160
			*vpp = vp;
175
			vp->text = strdup(ip->text);
161
	} while (++vp < end);
176
			vp->flags = ip->flags;
177
			vp->func = ip->func;
178
		}
179
	}
180
	/*
162
	/*
181
	 * PS1 depends on uid
163
	 * PS1 depends on uid
182
	 */
164
	 */
183
	if ((vps1.flags & VEXPORT) == 0) {
165
	if (!geteuid())
184
		vpp = hashvar("PS1=");
166
		vps1.text = "PS1=# ";
185
		vps1.next = *vpp;
186
		*vpp = &vps1;
187
		vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
188
		vps1.flags = VSTRFIXED|VTEXTFIXED;
189
	}
190
}
167
}
191
168
192
/*
169
/*
Lines 198-217 Link Here
198
	const char *name, *val;
175
	const char *name, *val;
199
	int flags;
176
	int flags;
200
{
177
{
201
	struct jmploc jmploc;
178
	int err;
179
	volatile int saveint;
202
	struct jmploc *volatile savehandler = handler;
180
	struct jmploc *volatile savehandler = handler;
203
	int err = 0;
181
	struct jmploc jmploc;
204
#ifdef __GNUC__
205
	(void) &err;
206
#endif
207
182
183
	SAVEINT(saveint);
208
	if (setjmp(jmploc.loc))
184
	if (setjmp(jmploc.loc))
209
		err = 1;
185
		err = 1;
210
	else {
186
	else {
211
		handler = &jmploc;
187
		handler = &jmploc;
212
		setvar(name, val, flags);
188
		setvar(name, val, flags);
189
		err = 0;
213
	}
190
	}
214
	handler = savehandler;
191
	handler = savehandler;
192
	RESTOREINT(saveint);
215
	return err;
193
	return err;
216
}
194
}
217
195
Lines 225-269 Link Here
225
	const char *name, *val;
203
	const char *name, *val;
226
	int flags;
204
	int flags;
227
{
205
{
228
	const char *p;
206
	char *p, *q;
229
	const char *q;
207
	size_t namelen;
230
	char *d;
231
	int len;
232
	int namelen;
233
	char *nameeq;
208
	char *nameeq;
234
	int isbad;
209
	size_t vallen;
235
210
236
	isbad = 0;
211
	q = endofname(name);
237
	p = name;
212
	p = strchrnul(q, '=');
238
	if (! is_name(*p))
239
		isbad = 1;
240
	p++;
241
	for (;;) {
242
		if (! is_in_name(*p)) {
243
			if (*p == '\0' || *p == '=')
244
				break;
245
			isbad = 1;
246
		}
247
		p++;
248
	}
249
	namelen = p - name;
213
	namelen = p - name;
250
	if (isbad)
214
	if (!namelen || p != q)
251
		error("%.*s: bad variable name", namelen, name);
215
		error("%.*s: bad variable name", namelen, name);
252
	len = namelen + 2;		/* 2 is space for '=' and '\0' */
216
	vallen = 0;
253
	if (val == NULL) {
217
	if (val == NULL) {
254
		flags |= VUNSET;
218
		flags |= VUNSET;
255
	} else {
219
	} else {
256
		len += strlen(val);
220
		vallen = strlen(val);
257
	}
221
	}
258
	d = nameeq = ckmalloc(len);
222
	INTOFF;
259
	q = name;
223
	p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
260
	while (--namelen >= 0)
224
	*p++ = '=';
261
		*d++ = *q++;
225
	if (vallen) {
262
	*d++ = '=';
226
		p = mempcpy(p, val, vallen);
263
	*d = '\0';
227
	}
264
	if (val)
228
	*p = '\0';
265
		scopy(val, d);
266
	setvareq(nameeq, flags);
229
	setvareq(nameeq, flags);
230
	INTON;
267
}
231
}
268
232
269
233
Lines 282-297 Link Here
282
{
246
{
283
	struct var *vp, **vpp;
247
	struct var *vp, **vpp;
284
248
285
	if (aflag)
286
		flags |= VEXPORT;
287
	vpp = hashvar(s);
249
	vpp = hashvar(s);
288
	for (vp = *vpp ; vp ; vp = vp->next) {
250
	flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
289
		if (varequal(s, vp->text)) {
251
	vp = *findvar(vpp, s);
252
	INTOFF;
253
	if (vp) {
290
			if (vp->flags & VREADONLY) {
254
			if (vp->flags & VREADONLY) {
291
				size_t len = strchr(s, '=') - s;
255
				size_t len = strchr(s, '=') - s;
292
				error("%.*s: is read only", len, s);
256
				error("%.*s: is read only", len, s);
293
			}
257
			}
294
			INTOFF;
295
258
296
			if (vp->func && (flags & VNOFUNC) == 0)
259
			if (vp->func && (flags & VNOFUNC) == 0)
297
				(*vp->func)(strchr(s, '=') + 1);
260
				(*vp->func)(strchr(s, '=') + 1);
Lines 299-325 Link Here
299
			if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
262
			if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
300
				ckfree(vp->text);
263
				ckfree(vp->text);
301
264
302
			vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
265
		flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VUNSET);
303
			vp->flags |= flags;
266
	} else {
304
			vp->text = s;
305
306
			/*
307
			 * We could roll this to a function, to handle it as
308
			 * a regular variable function callback, but why bother?
309
			 */
310
			if (vp == &vmpath || (vp == &vmail && ! mpathset()))
311
				chkmail(1);
312
			INTON;
313
			return;
314
		}
315
	}
316
	/* not found */
267
	/* not found */
317
	vp = ckmalloc(sizeof (*vp));
268
	vp = ckmalloc(sizeof (*vp));
318
	vp->flags = flags;
319
	vp->text = s;
320
	vp->next = *vpp;
269
	vp->next = *vpp;
321
	vp->func = NULL;
270
	vp->func = NULL;
322
	*vpp = vp;
271
	*vpp = vp;
272
	}
273
	vp->text = s;
274
	vp->flags = flags;
275
	INTON;
323
}
276
}
324
277
325
278
Lines 329-342 Link Here
329
 */
282
 */
330
283
331
void
284
void
332
listsetvar(list)
285
listsetvar(struct strlist *list, int flags)
333
	struct strlist *list;
286
{
334
	{
335
	struct strlist *lp;
287
	struct strlist *lp;
336
288
337
	INTOFF;
289
	INTOFF;
338
	for (lp = list ; lp ; lp = lp->next) {
290
	for (lp = list ; lp ; lp = lp->next) {
339
		setvareq(savestr(lp->text), 0);
291
		setvareq(savestr(lp->text), flags);
340
	}
292
	}
341
	INTON;
293
	INTON;
342
}
294
}
Lines 353-397 Link Here
353
	{
305
	{
354
	struct var *v;
306
	struct var *v;
355
307
356
	for (v = *hashvar(name) ; v ; v = v->next) {
308
	if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
357
		if (varequal(v->text, name)) {
358
			if (v->flags & VUNSET)
359
				return NULL;
360
			return strchr(v->text, '=') + 1;
309
			return strchr(v->text, '=') + 1;
361
		}
310
		}
362
	}
363
	return NULL;
311
	return NULL;
364
}
312
}
365
313
366
314
367
315
368
/*
316
/*
369
 * Search the environment of a builtin command.  If the second argument
317
 * Search the environment of a builtin command.
370
 * is nonzero, return the value of a variable even if it hasn't been
371
 * exported.
372
 */
318
 */
373
319
374
char *
320
char *
375
bltinlookup(name, doall)
321
bltinlookup(name)
376
	const char *name;
322
	const char *name;
377
	int doall;
378
{
323
{
379
	struct strlist *sp;
324
	struct strlist *sp;
380
	struct var *v;
381
325
382
	for (sp = cmdenviron ; sp ; sp = sp->next) {
326
	for (sp = cmdenviron ; sp ; sp = sp->next) {
383
		if (varequal(sp->text, name))
327
		if (varequal(sp->text, name))
384
			return strchr(sp->text, '=') + 1;
328
			return strchr(sp->text, '=') + 1;
385
	}
329
	}
386
	for (v = *hashvar(name) ; v ; v = v->next) {
330
	return lookupvar(name);
387
		if (varequal(v->text, name)) {
388
			if ((v->flags & VUNSET)
389
			 || (!doall && (v->flags & VEXPORT) == 0))
390
				return NULL;
391
			return strchr(v->text, '=') + 1;
392
		}
393
	}
394
	return NULL;
395
}
331
}
396
332
397
333
Lines 403-468 Link Here
403
339
404
char **
340
char **
405
environment() {
341
environment() {
406
	int nenv;
407
	struct var **vpp;
342
	struct var **vpp;
408
	struct var *vp;
343
	struct var *vp;
409
	char **env;
410
	char **ep;
344
	char **ep;
345
	void *epend;
411
346
412
	nenv = 0;
347
	STARTSTACKSTR(ep);
413
	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
348
	epend = sstrend;
414
		for (vp = *vpp ; vp ; vp = vp->next)
349
	vpp = vartab;
415
			if (vp->flags & VEXPORT)
350
	do {
416
				nenv++;
417
	}
418
	ep = env = stalloc((nenv + 1) * sizeof *env);
419
	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
420
		for (vp = *vpp ; vp ; vp = vp->next)
351
		for (vp = *vpp ; vp ; vp = vp->next)
421
			if (vp->flags & VEXPORT)
352
			if (vp->flags & VEXPORT && !(vp->flags & VUNSET)) {
422
				*ep++ = vp->text;
353
				if (ep == epend) {
423
	}
354
					ep = growstackstr();
424
	*ep = NULL;
355
					epend = sstrend;
425
	return env;
426
}
427
428
429
/*
430
 * Called when a shell procedure is invoked to clear out nonexported
431
 * variables.  It is also necessary to reallocate variables of with
432
 * VSTACK set since these are currently allocated on the stack.
433
 */
434
435
#ifdef mkinit
436
void shprocvar __P((void));
437
438
SHELLPROC {
439
	shprocvar();
440
}
441
#endif
442
443
void
444
shprocvar() {
445
	struct var **vpp;
446
	struct var *vp, **prev;
447
448
	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
449
		for (prev = vpp ; (vp = *prev) != NULL ; ) {
450
			if ((vp->flags & VEXPORT) == 0) {
451
				*prev = vp->next;
452
				if ((vp->flags & VTEXTFIXED) == 0)
453
					ckfree(vp->text);
454
				if ((vp->flags & VSTRFIXED) == 0)
455
					ckfree(vp);
456
			} else {
457
				if (vp->flags & VSTACK) {
458
					vp->text = savestr(vp->text);
459
					vp->flags &=~ VSTACK;
460
				}
461
				prev = &vp->next;
462
			}
463
		}
356
		}
357
				*ep++ = (char *) vp->text;
464
	}
358
	}
465
	initvar();
359
	} while (++vpp < vartab + VTABSIZE);
360
	if (ep == epend)
361
		ep = growstackstr();
362
	*ep++ = NULL;
363
	return grabstackstr(ep);
466
}
364
}
467
365
468
366
Lines 478-492 Link Here
478
	int argc;
376
	int argc;
479
	char **argv;
377
	char **argv;
480
{
378
{
481
	struct var **vpp;
379
	showvars(nullstr, VUNSET, VUNSET);
482
	struct var *vp;
483
484
	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
485
		for (vp = *vpp ; vp ; vp = vp->next) {
486
			if ((vp->flags & VUNSET) == 0)
487
				out1fmt("%s\n", vp->text);
488
		}
489
	}
490
	return 0;
380
	return 0;
491
}
381
}
492
382
Lines 501-545 Link Here
501
	int argc;
391
	int argc;
502
	char **argv;
392
	char **argv;
503
{
393
{
504
	struct var **vpp;
505
	struct var *vp;
394
	struct var *vp;
506
	char *name;
395
	char *name;
507
	const char *p;
396
	const char *p;
397
	char **aptr;
508
	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
398
	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
509
	int pflag;
399
	int notp;
510
400
511
	listsetvar(cmdenviron);
401
	notp = nextopt("p") - 'p';
512
	pflag = (nextopt("p") == 'p');
402
	if (notp && ((name = *(aptr = argptr)))) {
513
	if (argc > 1 && !pflag) {
403
		do {
514
		while ((name = *argptr++) != NULL) {
515
			if ((p = strchr(name, '=')) != NULL) {
404
			if ((p = strchr(name, '=')) != NULL) {
516
				p++;
405
				p++;
517
			} else {
406
			} else {
518
				vpp = hashvar(name);
407
				if ((vp = *findvar(hashvar(name), name))) {
519
				for (vp = *vpp ; vp ; vp = vp->next) {
520
					if (varequal(vp->text, name)) {
521
						vp->flags |= flag;
408
						vp->flags |= flag;
522
						goto found;
409
					continue;
523
					}
524
				}
410
				}
525
			}
411
			}
526
			setvar(name, p, flag);
412
			setvar(name, p, flag);
527
found:;
413
		} while ((name = *++aptr) != NULL);
528
		}
529
	} else {
530
		for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
531
			for (vp = *vpp ; vp ; vp = vp->next) {
532
				if ((vp->flags & flag) == 0)
533
					continue;
534
				if (pflag) {
535
					out1fmt("%s %s\n", argv[0], vp->text);
536
				} else {
414
				} else {
537
					for (p = vp->text ; *p != '=' ; p++)
415
		showvars(argv[0], flag, 0);
538
						out1c(*p);
539
					out1c('\n');
540
				}
541
			}
542
		}
543
	}
416
	}
544
	return 0;
417
	return 0;
545
}
418
}
Lines 589-595 Link Here
589
		vp = NULL;
462
		vp = NULL;
590
	} else {
463
	} else {
591
		vpp = hashvar(name);
464
		vpp = hashvar(name);
592
		for (vp = *vpp ; vp && ! varequal(vp->text, name) ; vp = vp->next);
465
		vp = *findvar(vpp, name);
593
		if (vp == NULL) {
466
		if (vp == NULL) {
594
			if (strchr(name, '='))
467
			if (strchr(name, '='))
595
				setvareq(savestr(name), VSTRFIXED);
468
				setvareq(savestr(name), VSTRFIXED);
Lines 684-690 Link Here
684
557
685
	for (ap = argptr; *ap ; ap++) {
558
	for (ap = argptr; *ap ; ap++) {
686
		if (flg_func)
559
		if (flg_func)
687
			ret |= unsetfunc(*ap);
560
			unsetfunc(*ap);
688
		if (flg_var)
561
		if (flg_var)
689
			ret |= unsetvar(*ap);
562
			ret |= unsetvar(*ap);
690
	}
563
	}
Lines 703-711 Link Here
703
	struct var **vpp;
576
	struct var **vpp;
704
	struct var *vp;
577
	struct var *vp;
705
578
706
	vpp = hashvar(s);
579
	vpp = findvar(hashvar(s), s);
707
	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
580
	vp = *vpp;
708
		if (varequal(vp->text, s)) {
581
	if (vp) {
709
			if (vp->flags & VREADONLY)
582
			if (vp->flags & VREADONLY)
710
				return (1);
583
				return (1);
711
			INTOFF;
584
			INTOFF;
Lines 722-730 Link Here
722
			INTON;
595
			INTON;
723
			return (0);
596
			return (0);
724
		}
597
		}
725
	}
726
598
727
	return (1);
599
	return (0);
728
}
600
}
729
601
730
602
Lines 753-759 Link Here
753
 * either '=' or '\0'.
625
 * either '=' or '\0'.
754
 */
626
 */
755
627
756
STATIC int
628
int
757
varequal(p, q)
629
varequal(p, q)
758
	const char *p, *q;
630
	const char *p, *q;
759
	{
631
	{
Lines 765-767 Link Here
765
		return 1;
637
		return 1;
766
	return 0;
638
	return 0;
767
}
639
}
640
641
STATIC void
642
showvars(const char *prefix, int mask, int xor)
643
{
644
	struct var **vpp;
645
	struct var *vp;
646
	const char *sep = *prefix ? spcstr : prefix;
647
648
	vpp = vartab;
649
	do {
650
		for (vp = *vpp ; vp ; vp = vp->next) {
651
			if ((vp->flags & mask) ^ xor) {
652
				const char *p;
653
				const char *q;
654
				int len;
655
656
				p = strchr(vp->text, '=');
657
				q = nullstr;
658
				if (!(vp->flags & VUNSET))
659
					q = single_quote(++p);
660
				len = p - vp->text;
661
662
				out1fmt(
663
					"%s%s%.*s%s\n", prefix, sep, len,
664
					vp->text, q
665
				);
666
			}
667
		}
668
	} while (++vpp < vartab + VTABSIZE);
669
}
670
671
STATIC struct var **
672
findvar(struct var **vpp, const char *name)
673
{
674
	for (; *vpp; vpp = &(*vpp)->next) {
675
		if (varequal((*vpp)->text, name)) {
676
			break;
677
		}
678
	}
679
	return vpp;
680
}
(-)bin_NetBSD-1.6release.orig/src/bin/sh/var.h (-16 / +28 lines)
Lines 55-61 Link Here
55
struct var {
55
struct var {
56
	struct var *next;		/* next entry in hash list */
56
	struct var *next;		/* next entry in hash list */
57
	int flags;			/* flags are defined above */
57
	int flags;			/* flags are defined above */
58
	char *text;			/* name=value */
58
	const char *text;		/* name=value */
59
	void (*func) __P((const char *));
59
	void (*func) __P((const char *));
60
					/* function to be called when  */
60
					/* function to be called when  */
61
					/* the variable gets set/unset */
61
					/* the variable gets set/unset */
Lines 66-91 Link Here
66
	struct localvar *next;		/* next local variable in list */
66
	struct localvar *next;		/* next local variable in list */
67
	struct var *vp;			/* the variable that was made local */
67
	struct var *vp;			/* the variable that was made local */
68
	int flags;			/* saved flags */
68
	int flags;			/* saved flags */
69
	char *text;			/* saved text */
69
	const char *text;		/* saved text */
70
};
70
};
71
71
72
72
73
struct localvar *localvars;
73
extern struct localvar *localvars;
74
extern struct var varinit[];
74
75
75
#if ATTY
76
#if ATTY
76
extern struct var vatty;
77
#define vatty varinit[0]
78
#define vifs varinit[1]
79
#else
80
#define vifs varinit[0]
77
#endif
81
#endif
78
extern struct var vifs;
82
#define vmail (&vifs)[1]
79
extern struct var vmail;
83
#define vmpath (&vmail)[1]
80
extern struct var vmpath;
84
#define vpath (&vmpath)[1]
81
extern struct var vpath;
85
#define vps1 (&vpath)[1]
82
extern struct var vps1;
86
#define vps2 (&vps1)[1]
83
extern struct var vps2;
87
#define voptind (&vps2)[1]
84
#ifndef SMALL
88
#ifndef SMALL
85
extern struct var vterm;
89
#define vterm (&voptind)[1]
86
extern struct var vtermcap;
90
#define vhistsize (&vterm)[1]
87
extern struct var vhistsize;
91
#endif
92
93
#ifdef IFS_BROKEN
94
extern const char defifsvar[];
95
#define defifs (defifsvar + 4)
96
#else
97
extern const char defifs[];
88
#endif
98
#endif
99
extern const char defpathvar[];
100
#define defpath (defpathvar + 5)
89
101
90
/*
102
/*
91
 * The following macros access the values of the above variables.
103
 * The following macros access the values of the above variables.
Lines 115-125 Link Here
115
void setvar __P((const char *, const char *, int));
127
void setvar __P((const char *, const char *, int));
116
void setvareq __P((char *, int));
128
void setvareq __P((char *, int));
117
struct strlist;
129
struct strlist;
118
void listsetvar __P((struct strlist *));
130
void listsetvar __P((struct strlist *, int));
119
char *lookupvar __P((const char *));
131
char *lookupvar __P((const char *));
120
char *bltinlookup __P((const char *, int));
132
char *bltinlookup __P((const char *));
121
char **environment __P((void));
133
char **environment __P((void));
122
void shprocvar __P((void));
123
int showvarscmd __P((int, char **));
134
int showvarscmd __P((int, char **));
124
int exportcmd __P((int, char **));
135
int exportcmd __P((int, char **));
125
int localcmd __P((int, char **));
136
int localcmd __P((int, char **));
Lines 129-131 Link Here
129
int unsetcmd __P((int, char **));
140
int unsetcmd __P((int, char **));
130
int unsetvar __P((const char *));
141
int unsetvar __P((const char *));
131
int setvarsafe __P((const char *, const char *, int));
142
int setvarsafe __P((const char *, const char *, int));
143
int varequal __P((const char *, const char *));
(-)bin_NetBSD-1.6release.orig/src/bin/sh/yaccfe.sh (+29 lines)
Line 0 Link Here
1
#!/bin/sh
2
# 
3
# Quick script to reformat yacc commands
4
# so byacc isnt required.
5
# 
6
# Expects:
7
# 	yacc -d -o yourfile.c yourfile.y
8
# Executes:
9
# 	yacc -d -b yourfile yourfile.y
10
# 	mv yourfile.tab.c yourfile.c
11
# 	mv yourfile.tab.h yourfile.h
12
#
13
14
yaccbin="/usr/bin/yacc"
15
yaccflags="-d"
16
17
[ ! ${#} -gt 0 ] && exit 1
18
while getopts ":o:" opt
19
do
20
        case $opt in
21
                o) output=${OPTARG%*.c} ;;
22
                ?) ;;
23
        esac
24
done
25
${yaccbin} ${yaccflags} -b ${output} ${output}.y || exit 1
26
for files in ${output}.tab.{c,h}
27
do
28
	mv ${files} $(sed 's/.tab//' <<< ${files}) || exit 1
29
done

Return to bug 15319