blob: 39aecdf109b41e40aecba67262bfebe10f362b24 [file] [log] [blame]
Eric Andersenff9eee42001-06-29 04:57:14 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Minix shell port for busybox
4 *
5 * This version of the Minix shell was adapted for use in busybox
Eric Andersencb81e642003-07-14 21:21:08 +00006 * by Erik Andersen <andersen@codepoet.org>
Eric Andersenff9eee42001-06-29 04:57:14 +00007 *
Eric Andersen737f5fb2003-03-14 16:05:59 +00008 * - backtick expansion did not work properly
9 * Jonas Holmberg <jonas.holmberg@axis.com>
10 * Robert Schwebel <r.schwebel@pengutronix.de>
Eric Andersencb81e642003-07-14 21:21:08 +000011 * Erik Andersen <andersen@codepoet.org>
Eric Andersen737f5fb2003-03-14 16:05:59 +000012 *
Eric Andersenff9eee42001-06-29 04:57:14 +000013 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Eric Andersenc7bda1c2004-03-15 08:29:22 +000026 *
Eric Andersenff9eee42001-06-29 04:57:14 +000027 * Original copyright notice is retained at the end of this file.
28 */
29
30#include <ctype.h>
31#include <dirent.h>
32#include <errno.h>
33#include <fcntl.h>
34#include <limits.h>
35#include <setjmp.h>
36#include <signal.h>
37#include <stddef.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <time.h>
42#include <unistd.h>
43#include <sys/stat.h>
44#include <sys/times.h>
45#include <sys/types.h>
46#include <sys/wait.h>
47
48#include "cmdedit.h"
49#include "busybox.h"
50
51
Eric Andersen12de6cf2004-08-04 19:19:10 +000052/* Conditional use of "register" keyword */
53#define REGISTER register
54
55
Mike Frysinger17811882006-05-05 20:33:07 +000056/*#define MSHDEBUG 1*/
Eric Andersen12de6cf2004-08-04 19:19:10 +000057
58#ifdef MSHDEBUG
59int mshdbg = 0;
60
61#define DBGPRINTF(x) if(mshdbg>0)printf x
62#define DBGPRINTF0(x) if(mshdbg>0)printf x
63#define DBGPRINTF1(x) if(mshdbg>1)printf x
64#define DBGPRINTF2(x) if(mshdbg>2)printf x
65#define DBGPRINTF3(x) if(mshdbg>3)printf x
66#define DBGPRINTF4(x) if(mshdbg>4)printf x
67#define DBGPRINTF5(x) if(mshdbg>5)printf x
68#define DBGPRINTF6(x) if(mshdbg>6)printf x
69#define DBGPRINTF7(x) if(mshdbg>7)printf x
70#define DBGPRINTF8(x) if(mshdbg>8)printf x
71#define DBGPRINTF9(x) if(mshdbg>9)printf x
72
73int mshdbg_rc = 0;
74
75#define RCPRINTF(x) if(mshdbg_rc)printf x
76
77#else
78
79#define DBGPRINTF(x)
80#define DBGPRINTF0(x)
81#define DBGPRINTF1(x)
82#define DBGPRINTF2(x)
83#define DBGPRINTF3(x)
84#define DBGPRINTF4(x)
85#define DBGPRINTF5(x)
86#define DBGPRINTF6(x)
87#define DBGPRINTF7(x)
88#define DBGPRINTF8(x)
89#define DBGPRINTF9(x)
90
91#define RCPRINTF(x)
92
93#endif /* MSHDEBUG */
94
95
Eric Andersenff9eee42001-06-29 04:57:14 +000096/* -------- sh.h -------- */
97/*
98 * shell
99 */
100
Eric Andersen12de6cf2004-08-04 19:19:10 +0000101#define LINELIM 2100
102#define NPUSH 8 /* limit to input nesting */
Eric Andersenff9eee42001-06-29 04:57:14 +0000103
Eric Andersen392947c2002-12-11 07:42:46 +0000104#undef NOFILE
Eric Andersen12de6cf2004-08-04 19:19:10 +0000105#define NOFILE 20 /* Number of open files */
106#define NUFILE 10 /* Number of user-accessible files */
107#define FDBASE 10 /* First file usable by Shell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000108
109/*
110 * values returned by wait
111 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000112#define WAITSIG(s) ((s)&0177)
113#define WAITVAL(s) (((s)>>8)&0377)
Eric Andersenff9eee42001-06-29 04:57:14 +0000114#define WAITCORE(s) (((s)&0200)!=0)
115
116/*
Eric Andersenaff114c2004-04-14 17:51:38 +0000117 * library and system definitions
Eric Andersenff9eee42001-06-29 04:57:14 +0000118 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000119typedef void xint; /* base type of jmp_buf, for not broken compilers */
Eric Andersenff9eee42001-06-29 04:57:14 +0000120
121/*
122 * shell components
123 */
124
125#define QUOTE 0200
126
127#define NOBLOCK ((struct op *)NULL)
128#define NOWORD ((char *)NULL)
129#define NOWORDS ((char **)NULL)
130#define NOPIPE ((int *)NULL)
131
132/*
133 * Description of a command or an operation on commands.
134 * Might eventually use a union.
135 */
136struct op {
Eric Andersen8401eea2004-08-04 19:16:54 +0000137 int type; /* operation type, see below */
138 char **words; /* arguments to a command */
139 struct ioword **ioact; /* IO actions (eg, < > >>) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000140 struct op *left;
141 struct op *right;
Eric Andersen8401eea2004-08-04 19:16:54 +0000142 char *str; /* identifier for case and for */
Eric Andersenff9eee42001-06-29 04:57:14 +0000143};
144
Eric Andersen8401eea2004-08-04 19:16:54 +0000145#define TCOM 1 /* command */
146#define TPAREN 2 /* (c-list) */
147#define TPIPE 3 /* a | b */
148#define TLIST 4 /* a [&;] b */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000149#define TOR 5 /* || */
Eric Andersen8401eea2004-08-04 19:16:54 +0000150#define TAND 6 /* && */
Eric Andersenff9eee42001-06-29 04:57:14 +0000151#define TFOR 7
Eric Andersen12de6cf2004-08-04 19:19:10 +0000152#define TDO 8
Eric Andersenff9eee42001-06-29 04:57:14 +0000153#define TCASE 9
Eric Andersen12de6cf2004-08-04 19:19:10 +0000154#define TIF 10
Eric Andersenff9eee42001-06-29 04:57:14 +0000155#define TWHILE 11
156#define TUNTIL 12
157#define TELIF 13
Eric Andersen8401eea2004-08-04 19:16:54 +0000158#define TPAT 14 /* pattern in case */
159#define TBRACE 15 /* {c-list} */
160#define TASYNC 16 /* c & */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000161/* Added to support "." file expansion */
162#define TDOT 17
163
164/* Strings for names to make debug easier */
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000165#ifdef MSHDEBUG
166static char *T_CMD_NAMES[] = {
Eric Andersen12de6cf2004-08-04 19:19:10 +0000167 "PLACEHOLDER",
168 "TCOM",
169 "TPAREN",
170 "TPIPE",
171 "TLIST",
172 "TOR",
173 "TAND",
174 "TFOR",
175 "TDO",
176 "TCASE",
177 "TIF",
178 "TWHILE",
179 "TUNTIL",
180 "TELIF",
181 "TPAT",
182 "TBRACE",
183 "TASYNC",
184 "TDOT",
185};
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000186#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000187
188/*
189 * actions determining the environment of a process
190 */
191#define BIT(i) (1<<(i))
Eric Andersen8401eea2004-08-04 19:16:54 +0000192#define FEXEC BIT(0) /* execute without forking */
Eric Andersenff9eee42001-06-29 04:57:14 +0000193
Eric Andersen12de6cf2004-08-04 19:19:10 +0000194#if 0 /* Original value */
195#define AREASIZE (65000)
196#else
197#define AREASIZE (90000)
198#endif
199
Eric Andersenff9eee42001-06-29 04:57:14 +0000200/*
201 * flags to control evaluation of words
202 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000203#define DOSUB 1 /* interpret $, `, and quotes */
204#define DOBLANK 2 /* perform blank interpretation */
205#define DOGLOB 4 /* interpret [?* */
206#define DOKEY 8 /* move words with `=' to 2nd arg. list */
207#define DOTRIM 16 /* trim resulting string */
Eric Andersenff9eee42001-06-29 04:57:14 +0000208
209#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
210
Eric Andersenff9eee42001-06-29 04:57:14 +0000211
Eric Andersen12de6cf2004-08-04 19:19:10 +0000212/* PROTOTYPES */
Eric Andersenff9eee42001-06-29 04:57:14 +0000213static int newfile(char *s);
214static char *findeq(char *cp);
215static char *cclass(char *p, int sub);
216static void initarea(void);
Matt Kraai2d91deb2001-08-01 17:21:35 +0000217extern int msh_main(int argc, char **argv);
Eric Andersenff9eee42001-06-29 04:57:14 +0000218
219
Eric Andersen8401eea2004-08-04 19:16:54 +0000220struct brkcon {
221 jmp_buf brkpt;
222 struct brkcon *nextlev;
223};
Eric Andersenff9eee42001-06-29 04:57:14 +0000224
Eric Andersen12de6cf2004-08-04 19:19:10 +0000225
Eric Andersenff9eee42001-06-29 04:57:14 +0000226/*
227 * redirection
228 */
229struct ioword {
Eric Andersen8401eea2004-08-04 19:16:54 +0000230 short io_unit; /* unit affected */
231 short io_flag; /* action (below) */
232 char *io_name; /* file name */
Eric Andersenff9eee42001-06-29 04:57:14 +0000233};
Eric Andersenff9eee42001-06-29 04:57:14 +0000234
Eric Andersen12de6cf2004-08-04 19:19:10 +0000235#define IOREAD 1 /* < */
236#define IOHERE 2 /* << (here file) */
237#define IOWRITE 4 /* > */
238#define IOCAT 8 /* >> */
239#define IOXHERE 16 /* ${}, ` in << */
240#define IODUP 32 /* >&digit */
241#define IOCLOSE 64 /* >&- */
Eric Andersenff9eee42001-06-29 04:57:14 +0000242
Eric Andersen8401eea2004-08-04 19:16:54 +0000243#define IODEFAULT (-1) /* token for default IO unit */
244
Eric Andersen12de6cf2004-08-04 19:19:10 +0000245
Eric Andersenff9eee42001-06-29 04:57:14 +0000246
247/*
248 * parsing & execution environment
249 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000250static struct env {
251 char *linep;
252 struct io *iobase;
253 struct io *iop;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000254 xint *errpt; /* void * */
Eric Andersen8401eea2004-08-04 19:16:54 +0000255 int iofd;
256 struct env *oenv;
Eric Andersenff9eee42001-06-29 04:57:14 +0000257} e;
258
259/*
260 * flags:
261 * -e: quit on error
262 * -k: look for name=value everywhere on command line
263 * -n: no execution
264 * -t: exit after reading and executing one command
265 * -v: echo as read
266 * -x: trace
267 * -u: unset variables net diagnostic
268 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000269static char *flag;
Eric Andersenff9eee42001-06-29 04:57:14 +0000270
Eric Andersen8401eea2004-08-04 19:16:54 +0000271static char *null; /* null value for variable */
272static int intr; /* interrupt pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000273
Eric Andersen8401eea2004-08-04 19:16:54 +0000274static char *trap[_NSIG + 1];
275static char ourtrap[_NSIG + 1];
276static int trapset; /* trap pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000277
Eric Andersen8401eea2004-08-04 19:16:54 +0000278static int heedint; /* heed interrupt signals */
Eric Andersenff9eee42001-06-29 04:57:14 +0000279
Eric Andersen8401eea2004-08-04 19:16:54 +0000280static int yynerrs; /* yacc */
Eric Andersenff9eee42001-06-29 04:57:14 +0000281
Eric Andersen8401eea2004-08-04 19:16:54 +0000282static char line[LINELIM];
283static char *elinep;
Eric Andersenff9eee42001-06-29 04:57:14 +0000284
Eric Andersen12de6cf2004-08-04 19:19:10 +0000285
Eric Andersenff9eee42001-06-29 04:57:14 +0000286/*
287 * other functions
288 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000289static int (*inbuilt(char *s)) (struct op *);
Eric Andersen392947c2002-12-11 07:42:46 +0000290
Eric Andersen8401eea2004-08-04 19:16:54 +0000291static char *rexecve(char *c, char **v, char **envp);
292static char *space(int n);
293static char *strsave(char *s, int a);
294static char *evalstr(char *cp, int f);
295static char *putn(int n);
296static char *itoa(int n);
297static char *unquote(char *as);
298static struct var *lookup(char *n);
299static int rlookup(char *n);
300static struct wdblock *glob(char *cp, struct wdblock *wb);
301static int my_getc(int ec);
302static int subgetc(int ec, int quoted);
Eric Andersenfd7a4c82004-09-02 23:13:10 +0000303static char **makenv(int all, struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000304static char **eval(char **ap, int f);
305static int setstatus(int s);
306static int waitfor(int lastpid, int canintr);
Eric Andersenff9eee42001-06-29 04:57:14 +0000307
Eric Andersen8401eea2004-08-04 19:16:54 +0000308static void onintr(int s); /* SIGINT handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000309
Eric Andersen8401eea2004-08-04 19:16:54 +0000310static int newenv(int f);
311static void quitenv(void);
312static void err(char *s);
313static int anys(char *s1, char *s2);
314static int any(int c, char *s);
315static void next(int f);
316static void setdash(void);
317static void onecommand(void);
318static void runtrap(int i);
319static int gmatch(char *s, char *p);
Eric Andersenff9eee42001-06-29 04:57:14 +0000320
Eric Andersen12de6cf2004-08-04 19:19:10 +0000321
Eric Andersenff9eee42001-06-29 04:57:14 +0000322/*
323 * error handling
324 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000325static void leave(void); /* abort shell (or fail in subshell) */
326static void fail(void); /* fail but return to process next command */
327static void warn(char *s);
328static void sig(int i); /* default signal handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000329
330
331
332/* -------- area stuff -------- */
333
Eric Andersen12de6cf2004-08-04 19:19:10 +0000334#define REGSIZE sizeof(struct region)
335#define GROWBY (256)
336/* #define SHRINKBY (64) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000337#undef SHRINKBY
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000338#define FREE (32767)
339#define BUSY (0)
340#define ALIGN (sizeof(int)-1)
Eric Andersenff9eee42001-06-29 04:57:14 +0000341
342
343struct region {
Eric Andersen8401eea2004-08-04 19:16:54 +0000344 struct region *next;
345 int area;
Eric Andersenff9eee42001-06-29 04:57:14 +0000346};
347
348
349
350/* -------- grammar stuff -------- */
351typedef union {
Eric Andersen8401eea2004-08-04 19:16:54 +0000352 char *cp;
353 char **wp;
354 int i;
355 struct op *o;
Eric Andersenff9eee42001-06-29 04:57:14 +0000356} YYSTYPE;
Eric Andersen8401eea2004-08-04 19:16:54 +0000357
Eric Andersenff9eee42001-06-29 04:57:14 +0000358#define WORD 256
359#define LOGAND 257
360#define LOGOR 258
361#define BREAK 259
Eric Andersen12de6cf2004-08-04 19:19:10 +0000362#define IF 260
Eric Andersenff9eee42001-06-29 04:57:14 +0000363#define THEN 261
364#define ELSE 262
365#define ELIF 263
Eric Andersen12de6cf2004-08-04 19:19:10 +0000366#define FI 264
Eric Andersenff9eee42001-06-29 04:57:14 +0000367#define CASE 265
368#define ESAC 266
Eric Andersen12de6cf2004-08-04 19:19:10 +0000369#define FOR 267
Eric Andersenff9eee42001-06-29 04:57:14 +0000370#define WHILE 268
371#define UNTIL 269
Eric Andersen12de6cf2004-08-04 19:19:10 +0000372#define DO 270
Eric Andersenff9eee42001-06-29 04:57:14 +0000373#define DONE 271
Eric Andersen12de6cf2004-08-04 19:19:10 +0000374#define IN 272
375/* Added for "." file expansion */
376#define DOT 273
377
Eric Andersenff9eee42001-06-29 04:57:14 +0000378#define YYERRCODE 300
379
380/* flags to yylex */
Eric Andersen8401eea2004-08-04 19:16:54 +0000381#define CONTIN 01 /* skip new lines to complete command */
Eric Andersenff9eee42001-06-29 04:57:14 +0000382
383#define SYNTAXERR zzerr()
Eric Andersen12de6cf2004-08-04 19:19:10 +0000384
Eric Andersen8401eea2004-08-04 19:16:54 +0000385static struct op *pipeline(int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000386static struct op *andor(void);
387static struct op *c_list(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000388static int synio(int cf);
389static void musthave(int c, int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000390static struct op *simple(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000391static struct op *nested(int type, int mark);
392static struct op *command(int cf);
393static struct op *dogroup(int onlydone);
Eric Andersenff9eee42001-06-29 04:57:14 +0000394static struct op *thenpart(void);
395static struct op *elsepart(void);
396static struct op *caselist(void);
397static struct op *casepart(void);
398static char **pattern(void);
399static char **wordlist(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000400static struct op *list(struct op *t1, struct op *t2);
401static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000402static struct op *newtp(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000403static struct op *namelist(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000404static char **copyw(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000405static void word(char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000406static struct ioword **copyio(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000407static struct ioword *io(int u, int f, char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000408static void zzerr(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000409static void yyerror(char *s);
410static int yylex(int cf);
411static int collect(int c, int c1);
412static int dual(int c);
413static void diag(int ec);
414static char *tree(unsigned size);
Eric Andersenff9eee42001-06-29 04:57:14 +0000415
416/* -------- var.h -------- */
417
Eric Andersen8401eea2004-08-04 19:16:54 +0000418struct var {
419 char *value;
420 char *name;
421 struct var *next;
422 char status;
Eric Andersenff9eee42001-06-29 04:57:14 +0000423};
Eric Andersenff9eee42001-06-29 04:57:14 +0000424
Eric Andersen8401eea2004-08-04 19:16:54 +0000425#define COPYV 1 /* flag to setval, suggesting copy */
426#define RONLY 01 /* variable is read-only */
427#define EXPORT 02 /* variable is to be exported */
428#define GETCELL 04 /* name & value space was got with getcell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000429
Eric Andersen8401eea2004-08-04 19:16:54 +0000430static int yyparse(void);
431static struct var *lookup(char *n);
432static void setval(struct var *vp, char *val);
433static void nameval(struct var *vp, char *val, char *name);
434static void export(struct var *vp);
435static void ronly(struct var *vp);
436static int isassign(char *s);
437static int checkname(char *cp);
438static int assign(char *s, int cf);
439static void putvlist(int f, int out);
440static int eqname(char *n1, char *n2);
441
442static int execute(struct op *t, int *pin, int *pout, int act);
Eric Andersenff9eee42001-06-29 04:57:14 +0000443
Eric Andersen12de6cf2004-08-04 19:19:10 +0000444
Eric Andersenff9eee42001-06-29 04:57:14 +0000445/* -------- io.h -------- */
446/* io buffer */
447struct iobuf {
Eric Andersen8401eea2004-08-04 19:16:54 +0000448 unsigned id; /* buffer id */
449 char buf[512]; /* buffer */
450 char *bufp; /* pointer into buffer */
451 char *ebufp; /* pointer to end of buffer */
Eric Andersenff9eee42001-06-29 04:57:14 +0000452};
453
454/* possible arguments to an IO function */
455struct ioarg {
Eric Andersen8401eea2004-08-04 19:16:54 +0000456 char *aword;
457 char **awordlist;
458 int afile; /* file descriptor */
459 unsigned afid; /* buffer id */
460 long afpos; /* file position */
461 struct iobuf *afbuf; /* buffer for this file */
Eric Andersenff9eee42001-06-29 04:57:14 +0000462};
Eric Andersen8401eea2004-08-04 19:16:54 +0000463
Eric Andersenff9eee42001-06-29 04:57:14 +0000464//static struct ioarg ioargstack[NPUSH];
465#define AFID_NOBUF (~0)
466#define AFID_ID 0
467
468/* an input generator's state */
Eric Andersen8401eea2004-08-04 19:16:54 +0000469struct io {
470 int (*iofn) (struct ioarg *, struct io *);
471 struct ioarg *argp;
472 int peekc;
473 char prev; /* previous character read by readc() */
474 char nlcount; /* for `'s */
475 char xchar; /* for `'s */
476 char task; /* reason for pushed IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000477};
Eric Andersen8401eea2004-08-04 19:16:54 +0000478
479//static struct io iostack[NPUSH];
480#define XOTHER 0 /* none of the below */
481#define XDOLL 1 /* expanding ${} */
482#define XGRAVE 2 /* expanding `'s */
483#define XIO 3 /* file IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000484
485/* in substitution */
486#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
487
Eric Andersen12de6cf2004-08-04 19:19:10 +0000488
Eric Andersenff9eee42001-06-29 04:57:14 +0000489/*
490 * input generators for IO structure
491 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000492static int nlchar(struct ioarg *ap);
493static int strchar(struct ioarg *ap);
494static int qstrchar(struct ioarg *ap);
495static int filechar(struct ioarg *ap);
496static int herechar(struct ioarg *ap);
497static int linechar(struct ioarg *ap);
498static int gravechar(struct ioarg *ap, struct io *iop);
499static int qgravechar(struct ioarg *ap, struct io *iop);
500static int dolchar(struct ioarg *ap);
501static int wdchar(struct ioarg *ap);
502static void scraphere(void);
503static void freehere(int area);
504static void gethere(void);
505static void markhere(char *s, struct ioword *iop);
506static int herein(char *hname, int xdoll);
507static int run(struct ioarg *argp, int (*f) (struct ioarg *));
Eric Andersenff9eee42001-06-29 04:57:14 +0000508
Eric Andersen12de6cf2004-08-04 19:19:10 +0000509
Eric Andersenff9eee42001-06-29 04:57:14 +0000510/*
511 * IO functions
512 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000513static int eofc(void);
514static int readc(void);
515static void unget(int c);
516static void ioecho(int c);
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000517static void prs(const char *s);
Eric Andersen8401eea2004-08-04 19:16:54 +0000518static void prn(unsigned u);
519static void closef(int i);
520static void closeall(void);
Eric Andersenff9eee42001-06-29 04:57:14 +0000521
Eric Andersen12de6cf2004-08-04 19:19:10 +0000522
Eric Andersenff9eee42001-06-29 04:57:14 +0000523/*
524 * IO control
525 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000526static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
527static int remap(int fd);
528static int openpipe(int *pv);
529static void closepipe(int *pv);
530static struct io *setbase(struct io *ip);
Eric Andersenff9eee42001-06-29 04:57:14 +0000531
Eric Andersenff9eee42001-06-29 04:57:14 +0000532#define PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))
533#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
534
535/* -------- word.h -------- */
536
Eric Andersen8401eea2004-08-04 19:16:54 +0000537#define NSTART 16 /* default number of words to allow for initially */
Eric Andersenff9eee42001-06-29 04:57:14 +0000538
Eric Andersen8401eea2004-08-04 19:16:54 +0000539struct wdblock {
540 short w_bsize;
541 short w_nword;
Eric Andersenff9eee42001-06-29 04:57:14 +0000542 /* bounds are arbitrary */
Eric Andersen8401eea2004-08-04 19:16:54 +0000543 char *w_words[1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000544};
545
Eric Andersen8401eea2004-08-04 19:16:54 +0000546static struct wdblock *addword(char *wd, struct wdblock *wb);
547static struct wdblock *newword(int nw);
548static char **getwords(struct wdblock *wb);
Eric Andersenff9eee42001-06-29 04:57:14 +0000549
550/* -------- area.h -------- */
551
552/*
553 * storage allocation
554 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000555static char *getcell(unsigned nbytes);
556static void garbage(void);
557static void setarea(char *cp, int a);
558static int getarea(char *cp);
559static void freearea(int a);
560static void freecell(char *cp);
561static int areanum; /* current allocation area */
Eric Andersenff9eee42001-06-29 04:57:14 +0000562
Eric Andersen12de6cf2004-08-04 19:19:10 +0000563#define NEW(type) (type *)getcell(sizeof(type))
Eric Andersenff9eee42001-06-29 04:57:14 +0000564#define DELETE(obj) freecell((char *)obj)
565
566
567/* -------- misc stuff -------- */
568
Eric Andersen12de6cf2004-08-04 19:19:10 +0000569static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000570static int iosetup(struct ioword *iop, int pipein, int pipeout);
571static void echo(char **wp);
572static struct op **find1case(struct op *t, char *w);
573static struct op *findcase(struct op *t, char *w);
574static void brkset(struct brkcon *bc);
575static int dolabel(struct op *t);
576static int dohelp(struct op *t);
577static int dochdir(struct op *t);
578static int doshift(struct op *t);
579static int dologin(struct op *t);
580static int doumask(struct op *t);
581static int doexec(struct op *t);
582static int dodot(struct op *t);
583static int dowait(struct op *t);
584static int doread(struct op *t);
585static int doeval(struct op *t);
586static int dotrap(struct op *t);
587static int getsig(char *s);
588static void setsig(int n, sighandler_t f);
589static int getn(char *as);
590static int dobreak(struct op *t);
591static int docontinue(struct op *t);
592static int brkcontin(char *cp, int val);
593static int doexit(struct op *t);
594static int doexport(struct op *t);
595static int doreadonly(struct op *t);
596static void rdexp(char **wp, void (*f) (struct var *), int key);
597static void badid(char *s);
598static int doset(struct op *t);
599static void varput(char *s, int out);
600static int dotimes(struct op *t);
601static int expand(char *cp, struct wdblock **wbp, int f);
602static char *blank(int f);
603static int dollar(int quoted);
604static int grave(int quoted);
605static void globname(char *we, char *pp);
606static char *generate(char *start1, char *end1, char *middle, char *end);
607static int anyspcl(struct wdblock *wb);
608static int xstrcmp(char *p1, char *p2);
609static void glob0(char *a0, unsigned int a1, int a2,
610 int (*a3) (char *, char *));
611static void glob1(char *base, char *lim);
612static void glob2(char *i, char *j);
613static void glob3(char *i, char *j, char *k);
614static void readhere(char **name, char *s, int ec);
615static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
616static int xxchar(struct ioarg *ap);
Eric Andersenff9eee42001-06-29 04:57:14 +0000617
Eric Andersen8401eea2004-08-04 19:16:54 +0000618struct here {
619 char *h_tag;
620 int h_dosub;
621 struct ioword *h_iop;
622 struct here *h_next;
Eric Andersenff9eee42001-06-29 04:57:14 +0000623};
624
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000625static const char * const signame[] = {
Eric Andersenff9eee42001-06-29 04:57:14 +0000626 "Signal 0",
627 "Hangup",
Eric Andersen8401eea2004-08-04 19:16:54 +0000628 (char *) NULL, /* interrupt */
Eric Andersenff9eee42001-06-29 04:57:14 +0000629 "Quit",
630 "Illegal instruction",
631 "Trace/BPT trap",
632 "Abort",
633 "Bus error",
634 "Floating Point Exception",
635 "Killed",
636 "SIGUSR1",
637 "SIGSEGV",
638 "SIGUSR2",
Eric Andersen8401eea2004-08-04 19:16:54 +0000639 (char *) NULL, /* broken pipe */
Eric Andersenff9eee42001-06-29 04:57:14 +0000640 "Alarm clock",
641 "Terminated",
642};
Eric Andersen8401eea2004-08-04 19:16:54 +0000643
Eric Andersenff9eee42001-06-29 04:57:14 +0000644#define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
645
646struct res {
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000647 const char *r_name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000648 int r_val;
Eric Andersenff9eee42001-06-29 04:57:14 +0000649};
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000650static const struct res restab[] = {
Eric Andersen8401eea2004-08-04 19:16:54 +0000651 {"for", FOR},
652 {"case", CASE},
653 {"esac", ESAC},
654 {"while", WHILE},
655 {"do", DO},
656 {"done", DONE},
657 {"if", IF},
658 {"in", IN},
659 {"then", THEN},
660 {"else", ELSE},
661 {"elif", ELIF},
662 {"until", UNTIL},
663 {"fi", FI},
Eric Andersen8401eea2004-08-04 19:16:54 +0000664 {";;", BREAK},
665 {"||", LOGOR},
666 {"&&", LOGAND},
667 {"{", '{'},
668 {"}", '}'},
Eric Andersen12de6cf2004-08-04 19:19:10 +0000669 {".", DOT},
Eric Andersen8401eea2004-08-04 19:16:54 +0000670 {0, 0},
Eric Andersenff9eee42001-06-29 04:57:14 +0000671};
672
673
Eric Andersen1c039232001-07-07 00:05:55 +0000674struct builtincmd {
675 const char *name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000676 int (*builtinfunc) (struct op * t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000677};
Eric Andersen8401eea2004-08-04 19:16:54 +0000678static const struct builtincmd builtincmds[] = {
679 {".", dodot},
680 {":", dolabel},
681 {"break", dobreak},
682 {"cd", dochdir},
683 {"continue", docontinue},
684 {"eval", doeval},
685 {"exec", doexec},
686 {"exit", doexit},
687 {"export", doexport},
688 {"help", dohelp},
689 {"login", dologin},
690 {"newgrp", dologin},
691 {"read", doread},
692 {"readonly", doreadonly},
693 {"set", doset},
694 {"shift", doshift},
695 {"times", dotimes},
696 {"trap", dotrap},
697 {"umask", doumask},
698 {"wait", dowait},
699 {0, 0}
Eric Andersenff9eee42001-06-29 04:57:14 +0000700};
701
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000702static struct op *scantree(struct op *);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000703static struct op *dowholefile(int, int);
704
Eric Andersenff9eee42001-06-29 04:57:14 +0000705/* Globals */
Eric Andersen8401eea2004-08-04 19:16:54 +0000706extern char **environ; /* environment pointer */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000707
Eric Andersen8401eea2004-08-04 19:16:54 +0000708static char **dolv;
709static int dolc;
710static int exstat;
711static char gflg;
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000712static int interactive; /* Is this an interactive shell */
Eric Andersen8401eea2004-08-04 19:16:54 +0000713static int execflg;
714static int multiline; /* \n changed to ; */
715static struct op *outtree; /* result from parser */
716static xint *failpt;
717static xint *errpt;
718static struct brkcon *brklist;
719static int isbreak;
720static struct wdblock *wdlist;
721static struct wdblock *iolist;
722static char *trap[_NSIG + 1];
723static char ourtrap[_NSIG + 1];
724static int trapset; /* trap pending */
725static int yynerrs; /* yacc */
726static char line[LINELIM];
Eric Andersen12de6cf2004-08-04 19:19:10 +0000727
728#ifdef MSHDEBUG
729static struct var *mshdbg_var;
730#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000731static struct var *vlist; /* dictionary */
732static struct var *homedir; /* home directory */
733static struct var *prompt; /* main prompt */
734static struct var *cprompt; /* continuation prompt */
735static struct var *path; /* search path for commands */
736static struct var *shell; /* shell to interpret command files */
737static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000738
Eric Andersen8401eea2004-08-04 19:16:54 +0000739static int areanum; /* current allocation area */
740static int intr;
741static int inparse;
742static char flags['z' - 'a' + 1];
743static char *flag = flags - 'a';
Eric Andersen8401eea2004-08-04 19:16:54 +0000744static char *null = "";
745static int heedint = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +0000746static void (*qflag) (int) = SIG_IGN;
747static int startl;
748static int peeksym;
749static int nlseen;
750static int iounit = IODEFAULT;
751static YYSTYPE yylval;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000752static char *elinep = line + sizeof(line) - 5;
753
754static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
755static struct ioarg ioargstack[NPUSH];
756static struct io iostack[NPUSH];
Eric Andersen8401eea2004-08-04 19:16:54 +0000757static struct iobuf sharedbuf = { AFID_NOBUF };
758static struct iobuf mainbuf = { AFID_NOBUF };
Eric Andersenff9eee42001-06-29 04:57:14 +0000759static unsigned bufid = AFID_ID; /* buffer id counter */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000760
Eric Andersen8401eea2004-08-04 19:16:54 +0000761static struct here *inhere; /* list of hear docs while parsing */
762static struct here *acthere; /* list of active here documents */
763static struct region *areabot; /* bottom of area */
764static struct region *areatop; /* top of area */
765static struct region *areanxt; /* starting point of scan */
766static void *brktop;
767static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000768
Eric Andersen12de6cf2004-08-04 19:19:10 +0000769static struct env e = {
770 line, /* linep: char ptr */
771 iostack, /* iobase: struct io ptr */
772 iostack - 1, /* iop: struct io ptr */
773 (xint *) NULL, /* errpt: void ptr for errors? */
774 FDBASE, /* iofd: file desc */
775 (struct env *) NULL /* oenv: struct env ptr */
776};
777
778#ifdef MSHDEBUG
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000779void print_t(struct op *t);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000780void print_t(struct op *t)
781{
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000782 DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
783 T_CMD_NAMES[t->type], t->words, t->ioact));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000784
785 if (t->words) {
786 DBGPRINTF(("T: W1: %s", t->words[0]));
787 }
788
789 return;
790}
791
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000792void print_tree(struct op *head);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000793void print_tree(struct op *head)
794{
795 if (head == NULL) {
796 DBGPRINTF(("PRINT_TREE: no tree\n"));
797 return;
798 }
799
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000800 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000801 head->right));
802
803 if (head->left)
804 print_tree(head->left);
805
806 if (head->right)
807 print_tree(head->right);
808
809 return;
810}
811#endif /* MSHDEBUG */
812
Eric Andersenff9eee42001-06-29 04:57:14 +0000813
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000814#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +0000815static char *current_prompt;
Eric Andersenff9eee42001-06-29 04:57:14 +0000816#endif
817
Eric Andersenff9eee42001-06-29 04:57:14 +0000818/* -------- sh.c -------- */
819/*
820 * shell
821 */
822
823
Rob Landleydfba7412006-03-06 20:47:33 +0000824int msh_main(int argc, char **argv)
Eric Andersenff9eee42001-06-29 04:57:14 +0000825{
Eric Andersen12de6cf2004-08-04 19:19:10 +0000826 REGISTER int f;
827 REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +0000828 int cflag;
829 char *name, **ap;
Eric Andersen8401eea2004-08-04 19:16:54 +0000830 int (*iof) (struct ioarg *);
Eric Andersenff9eee42001-06-29 04:57:14 +0000831
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000832 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000833
Eric Andersenff9eee42001-06-29 04:57:14 +0000834 initarea();
835 if ((ap = environ) != NULL) {
836 while (*ap)
837 assign(*ap++, !COPYV);
838 for (ap = environ; *ap;)
839 export(lookup(*ap++));
840 }
841 closeall();
842 areanum = 1;
843
844 shell = lookup("SHELL");
845 if (shell->value == null)
Eric Andersen78500142004-08-27 19:55:28 +0000846 setval(shell, (char *)DEFAULT_SHELL);
Eric Andersenff9eee42001-06-29 04:57:14 +0000847 export(shell);
848
849 homedir = lookup("HOME");
850 if (homedir->value == null)
851 setval(homedir, "/");
852 export(homedir);
853
Eric Andersen737f5fb2003-03-14 16:05:59 +0000854 setval(lookup("$"), putn(getpid()));
Eric Andersenff9eee42001-06-29 04:57:14 +0000855
856 path = lookup("PATH");
Eric Andersen737f5fb2003-03-14 16:05:59 +0000857 if (path->value == null) {
858 if (geteuid() == 0)
859 setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
860 else
861 setval(path, "/bin:/usr/bin");
862 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000863 export(path);
864
865 ifs = lookup("IFS");
866 if (ifs->value == null)
867 setval(ifs, " \t\n");
868
Eric Andersen12de6cf2004-08-04 19:19:10 +0000869#ifdef MSHDEBUG
870 mshdbg_var = lookup("MSHDEBUG");
871 if (mshdbg_var->value == null)
872 setval(mshdbg_var, "0");
873#endif
874
875
Eric Andersenff9eee42001-06-29 04:57:14 +0000876 prompt = lookup("PS1");
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000877#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
Eric Andersenff9eee42001-06-29 04:57:14 +0000878 if (prompt->value == null)
Eric Andersen1c039232001-07-07 00:05:55 +0000879#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000880 setval(prompt, "$ ");
881 if (geteuid() == 0) {
882 setval(prompt, "# ");
883 prompt->status &= ~EXPORT;
884 }
885 cprompt = lookup("PS2");
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000886#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
Eric Andersenff9eee42001-06-29 04:57:14 +0000887 if (cprompt->value == null)
Eric Andersen1c039232001-07-07 00:05:55 +0000888#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000889 setval(cprompt, "> ");
890
891 iof = filechar;
892 cflag = 0;
893 name = *argv++;
894 if (--argc >= 1) {
Eric Andersen8401eea2004-08-04 19:16:54 +0000895 if (argv[0][0] == '-' && argv[0][1] != '\0') {
896 for (s = argv[0] + 1; *s; s++)
Eric Andersenff9eee42001-06-29 04:57:14 +0000897 switch (*s) {
898 case 'c':
899 prompt->status &= ~EXPORT;
900 cprompt->status &= ~EXPORT;
901 setval(prompt, "");
902 setval(cprompt, "");
903 cflag = 1;
904 if (--argc > 0)
905 PUSHIO(aword, *++argv, iof = nlchar);
906 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000907
Eric Andersenff9eee42001-06-29 04:57:14 +0000908 case 'q':
909 qflag = SIG_DFL;
910 break;
911
912 case 's':
913 /* standard input */
914 break;
915
916 case 't':
917 prompt->status &= ~EXPORT;
918 setval(prompt, "");
919 iof = linechar;
920 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000921
Eric Andersenff9eee42001-06-29 04:57:14 +0000922 case 'i':
923 interactive++;
924 default:
Eric Andersen8401eea2004-08-04 19:16:54 +0000925 if (*s >= 'a' && *s <= 'z')
926 flag[(int) *s]++;
Eric Andersenff9eee42001-06-29 04:57:14 +0000927 }
928 } else {
929 argv--;
930 argc++;
931 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000932
Eric Andersenff9eee42001-06-29 04:57:14 +0000933 if (iof == filechar && --argc > 0) {
934 setval(prompt, "");
935 setval(cprompt, "");
936 prompt->status &= ~EXPORT;
937 cprompt->status &= ~EXPORT;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000938
939/* Shell is non-interactive, activate printf-based debug */
940#ifdef MSHDEBUG
941 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
942 if (mshdbg < 0)
943 mshdbg = 0;
944#endif
945 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
946
Eric Andersenff9eee42001-06-29 04:57:14 +0000947 if (newfile(name = *++argv))
Eric Andersen12de6cf2004-08-04 19:19:10 +0000948 exit(1); /* Exit on error */
Eric Andersenff9eee42001-06-29 04:57:14 +0000949 }
950 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000951
Eric Andersenff9eee42001-06-29 04:57:14 +0000952 setdash();
Eric Andersen12de6cf2004-08-04 19:19:10 +0000953
954 /* This won't be true if PUSHIO has been called, say from newfile() above */
Eric Andersenff9eee42001-06-29 04:57:14 +0000955 if (e.iop < iostack) {
956 PUSHIO(afile, 0, iof);
Eric Andersen1c039232001-07-07 00:05:55 +0000957 if (isatty(0) && isatty(1) && !cflag) {
Eric Andersenff9eee42001-06-29 04:57:14 +0000958 interactive++;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000959#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
Eric Andersen12de6cf2004-08-04 19:19:10 +0000960#ifdef MSHDEBUG
"Vladimir N. Oleynik"dd1ccdd2006-02-16 15:40:24 +0000961 printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000962#else
"Vladimir N. Oleynik"dd1ccdd2006-02-16 15:40:24 +0000963 printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000964#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000965 printf("Enter 'help' for a list of built-in commands.\n\n");
Eric Andersend63dee42001-10-19 00:22:23 +0000966#endif
Eric Andersen1c039232001-07-07 00:05:55 +0000967 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000968 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000969
Eric Andersenff9eee42001-06-29 04:57:14 +0000970 signal(SIGQUIT, qflag);
971 if (name && name[0] == '-') {
972 interactive++;
973 if ((f = open(".profile", 0)) >= 0)
974 next(remap(f));
975 if ((f = open("/etc/profile", 0)) >= 0)
976 next(remap(f));
977 }
978 if (interactive)
979 signal(SIGTERM, sig);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000980
Eric Andersenff9eee42001-06-29 04:57:14 +0000981 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
982 signal(SIGINT, onintr);
983 dolv = argv;
984 dolc = argc;
985 dolv[0] = name;
986 if (dolc > 1) {
987 for (ap = ++argv; --argc > 0;) {
988 if (assign(*ap = *argv++, !COPYV)) {
Eric Andersen8401eea2004-08-04 19:16:54 +0000989 dolc--; /* keyword */
Eric Andersenff9eee42001-06-29 04:57:14 +0000990 } else {
991 ap++;
992 }
993 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000994 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000995 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
996
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000997 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000998
Eric Andersenff9eee42001-06-29 04:57:14 +0000999 for (;;) {
1000 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001001#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00001002 current_prompt = prompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00001003#else
1004 prs(prompt->value);
1005#endif
1006 }
1007 onecommand();
Eric Andersen1c315012002-04-26 23:40:09 +00001008 /* Ensure that getenv("PATH") stays current */
1009 setenv("PATH", path->value, 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001010 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001011
1012 DBGPRINTF(("MSH_MAIN: returning.\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001013}
1014
Eric Andersen8401eea2004-08-04 19:16:54 +00001015static void setdash()
Eric Andersenff9eee42001-06-29 04:57:14 +00001016{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001017 REGISTER char *cp;
1018 REGISTER int c;
Eric Andersen8401eea2004-08-04 19:16:54 +00001019 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00001020
1021 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +00001022 for (c = 'a'; c <= 'z'; c++)
1023 if (flag[(int) c])
Eric Andersenff9eee42001-06-29 04:57:14 +00001024 *cp++ = c;
1025 *cp = 0;
1026 setval(lookup("-"), m);
1027}
1028
Eric Andersen8401eea2004-08-04 19:16:54 +00001029static int newfile(s)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001030REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00001031{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001032 REGISTER int f;
1033
1034 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001035
1036 if (strcmp(s, "-") != 0) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001037 DBGPRINTF(("NEWFILE: s is %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001038 f = open(s, 0);
1039 if (f < 0) {
1040 prs(s);
1041 err(": cannot open");
Eric Andersen8401eea2004-08-04 19:16:54 +00001042 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001043 }
1044 } else
1045 f = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001046
Eric Andersenff9eee42001-06-29 04:57:14 +00001047 next(remap(f));
Eric Andersen8401eea2004-08-04 19:16:54 +00001048 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001049}
1050
Eric Andersen12de6cf2004-08-04 19:19:10 +00001051
Eric Andersen12de6cf2004-08-04 19:19:10 +00001052struct op *scantree(head)
1053struct op *head;
1054{
1055 struct op *dotnode;
1056
1057 if (head == NULL)
1058 return (NULL);
1059
1060 if (head->left != NULL) {
1061 dotnode = scantree(head->left);
1062 if (dotnode)
1063 return (dotnode);
1064 }
1065
1066 if (head->right != NULL) {
1067 dotnode = scantree(head->right);
1068 if (dotnode)
1069 return (dotnode);
1070 }
1071
1072 if (head->words == NULL)
1073 return (NULL);
1074
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001075 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001076
1077 if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001078 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001079 return (head);
1080 }
1081
1082 return (NULL);
1083}
1084
1085
Eric Andersen8401eea2004-08-04 19:16:54 +00001086static void onecommand()
Eric Andersenff9eee42001-06-29 04:57:14 +00001087{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001088 REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001089 jmp_buf m1;
1090
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001091 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001092
Eric Andersenff9eee42001-06-29 04:57:14 +00001093 while (e.oenv)
1094 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001095
Eric Andersenff9eee42001-06-29 04:57:14 +00001096 areanum = 1;
1097 freehere(areanum);
1098 freearea(areanum);
1099 garbage();
1100 wdlist = 0;
1101 iolist = 0;
1102 e.errpt = 0;
1103 e.linep = line;
1104 yynerrs = 0;
1105 multiline = 0;
1106 inparse = 1;
1107 intr = 0;
1108 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001109
Eric Andersen8401eea2004-08-04 19:16:54 +00001110 setjmp(failpt = m1); /* Bruce Evans' fix */
Eric Andersenff9eee42001-06-29 04:57:14 +00001111 if (setjmp(failpt = m1) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001112
1113 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1114
Eric Andersenff9eee42001-06-29 04:57:14 +00001115 while (e.oenv)
1116 quitenv();
1117 scraphere();
1118 if (!interactive && intr)
1119 leave();
1120 inparse = 0;
1121 intr = 0;
1122 return;
1123 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001124
Eric Andersenff9eee42001-06-29 04:57:14 +00001125 inparse = 0;
1126 brklist = 0;
1127 intr = 0;
1128 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001129
1130 if (!flag['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001131 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001132 outtree));
Eric Andersenff9eee42001-06-29 04:57:14 +00001133 execute(outtree, NOPIPE, NOPIPE, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001134 }
1135
Eric Andersenff9eee42001-06-29 04:57:14 +00001136 if (!interactive && intr) {
1137 execflg = 0;
1138 leave();
1139 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001140
Eric Andersenff9eee42001-06-29 04:57:14 +00001141 if ((i = trapset) != 0) {
1142 trapset = 0;
1143 runtrap(i);
1144 }
1145}
1146
Eric Andersen8401eea2004-08-04 19:16:54 +00001147static void fail()
Eric Andersenff9eee42001-06-29 04:57:14 +00001148{
1149 longjmp(failpt, 1);
1150 /* NOTREACHED */
1151}
1152
Eric Andersen8401eea2004-08-04 19:16:54 +00001153static void leave()
Eric Andersenff9eee42001-06-29 04:57:14 +00001154{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001155 DBGPRINTF(("LEAVE: leave called!\n"));
1156
Eric Andersenff9eee42001-06-29 04:57:14 +00001157 if (execflg)
1158 fail();
1159 scraphere();
1160 freehere(1);
1161 runtrap(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001162 _exit(exstat);
Eric Andersenff9eee42001-06-29 04:57:14 +00001163 /* NOTREACHED */
1164}
1165
Eric Andersen8401eea2004-08-04 19:16:54 +00001166static void warn(s)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001167REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00001168{
Eric Andersen8401eea2004-08-04 19:16:54 +00001169 if (*s) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001170 prs(s);
1171 exstat = -1;
1172 }
1173 prs("\n");
1174 if (flag['e'])
1175 leave();
1176}
1177
Eric Andersen8401eea2004-08-04 19:16:54 +00001178static void err(s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001179char *s;
1180{
1181 warn(s);
1182 if (flag['n'])
1183 return;
1184 if (!interactive)
1185 leave();
1186 if (e.errpt)
1187 longjmp(e.errpt, 1);
1188 closeall();
1189 e.iop = e.iobase = iostack;
1190}
1191
Eric Andersen8401eea2004-08-04 19:16:54 +00001192static int newenv(f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001193int f;
1194{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001195 REGISTER struct env *ep;
1196
1197 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001198
1199 if (f) {
1200 quitenv();
Eric Andersen8401eea2004-08-04 19:16:54 +00001201 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001202 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001203
Eric Andersenff9eee42001-06-29 04:57:14 +00001204 ep = (struct env *) space(sizeof(*ep));
1205 if (ep == NULL) {
1206 while (e.oenv)
1207 quitenv();
1208 fail();
1209 }
1210 *ep = e;
1211 e.oenv = ep;
1212 e.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001213
Eric Andersen8401eea2004-08-04 19:16:54 +00001214 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001215}
1216
Eric Andersen8401eea2004-08-04 19:16:54 +00001217static void quitenv()
Eric Andersenff9eee42001-06-29 04:57:14 +00001218{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001219 REGISTER struct env *ep;
1220 REGISTER int fd;
1221
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001222 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001223
1224 if ((ep = e.oenv) != NULL) {
1225 fd = e.iofd;
1226 e = *ep;
1227 /* should close `'d files */
1228 DELETE(ep);
1229 while (--fd >= e.iofd)
1230 close(fd);
1231 }
1232}
1233
1234/*
1235 * Is any character from s1 in s2?
1236 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001237static int anys(s1, s2)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001238REGISTER char *s1, *s2;
Eric Andersenff9eee42001-06-29 04:57:14 +00001239{
1240 while (*s1)
1241 if (any(*s1++, s2))
Eric Andersen8401eea2004-08-04 19:16:54 +00001242 return (1);
1243 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001244}
1245
1246/*
1247 * Is character c in s?
1248 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001249static int any(c, s)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001250REGISTER int c;
1251REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00001252{
1253 while (*s)
1254 if (*s++ == c)
Eric Andersen8401eea2004-08-04 19:16:54 +00001255 return (1);
1256 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001257}
1258
Eric Andersen8401eea2004-08-04 19:16:54 +00001259static char *putn(n)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001260REGISTER int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00001261{
Eric Andersen8401eea2004-08-04 19:16:54 +00001262 return (itoa(n));
Eric Andersenff9eee42001-06-29 04:57:14 +00001263}
1264
Eric Andersen8401eea2004-08-04 19:16:54 +00001265static char *itoa(n)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001266REGISTER int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00001267{
Eric Andersenff9eee42001-06-29 04:57:14 +00001268 static char s[20];
Eric Andersen8401eea2004-08-04 19:16:54 +00001269
Eric Andersen737f5fb2003-03-14 16:05:59 +00001270 snprintf(s, sizeof(s), "%u", n);
Eric Andersen8401eea2004-08-04 19:16:54 +00001271 return (s);
Eric Andersenff9eee42001-06-29 04:57:14 +00001272}
1273
Eric Andersen12de6cf2004-08-04 19:19:10 +00001274
Eric Andersen8401eea2004-08-04 19:16:54 +00001275static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001276{
1277 PUSHIO(afile, f, filechar);
1278}
1279
Eric Andersen8401eea2004-08-04 19:16:54 +00001280static void onintr(s)
1281int s; /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001282{
1283 signal(SIGINT, onintr);
1284 intr = 1;
1285 if (interactive) {
1286 if (inparse) {
1287 prs("\n");
1288 fail();
1289 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001290 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001291 execflg = 0;
1292 leave();
1293 }
1294}
1295
Eric Andersen8401eea2004-08-04 19:16:54 +00001296static char *space(n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001297int n;
1298{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001299 REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001300
1301 if ((cp = getcell(n)) == 0)
1302 err("out of string space");
Eric Andersen8401eea2004-08-04 19:16:54 +00001303 return (cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00001304}
1305
Eric Andersen8401eea2004-08-04 19:16:54 +00001306static char *strsave(s, a)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001307REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00001308int a;
1309{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001310 REGISTER char *cp, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001311
Eric Andersen8401eea2004-08-04 19:16:54 +00001312 if ((cp = space(strlen(s) + 1)) != NULL) {
1313 setarea((char *) cp, a);
1314 for (xp = cp; (*xp++ = *s++) != '\0';);
1315 return (cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00001316 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001317 return ("");
Eric Andersenff9eee42001-06-29 04:57:14 +00001318}
1319
1320/*
1321 * trap handling
1322 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001323static void sig(i)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001324REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001325{
1326 trapset = i;
1327 signal(i, sig);
1328}
1329
1330static void runtrap(i)
1331int i;
1332{
1333 char *trapstr;
1334
1335 if ((trapstr = trap[i]) == NULL)
1336 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001337
Eric Andersenff9eee42001-06-29 04:57:14 +00001338 if (i == 0)
1339 trap[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001340
Eric Andersenff9eee42001-06-29 04:57:14 +00001341 RUN(aword, trapstr, nlchar);
1342}
1343
1344/* -------- var.c -------- */
1345
1346/*
1347 * Find the given name in the dictionary
1348 * and return its value. If the name was
1349 * not previously there, enter it now and
1350 * return a null value.
1351 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001352static struct var *lookup(n)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001353REGISTER char *n;
Eric Andersenff9eee42001-06-29 04:57:14 +00001354{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001355 REGISTER struct var *vp;
1356 REGISTER char *cp;
1357 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00001358 static struct var dummy;
1359
1360 if (isdigit(*n)) {
1361 dummy.name = n;
1362 for (c = 0; isdigit(*n) && c < 1000; n++)
Eric Andersen8401eea2004-08-04 19:16:54 +00001363 c = c * 10 + *n - '0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001364 dummy.status = RONLY;
Eric Andersen8401eea2004-08-04 19:16:54 +00001365 dummy.value = c <= dolc ? dolv[c] : null;
1366 return (&dummy);
Eric Andersenff9eee42001-06-29 04:57:14 +00001367 }
1368 for (vp = vlist; vp; vp = vp->next)
1369 if (eqname(vp->name, n))
Eric Andersen8401eea2004-08-04 19:16:54 +00001370 return (vp);
Eric Andersenff9eee42001-06-29 04:57:14 +00001371 cp = findeq(n);
Eric Andersen8401eea2004-08-04 19:16:54 +00001372 vp = (struct var *) space(sizeof(*vp));
1373 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001374 dummy.name = dummy.value = "";
Eric Andersen8401eea2004-08-04 19:16:54 +00001375 return (&dummy);
Eric Andersenff9eee42001-06-29 04:57:14 +00001376 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001377 for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++);
Eric Andersenff9eee42001-06-29 04:57:14 +00001378 if (*cp == 0)
1379 *cp = '=';
1380 *++cp = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00001381 setarea((char *) vp, 0);
1382 setarea((char *) vp->name, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001383 vp->value = null;
1384 vp->next = vlist;
1385 vp->status = GETCELL;
1386 vlist = vp;
Eric Andersen8401eea2004-08-04 19:16:54 +00001387 return (vp);
Eric Andersenff9eee42001-06-29 04:57:14 +00001388}
1389
1390/*
1391 * give variable at `vp' the value `val'.
1392 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001393static void setval(vp, val)
Eric Andersenff9eee42001-06-29 04:57:14 +00001394struct var *vp;
1395char *val;
1396{
Eric Andersen8401eea2004-08-04 19:16:54 +00001397 nameval(vp, val, (char *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001398}
1399
1400/*
1401 * if name is not NULL, it must be
1402 * a prefix of the space `val',
1403 * and end with `='.
1404 * this is all so that exporting
1405 * values is reasonably painless.
1406 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001407static void nameval(vp, val, name)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001408REGISTER struct var *vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001409char *val, *name;
1410{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001411 REGISTER char *cp, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001412 char *nv;
1413 int fl;
1414
1415 if (vp->status & RONLY) {
1416 for (xp = vp->name; *xp && *xp != '=';)
1417 putc(*xp++, stderr);
1418 err(" is read-only");
1419 return;
1420 }
1421 fl = 0;
1422 if (name == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001423 xp = space(strlen(vp->name) + strlen(val) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00001424 if (xp == 0)
1425 return;
1426 /* make string: name=value */
Eric Andersen8401eea2004-08-04 19:16:54 +00001427 setarea((char *) xp, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001428 name = xp;
Eric Andersen8401eea2004-08-04 19:16:54 +00001429 for (cp = vp->name; (*xp = *cp++) && *xp != '='; xp++);
Eric Andersenff9eee42001-06-29 04:57:14 +00001430 if (*xp++ == 0)
1431 xp[-1] = '=';
1432 nv = xp;
Eric Andersen8401eea2004-08-04 19:16:54 +00001433 for (cp = val; (*xp++ = *cp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00001434 val = nv;
1435 fl = GETCELL;
1436 }
1437 if (vp->status & GETCELL)
Eric Andersen8401eea2004-08-04 19:16:54 +00001438 freecell(vp->name); /* form new string `name=value' */
Eric Andersenff9eee42001-06-29 04:57:14 +00001439 vp->name = name;
1440 vp->value = val;
1441 vp->status |= fl;
1442}
1443
Eric Andersen8401eea2004-08-04 19:16:54 +00001444static void export(vp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001445struct var *vp;
1446{
1447 vp->status |= EXPORT;
1448}
1449
Eric Andersen8401eea2004-08-04 19:16:54 +00001450static void ronly(vp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001451struct var *vp;
1452{
Matt Kraai69edfec2001-08-06 14:14:18 +00001453 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
Eric Andersenff9eee42001-06-29 04:57:14 +00001454 vp->status |= RONLY;
1455}
1456
Eric Andersen8401eea2004-08-04 19:16:54 +00001457static int isassign(s)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001458REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00001459{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001460 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1461
Eric Andersen8401eea2004-08-04 19:16:54 +00001462 if (!isalpha((int) *s) && *s != '_')
1463 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001464 for (; *s != '='; s++)
Matt Kraai69edfec2001-08-06 14:14:18 +00001465 if (*s == 0 || (!isalnum(*s) && *s != '_'))
Eric Andersen8401eea2004-08-04 19:16:54 +00001466 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001467
Eric Andersen8401eea2004-08-04 19:16:54 +00001468 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001469}
1470
Eric Andersen8401eea2004-08-04 19:16:54 +00001471static int assign(s, cf)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001472REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00001473int cf;
1474{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001475 REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001476 struct var *vp;
1477
Eric Andersen12de6cf2004-08-04 19:19:10 +00001478 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1479
Matt Kraai69edfec2001-08-06 14:14:18 +00001480 if (!isalpha(*s) && *s != '_')
Eric Andersen8401eea2004-08-04 19:16:54 +00001481 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001482 for (cp = s; *cp != '='; cp++)
Matt Kraai69edfec2001-08-06 14:14:18 +00001483 if (*cp == 0 || (!isalnum(*cp) && *cp != '_'))
Eric Andersen8401eea2004-08-04 19:16:54 +00001484 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001485 vp = lookup(s);
Eric Andersen8401eea2004-08-04 19:16:54 +00001486 nameval(vp, ++cp, cf == COPYV ? (char *) NULL : s);
Eric Andersenff9eee42001-06-29 04:57:14 +00001487 if (cf != COPYV)
1488 vp->status &= ~GETCELL;
Eric Andersen8401eea2004-08-04 19:16:54 +00001489 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001490}
1491
Eric Andersen8401eea2004-08-04 19:16:54 +00001492static int checkname(cp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001493REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001494{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001495 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1496
Eric Andersen8401eea2004-08-04 19:16:54 +00001497 if (!isalpha(*cp++) && *(cp - 1) != '_')
1498 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001499 while (*cp)
Eric Andersen8401eea2004-08-04 19:16:54 +00001500 if (!isalnum(*cp++) && *(cp - 1) != '_')
1501 return (0);
1502 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001503}
1504
Eric Andersen8401eea2004-08-04 19:16:54 +00001505static void putvlist(f, out)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001506REGISTER int f, out;
Eric Andersenff9eee42001-06-29 04:57:14 +00001507{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001508 REGISTER struct var *vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001509
1510 for (vp = vlist; vp; vp = vp->next)
Matt Kraai69edfec2001-08-06 14:14:18 +00001511 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001512 if (vp->status & EXPORT)
1513 write(out, "export ", 7);
1514 if (vp->status & RONLY)
1515 write(out, "readonly ", 9);
Eric Andersen8401eea2004-08-04 19:16:54 +00001516 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
Eric Andersenff9eee42001-06-29 04:57:14 +00001517 write(out, "\n", 1);
1518 }
1519}
1520
Eric Andersen8401eea2004-08-04 19:16:54 +00001521static int eqname(n1, n2)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001522REGISTER char *n1, *n2;
Eric Andersenff9eee42001-06-29 04:57:14 +00001523{
1524 for (; *n1 != '=' && *n1 != 0; n1++)
1525 if (*n2++ != *n1)
Eric Andersen8401eea2004-08-04 19:16:54 +00001526 return (0);
1527 return (*n2 == 0 || *n2 == '=');
Eric Andersenff9eee42001-06-29 04:57:14 +00001528}
1529
Eric Andersen8401eea2004-08-04 19:16:54 +00001530static char *findeq(cp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001531REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001532{
1533 while (*cp != '\0' && *cp != '=')
1534 cp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00001535 return (cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00001536}
1537
1538/* -------- gmatch.c -------- */
1539/*
1540 * int gmatch(string, pattern)
1541 * char *string, *pattern;
1542 *
1543 * Match a pattern as in sh(1).
1544 */
1545
1546#define CMASK 0377
1547#define QUOTE 0200
1548#define QMASK (CMASK&~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001549#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001550
Eric Andersen8401eea2004-08-04 19:16:54 +00001551static int gmatch(s, p)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001552REGISTER char *s, *p;
Eric Andersenff9eee42001-06-29 04:57:14 +00001553{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001554 REGISTER int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001555
1556 if (s == NULL || p == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00001557 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001558 while ((pc = *p++ & CMASK) != '\0') {
1559 sc = *s++ & QMASK;
1560 switch (pc) {
1561 case '[':
1562 if ((p = cclass(p, sc)) == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00001563 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001564 break;
1565
1566 case '?':
1567 if (sc == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00001568 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001569 break;
1570
1571 case '*':
1572 s--;
1573 do {
1574 if (*p == '\0' || gmatch(s, p))
Eric Andersen8401eea2004-08-04 19:16:54 +00001575 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001576 } while (*s++ != '\0');
Eric Andersen8401eea2004-08-04 19:16:54 +00001577 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001578
1579 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001580 if (sc != (pc & ~QUOTE))
1581 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001582 }
1583 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001584 return (*s == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001585}
1586
Eric Andersen8401eea2004-08-04 19:16:54 +00001587static char *cclass(p, sub)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001588REGISTER char *p;
1589REGISTER int sub;
Eric Andersenff9eee42001-06-29 04:57:14 +00001590{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001591 REGISTER int c, d, not, found;
Eric Andersenff9eee42001-06-29 04:57:14 +00001592
1593 if ((not = *p == NOT) != 0)
1594 p++;
1595 found = not;
1596 do {
1597 if (*p == '\0')
Eric Andersen8401eea2004-08-04 19:16:54 +00001598 return ((char *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001599 c = *p & CMASK;
1600 if (p[1] == '-' && p[2] != ']') {
1601 d = p[2] & CMASK;
1602 p++;
1603 } else
1604 d = c;
1605 if (c == sub || (c <= sub && sub <= d))
1606 found = !not;
1607 } while (*++p != ']');
Eric Andersen8401eea2004-08-04 19:16:54 +00001608 return (found ? p + 1 : (char *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001609}
1610
1611
1612/* -------- area.c -------- */
1613
1614/*
1615 * All memory between (char *)areabot and (char *)(areatop+1) is
1616 * exclusively administered by the area management routines.
1617 * It is assumed that sbrk() and brk() manipulate the high end.
1618 */
1619
1620#define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;})
1621
Eric Andersen8401eea2004-08-04 19:16:54 +00001622static void initarea()
Eric Andersenff9eee42001-06-29 04:57:14 +00001623{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001624 brkaddr = malloc(AREASIZE);
1625 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +00001626
Eric Andersena68ea1c2006-01-30 22:48:39 +00001627 while ((long) sbrk(0) & ALIGN)
Eric Andersenff9eee42001-06-29 04:57:14 +00001628 sbrk(1);
Eric Andersen8401eea2004-08-04 19:16:54 +00001629 areabot = (struct region *) sbrk(REGSIZE);
Eric Andersenff9eee42001-06-29 04:57:14 +00001630
1631 areabot->next = areabot;
1632 areabot->area = BUSY;
1633 areatop = areabot;
1634 areanxt = areabot;
1635}
1636
Eric Andersen8401eea2004-08-04 19:16:54 +00001637char *getcell(nbytes)
Eric Andersenff9eee42001-06-29 04:57:14 +00001638unsigned nbytes;
1639{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001640 REGISTER int nregio;
1641 REGISTER struct region *p, *q;
1642 REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001643
1644 if (nbytes == 0) {
1645 puts("getcell(0)");
1646 abort();
Eric Andersen8401eea2004-08-04 19:16:54 +00001647 }
1648 /* silly and defeats the algorithm */
Eric Andersenff9eee42001-06-29 04:57:14 +00001649 /*
1650 * round upwards and add administration area
1651 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001652 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001653 for (p = areanxt;;) {
1654 if (p->area > areanum) {
1655 /*
1656 * merge free cells
1657 */
1658 while ((q = p->next)->area > areanum && q != areanxt)
1659 p->next = q->next;
1660 /*
1661 * exit loop if cell big enough
1662 */
1663 if (q >= p + nregio)
1664 goto found;
1665 }
1666 p = p->next;
1667 if (p == areanxt)
1668 break;
1669 }
1670 i = nregio >= GROWBY ? nregio : GROWBY;
Eric Andersen8401eea2004-08-04 19:16:54 +00001671 p = (struct region *) sbrk(i * REGSIZE);
1672 if (p == (struct region *) -1)
1673 return ((char *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001674 p--;
1675 if (p != areatop) {
1676 puts("not contig");
Eric Andersen8401eea2004-08-04 19:16:54 +00001677 abort(); /* allocated areas are contiguous */
Eric Andersenff9eee42001-06-29 04:57:14 +00001678 }
1679 q = p + i;
1680 p->next = q;
1681 p->area = FREE;
1682 q->next = areabot;
1683 q->area = BUSY;
1684 areatop = q;
Eric Andersen8401eea2004-08-04 19:16:54 +00001685 found:
Eric Andersenff9eee42001-06-29 04:57:14 +00001686 /*
1687 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
1688 */
1689 areanxt = p + nregio;
1690 if (areanxt < q) {
1691 /*
1692 * split into requested area and rest
1693 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001694 if (areanxt + 1 > q) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001695 puts("OOM");
Eric Andersen8401eea2004-08-04 19:16:54 +00001696 abort(); /* insufficient space left for admin */
Eric Andersenff9eee42001-06-29 04:57:14 +00001697 }
1698 areanxt->next = q;
1699 areanxt->area = FREE;
1700 p->next = areanxt;
1701 }
1702 p->area = areanum;
Eric Andersen8401eea2004-08-04 19:16:54 +00001703 return ((char *) (p + 1));
Eric Andersenff9eee42001-06-29 04:57:14 +00001704}
1705
Eric Andersen8401eea2004-08-04 19:16:54 +00001706static void freecell(cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001707char *cp;
1708{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001709 REGISTER struct region *p;
Eric Andersenff9eee42001-06-29 04:57:14 +00001710
Eric Andersen8401eea2004-08-04 19:16:54 +00001711 if ((p = (struct region *) cp) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001712 p--;
1713 if (p < areanxt)
1714 areanxt = p;
1715 p->area = FREE;
1716 }
1717}
1718
Eric Andersen8401eea2004-08-04 19:16:54 +00001719static void freearea(a)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001720REGISTER int a;
Eric Andersenff9eee42001-06-29 04:57:14 +00001721{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001722 REGISTER struct region *p, *top;
Eric Andersenff9eee42001-06-29 04:57:14 +00001723
1724 top = areatop;
1725 for (p = areabot; p != top; p = p->next)
1726 if (p->area >= a)
1727 p->area = FREE;
1728}
1729
Eric Andersen8401eea2004-08-04 19:16:54 +00001730static void setarea(cp, a)
Eric Andersenff9eee42001-06-29 04:57:14 +00001731char *cp;
1732int a;
1733{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001734 REGISTER struct region *p;
Eric Andersenff9eee42001-06-29 04:57:14 +00001735
Eric Andersen8401eea2004-08-04 19:16:54 +00001736 if ((p = (struct region *) cp) != NULL)
1737 (p - 1)->area = a;
Eric Andersenff9eee42001-06-29 04:57:14 +00001738}
1739
Eric Andersen8401eea2004-08-04 19:16:54 +00001740int getarea(cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001741char *cp;
1742{
Eric Andersen8401eea2004-08-04 19:16:54 +00001743 return ((struct region *) cp - 1)->area;
Eric Andersenff9eee42001-06-29 04:57:14 +00001744}
1745
Eric Andersen8401eea2004-08-04 19:16:54 +00001746static void garbage()
Eric Andersenff9eee42001-06-29 04:57:14 +00001747{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001748 REGISTER struct region *p, *q, *top;
Eric Andersenff9eee42001-06-29 04:57:14 +00001749
1750 top = areatop;
1751 for (p = areabot; p != top; p = p->next) {
1752 if (p->area > areanum) {
1753 while ((q = p->next)->area > areanum)
1754 p->next = q->next;
1755 areanxt = p;
1756 }
1757 }
1758#ifdef SHRINKBY
1759 if (areatop >= q + SHRINKBY && q->area > areanum) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001760 brk((char *) (q + 1));
Eric Andersenff9eee42001-06-29 04:57:14 +00001761 q->next = areabot;
1762 q->area = BUSY;
1763 areatop = q;
1764 }
1765#endif
1766}
1767
1768/* -------- csyn.c -------- */
1769/*
1770 * shell: syntax (C version)
1771 */
1772
Eric Andersen8401eea2004-08-04 19:16:54 +00001773int yyparse()
Eric Andersenff9eee42001-06-29 04:57:14 +00001774{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001775 DBGPRINTF7(("YYPARSE: enter...\n"));
1776
Eric Andersen8401eea2004-08-04 19:16:54 +00001777 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001778 peeksym = 0;
1779 yynerrs = 0;
1780 outtree = c_list();
1781 musthave('\n', 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00001782 return (yynerrs != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001783}
1784
Eric Andersen8401eea2004-08-04 19:16:54 +00001785static struct op *pipeline(cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001786int cf;
1787{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001788 REGISTER struct op *t, *p;
1789 REGISTER int c;
1790
1791 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001792
1793 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001794
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001795 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001796
Eric Andersenff9eee42001-06-29 04:57:14 +00001797 if (t != NULL) {
1798 while ((c = yylex(0)) == '|') {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001799 if ((p = command(CONTIN)) == NULL) {
1800 DBGPRINTF8(("PIPELINE: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001801 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001802 }
1803
Eric Andersenff9eee42001-06-29 04:57:14 +00001804 if (t->type != TPAREN && t->type != TCOM) {
1805 /* shell statement */
1806 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1807 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001808
Eric Andersenff9eee42001-06-29 04:57:14 +00001809 t = block(TPIPE, t, p, NOWORDS);
1810 }
1811 peeksym = c;
1812 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001813
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001814 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Eric Andersen8401eea2004-08-04 19:16:54 +00001815 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00001816}
1817
Eric Andersen8401eea2004-08-04 19:16:54 +00001818static struct op *andor()
Eric Andersenff9eee42001-06-29 04:57:14 +00001819{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001820 REGISTER struct op *t, *p;
1821 REGISTER int c;
1822
1823 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001824
1825 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001826
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001827 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001828
Eric Andersenff9eee42001-06-29 04:57:14 +00001829 if (t != NULL) {
1830 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001831 if ((p = pipeline(CONTIN)) == NULL) {
1832 DBGPRINTF8(("ANDOR: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001833 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001834 }
1835
Eric Andersen8401eea2004-08-04 19:16:54 +00001836 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001837 } /* WHILE */
1838
Eric Andersenff9eee42001-06-29 04:57:14 +00001839 peeksym = c;
1840 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001841
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001842 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Eric Andersen8401eea2004-08-04 19:16:54 +00001843 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00001844}
1845
Eric Andersen8401eea2004-08-04 19:16:54 +00001846static struct op *c_list()
Eric Andersenff9eee42001-06-29 04:57:14 +00001847{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001848 REGISTER struct op *t, *p;
1849 REGISTER int c;
1850
1851 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001852
1853 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001854
Eric Andersenff9eee42001-06-29 04:57:14 +00001855 if (t != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001856 if ((peeksym = yylex(0)) == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001857 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001858
Eric Andersen8401eea2004-08-04 19:16:54 +00001859 while ((c = yylex(0)) == ';' || c == '&'
1860 || (multiline && c == '\n')) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001861
Eric Andersenff9eee42001-06-29 04:57:14 +00001862 if ((p = andor()) == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00001863 return (t);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001864
Eric Andersen8401eea2004-08-04 19:16:54 +00001865 if ((peeksym = yylex(0)) == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001866 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001867
Eric Andersenff9eee42001-06-29 04:57:14 +00001868 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001869 } /* WHILE */
1870
Eric Andersenff9eee42001-06-29 04:57:14 +00001871 peeksym = c;
1872 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001873 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001874 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Eric Andersen8401eea2004-08-04 19:16:54 +00001875 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00001876}
1877
Eric Andersen8401eea2004-08-04 19:16:54 +00001878static int synio(cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001879int cf;
1880{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001881 REGISTER struct ioword *iop;
1882 REGISTER int i;
1883 REGISTER int c;
1884
1885 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001886
1887 if ((c = yylex(cf)) != '<' && c != '>') {
1888 peeksym = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00001889 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001890 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001891
Eric Andersenff9eee42001-06-29 04:57:14 +00001892 i = yylval.i;
1893 musthave(WORD, 0);
1894 iop = io(iounit, i, yylval.cp);
1895 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001896
Eric Andersenff9eee42001-06-29 04:57:14 +00001897 if (i & IOHERE)
1898 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001899
1900 DBGPRINTF7(("SYNIO: returning 1\n"));
Eric Andersen8401eea2004-08-04 19:16:54 +00001901 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001902}
1903
Eric Andersen8401eea2004-08-04 19:16:54 +00001904static void musthave(c, cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001905int c, cf;
1906{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001907 if ((peeksym = yylex(cf)) != c) {
1908 DBGPRINTF7(("MUSTHAVE: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001909 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001910 }
1911
Eric Andersenff9eee42001-06-29 04:57:14 +00001912 peeksym = 0;
1913}
1914
Eric Andersen8401eea2004-08-04 19:16:54 +00001915static struct op *simple()
Eric Andersenff9eee42001-06-29 04:57:14 +00001916{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001917 REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001918
1919 t = NULL;
1920 for (;;) {
1921 switch (peeksym = yylex(0)) {
1922 case '<':
1923 case '>':
1924 (void) synio(0);
1925 break;
1926
1927 case WORD:
1928 if (t == NULL) {
1929 t = newtp();
1930 t->type = TCOM;
1931 }
1932 peeksym = 0;
1933 word(yylval.cp);
1934 break;
1935
1936 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001937 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00001938 }
1939 }
1940}
1941
Eric Andersen8401eea2004-08-04 19:16:54 +00001942static struct op *nested(type, mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001943int type, mark;
1944{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001945 REGISTER struct op *t;
1946
1947 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001948
1949 multiline++;
1950 t = c_list();
1951 musthave(mark, 0);
1952 multiline--;
Eric Andersen8401eea2004-08-04 19:16:54 +00001953 return (block(type, t, NOBLOCK, NOWORDS));
Eric Andersenff9eee42001-06-29 04:57:14 +00001954}
1955
Eric Andersen8401eea2004-08-04 19:16:54 +00001956static struct op *command(cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001957int cf;
1958{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001959 REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001960 struct wdblock *iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001961 REGISTER int c;
1962
1963 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001964
1965 iosave = iolist;
1966 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001967
Eric Andersenff9eee42001-06-29 04:57:14 +00001968 if (multiline)
1969 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001970
Eric Andersenff9eee42001-06-29 04:57:14 +00001971 while (synio(cf))
1972 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001973
1974 c = yylex(cf);
1975
1976 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001977 default:
1978 peeksym = c;
1979 if ((t = simple()) == NULL) {
1980 if (iolist == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00001981 return ((struct op *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001982 t = newtp();
1983 t->type = TCOM;
1984 }
1985 break;
1986
1987 case '(':
1988 t = nested(TPAREN, ')');
1989 break;
1990
1991 case '{':
1992 t = nested(TBRACE, '}');
1993 break;
1994
1995 case FOR:
1996 t = newtp();
1997 t->type = TFOR;
1998 musthave(WORD, 0);
1999 startl = 1;
2000 t->str = yylval.cp;
2001 multiline++;
2002 t->words = wordlist();
2003 if ((c = yylex(0)) != '\n' && c != ';')
2004 peeksym = c;
2005 t->left = dogroup(0);
2006 multiline--;
2007 break;
2008
2009 case WHILE:
2010 case UNTIL:
2011 multiline++;
2012 t = newtp();
Eric Andersen8401eea2004-08-04 19:16:54 +00002013 t->type = c == WHILE ? TWHILE : TUNTIL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002014 t->left = c_list();
2015 t->right = dogroup(1);
2016 t->words = NULL;
2017 multiline--;
2018 break;
2019
2020 case CASE:
2021 t = newtp();
2022 t->type = TCASE;
2023 musthave(WORD, 0);
2024 t->str = yylval.cp;
2025 startl++;
2026 multiline++;
2027 musthave(IN, CONTIN);
2028 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002029
Eric Andersenff9eee42001-06-29 04:57:14 +00002030 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002031
Eric Andersenff9eee42001-06-29 04:57:14 +00002032 musthave(ESAC, 0);
2033 multiline--;
2034 break;
2035
2036 case IF:
2037 multiline++;
2038 t = newtp();
2039 t->type = TIF;
2040 t->left = c_list();
2041 t->right = thenpart();
2042 musthave(FI, 0);
2043 multiline--;
2044 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002045
2046 case DOT:
2047 t = newtp();
2048 t->type = TDOT;
2049
2050 musthave(WORD, 0); /* gets name of file */
2051 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
2052
2053 word(yylval.cp); /* add word to wdlist */
2054 word(NOWORD); /* terminate wdlist */
2055 t->words = copyw(); /* dup wdlist */
2056 break;
2057
Eric Andersenff9eee42001-06-29 04:57:14 +00002058 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002059
Eric Andersen8401eea2004-08-04 19:16:54 +00002060 while (synio(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002061
Eric Andersenff9eee42001-06-29 04:57:14 +00002062 t = namelist(t);
2063 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002064
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002065 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002066
2067 return (t);
2068}
2069
2070static struct op *dowholefile(type, mark)
2071int type;
2072int mark;
2073{
2074 REGISTER struct op *t;
2075
2076 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
2077
2078 multiline++;
2079 t = c_list();
2080 multiline--;
2081 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002082 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Eric Andersen8401eea2004-08-04 19:16:54 +00002083 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002084}
2085
Eric Andersen8401eea2004-08-04 19:16:54 +00002086static struct op *dogroup(onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00002087int onlydone;
2088{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002089 REGISTER int c;
2090 REGISTER struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002091
2092 c = yylex(CONTIN);
2093 if (c == DONE && onlydone)
Eric Andersen8401eea2004-08-04 19:16:54 +00002094 return ((struct op *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002095 if (c != DO)
2096 SYNTAXERR;
2097 mylist = c_list();
2098 musthave(DONE, 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00002099 return (mylist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002100}
2101
Eric Andersen8401eea2004-08-04 19:16:54 +00002102static struct op *thenpart()
Eric Andersenff9eee42001-06-29 04:57:14 +00002103{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002104 REGISTER int c;
2105 REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002106
2107 if ((c = yylex(0)) != THEN) {
2108 peeksym = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00002109 return ((struct op *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002110 }
2111 t = newtp();
2112 t->type = 0;
2113 t->left = c_list();
2114 if (t->left == NULL)
2115 SYNTAXERR;
2116 t->right = elsepart();
Eric Andersen8401eea2004-08-04 19:16:54 +00002117 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002118}
2119
Eric Andersen8401eea2004-08-04 19:16:54 +00002120static struct op *elsepart()
Eric Andersenff9eee42001-06-29 04:57:14 +00002121{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002122 REGISTER int c;
2123 REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002124
2125 switch (c = yylex(0)) {
2126 case ELSE:
2127 if ((t = c_list()) == NULL)
2128 SYNTAXERR;
Eric Andersen8401eea2004-08-04 19:16:54 +00002129 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002130
2131 case ELIF:
2132 t = newtp();
2133 t->type = TELIF;
2134 t->left = c_list();
2135 t->right = thenpart();
Eric Andersen8401eea2004-08-04 19:16:54 +00002136 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002137
2138 default:
2139 peeksym = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00002140 return ((struct op *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002141 }
2142}
2143
Eric Andersen8401eea2004-08-04 19:16:54 +00002144static struct op *caselist()
Eric Andersenff9eee42001-06-29 04:57:14 +00002145{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002146 REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002147
2148 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002149 while ((peeksym = yylex(CONTIN)) != ESAC) {
2150 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00002151 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00002152 }
2153
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002154 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Eric Andersen8401eea2004-08-04 19:16:54 +00002155 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002156}
2157
Eric Andersen8401eea2004-08-04 19:16:54 +00002158static struct op *casepart()
Eric Andersenff9eee42001-06-29 04:57:14 +00002159{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002160 REGISTER struct op *t;
2161
2162 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002163
2164 t = newtp();
2165 t->type = TPAT;
2166 t->words = pattern();
2167 musthave(')', 0);
2168 t->left = c_list();
2169 if ((peeksym = yylex(CONTIN)) != ESAC)
2170 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002171
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002172 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002173
Eric Andersen8401eea2004-08-04 19:16:54 +00002174 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002175}
2176
Eric Andersen8401eea2004-08-04 19:16:54 +00002177static char **pattern()
Eric Andersenff9eee42001-06-29 04:57:14 +00002178{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002179 REGISTER int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00002180
2181 cf = CONTIN;
2182 do {
2183 musthave(WORD, cf);
2184 word(yylval.cp);
2185 cf = 0;
2186 } while ((c = yylex(0)) == '|');
2187 peeksym = c;
2188 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002189
Eric Andersen8401eea2004-08-04 19:16:54 +00002190 return (copyw());
Eric Andersenff9eee42001-06-29 04:57:14 +00002191}
2192
Eric Andersen8401eea2004-08-04 19:16:54 +00002193static char **wordlist()
Eric Andersenff9eee42001-06-29 04:57:14 +00002194{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002195 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002196
2197 if ((c = yylex(0)) != IN) {
2198 peeksym = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00002199 return ((char **) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002200 }
2201 startl = 0;
2202 while ((c = yylex(0)) == WORD)
2203 word(yylval.cp);
2204 word(NOWORD);
2205 peeksym = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00002206 return (copyw());
Eric Andersenff9eee42001-06-29 04:57:14 +00002207}
2208
2209/*
2210 * supporting functions
2211 */
Eric Andersen8401eea2004-08-04 19:16:54 +00002212static struct op *list(t1, t2)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002213REGISTER struct op *t1, *t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002214{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002215 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002216
Eric Andersenff9eee42001-06-29 04:57:14 +00002217 if (t1 == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00002218 return (t2);
Eric Andersenff9eee42001-06-29 04:57:14 +00002219 if (t2 == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00002220 return (t1);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002221
Eric Andersen8401eea2004-08-04 19:16:54 +00002222 return (block(TLIST, t1, t2, NOWORDS));
Eric Andersenff9eee42001-06-29 04:57:14 +00002223}
2224
Eric Andersen8401eea2004-08-04 19:16:54 +00002225static struct op *block(type, t1, t2, wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002226int type;
2227struct op *t1, *t2;
2228char **wp;
2229{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002230 REGISTER struct op *t;
2231
2232 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00002233
2234 t = newtp();
2235 t->type = type;
2236 t->left = t1;
2237 t->right = t2;
2238 t->words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002239
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002240 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002241 t2));
2242
Eric Andersen8401eea2004-08-04 19:16:54 +00002243 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002244}
2245
Eric Andersen12de6cf2004-08-04 19:19:10 +00002246/* See if given string is a shell multiline (FOR, IF, etc) */
Eric Andersen8401eea2004-08-04 19:16:54 +00002247static int rlookup(n)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002248REGISTER char *n;
Eric Andersenff9eee42001-06-29 04:57:14 +00002249{
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +00002250 REGISTER const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002251
2252 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002253
2254 for (rp = restab; rp->r_name; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002255 if (strcmp(rp->r_name, n) == 0) {
2256 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
2257 return (rp->r_val); /* Return numeric code for shell multiline */
2258 }
2259
2260 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
2261 return (0); /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002262}
2263
Eric Andersen8401eea2004-08-04 19:16:54 +00002264static struct op *newtp()
Eric Andersenff9eee42001-06-29 04:57:14 +00002265{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002266 REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002267
Eric Andersen8401eea2004-08-04 19:16:54 +00002268 t = (struct op *) tree(sizeof(*t));
Eric Andersenff9eee42001-06-29 04:57:14 +00002269 t->type = 0;
2270 t->words = NULL;
2271 t->ioact = NULL;
2272 t->left = NULL;
2273 t->right = NULL;
2274 t->str = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002275
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002276 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002277
Eric Andersen8401eea2004-08-04 19:16:54 +00002278 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002279}
2280
Eric Andersen8401eea2004-08-04 19:16:54 +00002281static struct op *namelist(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002282REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002283{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002284
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002285 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002286 T_CMD_NAMES[t->type], iolist));
2287
Eric Andersenff9eee42001-06-29 04:57:14 +00002288 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002289 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002290 t->ioact = copyio();
2291 } else
2292 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002293
Eric Andersenff9eee42001-06-29 04:57:14 +00002294 if (t->type != TCOM) {
2295 if (t->type != TPAREN && t->ioact != NULL) {
2296 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2297 t->ioact = t->left->ioact;
2298 t->left->ioact = NULL;
2299 }
Eric Andersen8401eea2004-08-04 19:16:54 +00002300 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002301 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002302
Eric Andersenff9eee42001-06-29 04:57:14 +00002303 word(NOWORD);
2304 t->words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002305
2306
Eric Andersen8401eea2004-08-04 19:16:54 +00002307 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002308}
2309
Eric Andersen8401eea2004-08-04 19:16:54 +00002310static char **copyw()
Eric Andersenff9eee42001-06-29 04:57:14 +00002311{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002312 REGISTER char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002313
2314 wd = getwords(wdlist);
2315 wdlist = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002316 return (wd);
Eric Andersenff9eee42001-06-29 04:57:14 +00002317}
2318
Eric Andersen8401eea2004-08-04 19:16:54 +00002319static void word(cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002320char *cp;
2321{
2322 wdlist = addword(cp, wdlist);
2323}
2324
Eric Andersen8401eea2004-08-04 19:16:54 +00002325static struct ioword **copyio()
Eric Andersenff9eee42001-06-29 04:57:14 +00002326{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002327 REGISTER struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002328
2329 iop = (struct ioword **) getwords(iolist);
2330 iolist = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002331 return (iop);
Eric Andersenff9eee42001-06-29 04:57:14 +00002332}
2333
Eric Andersen8401eea2004-08-04 19:16:54 +00002334static struct ioword *io(u, f, cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002335int u;
2336int f;
2337char *cp;
2338{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002339 REGISTER struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002340
2341 iop = (struct ioword *) tree(sizeof(*iop));
2342 iop->io_unit = u;
2343 iop->io_flag = f;
2344 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002345 iolist = addword((char *) iop, iolist);
2346 return (iop);
Eric Andersenff9eee42001-06-29 04:57:14 +00002347}
2348
Eric Andersen8401eea2004-08-04 19:16:54 +00002349static void zzerr()
Eric Andersenff9eee42001-06-29 04:57:14 +00002350{
2351 yyerror("syntax error");
2352}
2353
Eric Andersen8401eea2004-08-04 19:16:54 +00002354static void yyerror(s)
Eric Andersenff9eee42001-06-29 04:57:14 +00002355char *s;
2356{
2357 yynerrs++;
2358 if (interactive && e.iop <= iostack) {
2359 multiline = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002360 while (eofc() == 0 && yylex(0) != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002361 }
2362 err(s);
2363 fail();
2364}
2365
Eric Andersen8401eea2004-08-04 19:16:54 +00002366static int yylex(cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002367int cf;
2368{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002369 REGISTER int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002370 int atstart;
2371
2372 if ((c = peeksym) > 0) {
2373 peeksym = 0;
2374 if (c == '\n')
2375 startl = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002376 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002377 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002378
2379
Eric Andersenff9eee42001-06-29 04:57:14 +00002380 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002381 atstart = startl;
2382 startl = 0;
2383 yylval.i = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002384 e.linep = line;
2385
2386/* MALAMO */
2387 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002388
Eric Andersen8401eea2004-08-04 19:16:54 +00002389 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002390 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
2391 ;
2392
Eric Andersenff9eee42001-06-29 04:57:14 +00002393 switch (c) {
2394 default:
2395 if (any(c, "0123456789")) {
2396 unget(c1 = my_getc(0));
2397 if (c1 == '<' || c1 == '>') {
2398 iounit = c - '0';
2399 goto loop;
2400 }
2401 *e.linep++ = c;
2402 c = c1;
2403 }
2404 break;
2405
Eric Andersen12de6cf2004-08-04 19:19:10 +00002406 case '#': /* Comment, skip to next newline or End-of-string */
Eric Andersen8401eea2004-08-04 19:16:54 +00002407 while ((c = my_getc(0)) != 0 && c != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002408 unget(c);
2409 goto loop;
2410
2411 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002412 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Eric Andersen8401eea2004-08-04 19:16:54 +00002413 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002414
2415 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002416 DBGPRINTF9(("YYLEX: found $\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002417 *e.linep++ = c;
2418 if ((c = my_getc(0)) == '{') {
2419 if ((c = collect(c, '}')) != '\0')
Eric Andersen8401eea2004-08-04 19:16:54 +00002420 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002421 goto pack;
2422 }
2423 break;
2424
2425 case '`':
2426 case '\'':
2427 case '"':
2428 if ((c = collect(c, c)) != '\0')
Eric Andersen8401eea2004-08-04 19:16:54 +00002429 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002430 goto pack;
2431
2432 case '|':
2433 case '&':
2434 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002435 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002436 /* If more chars process them, else return NULL char */
2437 if ((c1 = dual(c)) != '\0')
2438 return (c1);
2439 else
2440 return (c);
2441
Eric Andersenff9eee42001-06-29 04:57:14 +00002442 case '^':
2443 startl = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002444 return ('|');
Eric Andersenff9eee42001-06-29 04:57:14 +00002445 case '>':
2446 case '<':
2447 diag(c);
Eric Andersen8401eea2004-08-04 19:16:54 +00002448 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002449
2450 case '\n':
2451 nlseen++;
2452 gethere();
2453 startl = 1;
2454 if (multiline || cf & CONTIN) {
2455 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002456#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002457 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002458#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002459 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002460#endif
2461 }
2462 if (cf & CONTIN)
2463 goto loop;
2464 }
Eric Andersen8401eea2004-08-04 19:16:54 +00002465 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002466
2467 case '(':
2468 case ')':
2469 startl = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002470 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002471 }
2472
2473 unget(c);
2474
Eric Andersen8401eea2004-08-04 19:16:54 +00002475 pack:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002476 while ((c = my_getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n")) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002477 if (e.linep >= elinep)
2478 err("word too long");
2479 else
2480 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002481 };
2482
Eric Andersenff9eee42001-06-29 04:57:14 +00002483 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002484
Eric Andersen8401eea2004-08-04 19:16:54 +00002485 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002486 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002487
Eric Andersenff9eee42001-06-29 04:57:14 +00002488 *e.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002489
Eric Andersen8401eea2004-08-04 19:16:54 +00002490 if (atstart && (c = rlookup(line)) != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002491 startl = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002492 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002493 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002494
Eric Andersenff9eee42001-06-29 04:57:14 +00002495 yylval.cp = strsave(line, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00002496 return (WORD);
Eric Andersenff9eee42001-06-29 04:57:14 +00002497}
2498
Eric Andersen12de6cf2004-08-04 19:19:10 +00002499
Eric Andersen8401eea2004-08-04 19:16:54 +00002500static int collect(c, c1)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002501REGISTER int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002502{
2503 char s[2];
2504
Eric Andersen12de6cf2004-08-04 19:19:10 +00002505 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2506
Eric Andersenff9eee42001-06-29 04:57:14 +00002507 *e.linep++ = c;
2508 while ((c = my_getc(c1)) != c1) {
2509 if (c == 0) {
2510 unget(c);
2511 s[0] = c1;
2512 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002513 prs("no closing ");
2514 yyerror(s);
2515 return (YYERRCODE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002516 }
2517 if (interactive && c == '\n' && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002518#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002519 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002520#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002521 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002522#endif
2523 }
2524 *e.linep++ = c;
2525 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002526
Eric Andersenff9eee42001-06-29 04:57:14 +00002527 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002528
2529 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2530
Eric Andersen8401eea2004-08-04 19:16:54 +00002531 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002532}
2533
Eric Andersen12de6cf2004-08-04 19:19:10 +00002534/* "multiline commands" helper func */
2535/* see if next 2 chars form a shell multiline */
Eric Andersen8401eea2004-08-04 19:16:54 +00002536static int dual(c)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002537REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002538{
2539 char s[3];
Eric Andersen12de6cf2004-08-04 19:19:10 +00002540 REGISTER char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002541
Eric Andersen12de6cf2004-08-04 19:19:10 +00002542 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2543
2544 *cp++ = c; /* c is the given "peek" char */
2545 *cp++ = my_getc(0); /* get next char of input */
2546 *cp = 0; /* add EOS marker */
2547
2548 c = rlookup(s); /* see if 2 chars form a shell multiline */
2549 if (c == 0)
2550 unget(*--cp); /* String is not a shell multiline, put peek char back */
2551
2552 return (c); /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002553}
2554
Eric Andersen8401eea2004-08-04 19:16:54 +00002555static void diag(ec)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002556REGISTER int ec;
Eric Andersenff9eee42001-06-29 04:57:14 +00002557{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002558 REGISTER int c;
2559
2560 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002561
2562 c = my_getc(0);
2563 if (c == '>' || c == '<') {
2564 if (c != ec)
2565 zzerr();
Eric Andersen8401eea2004-08-04 19:16:54 +00002566 yylval.i = ec == '>' ? IOWRITE | IOCAT : IOHERE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002567 c = my_getc(0);
2568 } else
Eric Andersen8401eea2004-08-04 19:16:54 +00002569 yylval.i = ec == '>' ? IOWRITE : IOREAD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002570 if (c != '&' || yylval.i == IOHERE)
2571 unget(c);
2572 else
2573 yylval.i |= IODUP;
2574}
2575
Eric Andersen8401eea2004-08-04 19:16:54 +00002576static char *tree(size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002577unsigned size;
2578{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002579 REGISTER char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002580
2581 if ((t = getcell(size)) == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002582 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002583 prs("command line too complicated\n");
2584 fail();
2585 /* NOTREACHED */
2586 }
Eric Andersen8401eea2004-08-04 19:16:54 +00002587 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002588}
2589
2590/* VARARGS1 */
2591/* ARGSUSED */
2592
2593/* -------- exec.c -------- */
2594
2595/*
2596 * execute tree
2597 */
2598
2599
Eric Andersen8401eea2004-08-04 19:16:54 +00002600static int execute(t, pin, pout, act)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002601REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002602int *pin, *pout;
2603int act;
2604{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002605 REGISTER struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002606 volatile int i, rv, a;
2607 char *cp, **wp, **wp2;
2608 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002609 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002610 struct brkcon bc;
2611
2612#if __GNUC__
2613 /* Avoid longjmp clobbering */
2614 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002615#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002616
Eric Andersen12de6cf2004-08-04 19:19:10 +00002617 if (t == NULL) {
2618 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Eric Andersen8401eea2004-08-04 19:16:54 +00002619 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002620 }
2621
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002622 DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002623 t->type, T_CMD_NAMES[t->type],
2624 ((t->words == NULL) ? "NULL" : t->words[0])));
2625
Eric Andersenff9eee42001-06-29 04:57:14 +00002626 rv = 0;
2627 a = areanum++;
2628 wp = (wp2 = t->words) != NULL
Eric Andersen8401eea2004-08-04 19:16:54 +00002629 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2630 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002631
Eric Andersen12de6cf2004-08-04 19:19:10 +00002632/* Hard to know how many words there are, be careful of garbage pointer values */
2633/* They are likely to cause "PCI bus fault" errors */
2634#if 0
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002635 DBGPRINTF(("EXECUTE: t->left=%p, t->right=%p, t->words[1] is %s\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002636 t->left, t->right,
2637 ((t->words[1] == NULL) ? "NULL" : t->words[1])));
2638 DBGPRINTF7(("EXECUTE: t->words[2] is %s, t->words[3] is %s\n",
2639 ((t->words[2] == NULL) ? "NULL" : t->words[2]),
2640 ((t->words[3] == NULL) ? "NULL" : t->words[3])));
2641#endif
2642
2643
Eric Andersen8401eea2004-08-04 19:16:54 +00002644 switch (t->type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002645 case TDOT:
2646 DBGPRINTF3(("EXECUTE: TDOT\n"));
2647
2648 outtree_save = outtree;
2649
2650 newfile(evalstr(t->words[0], DOALL));
2651
2652 t->left = dowholefile(TLIST, 0);
2653 t->right = NULL;
2654
2655 outtree = outtree_save;
2656
2657 if (t->left)
2658 rv = execute(t->left, pin, pout, 0);
2659 if (t->right)
2660 rv = execute(t->right, pin, pout, 0);
2661 break;
2662
Eric Andersenff9eee42001-06-29 04:57:14 +00002663 case TPAREN:
Eric Andersen737f5fb2003-03-14 16:05:59 +00002664 rv = execute(t->left, pin, pout, 0);
2665 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002666
Eric Andersenff9eee42001-06-29 04:57:14 +00002667 case TCOM:
Eric Andersen1c039232001-07-07 00:05:55 +00002668 {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002669 rv = forkexec(t, pin, pout, act, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002670 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002671 break;
2672
2673 case TPIPE:
2674 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002675 int pv[2];
2676
2677 if ((rv = openpipe(pv)) < 0)
2678 break;
2679 pv[0] = remap(pv[0]);
2680 pv[1] = remap(pv[1]);
2681 (void) execute(t->left, pin, pv, 0);
2682 rv = execute(t->right, pv, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002683 }
2684 break;
2685
2686 case TLIST:
2687 (void) execute(t->left, pin, pout, 0);
2688 rv = execute(t->right, pin, pout, 0);
2689 break;
2690
2691 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002692 {
2693 int hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002694
Eric Andersen12de6cf2004-08-04 19:19:10 +00002695 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2696
Eric Andersen8401eea2004-08-04 19:16:54 +00002697 i = vfork();
2698 if (i != 0) {
2699 interactive = hinteractive;
2700 if (i != -1) {
2701 setval(lookup("!"), putn(i));
2702 if (pin != NULL)
2703 closepipe(pin);
2704 if (interactive) {
2705 prs(putn(i));
2706 prs("\n");
2707 }
2708 } else
2709 rv = -1;
2710 setstatus(rv);
2711 } else {
2712 signal(SIGINT, SIG_IGN);
2713 signal(SIGQUIT, SIG_IGN);
2714 if (interactive)
2715 signal(SIGTERM, SIG_DFL);
2716 interactive = 0;
2717 if (pin == NULL) {
2718 close(0);
"Vladimir N. Oleynik"6c35c7c2005-10-12 15:34:25 +00002719 open(bb_dev_null, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002720 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002721 _exit(execute(t->left, pin, pout, FEXEC));
Eric Andersenff9eee42001-06-29 04:57:14 +00002722 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002723 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002724 break;
2725
2726 case TOR:
2727 case TAND:
2728 rv = execute(t->left, pin, pout, 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00002729 if ((t1 = t->right) != NULL && (rv == 0) == (t->type == TAND))
Eric Andersenff9eee42001-06-29 04:57:14 +00002730 rv = execute(t1, pin, pout, 0);
2731 break;
2732
2733 case TFOR:
2734 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002735 wp = dolv + 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002736 if ((i = dolc) < 0)
2737 i = 0;
2738 } else {
2739 i = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002740 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002741 }
2742 vp = lookup(t->str);
2743 while (setjmp(bc.brkpt))
2744 if (isbreak)
2745 goto broken;
2746 brkset(&bc);
2747 for (t1 = t->left; i-- && *wp != NULL;) {
2748 setval(vp, *wp++);
2749 rv = execute(t1, pin, pout, 0);
2750 }
2751 brklist = brklist->nextlev;
2752 break;
2753
2754 case TWHILE:
2755 case TUNTIL:
2756 while (setjmp(bc.brkpt))
2757 if (isbreak)
2758 goto broken;
2759 brkset(&bc);
2760 t1 = t->left;
2761 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2762 rv = execute(t->right, pin, pout, 0);
2763 brklist = brklist->nextlev;
2764 break;
2765
2766 case TIF:
2767 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002768 if (t->right != NULL) {
2769 rv = !execute(t->left, pin, pout, 0) ?
2770 execute(t->right->left, pin, pout, 0) :
2771 execute(t->right->right, pin, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002772 }
2773 break;
2774
2775 case TCASE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002776 if ((cp = evalstr(t->str, DOSUB | DOTRIM)) == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002777 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002778
2779 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2780 ((t->str == NULL) ? "NULL" : t->str),
2781 ((cp == NULL) ? "NULL" : cp)));
2782
2783 if ((t1 = findcase(t->left, cp)) != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002784 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002785 rv = execute(t1, pin, pout, 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002786 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002787 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002788 break;
2789
2790 case TBRACE:
2791/*
2792 if (iopp = t->ioact)
2793 while (*iopp)
2794 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2795 rv = -1;
2796 break;
2797 }
2798*/
2799 if (rv >= 0 && (t1 = t->left))
2800 rv = execute(t1, pin, pout, 0);
2801 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002802
2803 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002804
Eric Andersen8401eea2004-08-04 19:16:54 +00002805 broken:
Eric Andersenff9eee42001-06-29 04:57:14 +00002806 t->words = wp2;
2807 isbreak = 0;
2808 freehere(areanum);
2809 freearea(areanum);
2810 areanum = a;
2811 if (interactive && intr) {
2812 closeall();
2813 fail();
2814 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002815
Eric Andersenff9eee42001-06-29 04:57:14 +00002816 if ((i = trapset) != 0) {
2817 trapset = 0;
2818 runtrap(i);
2819 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002820
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002821 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Eric Andersen8401eea2004-08-04 19:16:54 +00002822 return (rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00002823}
2824
2825static int
Eric Andersen12de6cf2004-08-04 19:19:10 +00002826forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002827{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002828 pid_t newpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00002829 int i, rv;
Eric Andersen8401eea2004-08-04 19:16:54 +00002830 int (*shcom) (struct op *) = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002831 REGISTER int f;
Eric Andersenff9eee42001-06-29 04:57:14 +00002832 char *cp = NULL;
2833 struct ioword **iopp;
2834 int resetsig;
2835 char **owp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002836 int forked = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002837
2838 int *hpin = pin;
2839 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002840 char *hwp;
2841 int hinteractive;
2842 int hintr;
Eric Andersen8401eea2004-08-04 19:16:54 +00002843 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002844 int hexecflg;
2845
2846#if __GNUC__
2847 /* Avoid longjmp clobbering */
2848 (void) &pin;
2849 (void) &pout;
2850 (void) &wp;
2851 (void) &shcom;
2852 (void) &cp;
2853 (void) &resetsig;
2854 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002855#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002856
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002857 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002858 pout, act));
2859 DBGPRINTF7(("FORKEXEC: t->words is %s\n",
2860 ((t->words == NULL) ? "NULL" : t->words[0])));
2861
2862/* Hard to know how many words there are, be careful of garbage pointer values */
2863/* They are likely to cause "PCI bus fault" errors */
2864#if 0
2865 DBGPRINTF7(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
2866 ((t->words == NULL) ? "NULL" : t->words[0]),
2867 ((t->words == NULL) ? "NULL" : t->words[1])));
2868 DBGPRINTF7(("FORKEXEC: wp is %s, wp[1] is %s\n",
2869 ((wp == NULL) ? "NULL" : wp[0]),
2870 ((wp[1] == NULL) ? "NULL" : wp[1])));
2871 DBGPRINTF7(("FORKEXEC: wp2 is %s, wp[3] is %s\n",
2872 ((wp[2] == NULL) ? "NULL" : wp[2]),
2873 ((wp[3] == NULL) ? "NULL" : wp[3])));
2874#endif
2875
2876
Eric Andersenff9eee42001-06-29 04:57:14 +00002877 owp = wp;
2878 resetsig = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002879 rv = -1; /* system-detected error */
Eric Andersenff9eee42001-06-29 04:57:14 +00002880 if (t->type == TCOM) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002881 while ((cp = *wp++) != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002882 cp = *wp;
2883
2884 /* strip all initial assignments */
2885 /* not correct wrt PATH=yyy command etc */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002886 if (flag['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002887 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002888 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002889 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002890 }
2891#if 0
2892 DBGPRINTF9(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
2893 ((t->words == NULL) ? "NULL" : t->words[0]),
2894 ((t->words == NULL) ? "NULL" : t->words[1])));
2895 DBGPRINTF9(("FORKEXEC: wp is %s, wp[1] is %s\n",
2896 ((wp == NULL) ? "NULL" : wp[0]),
2897 ((wp == NULL) ? "NULL" : wp[1])));
2898#endif
2899
Eric Andersenff9eee42001-06-29 04:57:14 +00002900 if (cp == NULL && t->ioact == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002901 while ((cp = *owp++) != NULL && assign(cp, COPYV));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002902 DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
Eric Andersen8401eea2004-08-04 19:16:54 +00002903 return (setstatus(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002904 } else if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002905 shcom = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002906 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002907 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002908
Eric Andersenff9eee42001-06-29 04:57:14 +00002909 t->words = wp;
2910 f = act;
Eric Andersenff9eee42001-06-29 04:57:14 +00002911
Eric Andersen12de6cf2004-08-04 19:19:10 +00002912#if 0
2913 DBGPRINTF3(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
2914 ((t->words == NULL) ? "NULL" : t->words[0]),
2915 ((t->words == NULL) ? "NULL" : t->words[1])));
2916#endif
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002917 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002918 f & FEXEC, owp));
2919
2920 if (shcom == NULL && (f & FEXEC) == 0) {
2921 /* Save values in case the child process alters them */
Eric Andersenff9eee42001-06-29 04:57:14 +00002922 hpin = pin;
2923 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002924 hwp = *wp;
2925 hinteractive = interactive;
2926 hintr = intr;
2927 hbrklist = brklist;
2928 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002929
Eric Andersen12de6cf2004-08-04 19:19:10 +00002930 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
2931
2932 newpid = vfork();
2933
2934 if (newpid == -1) {
2935 DBGPRINTF(("FORKEXEC: ERROR, unable to vfork()!\n"));
2936 return (-1);
2937 }
2938
2939
2940 if (newpid > 0) { /* Parent */
2941
2942 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002943 pin = hpin;
2944 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002945 *wp = hwp;
2946 interactive = hinteractive;
2947 intr = hintr;
2948 brklist = hbrklist;
2949 execflg = hexecflg;
2950
Eric Andersen12de6cf2004-08-04 19:19:10 +00002951/* moved up
Eric Andersenff9eee42001-06-29 04:57:14 +00002952 if (i == -1)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002953 return(rv);
2954*/
2955
Eric Andersenff9eee42001-06-29 04:57:14 +00002956 if (pin != NULL)
2957 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002958
2959 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002960 }
2961
Eric Andersen12de6cf2004-08-04 19:19:10 +00002962 /* Must be the child process, pid should be 0 */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002963 DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002964
Eric Andersenff9eee42001-06-29 04:57:14 +00002965 if (interactive) {
2966 signal(SIGINT, SIG_IGN);
2967 signal(SIGQUIT, SIG_IGN);
2968 resetsig = 1;
2969 }
2970 interactive = 0;
2971 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002972 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002973 brklist = 0;
2974 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002975 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002976
2977
Eric Andersenff9eee42001-06-29 04:57:14 +00002978 if (owp != NULL)
2979 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2980 if (shcom == NULL)
2981 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002982
Eric Andersenff9eee42001-06-29 04:57:14 +00002983#ifdef COMPIPE
2984 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2985 err("piping to/from shell builtins not yet done");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002986 if (forked)
2987 _exit(-1);
Eric Andersen8401eea2004-08-04 19:16:54 +00002988 return (-1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002989 }
2990#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00002991
Eric Andersenff9eee42001-06-29 04:57:14 +00002992 if (pin != NULL) {
2993 dup2(pin[0], 0);
2994 closepipe(pin);
2995 }
2996 if (pout != NULL) {
2997 dup2(pout[1], 1);
2998 closepipe(pout);
2999 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003000
Eric Andersenff9eee42001-06-29 04:57:14 +00003001 if ((iopp = t->ioact) != NULL) {
3002 if (shcom != NULL && shcom != doexec) {
3003 prs(cp);
3004 err(": cannot redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003005 if (forked)
3006 _exit(-1);
Eric Andersen8401eea2004-08-04 19:16:54 +00003007 return (-1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003008 }
3009 while (*iopp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003010 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
3011 if (forked)
3012 _exit(rv);
Eric Andersen8401eea2004-08-04 19:16:54 +00003013 return (rv);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003014 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003015 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003016
3017 if (shcom) {
3018 i = setstatus((*shcom) (t));
3019 if (forked)
3020 _exit(i);
3021 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
3022 return (i);
3023 }
3024
Eric Andersenff9eee42001-06-29 04:57:14 +00003025 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00003026 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003027 close(i);
3028 if (resetsig) {
3029 signal(SIGINT, SIG_DFL);
3030 signal(SIGQUIT, SIG_DFL);
Mike Frysinger4e512f12006-05-05 18:38:07 +00003031 } else {
3032 /* put non-interactive processes into a different process group.
3033 * we don't support jobs, but this is at least sane: see Bug 659 */
3034 setpgrp();
Eric Andersenff9eee42001-06-29 04:57:14 +00003035 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003036
Eric Andersen12de6cf2004-08-04 19:19:10 +00003037 if (t->type == TPAREN)
3038 _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
3039 if (wp[0] == NULL)
3040 _exit(0);
3041
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003042 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003043 prs(wp[0]);
3044 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003045 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003046 if (!execflg)
3047 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003048
3049 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
3050
Eric Andersenff9eee42001-06-29 04:57:14 +00003051 leave();
3052 /* NOTREACHED */
Eric Andersen12de6cf2004-08-04 19:19:10 +00003053 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003054}
3055
3056/*
3057 * 0< 1> are ignored as required
3058 * within pipelines.
3059 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003060static int iosetup(iop, pipein, pipeout)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003061REGISTER struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00003062int pipein, pipeout;
3063{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003064 REGISTER int u = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003065 char *cp = NULL, *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00003066
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003067 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00003068 pipein, pipeout));
3069
Eric Andersenff9eee42001-06-29 04:57:14 +00003070 if (iop->io_unit == IODEFAULT) /* take default */
Eric Andersen8401eea2004-08-04 19:16:54 +00003071 iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003072
Eric Andersenff9eee42001-06-29 04:57:14 +00003073 if (pipein && iop->io_unit == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00003074 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003075
Eric Andersenff9eee42001-06-29 04:57:14 +00003076 if (pipeout && iop->io_unit == 1)
Eric Andersen8401eea2004-08-04 19:16:54 +00003077 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003078
Eric Andersen8401eea2004-08-04 19:16:54 +00003079 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00003080 if ((iop->io_flag & IOHERE) == 0) {
3081 cp = iop->io_name;
Eric Andersen8401eea2004-08-04 19:16:54 +00003082 if ((cp = evalstr(cp, DOSUB | DOTRIM)) == NULL)
3083 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003084 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003085
Eric Andersenff9eee42001-06-29 04:57:14 +00003086 if (iop->io_flag & IODUP) {
3087 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
3088 prs(cp);
3089 err(": illegal >& argument");
Eric Andersen8401eea2004-08-04 19:16:54 +00003090 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003091 }
3092 if (*cp == '-')
3093 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00003094 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00003095 }
3096 switch (iop->io_flag) {
3097 case IOREAD:
3098 u = open(cp, 0);
3099 break;
3100
3101 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00003102 case IOHERE | IOXHERE:
3103 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00003104 cp = "here file";
3105 break;
3106
Eric Andersen8401eea2004-08-04 19:16:54 +00003107 case IOWRITE | IOCAT:
Eric Andersenff9eee42001-06-29 04:57:14 +00003108 if ((u = open(cp, 1)) >= 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003109 lseek(u, (long) 0, 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00003110 break;
3111 }
3112 case IOWRITE:
3113 u = creat(cp, 0666);
3114 break;
3115
3116 case IODUP:
Eric Andersen8401eea2004-08-04 19:16:54 +00003117 u = dup2(*cp - '0', iop->io_unit);
Eric Andersenff9eee42001-06-29 04:57:14 +00003118 break;
3119
3120 case IOCLOSE:
3121 close(iop->io_unit);
Eric Andersen8401eea2004-08-04 19:16:54 +00003122 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003123 }
3124 if (u < 0) {
3125 prs(cp);
3126 prs(": cannot ");
3127 warn(msg);
Eric Andersen8401eea2004-08-04 19:16:54 +00003128 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003129 } else {
3130 if (u != iop->io_unit) {
3131 dup2(u, iop->io_unit);
3132 close(u);
3133 }
3134 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003135 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003136}
3137
Eric Andersen8401eea2004-08-04 19:16:54 +00003138static void echo(wp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003139REGISTER char **wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003140{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003141 REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003142
3143 prs("+");
Eric Andersen8401eea2004-08-04 19:16:54 +00003144 for (i = 0; wp[i]; i++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003145 if (i)
3146 prs(" ");
3147 prs(wp[i]);
3148 }
3149 prs("\n");
3150}
3151
Eric Andersen8401eea2004-08-04 19:16:54 +00003152static struct op **find1case(t, w)
Eric Andersenff9eee42001-06-29 04:57:14 +00003153struct op *t;
3154char *w;
3155{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003156 REGISTER struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003157 struct op **tp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003158 REGISTER char **wp, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003159
Eric Andersen12de6cf2004-08-04 19:19:10 +00003160
3161 if (t == NULL) {
3162 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
Eric Andersen8401eea2004-08-04 19:16:54 +00003163 return ((struct op **) NULL);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003164 }
3165
3166 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
3167 T_CMD_NAMES[t->type]));
3168
Eric Andersenff9eee42001-06-29 04:57:14 +00003169 if (t->type == TLIST) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003170 if ((tp = find1case(t->left, w)) != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003171 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
Eric Andersen8401eea2004-08-04 19:16:54 +00003172 return (tp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003173 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003174 t1 = t->right; /* TPAT */
Eric Andersenff9eee42001-06-29 04:57:14 +00003175 } else
3176 t1 = t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003177
Eric Andersenff9eee42001-06-29 04:57:14 +00003178 for (wp = t1->words; *wp;)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003179 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003180 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003181 &t1->left));
Eric Andersen8401eea2004-08-04 19:16:54 +00003182 return (&t1->left);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003183 }
3184
3185 DBGPRINTF(("FIND1CASE: returning NULL\n"));
Eric Andersen8401eea2004-08-04 19:16:54 +00003186 return ((struct op **) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003187}
3188
Eric Andersen8401eea2004-08-04 19:16:54 +00003189static struct op *findcase(t, w)
Eric Andersenff9eee42001-06-29 04:57:14 +00003190struct op *t;
3191char *w;
3192{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003193 REGISTER struct op **tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003194
Eric Andersen8401eea2004-08-04 19:16:54 +00003195 return ((tp = find1case(t, w)) != NULL ? *tp : (struct op *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003196}
3197
3198/*
3199 * Enter a new loop level (marked for break/continue).
3200 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003201static void brkset(bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00003202struct brkcon *bc;
3203{
3204 bc->nextlev = brklist;
3205 brklist = bc;
3206}
3207
3208/*
3209 * Wait for the last process created.
3210 * Print a message for each process found
3211 * that was killed by a signal.
3212 * Ignore interrupt signals while waiting
3213 * unless `canintr' is true.
3214 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003215static int waitfor(lastpid, canintr)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003216REGISTER int lastpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00003217int canintr;
3218{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003219 REGISTER int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003220 int s;
3221 int oheedint = heedint;
3222
3223 heedint = 0;
3224 rv = 0;
3225 do {
3226 pid = wait(&s);
3227 if (pid == -1) {
3228 if (errno != EINTR || canintr)
3229 break;
3230 } else {
3231 if ((rv = WAITSIG(s)) != 0) {
3232 if (rv < NSIGNAL) {
3233 if (signame[rv] != NULL) {
3234 if (pid != lastpid) {
3235 prn(pid);
3236 prs(": ");
3237 }
3238 prs(signame[rv]);
3239 }
3240 } else {
3241 if (pid != lastpid) {
3242 prn(pid);
3243 prs(": ");
3244 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003245 prs("Signal ");
3246 prn(rv);
3247 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00003248 }
3249 if (WAITCORE(s))
3250 prs(" - core dumped");
3251 if (rv >= NSIGNAL || signame[rv])
3252 prs("\n");
3253 rv = -1;
3254 } else
3255 rv = WAITVAL(s);
3256 }
3257 } while (pid != lastpid);
3258 heedint = oheedint;
3259 if (intr) {
3260 if (interactive) {
3261 if (canintr)
3262 intr = 0;
3263 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003264 if (exstat == 0)
3265 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003266 onintr(0);
3267 }
3268 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003269 return (rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00003270}
3271
Eric Andersen8401eea2004-08-04 19:16:54 +00003272static int setstatus(s)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003273REGISTER int s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003274{
3275 exstat = s;
3276 setval(lookup("?"), putn(s));
Eric Andersen8401eea2004-08-04 19:16:54 +00003277 return (s);
Eric Andersenff9eee42001-06-29 04:57:14 +00003278}
3279
3280/*
3281 * PATH-searching interface to execve.
3282 * If getenv("PATH") were kept up-to-date,
3283 * execvp might be used.
3284 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003285static char *rexecve(c, v, envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003286char *c, **v, **envp;
3287{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003288 REGISTER int i;
3289 REGISTER char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003290 int eacces = 0, asis = 0;
3291
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003292#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003293 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00003294
Eric Andersen1c039232001-07-07 00:05:55 +00003295 optind = 1;
3296 if (find_applet_by_name(name)) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003297 /* We have to exec here since we vforked. Running
Eric Andersen1c039232001-07-07 00:05:55 +00003298 * run_applet_by_name() won't work and bad things
3299 * will happen. */
3300 execve("/proc/self/exe", v, envp);
3301 execve("busybox", v, envp);
3302 }
3303#endif
3304
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003305 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003306
Eric Andersen8401eea2004-08-04 19:16:54 +00003307 sp = any('/', c) ? "" : path->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00003308 asis = *sp == '\0';
3309 while (asis || *sp != '\0') {
3310 asis = 0;
3311 tp = e.linep;
3312 for (; *sp != '\0'; tp++)
3313 if ((*tp = *sp++) == ':') {
3314 asis = *sp == '\0';
3315 break;
3316 }
3317 if (tp != e.linep)
3318 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003319 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003320
Eric Andersen12de6cf2004-08-04 19:19:10 +00003321 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3322
Eric Andersenff9eee42001-06-29 04:57:14 +00003323 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003324
Eric Andersenff9eee42001-06-29 04:57:14 +00003325 switch (errno) {
3326 case ENOEXEC:
3327 *v = e.linep;
3328 tp = *--v;
3329 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003330 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003331 *v = tp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003332 return ("no Shell");
Eric Andersenff9eee42001-06-29 04:57:14 +00003333
3334 case ENOMEM:
Eric Andersen8401eea2004-08-04 19:16:54 +00003335 return ((char *) bb_msg_memory_exhausted);
Eric Andersenff9eee42001-06-29 04:57:14 +00003336
3337 case E2BIG:
Eric Andersen8401eea2004-08-04 19:16:54 +00003338 return ("argument list too long");
Eric Andersenff9eee42001-06-29 04:57:14 +00003339
3340 case EACCES:
3341 eacces++;
3342 break;
3343 }
3344 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003345 return (errno == ENOENT ? "not found" : "cannot execute");
Eric Andersenff9eee42001-06-29 04:57:14 +00003346}
3347
3348/*
3349 * Run the command produced by generator `f'
3350 * applied to stream `arg'.
3351 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003352static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003353{
3354 struct op *otree;
3355 struct wdblock *swdlist;
3356 struct wdblock *siolist;
3357 jmp_buf ev, rt;
3358 xint *ofail;
3359 int rv;
3360
3361#if __GNUC__
3362 /* Avoid longjmp clobbering */
3363 (void) &rv;
3364#endif
3365
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003366 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003367 areanum, outtree, failpt));
3368
Eric Andersenff9eee42001-06-29 04:57:14 +00003369 areanum++;
3370 swdlist = wdlist;
3371 siolist = iolist;
3372 otree = outtree;
3373 ofail = failpt;
3374 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003375
Eric Andersenff9eee42001-06-29 04:57:14 +00003376 if (newenv(setjmp(errpt = ev)) == 0) {
3377 wdlist = 0;
3378 iolist = 0;
3379 pushio(argp, f);
3380 e.iobase = e.iop;
3381 yynerrs = 0;
3382 if (setjmp(failpt = rt) == 0 && yyparse() == 0)
3383 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3384 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003385 } else {
3386 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003387 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003388
Eric Andersenff9eee42001-06-29 04:57:14 +00003389 wdlist = swdlist;
3390 iolist = siolist;
3391 failpt = ofail;
3392 outtree = otree;
3393 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003394
Eric Andersen8401eea2004-08-04 19:16:54 +00003395 return (rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00003396}
3397
3398/* -------- do.c -------- */
3399
3400/*
3401 * built-in commands: doX
3402 */
3403
Eric Andersen8401eea2004-08-04 19:16:54 +00003404static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003405{
3406 int col;
3407 const struct builtincmd *x;
3408
3409 printf("\nBuilt-in commands:\n");
3410 printf("-------------------\n");
3411
Eric Andersen8401eea2004-08-04 19:16:54 +00003412 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003413 if (!x->name)
3414 continue;
3415 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
3416 if (col > 60) {
3417 printf("\n");
3418 col = 0;
3419 }
3420 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003421#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003422 {
3423 int i;
3424 const struct BB_applet *applet;
3425 extern const struct BB_applet applets[];
3426 extern const size_t NUM_APPLETS;
3427
Eric Andersen8401eea2004-08-04 19:16:54 +00003428 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003429 if (!applet->name)
3430 continue;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003431
Eric Andersen8401eea2004-08-04 19:16:54 +00003432 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003433 if (col > 60) {
3434 printf("\n");
3435 col = 0;
3436 }
3437 }
3438 }
3439#endif
3440 printf("\n\n");
3441 return EXIT_SUCCESS;
3442}
3443
3444
3445
Eric Andersen8401eea2004-08-04 19:16:54 +00003446static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003447{
Eric Andersen8401eea2004-08-04 19:16:54 +00003448 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003449}
3450
Eric Andersen8401eea2004-08-04 19:16:54 +00003451static int dochdir(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003452REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00003453{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003454 REGISTER char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003455
3456 if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
3457 er = ": no home directory";
Eric Andersen8401eea2004-08-04 19:16:54 +00003458 else if (chdir(cp) < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003459 er = ": bad directory";
3460 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003461 return (0);
3462 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003463 err(er);
Eric Andersen8401eea2004-08-04 19:16:54 +00003464 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003465}
3466
Eric Andersen8401eea2004-08-04 19:16:54 +00003467static int doshift(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003468REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00003469{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003470 REGISTER int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003471
Eric Andersen8401eea2004-08-04 19:16:54 +00003472 n = t->words[1] ? getn(t->words[1]) : 1;
3473 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003474 err("nothing to shift");
Eric Andersen8401eea2004-08-04 19:16:54 +00003475 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003476 }
3477 dolv[n] = dolv[0];
3478 dolv += n;
3479 dolc -= n;
3480 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003481 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003482}
3483
3484/*
3485 * execute login and newgrp directly
3486 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003487static int dologin(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003488struct op *t;
3489{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003490 REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003491
3492 if (interactive) {
3493 signal(SIGINT, SIG_DFL);
3494 signal(SIGQUIT, SIG_DFL);
3495 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003496 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003497 prs(t->words[0]);
3498 prs(": ");
3499 err(cp);
3500 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003501}
3502
Eric Andersen8401eea2004-08-04 19:16:54 +00003503static int doumask(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003504REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00003505{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003506 REGISTER int i, n;
3507 REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003508
3509 if ((cp = t->words[1]) == NULL) {
3510 i = umask(0);
3511 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003512 for (n = 3 * 4; (n -= 3) >= 0;)
3513 putc('0' + ((i >> n) & 07), stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003514 putc('\n', stderr);
3515 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003516 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3517 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003518 umask(n);
3519 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003520 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003521}
3522
Eric Andersen8401eea2004-08-04 19:16:54 +00003523static int doexec(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003524REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00003525{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003526 REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003527 jmp_buf ex;
3528 xint *ofail;
3529
3530 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003531 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003532 if (i == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00003533 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003534 execflg = 1;
3535 ofail = failpt;
3536 if (setjmp(failpt = ex) == 0)
3537 execute(t, NOPIPE, NOPIPE, FEXEC);
3538 failpt = ofail;
3539 execflg = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003540 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003541}
3542
Eric Andersen8401eea2004-08-04 19:16:54 +00003543static int dodot(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003544struct op *t;
3545{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003546 REGISTER int i;
3547 REGISTER char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003548 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003549 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003550
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003551 DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep)));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003552
3553 if ((cp = t->words[1]) == NULL) {
3554 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Eric Andersen8401eea2004-08-04 19:16:54 +00003555 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003556 } else {
3557 DBGPRINTF(("DODOT: cp is %s\n", cp));
3558 }
3559
Eric Andersen8401eea2004-08-04 19:16:54 +00003560 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003561
3562 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3563 ((sp == NULL) ? "NULL" : sp),
3564 ((e.linep == NULL) ? "NULL" : e.linep)));
3565
Eric Andersenff9eee42001-06-29 04:57:14 +00003566 while (*sp) {
3567 tp = e.linep;
3568 while (*sp && (*tp = *sp++) != ':')
3569 tp++;
3570 if (tp != e.linep)
3571 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003572
Eric Andersen8401eea2004-08-04 19:16:54 +00003573 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003574
3575 /* Original code */
Eric Andersenff9eee42001-06-29 04:57:14 +00003576 if ((i = open(e.linep, 0)) >= 0) {
3577 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003578 maltmp = remap(i);
3579 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3580
3581 next(maltmp); /* Basically a PUSHIO */
3582
3583 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3584
Eric Andersen8401eea2004-08-04 19:16:54 +00003585 return (exstat);
Eric Andersenff9eee42001-06-29 04:57:14 +00003586 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003587
3588 } /* While */
3589
Eric Andersenff9eee42001-06-29 04:57:14 +00003590 prs(cp);
3591 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003592
Eric Andersen8401eea2004-08-04 19:16:54 +00003593 return (-1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003594}
3595
Eric Andersen8401eea2004-08-04 19:16:54 +00003596static int dowait(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003597struct op *t;
3598{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003599 REGISTER int i;
3600 REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003601
3602 if ((cp = t->words[1]) != NULL) {
3603 i = getn(cp);
3604 if (i == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00003605 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003606 } else
3607 i = -1;
3608 setstatus(waitfor(i, 1));
Eric Andersen8401eea2004-08-04 19:16:54 +00003609 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003610}
3611
Eric Andersen8401eea2004-08-04 19:16:54 +00003612static int doread(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003613struct op *t;
3614{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003615 REGISTER char *cp, **wp;
3616 REGISTER int nb = 0;
3617 REGISTER int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003618
3619 if (t->words[1] == NULL) {
3620 err("Usage: read name ...");
Eric Andersen8401eea2004-08-04 19:16:54 +00003621 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003622 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003623 for (wp = t->words + 1; *wp; wp++) {
3624 for (cp = e.linep; !nl && cp < elinep - 1; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003625 if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003626 (nl = (*cp == '\n')) || (wp[1] && any(*cp, ifs->value)))
Eric Andersenff9eee42001-06-29 04:57:14 +00003627 break;
3628 *cp = 0;
3629 if (nb <= 0)
3630 break;
3631 setval(lookup(*wp), e.linep);
3632 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003633 return (nb <= 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003634}
3635
Eric Andersen8401eea2004-08-04 19:16:54 +00003636static int doeval(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003637REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00003638{
Eric Andersen8401eea2004-08-04 19:16:54 +00003639 return (RUN(awordlist, t->words + 1, wdchar));
Eric Andersenff9eee42001-06-29 04:57:14 +00003640}
3641
Eric Andersen8401eea2004-08-04 19:16:54 +00003642static int dotrap(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003643REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00003644{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003645 REGISTER int n, i;
3646 REGISTER int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003647
3648 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003649 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003650 if (trap[i]) {
3651 prn(i);
3652 prs(": ");
3653 prs(trap[i]);
3654 prs("\n");
3655 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003656 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003657 }
3658 resetsig = isdigit(*t->words[1]);
3659 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3660 n = getsig(t->words[i]);
3661 freecell(trap[n]);
3662 trap[n] = 0;
3663 if (!resetsig) {
3664 if (*t->words[1] != '\0') {
3665 trap[n] = strsave(t->words[1], 0);
3666 setsig(n, sig);
3667 } else
3668 setsig(n, SIG_IGN);
3669 } else {
3670 if (interactive)
3671 if (n == SIGINT)
3672 setsig(n, onintr);
3673 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003674 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003675 else
3676 setsig(n, SIG_DFL);
3677 }
3678 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003679 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003680}
3681
Eric Andersen8401eea2004-08-04 19:16:54 +00003682static int getsig(s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003683char *s;
3684{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003685 REGISTER int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003686
3687 if ((n = getn(s)) < 0 || n > _NSIG) {
3688 err("trap: bad signal number");
3689 n = 0;
3690 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003691 return (n);
Eric Andersenff9eee42001-06-29 04:57:14 +00003692}
3693
Eric Andersen12de6cf2004-08-04 19:19:10 +00003694static void setsig(REGISTER int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003695{
3696 if (n == 0)
3697 return;
3698 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3699 ourtrap[n] = 1;
3700 signal(n, f);
3701 }
3702}
3703
Eric Andersen8401eea2004-08-04 19:16:54 +00003704static int getn(as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003705char *as;
3706{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003707 REGISTER char *s;
3708 REGISTER int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003709
3710 s = as;
3711 m = 1;
3712 if (*s == '-') {
3713 m = -1;
3714 s++;
3715 }
3716 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003717 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003718 if (*s) {
3719 prs(as);
3720 err(": bad number");
3721 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003722 return (n * m);
Eric Andersenff9eee42001-06-29 04:57:14 +00003723}
3724
Eric Andersen8401eea2004-08-04 19:16:54 +00003725static int dobreak(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003726struct op *t;
3727{
Eric Andersen8401eea2004-08-04 19:16:54 +00003728 return (brkcontin(t->words[1], 1));
Eric Andersenff9eee42001-06-29 04:57:14 +00003729}
3730
Eric Andersen8401eea2004-08-04 19:16:54 +00003731static int docontinue(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003732struct op *t;
3733{
Eric Andersen8401eea2004-08-04 19:16:54 +00003734 return (brkcontin(t->words[1], 0));
Eric Andersenff9eee42001-06-29 04:57:14 +00003735}
3736
Eric Andersen8401eea2004-08-04 19:16:54 +00003737static int brkcontin(cp, val)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003738REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003739int val;
3740{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003741 REGISTER struct brkcon *bc;
3742 REGISTER int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003743
Eric Andersen8401eea2004-08-04 19:16:54 +00003744 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003745 if (nl <= 0)
3746 nl = 999;
3747 do {
3748 if ((bc = brklist) == NULL)
3749 break;
3750 brklist = bc->nextlev;
3751 } while (--nl);
3752 if (nl) {
3753 err("bad break/continue level");
Eric Andersen8401eea2004-08-04 19:16:54 +00003754 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003755 }
3756 isbreak = val;
3757 longjmp(bc->brkpt, 1);
3758 /* NOTREACHED */
3759}
3760
Eric Andersen8401eea2004-08-04 19:16:54 +00003761static int doexit(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003762struct op *t;
3763{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003764 REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003765
3766 execflg = 0;
3767 if ((cp = t->words[1]) != NULL)
3768 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003769
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003770 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003771
Eric Andersenff9eee42001-06-29 04:57:14 +00003772 leave();
3773 /* NOTREACHED */
Eric Andersen8401eea2004-08-04 19:16:54 +00003774 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003775}
3776
Eric Andersen8401eea2004-08-04 19:16:54 +00003777static int doexport(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003778struct op *t;
3779{
Eric Andersen8401eea2004-08-04 19:16:54 +00003780 rdexp(t->words + 1, export, EXPORT);
3781 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003782}
3783
Eric Andersen8401eea2004-08-04 19:16:54 +00003784static int doreadonly(t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003785struct op *t;
3786{
Eric Andersen8401eea2004-08-04 19:16:54 +00003787 rdexp(t->words + 1, ronly, RONLY);
3788 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003789}
3790
Eric Andersen8401eea2004-08-04 19:16:54 +00003791static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003792{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003793 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003794 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3795
Eric Andersenff9eee42001-06-29 04:57:14 +00003796 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003797 for (; *wp != NULL; wp++) {
3798 if (isassign(*wp)) {
3799 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003800
Matt Kraaif69bfc72001-07-12 19:39:59 +00003801 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003802 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003803 *cp = '\0';
3804 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003805 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003806 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003807 else
3808 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003809 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003810 } else
3811 putvlist(key, 1);
3812}
3813
Eric Andersen8401eea2004-08-04 19:16:54 +00003814static void badid(s)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003815REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003816{
3817 prs(s);
3818 err(": bad identifier");
3819}
3820
Eric Andersen8401eea2004-08-04 19:16:54 +00003821static int doset(t)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003822REGISTER struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00003823{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003824 REGISTER struct var *vp;
3825 REGISTER char *cp;
3826 REGISTER int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003827
3828 if ((cp = t->words[1]) == NULL) {
3829 for (vp = vlist; vp; vp = vp->next)
3830 varput(vp->name, 1);
Eric Andersen8401eea2004-08-04 19:16:54 +00003831 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003832 }
3833 if (*cp == '-') {
3834 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003835 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003836 if (*++cp == 0)
3837 flag['x'] = flag['v'] = 0;
3838 else
3839 for (; *cp; cp++)
3840 switch (*cp) {
3841 case 'e':
3842 if (!interactive)
3843 flag['e']++;
3844 break;
3845
3846 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003847 if (*cp >= 'a' && *cp <= 'z')
3848 flag[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003849 break;
3850 }
3851 setdash();
3852 }
3853 if (t->words[1]) {
3854 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003855 for (n = 1; t->words[n]; n++)
3856 setarea((char *) t->words[n], 0);
3857 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003858 dolv = t->words;
3859 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003860 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003861 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003862 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003863}
3864
Eric Andersen8401eea2004-08-04 19:16:54 +00003865static void varput(s, out)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003866REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003867int out;
3868{
Matt Kraai69edfec2001-08-06 14:14:18 +00003869 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003870 write(out, s, strlen(s));
3871 write(out, "\n", 1);
3872 }
3873}
3874
3875
3876/*
3877 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3878 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003879 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003880static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003881{
3882 struct tms buf;
3883 long int clk_tck = sysconf(_SC_CLK_TCK);
3884
3885 times(&buf);
3886 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003887 (int) (buf.tms_utime / clk_tck / 60),
3888 ((double) buf.tms_utime) / clk_tck,
3889 (int) (buf.tms_stime / clk_tck / 60),
3890 ((double) buf.tms_stime) / clk_tck,
3891 (int) (buf.tms_cutime / clk_tck / 60),
3892 ((double) buf.tms_cutime) / clk_tck,
3893 (int) (buf.tms_cstime / clk_tck / 60),
3894 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003895 return 0;
3896}
3897
3898
Eric Andersen8401eea2004-08-04 19:16:54 +00003899static int (*inbuilt(char *s)) (struct op *) {
Eric Andersen1c039232001-07-07 00:05:55 +00003900 const struct builtincmd *bp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003901
Eric Andersen1c039232001-07-07 00:05:55 +00003902 for (bp = builtincmds; bp->name != NULL; bp++)
3903 if (strcmp(bp->name, s) == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00003904 return (bp->builtinfunc);
Eric Andersen1c039232001-07-07 00:05:55 +00003905
Eric Andersen8401eea2004-08-04 19:16:54 +00003906 return (NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003907}
3908
3909/* -------- eval.c -------- */
3910
3911/*
3912 * ${}
3913 * `command`
3914 * blank interpretation
3915 * quoting
3916 * glob
3917 */
3918
Eric Andersen8401eea2004-08-04 19:16:54 +00003919static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003920{
3921 struct wdblock *wb;
3922 char **wp;
3923 char **wf;
3924 jmp_buf ev;
3925
3926#if __GNUC__
3927 /* Avoid longjmp clobbering */
3928 (void) &wp;
3929 (void) &ap;
3930#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003931
3932 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3933
Eric Andersenff9eee42001-06-29 04:57:14 +00003934 wp = NULL;
3935 wb = NULL;
3936 wf = NULL;
3937 if (newenv(setjmp(errpt = ev)) == 0) {
3938 while (*ap && isassign(*ap))
3939 expand(*ap++, &wb, f & ~DOGLOB);
3940 if (flag['k']) {
3941 for (wf = ap; *wf; wf++) {
3942 if (isassign(*wf))
3943 expand(*wf, &wb, f & ~DOGLOB);
3944 }
3945 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003946 for (wb = addword((char *) 0, wb); *ap; ap++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003947 if (!flag['k'] || !isassign(*ap))
3948 expand(*ap, &wb, f & ~DOKEY);
3949 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003950 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003951 wp = getwords(wb);
3952 quitenv();
3953 } else
3954 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003955
Eric Andersen8401eea2004-08-04 19:16:54 +00003956 return (gflg ? (char **) NULL : wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003957}
3958
3959/*
3960 * Make the exported environment from the exported
3961 * names in the dictionary. Keyword assignments
3962 * will already have been done.
3963 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003964static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003965{
Eric Andersen12de6cf2004-08-04 19:19:10 +00003966 REGISTER struct var *vp;
3967
3968 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003969
Eric Andersenff9eee42001-06-29 04:57:14 +00003970 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003971 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003972 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003973 wb = addword((char *) 0, wb);
3974 return (getwords(wb));
Eric Andersenff9eee42001-06-29 04:57:14 +00003975}
3976
Eric Andersen8401eea2004-08-04 19:16:54 +00003977static char *evalstr(cp, f)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003978REGISTER char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003979int f;
3980{
3981 struct wdblock *wb;
3982
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003983 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003984
Eric Andersenff9eee42001-06-29 04:57:14 +00003985 wb = NULL;
3986 if (expand(cp, &wb, f)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003987 if (wb == NULL || wb->w_nword == 0
3988 || (cp = wb->w_words[0]) == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003989 cp = "";
3990 DELETE(wb);
3991 } else
3992 cp = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003993 return (cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003994}
3995
Eric Andersen12de6cf2004-08-04 19:19:10 +00003996static int expand(char *cp, REGISTER struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003997{
3998 jmp_buf ev;
3999
4000#if __GNUC__
4001 /* Avoid longjmp clobbering */
4002 (void) &cp;
4003#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00004004
4005 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
4006
Eric Andersenff9eee42001-06-29 04:57:14 +00004007 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004008
Eric Andersenff9eee42001-06-29 04:57:14 +00004009 if (cp == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00004010 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004011
Eric Andersenff9eee42001-06-29 04:57:14 +00004012 if (!anys("$`'\"", cp) &&
Eric Andersen8401eea2004-08-04 19:16:54 +00004013 !anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004014 cp = strsave(cp, areanum);
4015 if (f & DOTRIM)
4016 unquote(cp);
4017 *wbp = addword(cp, *wbp);
Eric Andersen8401eea2004-08-04 19:16:54 +00004018 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004019 }
4020 if (newenv(setjmp(errpt = ev)) == 0) {
4021 PUSHIO(aword, cp, strchar);
4022 e.iobase = e.iop;
4023 while ((cp = blank(f)) && gflg == 0) {
4024 e.linep = cp;
4025 cp = strsave(cp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00004026 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004027 if (f & DOTRIM)
4028 unquote(cp);
4029 *wbp = addword(cp, *wbp);
4030 } else
4031 *wbp = glob(cp, *wbp);
4032 }
4033 quitenv();
4034 } else
4035 gflg = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00004036 return (gflg == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004037}
4038
4039/*
4040 * Blank interpretation and quoting
4041 */
Eric Andersen8401eea2004-08-04 19:16:54 +00004042static char *blank(f)
Eric Andersenff9eee42001-06-29 04:57:14 +00004043int f;
4044{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004045 REGISTER int c, c1;
4046 REGISTER char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004047 int scanequals, foundequals;
4048
Eric Andersen12de6cf2004-08-04 19:19:10 +00004049 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
4050
Eric Andersenff9eee42001-06-29 04:57:14 +00004051 sp = e.linep;
4052 scanequals = f & DOKEY;
4053 foundequals = 0;
4054
Eric Andersen8401eea2004-08-04 19:16:54 +00004055 loop:
Eric Andersenff9eee42001-06-29 04:57:14 +00004056 switch (c = subgetc('"', foundequals)) {
4057 case 0:
4058 if (sp == e.linep)
Eric Andersen8401eea2004-08-04 19:16:54 +00004059 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004060 *e.linep++ = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004061 return (sp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004062
4063 default:
4064 if (f & DOBLANK && any(c, ifs->value))
4065 goto loop;
4066 break;
4067
4068 case '"':
4069 case '\'':
4070 scanequals = 0;
4071 if (INSUB())
4072 break;
4073 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
4074 if (c == 0)
4075 break;
4076 if (c == '\'' || !any(c, "$`\""))
4077 c |= QUOTE;
4078 *e.linep++ = c;
4079 }
4080 c = 0;
4081 }
4082 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00004083 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00004084 scanequals = 0;
4085 for (;;) {
4086 c = subgetc('"', foundequals);
4087 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00004088 f & (DOBLANK && any(c, ifs->value)) ||
4089 (!INSUB() && any(c, "\"'"))) {
4090 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004091 unget(c);
4092 if (any(c, "\"'"))
4093 goto loop;
4094 break;
4095 }
4096 if (scanequals) {
4097 if (c == '=') {
4098 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00004099 scanequals = 0;
4100 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00004101 scanequals = 0;
4102 }
4103 *e.linep++ = c;
4104 }
4105 *e.linep++ = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004106 return (sp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004107}
4108
4109/*
4110 * Get characters, substituting for ` and $
4111 */
Eric Andersen8401eea2004-08-04 19:16:54 +00004112static int subgetc(ec, quoted)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004113REGISTER char ec;
Eric Andersenff9eee42001-06-29 04:57:14 +00004114int quoted;
4115{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004116 REGISTER char c;
4117
4118 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00004119
Eric Andersen8401eea2004-08-04 19:16:54 +00004120 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00004121 c = my_getc(ec);
4122 if (!INSUB() && ec != '\'') {
4123 if (c == '`') {
4124 if (grave(quoted) == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00004125 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004126 e.iop->task = XGRAVE;
4127 goto again;
4128 }
4129 if (c == '$' && (c = dollar(quoted)) == 0) {
4130 e.iop->task = XDOLL;
4131 goto again;
4132 }
4133 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004134 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004135}
4136
4137/*
4138 * Prepare to generate the string returned by ${} substitution.
4139 */
Eric Andersen8401eea2004-08-04 19:16:54 +00004140static int dollar(quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004141int quoted;
4142{
4143 int otask;
4144 struct io *oiop;
4145 char *dolp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004146 REGISTER char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004147 struct var *vp;
4148
Eric Andersen12de6cf2004-08-04 19:19:10 +00004149 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
4150
Eric Andersenff9eee42001-06-29 04:57:14 +00004151 c = readc();
4152 s = e.linep;
4153 if (c != '{') {
4154 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00004155 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00004156 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00004157 if (e.linep < elinep)
4158 *e.linep++ = c;
4159 unget(c);
4160 }
4161 c = 0;
4162 } else {
4163 oiop = e.iop;
4164 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004165
Eric Andersenff9eee42001-06-29 04:57:14 +00004166 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00004167 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004168 if (e.linep < elinep)
4169 *e.linep++ = c;
4170 if (oiop == e.iop)
4171 e.iop->task = otask;
4172 if (c != '}') {
4173 err("unclosed ${");
4174 gflg++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004175 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004176 }
4177 }
4178 if (e.linep >= elinep) {
4179 err("string in ${} too long");
4180 gflg++;
4181 e.linep -= 10;
4182 }
4183 *e.linep = 0;
4184 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00004185 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004186 if (any(*cp, "=-+?")) {
4187 c = *cp;
4188 *cp++ = 0;
4189 break;
4190 }
4191 if (s[1] == 0 && (*s == '*' || *s == '@')) {
4192 if (dolc > 1) {
4193 /* currently this does not distinguish $* and $@ */
4194 /* should check dollar */
4195 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00004196 PUSHIO(awordlist, dolv + 1, dolchar);
4197 return (0);
4198 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00004199 s[0] = '1';
4200 s[1] = 0;
4201 }
4202 }
4203 vp = lookup(s);
4204 if ((dolp = vp->value) == null) {
4205 switch (c) {
4206 case '=':
4207 if (isdigit(*s)) {
4208 err("cannot use ${...=...} with $n");
4209 gflg++;
4210 break;
4211 }
4212 setval(vp, cp);
4213 dolp = vp->value;
4214 break;
4215
4216 case '-':
4217 dolp = strsave(cp, areanum);
4218 break;
4219
4220 case '?':
4221 if (*cp == 0) {
4222 prs("missing value for ");
4223 err(s);
4224 } else
4225 err(cp);
4226 gflg++;
4227 break;
4228 }
4229 } else if (c == '+')
4230 dolp = strsave(cp, areanum);
4231 if (flag['u'] && dolp == null) {
4232 prs("unset variable: ");
4233 err(s);
4234 gflg++;
4235 }
4236 e.linep = s;
4237 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Eric Andersen8401eea2004-08-04 19:16:54 +00004238 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004239}
4240
4241/*
4242 * Run the command in `...` and read its output.
4243 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004244
Eric Andersen8401eea2004-08-04 19:16:54 +00004245static int grave(quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004246int quoted;
4247{
Eric Andersenff9eee42001-06-29 04:57:14 +00004248 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004249 REGISTER int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004250 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004251 int pf[2];
Eric Andersen737f5fb2003-03-14 16:05:59 +00004252 static char child_cmd[LINELIM];
4253 char *src;
4254 char *dest;
4255 int count;
4256 int ignore;
4257 int ignore_once;
4258 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004259 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004260
4261#if __GNUC__
4262 /* Avoid longjmp clobbering */
4263 (void) &cp;
4264#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004265
Eric Andersenff9eee42001-06-29 04:57:14 +00004266 for (cp = e.iop->argp->aword; *cp != '`'; cp++)
4267 if (*cp == 0) {
4268 err("no closing `");
Eric Andersen8401eea2004-08-04 19:16:54 +00004269 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004270 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004271
4272 /* string copy with dollar expansion */
4273 src = e.iop->argp->aword;
4274 dest = child_cmd;
4275 count = 0;
4276 ignore = 0;
4277 ignore_once = 0;
4278 while ((*src != '`') && (count < LINELIM)) {
4279 if (*src == '\'')
4280 ignore = !ignore;
4281 if (*src == '\\')
4282 ignore_once = 1;
4283 if (*src == '$' && !ignore && !ignore_once) {
4284 struct var *vp;
4285 char var_name[LINELIM];
4286 char alt_value[LINELIM];
4287 int var_index = 0;
4288 int alt_index = 0;
4289 char operator = 0;
4290 int braces = 0;
4291 char *value;
4292
4293 src++;
4294 if (*src == '{') {
4295 braces = 1;
4296 src++;
4297 }
4298
4299 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00004300 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00004301 var_name[var_index++] = *src++;
4302 var_name[var_index] = 0;
4303
4304 if (braces) {
4305 switch (*src) {
4306 case '}':
4307 break;
4308 case '-':
4309 case '=':
4310 case '+':
4311 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004312 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004313 break;
4314 default:
4315 err("unclosed ${\n");
Eric Andersen8401eea2004-08-04 19:16:54 +00004316 return (0);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004317 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004318 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004319 src++;
4320 while (*src && (*src != '}')) {
4321 alt_value[alt_index++] = *src++;
4322 }
4323 alt_value[alt_index] = 0;
4324 if (*src != '}') {
4325 err("unclosed ${\n");
Eric Andersen8401eea2004-08-04 19:16:54 +00004326 return (0);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004327 }
4328 }
4329 src++;
4330 }
4331
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004332 if (isalpha(*var_name)) {
4333 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004334
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004335 char *namep = var_name;
4336
4337 *dest++ = '$';
4338 if (braces)
4339 *dest++ = '{';
4340 while (*namep)
4341 *dest++ = *namep++;
4342 if (operator) {
4343 char *altp = alt_value;
4344 *dest++ = operator;
4345 while (*altp)
4346 *dest++ = *altp++;
4347 }
4348 if (braces)
4349 *dest++ = '}';
4350
4351 wb = addword(lookup(var_name)->name, wb);
4352 } else {
4353 /* expand */
4354
4355 vp = lookup(var_name);
4356 if (vp->value != null)
4357 value = (operator == '+') ?
4358 alt_value : vp->value;
4359 else if (operator == '?') {
4360 err(alt_value);
4361 return (0);
4362 } else if (alt_index && (operator != '+')) {
4363 value = alt_value;
4364 if (operator == '=')
4365 setval(vp, value);
4366 } else
4367 continue;
4368
4369 while (*value && (count < LINELIM)) {
4370 *dest++ = *value++;
4371 count++;
4372 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004373 }
4374 } else {
4375 *dest++ = *src++;
4376 count++;
4377 ignore_once = 0;
4378 }
4379 }
4380 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004381
Eric Andersenff9eee42001-06-29 04:57:14 +00004382 if (openpipe(pf) < 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00004383 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004384
Eric Andersen8401eea2004-08-04 19:16:54 +00004385 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004386
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004387 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004388
Eric Andersen737f5fb2003-03-14 16:05:59 +00004389 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004390 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004391 err((char *) bb_msg_memory_exhausted);
4392 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004393 }
4394 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004395 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004396 e.iop->argp->aword = ++cp;
4397 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004398 PUSHIO(afile, remap(pf[0]),
4399 (int (*)(struct ioarg *)) ((quoted) ? qgravechar :
4400 gravechar));
4401 return (1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004402 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004403 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004404 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004405 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004406 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4407 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004408
Eric Andersenff9eee42001-06-29 04:57:14 +00004409 dup2(pf[1], 1);
4410 closepipe(pf);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004411
Eric Andersen8401eea2004-08-04 19:16:54 +00004412 argument_list[0] = (char *) DEFAULT_SHELL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004413 argument_list[1] = "-c";
4414 argument_list[2] = child_cmd;
4415 argument_list[3] = 0;
4416
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004417 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004418 prs(argument_list[0]);
4419 prs(": ");
4420 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004421 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004422}
4423
Eric Andersen737f5fb2003-03-14 16:05:59 +00004424
Eric Andersen8401eea2004-08-04 19:16:54 +00004425static char *unquote(as)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004426REGISTER char *as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004427{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004428 REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004429
4430 if ((s = as) != NULL)
4431 while (*s)
4432 *s++ &= ~QUOTE;
Eric Andersen8401eea2004-08-04 19:16:54 +00004433 return (as);
Eric Andersenff9eee42001-06-29 04:57:14 +00004434}
4435
4436/* -------- glob.c -------- */
4437
4438/*
4439 * glob
4440 */
4441
4442#define scopy(x) strsave((x), areanum)
4443#define BLKSIZ 512
4444#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4445
Eric Andersen8401eea2004-08-04 19:16:54 +00004446static struct wdblock *cl, *nl;
4447static char spcl[] = "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004448
Eric Andersen8401eea2004-08-04 19:16:54 +00004449static struct wdblock *glob(cp, wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004450char *cp;
4451struct wdblock *wb;
4452{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004453 REGISTER int i;
4454 REGISTER char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004455
4456 if (cp == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00004457 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004458 i = 0;
4459 for (pp = cp; *pp; pp++)
4460 if (any(*pp, spcl))
4461 i++;
4462 else if (!any(*pp & ~QUOTE, spcl))
4463 *pp &= ~QUOTE;
4464 if (i != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004465 for (cl = addword(scopy(cp), (struct wdblock *) 0); anyspcl(cl);
4466 cl = nl) {
4467 nl = newword(cl->w_nword * 2);
4468 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004469 for (pp = cl->w_words[i]; *pp; pp++)
4470 if (any(*pp, spcl)) {
4471 globname(cl->w_words[i], pp);
4472 break;
4473 }
4474 if (*pp == '\0')
4475 nl = addword(scopy(cl->w_words[i]), nl);
4476 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004477 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004478 DELETE(cl->w_words[i]);
4479 DELETE(cl);
4480 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004481 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004482 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004483 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004484 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004485 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004486 wb = addword(cl->w_words[i], wb);
4487 DELETE(cl);
Eric Andersen8401eea2004-08-04 19:16:54 +00004488 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004489 }
4490 }
4491 wb = addword(unquote(cp), wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00004492 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004493}
4494
Eric Andersen8401eea2004-08-04 19:16:54 +00004495static void globname(we, pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004496char *we;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004497REGISTER char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004498{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004499 REGISTER char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004500 char *name, *gp, *dp;
4501 int k;
4502 DIR *dirp;
4503 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004504 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004505 struct stat dbuf;
4506
4507 for (np = we; np != pp; pp--)
4508 if (pp[-1] == '/')
4509 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004510 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004511 *cp++ = *np++;
4512 *cp++ = '.';
4513 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004514 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004515 *cp++ = *np++;
4516 *cp = '\0';
4517 dirp = opendir(dp);
4518 if (dirp == 0) {
4519 DELETE(dp);
4520 DELETE(gp);
4521 return;
4522 }
4523 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004524 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004525 /* XXX Hmmm... What this could be? (abial) */
4526 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004527 if (ent[j].d_ino == 0)
4528 continue;
4529 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004530 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004531 if (dname[0] == '.')
4532 if (*gp != '.')
4533 continue;
4534 for (k = 0; k < NAME_MAX; k++)
4535 if (any(dname[k], spcl))
4536 dname[k] |= QUOTE;
4537 if (gmatch(dname, gp)) {
4538 name = generate(we, pp, dname, np);
4539 if (*np && !anys(np, spcl)) {
4540 if (stat(name, &dbuf)) {
4541 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004542 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004543 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004544 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004545 nl = addword(name, nl);
4546 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004547 }
4548 closedir(dirp);
4549 DELETE(dp);
4550 DELETE(gp);
4551}
4552
4553/*
4554 * generate a pathname as below.
4555 * start..end1 / middle end
4556 * the slashes come for free
4557 */
Eric Andersen8401eea2004-08-04 19:16:54 +00004558static char *generate(start1, end1, middle, end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004559char *start1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004560REGISTER char *end1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004561char *middle, *end;
4562{
4563 char *p;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004564 REGISTER char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004565
Eric Andersen8401eea2004-08-04 19:16:54 +00004566 p = op =
4567 space((int) (end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004568 for (xp = start1; xp != end1;)
4569 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004570 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004571 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004572 for (xp = end; (*op++ = *xp++) != '\0';);
4573 return (p);
Eric Andersenff9eee42001-06-29 04:57:14 +00004574}
4575
Eric Andersen8401eea2004-08-04 19:16:54 +00004576static int anyspcl(wb)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004577REGISTER struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004578{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004579 REGISTER int i;
4580 REGISTER char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004581
4582 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004583 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004584 if (anys(spcl, *wd++))
Eric Andersen8401eea2004-08-04 19:16:54 +00004585 return (1);
4586 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004587}
4588
Eric Andersen8401eea2004-08-04 19:16:54 +00004589static int xstrcmp(p1, p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004590char *p1, *p2;
4591{
Eric Andersen8401eea2004-08-04 19:16:54 +00004592 return (strcmp(*(char **) p1, *(char **) p2));
Eric Andersenff9eee42001-06-29 04:57:14 +00004593}
4594
4595/* -------- word.c -------- */
4596
Eric Andersen8401eea2004-08-04 19:16:54 +00004597static struct wdblock *newword(nw)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004598REGISTER int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004599{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004600 REGISTER struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004601
Eric Andersen8401eea2004-08-04 19:16:54 +00004602 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004603 wb->w_bsize = nw;
4604 wb->w_nword = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004605 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004606}
4607
Eric Andersen8401eea2004-08-04 19:16:54 +00004608static struct wdblock *addword(wd, wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004609char *wd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004610REGISTER struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004611{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004612 REGISTER struct wdblock *wb2;
4613 REGISTER int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004614
4615 if (wb == NULL)
4616 wb = newword(NSTART);
4617 if ((nw = wb->w_nword) >= wb->w_bsize) {
4618 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004619 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4620 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004621 wb2->w_nword = nw;
4622 DELETE(wb);
4623 wb = wb2;
4624 }
4625 wb->w_words[wb->w_nword++] = wd;
Eric Andersen8401eea2004-08-04 19:16:54 +00004626 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004627}
Eric Andersen8401eea2004-08-04 19:16:54 +00004628
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004629static
Eric Andersen8401eea2004-08-04 19:16:54 +00004630char **getwords(wb)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004631REGISTER struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004632{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004633 REGISTER char **wd;
4634 REGISTER int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004635
4636 if (wb == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00004637 return ((char **) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00004638 if (wb->w_nword == 0) {
4639 DELETE(wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00004640 return ((char **) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00004641 }
4642 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004643 memcpy((char *) wd, (char *) wb->w_words, nb);
4644 DELETE(wb); /* perhaps should done by caller */
4645 return (wd);
Eric Andersenff9eee42001-06-29 04:57:14 +00004646}
4647
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004648static int (*func) (char *, char *);
4649static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004650
Eric Andersen8401eea2004-08-04 19:16:54 +00004651static void glob0(a0, a1, a2, a3)
Eric Andersenff9eee42001-06-29 04:57:14 +00004652char *a0;
4653unsigned a1;
4654int a2;
4655int (*a3) (char *, char *);
4656{
4657 func = a3;
4658 globv = a2;
4659 glob1(a0, a0 + a1 * a2);
4660}
4661
Eric Andersen8401eea2004-08-04 19:16:54 +00004662static void glob1(base, lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004663char *base, *lim;
4664{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004665 REGISTER char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004666 int v2;
4667 char *lptr, *hptr;
4668 int c;
4669 unsigned n;
4670
4671
4672 v2 = globv;
4673
Eric Andersen8401eea2004-08-04 19:16:54 +00004674 top:
4675 if ((n = (int) (lim - base)) <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004676 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004677 n = v2 * (n / (2 * v2));
4678 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004679 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004680 j = lim - v2;
4681 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004682 if (i < lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004683 if ((c = (*func) (i, lptr)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004684 glob2(i, lptr -= v2);
4685 continue;
4686 }
4687 if (c < 0) {
4688 i += v2;
4689 continue;
4690 }
4691 }
4692
Eric Andersen8401eea2004-08-04 19:16:54 +00004693 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004694 if (j > hptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004695 if ((c = (*func) (hptr, j)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004696 glob2(hptr += v2, j);
4697 goto begin;
4698 }
4699 if (c > 0) {
4700 if (i == lptr) {
4701 glob3(i, hptr += v2, j);
4702 i = lptr += v2;
4703 goto begin;
4704 }
4705 glob2(i, j);
4706 j -= v2;
4707 i += v2;
4708 continue;
4709 }
4710 j -= v2;
4711 goto begin;
4712 }
4713
4714
4715 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004716 if (lptr - base >= lim - hptr) {
4717 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004718 lim = lptr;
4719 } else {
4720 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004721 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004722 }
4723 goto top;
4724 }
4725
4726
4727 glob3(j, lptr -= v2, i);
4728 j = hptr -= v2;
4729 }
4730}
4731
Eric Andersen8401eea2004-08-04 19:16:54 +00004732static void glob2(i, j)
Eric Andersenff9eee42001-06-29 04:57:14 +00004733char *i, *j;
4734{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004735 REGISTER char *index1, *index2, c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004736 int m;
4737
4738 m = globv;
4739 index1 = i;
4740 index2 = j;
4741 do {
4742 c = *index1;
4743 *index1++ = *index2;
4744 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004745 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004746}
4747
Eric Andersen8401eea2004-08-04 19:16:54 +00004748static void glob3(i, j, k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004749char *i, *j, *k;
4750{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004751 REGISTER char *index1, *index2, *index3;
Eric Andersenff9eee42001-06-29 04:57:14 +00004752 int c;
4753 int m;
4754
4755 m = globv;
4756 index1 = i;
4757 index2 = j;
4758 index3 = k;
4759 do {
4760 c = *index1;
4761 *index1++ = *index3;
4762 *index3++ = *index2;
4763 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004764 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004765}
4766
4767/* -------- io.c -------- */
4768
4769/*
4770 * shell IO
4771 */
4772
Eric Andersen8401eea2004-08-04 19:16:54 +00004773static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004774{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004775 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004776
Eric Andersen8401eea2004-08-04 19:16:54 +00004777 if (e.linep > elinep) {
4778 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004779 err("input line too long");
4780 gflg++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004781 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004782 }
4783 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004784 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004785 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004786 c = readc();
4787 if (c == '\n' && ec != '\"')
Eric Andersen8401eea2004-08-04 19:16:54 +00004788 return (my_getc(ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00004789 c |= QUOTE;
4790 }
4791 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004792 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004793}
4794
Eric Andersen8401eea2004-08-04 19:16:54 +00004795static void unget(c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004796int c;
4797{
4798 if (e.iop >= e.iobase)
4799 e.iop->peekc = c;
4800}
4801
Eric Andersen8401eea2004-08-04 19:16:54 +00004802static int eofc()
Eric Andersenff9eee42001-06-29 04:57:14 +00004803{
Eric Andersen8401eea2004-08-04 19:16:54 +00004804 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004805}
4806
Eric Andersen8401eea2004-08-04 19:16:54 +00004807static int readc()
Eric Andersenff9eee42001-06-29 04:57:14 +00004808{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004809 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004810
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004811 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004812
4813 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004814 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Eric Andersenff9eee42001-06-29 04:57:14 +00004815 if ((c = e.iop->peekc) != '\0') {
4816 e.iop->peekc = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004817 return (c);
4818 } else {
4819 if (e.iop->prev != 0) {
4820 if ((c = (*e.iop->iofn) (e.iop->argp, e.iop)) != '\0') {
4821 if (c == -1) {
4822 e.iop++;
4823 continue;
4824 }
4825 if (e.iop == iostack)
4826 ioecho(c);
4827 return (e.iop->prev = c);
4828 } else if (e.iop->task == XIO && e.iop->prev != '\n') {
4829 e.iop->prev = 0;
4830 if (e.iop == iostack)
4831 ioecho('\n');
4832 return '\n';
4833 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004834 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004835 if (e.iop->task == XIO) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004836 if (multiline) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004837 return e.iop->prev = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004838 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004839 if (interactive && e.iop == iostack + 1) {
4840#ifdef CONFIG_FEATURE_COMMAND_EDITING
4841 current_prompt = prompt->value;
4842#else
4843 prs(prompt->value);
4844#endif
4845 }
4846 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004847 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004848
4849 } /* FOR */
4850
4851 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004852 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Eric Andersen8401eea2004-08-04 19:16:54 +00004853 return (0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004854 }
4855
4856 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004857 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004858
Eric Andersenff9eee42001-06-29 04:57:14 +00004859 /* NOTREACHED */
Eric Andersen8401eea2004-08-04 19:16:54 +00004860 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004861}
4862
Eric Andersen8401eea2004-08-04 19:16:54 +00004863static void ioecho(c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004864char c;
4865{
4866 if (flag['v'])
4867 write(2, &c, sizeof c);
4868}
4869
Eric Andersen12de6cf2004-08-04 19:19:10 +00004870
Eric Andersen8401eea2004-08-04 19:16:54 +00004871static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004872{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004873 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004874 argp->afid, e.iop));
4875
4876 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004877 if (++e.iop >= &iostack[NPUSH]) {
4878 e.iop--;
4879 err("Shell input nested too deeply");
4880 gflg++;
4881 return;
4882 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004883
4884 /* We did not overflow the NPUSH array spots so setup data structs */
4885
4886 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004887
4888 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004889 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004890 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004891
4892 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4893 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4894
4895 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4896
4897 if (e.iop == &iostack[0])
4898 e.iop->argp->afbuf = &mainbuf;
4899 else
4900 e.iop->argp->afbuf = &sharedbuf;
4901
4902 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4903 /* This line appears to be active when running scripts from command line */
4904 if ((isatty(e.iop->argp->afile) == 0)
4905 && (e.iop == &iostack[0]
4906 || lseek(e.iop->argp->afile, 0L, 1) != -1)) {
4907 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4908 bufid = AFID_ID; /* AFID_ID = 0 */
4909
4910 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004911 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004912
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004913 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004914 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004915 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004916 &mainbuf, &sharedbuf, bufid, e.iop));
4917
Eric Andersenff9eee42001-06-29 04:57:14 +00004918 }
4919
Eric Andersen8401eea2004-08-04 19:16:54 +00004920 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004921 e.iop->peekc = 0;
4922 e.iop->xchar = 0;
4923 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004924
Eric Andersenff9eee42001-06-29 04:57:14 +00004925 if (fn == filechar || fn == linechar)
4926 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004927 else if (fn == (int (*)(struct ioarg *)) gravechar
4928 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004929 e.iop->task = XGRAVE;
4930 else
4931 e.iop->task = XOTHER;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004932
4933 return;
Eric Andersenff9eee42001-06-29 04:57:14 +00004934}
4935
Eric Andersen8401eea2004-08-04 19:16:54 +00004936static struct io *setbase(ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004937struct io *ip;
4938{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004939 REGISTER struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004940
4941 xp = e.iobase;
4942 e.iobase = ip;
Eric Andersen8401eea2004-08-04 19:16:54 +00004943 return (xp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004944}
4945
4946/*
4947 * Input generating functions
4948 */
4949
4950/*
4951 * Produce the characters of a string, then a newline, then EOF.
4952 */
Eric Andersen8401eea2004-08-04 19:16:54 +00004953static int nlchar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004954REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00004955{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004956 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004957
4958 if (ap->aword == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00004959 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004960 if ((c = *ap->aword++) == 0) {
4961 ap->aword = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00004962 return ('\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00004963 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004964 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004965}
4966
4967/*
4968 * Given a list of words, produce the characters
4969 * in them, with a space after each word.
4970 */
Eric Andersen8401eea2004-08-04 19:16:54 +00004971static int wdchar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004972REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00004973{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004974 REGISTER char c;
4975 REGISTER char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004976
4977 if ((wl = ap->awordlist) == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00004978 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004979 if (*wl != NULL) {
4980 if ((c = *(*wl)++) != 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00004981 return (c & 0177);
Eric Andersenff9eee42001-06-29 04:57:14 +00004982 ap->awordlist++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004983 return (' ');
Eric Andersenff9eee42001-06-29 04:57:14 +00004984 }
4985 ap->awordlist = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00004986 return ('\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00004987}
4988
4989/*
4990 * Return the characters of a list of words,
4991 * producing a space between them.
4992 */
Eric Andersen8401eea2004-08-04 19:16:54 +00004993static int dolchar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00004994REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00004995{
Eric Andersen12de6cf2004-08-04 19:19:10 +00004996 REGISTER char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004997
4998 if ((wp = *ap->awordlist++) != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004999 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
5000 return (-1);
Eric Andersenff9eee42001-06-29 04:57:14 +00005001 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005002 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00005003}
5004
Eric Andersen8401eea2004-08-04 19:16:54 +00005005static int xxchar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005006REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00005007{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005008 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005009
5010 if (ap->aword == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00005011 return (0);
Eric Andersenff9eee42001-06-29 04:57:14 +00005012 if ((c = *ap->aword++) == '\0') {
5013 ap->aword = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00005014 return (' ');
Eric Andersenff9eee42001-06-29 04:57:14 +00005015 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005016 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00005017}
5018
5019/*
5020 * Produce the characters from a single word (string).
5021 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005022static int strchar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005023REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00005024{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005025 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005026
5027 if (ap->aword == NULL || (c = *ap->aword++) == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00005028 return (0);
5029 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00005030}
5031
5032/*
5033 * Produce quoted characters from a single word (string).
5034 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005035static int qstrchar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005036REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00005037{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005038 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005039
5040 if (ap->aword == NULL || (c = *ap->aword++) == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00005041 return (0);
5042 return (c | QUOTE);
Eric Andersenff9eee42001-06-29 04:57:14 +00005043}
5044
5045/*
5046 * Return the characters from a file.
5047 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005048static int filechar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005049REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00005050{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005051 REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005052 char c;
5053 struct iobuf *bp = ap->afbuf;
5054
5055 if (ap->afid != AFID_NOBUF) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005056 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00005057
Eric Andersen8401eea2004-08-04 19:16:54 +00005058 if (i)
5059 lseek(ap->afile, ap->afpos, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00005060
Eric Andersen8401eea2004-08-04 19:16:54 +00005061 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005062
Eric Andersen8401eea2004-08-04 19:16:54 +00005063 if (i <= 0) {
5064 closef(ap->afile);
5065 return 0;
5066 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00005067
Eric Andersen8401eea2004-08-04 19:16:54 +00005068 bp->id = ap->afid;
5069 bp->ebufp = (bp->bufp = bp->buf) + i;
5070 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00005071
Eric Andersen8401eea2004-08-04 19:16:54 +00005072 ap->afpos++;
5073 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00005074 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00005075#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00005076 if (interactive && isatty(ap->afile)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005077 static char mycommand[BUFSIZ];
5078 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00005079
Eric Andersen8401eea2004-08-04 19:16:54 +00005080 while (size == 0 || position >= size) {
5081 cmdedit_read_input(current_prompt, mycommand);
5082 size = strlen(mycommand);
5083 position = 0;
5084 }
5085 c = mycommand[position];
5086 position++;
5087 return (c);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005088 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00005089#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005090
Eric Andersenff9eee42001-06-29 04:57:14 +00005091 {
Eric Andersen7467c8d2001-07-12 20:26:32 +00005092 i = safe_read(ap->afile, &c, sizeof(c));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005093 return (i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0));
Eric Andersenff9eee42001-06-29 04:57:14 +00005094 }
5095}
5096
5097/*
5098 * Return the characters from a here temp file.
5099 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005100static int herechar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005101REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00005102{
5103 char c;
5104
5105
5106 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
5107 close(ap->afile);
5108 c = 0;
5109 }
5110 return (c);
5111
5112}
5113
5114/*
5115 * Return the characters produced by a process (`...`).
5116 * Quote them if required, and remove any trailing newline characters.
5117 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005118static int gravechar(ap, iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00005119struct ioarg *ap;
5120struct io *iop;
5121{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005122 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005123
Eric Andersen8401eea2004-08-04 19:16:54 +00005124 if ((c = qgravechar(ap, iop) & ~QUOTE) == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00005125 c = ' ';
Eric Andersen8401eea2004-08-04 19:16:54 +00005126 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00005127}
5128
Eric Andersen8401eea2004-08-04 19:16:54 +00005129static int qgravechar(ap, iop)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005130REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00005131struct io *iop;
5132{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005133 REGISTER int c;
5134
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005135 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00005136
5137 if (iop->xchar) {
5138 if (iop->nlcount) {
5139 iop->nlcount--;
Eric Andersen8401eea2004-08-04 19:16:54 +00005140 return ('\n' | QUOTE);
Eric Andersenff9eee42001-06-29 04:57:14 +00005141 }
5142 c = iop->xchar;
5143 iop->xchar = 0;
5144 } else if ((c = filechar(ap)) == '\n') {
5145 iop->nlcount = 1;
5146 while ((c = filechar(ap)) == '\n')
5147 iop->nlcount++;
5148 iop->xchar = c;
5149 if (c == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00005150 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00005151 iop->nlcount--;
5152 c = '\n';
5153 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005154 return (c != 0 ? c | QUOTE : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00005155}
5156
5157/*
5158 * Return a single command (usually the first line) from a file.
5159 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005160static int linechar(ap)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005161REGISTER struct ioarg *ap;
Eric Andersenff9eee42001-06-29 04:57:14 +00005162{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005163 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005164
5165 if ((c = filechar(ap)) == '\n') {
5166 if (!multiline) {
5167 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00005168 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00005169 }
5170 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005171 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00005172}
5173
Eric Andersen8401eea2004-08-04 19:16:54 +00005174static void prs(s)
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +00005175REGISTER const char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00005176{
5177 if (*s)
5178 write(2, s, strlen(s));
5179}
5180
Eric Andersen8401eea2004-08-04 19:16:54 +00005181static void prn(u)
Eric Andersenff9eee42001-06-29 04:57:14 +00005182unsigned u;
5183{
Eric Andersen737f5fb2003-03-14 16:05:59 +00005184 prs(itoa(u));
Eric Andersenff9eee42001-06-29 04:57:14 +00005185}
5186
Eric Andersen8401eea2004-08-04 19:16:54 +00005187static void closef(i)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005188REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005189{
5190 if (i > 2)
5191 close(i);
5192}
5193
Eric Andersen8401eea2004-08-04 19:16:54 +00005194static void closeall()
Eric Andersenff9eee42001-06-29 04:57:14 +00005195{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005196 REGISTER int u;
Eric Andersenff9eee42001-06-29 04:57:14 +00005197
Eric Andersen8401eea2004-08-04 19:16:54 +00005198 for (u = NUFILE; u < NOFILE;)
Eric Andersenff9eee42001-06-29 04:57:14 +00005199 close(u++);
5200}
5201
Eric Andersen12de6cf2004-08-04 19:19:10 +00005202
Eric Andersenff9eee42001-06-29 04:57:14 +00005203/*
5204 * remap fd into Shell's fd space
5205 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005206static int remap(fd)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005207REGISTER int fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00005208{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005209 REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005210 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00005211 int newfd;
5212
5213
5214 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00005215
5216 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005217 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00005218 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005219
Eric Andersenff9eee42001-06-29 04:57:14 +00005220 do {
5221 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005222 newfd = dup(fd);
5223 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00005224 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00005225
Eric Andersen8401eea2004-08-04 19:16:54 +00005226 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00005227 if (map[i])
5228 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00005229
Eric Andersenff9eee42001-06-29 04:57:14 +00005230 if (fd < 0)
5231 err("too many files open in shell");
5232 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00005233
Eric Andersen8401eea2004-08-04 19:16:54 +00005234 return (fd);
Eric Andersenff9eee42001-06-29 04:57:14 +00005235}
5236
Eric Andersen8401eea2004-08-04 19:16:54 +00005237static int openpipe(pv)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005238REGISTER int *pv;
Eric Andersenff9eee42001-06-29 04:57:14 +00005239{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005240 REGISTER int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005241
5242 if ((i = pipe(pv)) < 0)
5243 err("can't create pipe - try again");
Eric Andersen8401eea2004-08-04 19:16:54 +00005244 return (i);
Eric Andersenff9eee42001-06-29 04:57:14 +00005245}
5246
Eric Andersen8401eea2004-08-04 19:16:54 +00005247static void closepipe(pv)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005248REGISTER int *pv;
Eric Andersenff9eee42001-06-29 04:57:14 +00005249{
5250 if (pv != NULL) {
5251 close(*pv++);
5252 close(*pv);
5253 }
5254}
5255
5256/* -------- here.c -------- */
5257
5258/*
5259 * here documents
5260 */
5261
Eric Andersen8401eea2004-08-04 19:16:54 +00005262static void markhere(s, iop)
Eric Andersen12de6cf2004-08-04 19:19:10 +00005263REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00005264struct ioword *iop;
5265{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005266 REGISTER struct here *h, *lh;
5267
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005268 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00005269
5270 h = (struct here *) space(sizeof(struct here));
5271 if (h == 0)
5272 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005273
Eric Andersenff9eee42001-06-29 04:57:14 +00005274 h->h_tag = evalstr(s, DOSUB);
5275 if (h->h_tag == 0)
5276 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005277
Eric Andersenff9eee42001-06-29 04:57:14 +00005278 h->h_iop = iop;
5279 iop->io_name = 0;
5280 h->h_next = NULL;
5281 if (inhere == 0)
5282 inhere = h;
5283 else
Eric Andersen8401eea2004-08-04 19:16:54 +00005284 for (lh = inhere; lh != NULL; lh = lh->h_next)
Eric Andersenff9eee42001-06-29 04:57:14 +00005285 if (lh->h_next == 0) {
5286 lh->h_next = h;
5287 break;
5288 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005289 iop->io_flag |= IOHERE | IOXHERE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005290 for (s = h->h_tag; *s; s++)
5291 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005292 iop->io_flag &= ~IOXHERE;
5293 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005294 }
5295 h->h_dosub = iop->io_flag & IOXHERE;
5296}
5297
Eric Andersen8401eea2004-08-04 19:16:54 +00005298static void gethere()
Eric Andersenff9eee42001-06-29 04:57:14 +00005299{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005300 REGISTER struct here *h, *hp;
5301
5302 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005303
5304 /* Scan here files first leaving inhere list in place */
5305 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00005306 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00005307
5308 /* Make inhere list active - keep list intact for scraphere */
5309 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005310 hp->h_next = acthere;
5311 acthere = inhere;
5312 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00005313 }
5314}
5315
Eric Andersen8401eea2004-08-04 19:16:54 +00005316static void readhere(name, s, ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00005317char **name;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005318REGISTER char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00005319int ec;
5320{
5321 int tf;
5322 char tname[30] = ".msh_XXXXXX";
Eric Andersen12de6cf2004-08-04 19:19:10 +00005323 REGISTER int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005324 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00005325 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00005326 char *thenext;
5327
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005328 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005329
Eric Andersenff9eee42001-06-29 04:57:14 +00005330 tf = mkstemp(tname);
5331 if (tf < 0)
5332 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005333
Eric Andersenff9eee42001-06-29 04:57:14 +00005334 *name = strsave(tname, areanum);
5335 if (newenv(setjmp(errpt = ev)) != 0)
5336 unlink(tname);
5337 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00005338 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00005339 e.iobase = e.iop;
5340 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005341 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00005342#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00005343 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00005344#else
Eric Andersen8401eea2004-08-04 19:16:54 +00005345 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00005346#endif
5347 }
5348 thenext = myline;
5349 while ((c = my_getc(ec)) != '\n' && c) {
5350 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00005351 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005352 if (thenext >= &myline[LINELIM]) {
5353 c = 0;
5354 break;
5355 }
5356 *thenext++ = c;
5357 }
5358 *thenext = 0;
5359 if (strcmp(s, myline) == 0 || c == 0)
5360 break;
5361 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00005362 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00005363 }
5364 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005365 prs("here document `");
5366 prs(s);
5367 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00005368 }
5369 quitenv();
5370 }
5371 close(tf);
5372}
5373
5374/*
5375 * open here temp file.
5376 * if unquoted here, expand here temp file into second temp file.
5377 */
Eric Andersen8401eea2004-08-04 19:16:54 +00005378static int herein(hname, xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005379char *hname;
5380int xdoll;
5381{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005382 REGISTER int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005383 int tf;
5384
5385#if __GNUC__
5386 /* Avoid longjmp clobbering */
5387 (void) &tf;
5388#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005389 if (hname == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00005390 return (-1);
Eric Andersen12de6cf2004-08-04 19:19:10 +00005391
5392 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5393
Eric Andersenff9eee42001-06-29 04:57:14 +00005394 hf = open(hname, 0);
5395 if (hf < 0)
5396 return (-1);
Eric Andersen12de6cf2004-08-04 19:19:10 +00005397
Eric Andersenff9eee42001-06-29 04:57:14 +00005398 if (xdoll) {
5399 char c;
5400 char tname[30] = ".msh_XXXXXX";
5401 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005402
Eric Andersenff9eee42001-06-29 04:57:14 +00005403 tf = mkstemp(tname);
5404 if (tf < 0)
5405 return (-1);
5406 if (newenv(setjmp(errpt = ev)) == 0) {
5407 PUSHIO(afile, hf, herechar);
5408 setbase(e.iop);
5409 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005410 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005411 write(tf, &c, sizeof c);
5412 }
5413 quitenv();
5414 } else
5415 unlink(tname);
5416 close(tf);
5417 tf = open(tname, 0);
5418 unlink(tname);
5419 return (tf);
5420 } else
5421 return (hf);
5422}
5423
Eric Andersen8401eea2004-08-04 19:16:54 +00005424static void scraphere()
Eric Andersenff9eee42001-06-29 04:57:14 +00005425{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005426 REGISTER struct here *h;
5427
5428 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005429
5430 for (h = inhere; h != NULL; h = h->h_next) {
5431 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005432 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005433 }
5434 inhere = NULL;
5435}
5436
5437/* unlink here temp files before a freearea(area) */
Eric Andersen8401eea2004-08-04 19:16:54 +00005438static void freehere(area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005439int area;
5440{
Eric Andersen12de6cf2004-08-04 19:19:10 +00005441 REGISTER struct here *h, *hl;
5442
5443 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005444
5445 hl = NULL;
5446 for (h = acthere; h != NULL; h = h->h_next)
5447 if (getarea((char *) h) >= area) {
5448 if (h->h_iop->io_name != NULL)
5449 unlink(h->h_iop->io_name);
5450 if (hl == NULL)
5451 acthere = h->h_next;
5452 else
5453 hl->h_next = h->h_next;
5454 } else
5455 hl = h;
5456}
5457
5458
5459
5460/*
5461 * Copyright (c) 1987,1997, Prentice Hall
5462 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005463 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005464 * Redistribution and use of the MINIX operating system in source and
5465 * binary forms, with or without modification, are permitted provided
5466 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005467 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005468 * Redistributions of source code must retain the above copyright
5469 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005470 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005471 * Redistributions in binary form must reproduce the above
5472 * copyright notice, this list of conditions and the following
5473 * disclaimer in the documentation and/or other materials provided
5474 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005475 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005476 * Neither the name of Prentice Hall nor the names of the software
5477 * authors or contributors may be used to endorse or promote
5478 * products derived from this software without specific prior
5479 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005480 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005481 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5482 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5483 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5484 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5485 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5486 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5487 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5488 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5489 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5490 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5491 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5492 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5493 *
5494 */