Commit f3a05c8f944ab2cd832e69a5705708ee7a1797fa

Authored by Rabin Vincent
Committed by Tom Rini
1 parent dee332ffb7

Revert "hush: fix segfault on syntax error"

128059b92 ("hush: fix segfault on syntax error") attempted to fix a
segfault on syntax errors, but it broke Ctrl-C handling, and the
assumption that it made, that rcode could not be -1, is incorrect.
Revert this change.

Reported-by: Stephen Warren <swarren@wwwdotorg.org>
Reported-by: Przemyslaw Marczak <p.marczak@samsung.com>
Signed-off-by: Rabin Vincent <rabin@rab.in>

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

1 /* 1 /*
2 * sh.c -- a prototype Bourne shell grammar parser 2 * sh.c -- a prototype Bourne shell grammar parser
3 * Intended to follow the original Thompson and Ritchie 3 * Intended to follow the original Thompson and Ritchie
4 * "small and simple is beautiful" philosophy, which 4 * "small and simple is beautiful" philosophy, which
5 * incidentally is a good match to today's BusyBox. 5 * incidentally is a good match to today's BusyBox.
6 * 6 *
7 * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org> 7 * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org>
8 * 8 *
9 * Credits: 9 * Credits:
10 * The parser routines proper are all original material, first 10 * The parser routines proper are all original material, first
11 * written Dec 2000 and Jan 2001 by Larry Doolittle. 11 * written Dec 2000 and Jan 2001 by Larry Doolittle.
12 * The execution engine, the builtins, and much of the underlying 12 * The execution engine, the builtins, and much of the underlying
13 * support has been adapted from busybox-0.49pre's lash, 13 * support has been adapted from busybox-0.49pre's lash,
14 * which is Copyright (C) 2000 by Lineo, Inc., and 14 * which is Copyright (C) 2000 by Lineo, Inc., and
15 * written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>. 15 * written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>.
16 * That, in turn, is based in part on ladsh.c, by Michael K. Johnson and 16 * That, in turn, is based in part on ladsh.c, by Michael K. Johnson and
17 * Erik W. Troan, which they placed in the public domain. I don't know 17 * Erik W. Troan, which they placed in the public domain. I don't know
18 * how much of the Johnson/Troan code has survived the repeated rewrites. 18 * how much of the Johnson/Troan code has survived the repeated rewrites.
19 * Other credits: 19 * Other credits:
20 * b_addchr() derived from similar w_addchar function in glibc-2.2 20 * b_addchr() derived from similar w_addchar function in glibc-2.2
21 * setup_redirect(), redirect_opt_num(), and big chunks of main() 21 * setup_redirect(), redirect_opt_num(), and big chunks of main()
22 * and many builtins derived from contributions by Erik Andersen 22 * and many builtins derived from contributions by Erik Andersen
23 * miscellaneous bugfixes from Matt Kraai 23 * miscellaneous bugfixes from Matt Kraai
24 * 24 *
25 * There are two big (and related) architecture differences between 25 * There are two big (and related) architecture differences between
26 * this parser and the lash parser. One is that this version is 26 * this parser and the lash parser. One is that this version is
27 * actually designed from the ground up to understand nearly all 27 * actually designed from the ground up to understand nearly all
28 * of the Bourne grammar. The second, consequential change is that 28 * of the Bourne grammar. The second, consequential change is that
29 * the parser and input reader have been turned inside out. Now, 29 * the parser and input reader have been turned inside out. Now,
30 * the parser is in control, and asks for input as needed. The old 30 * the parser is in control, and asks for input as needed. The old
31 * way had the input reader in control, and it asked for parsing to 31 * way had the input reader in control, and it asked for parsing to
32 * take place as needed. The new way makes it much easier to properly 32 * take place as needed. The new way makes it much easier to properly
33 * handle the recursion implicit in the various substitutions, especially 33 * handle the recursion implicit in the various substitutions, especially
34 * across continuation lines. 34 * across continuation lines.
35 * 35 *
36 * Bash grammar not implemented: (how many of these were in original sh?) 36 * Bash grammar not implemented: (how many of these were in original sh?)
37 * $@ (those sure look like weird quoting rules) 37 * $@ (those sure look like weird quoting rules)
38 * $_ 38 * $_
39 * ! negation operator for pipes 39 * ! negation operator for pipes
40 * &> and >& redirection of stdout+stderr 40 * &> and >& redirection of stdout+stderr
41 * Brace Expansion 41 * Brace Expansion
42 * Tilde Expansion 42 * Tilde Expansion
43 * fancy forms of Parameter Expansion 43 * fancy forms of Parameter Expansion
44 * aliases 44 * aliases
45 * Arithmetic Expansion 45 * Arithmetic Expansion
46 * <(list) and >(list) Process Substitution 46 * <(list) and >(list) Process Substitution
47 * reserved words: case, esac, select, function 47 * reserved words: case, esac, select, function
48 * Here Documents ( << word ) 48 * Here Documents ( << word )
49 * Functions 49 * Functions
50 * Major bugs: 50 * Major bugs:
51 * job handling woefully incomplete and buggy 51 * job handling woefully incomplete and buggy
52 * reserved word execution woefully incomplete and buggy 52 * reserved word execution woefully incomplete and buggy
53 * to-do: 53 * to-do:
54 * port selected bugfixes from post-0.49 busybox lash - done? 54 * port selected bugfixes from post-0.49 busybox lash - done?
55 * finish implementing reserved words: for, while, until, do, done 55 * finish implementing reserved words: for, while, until, do, done
56 * change { and } from special chars to reserved words 56 * change { and } from special chars to reserved words
57 * builtins: break, continue, eval, return, set, trap, ulimit 57 * builtins: break, continue, eval, return, set, trap, ulimit
58 * test magic exec 58 * test magic exec
59 * handle children going into background 59 * handle children going into background
60 * clean up recognition of null pipes 60 * clean up recognition of null pipes
61 * check setting of global_argc and global_argv 61 * check setting of global_argc and global_argv
62 * control-C handling, probably with longjmp 62 * control-C handling, probably with longjmp
63 * follow IFS rules more precisely, including update semantics 63 * follow IFS rules more precisely, including update semantics
64 * figure out what to do with backslash-newline 64 * figure out what to do with backslash-newline
65 * explain why we use signal instead of sigaction 65 * explain why we use signal instead of sigaction
66 * propagate syntax errors, die on resource errors? 66 * propagate syntax errors, die on resource errors?
67 * continuation lines, both explicit and implicit - done? 67 * continuation lines, both explicit and implicit - done?
68 * memory leak finding and plugging - done? 68 * memory leak finding and plugging - done?
69 * more testing, especially quoting rules and redirection 69 * more testing, especially quoting rules and redirection
70 * document how quoting rules not precisely followed for variable assignments 70 * document how quoting rules not precisely followed for variable assignments
71 * maybe change map[] to use 2-bit entries 71 * maybe change map[] to use 2-bit entries
72 * (eventually) remove all the printf's 72 * (eventually) remove all the printf's
73 * 73 *
74 * SPDX-License-Identifier: GPL-2.0+ 74 * SPDX-License-Identifier: GPL-2.0+
75 */ 75 */
76 76
77 #define __U_BOOT__ 77 #define __U_BOOT__
78 #ifdef __U_BOOT__ 78 #ifdef __U_BOOT__
79 #include <malloc.h> /* malloc, free, realloc*/ 79 #include <malloc.h> /* malloc, free, realloc*/
80 #include <linux/ctype.h> /* isalpha, isdigit */ 80 #include <linux/ctype.h> /* isalpha, isdigit */
81 #include <common.h> /* readline */ 81 #include <common.h> /* readline */
82 #include <bootretry.h> 82 #include <bootretry.h>
83 #include <cli.h> 83 #include <cli.h>
84 #include <cli_hush.h> 84 #include <cli_hush.h>
85 #include <command.h> /* find_cmd */ 85 #include <command.h> /* find_cmd */
86 #ifndef CONFIG_SYS_PROMPT_HUSH_PS2 86 #ifndef CONFIG_SYS_PROMPT_HUSH_PS2
87 #define CONFIG_SYS_PROMPT_HUSH_PS2 "> " 87 #define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
88 #endif 88 #endif
89 #endif 89 #endif
90 #ifndef __U_BOOT__ 90 #ifndef __U_BOOT__
91 #include <ctype.h> /* isalpha, isdigit */ 91 #include <ctype.h> /* isalpha, isdigit */
92 #include <unistd.h> /* getpid */ 92 #include <unistd.h> /* getpid */
93 #include <stdlib.h> /* getenv, atoi */ 93 #include <stdlib.h> /* getenv, atoi */
94 #include <string.h> /* strchr */ 94 #include <string.h> /* strchr */
95 #include <stdio.h> /* popen etc. */ 95 #include <stdio.h> /* popen etc. */
96 #include <glob.h> /* glob, of course */ 96 #include <glob.h> /* glob, of course */
97 #include <stdarg.h> /* va_list */ 97 #include <stdarg.h> /* va_list */
98 #include <errno.h> 98 #include <errno.h>
99 #include <fcntl.h> 99 #include <fcntl.h>
100 #include <getopt.h> /* should be pretty obvious */ 100 #include <getopt.h> /* should be pretty obvious */
101 101
102 #include <sys/stat.h> /* ulimit */ 102 #include <sys/stat.h> /* ulimit */
103 #include <sys/types.h> 103 #include <sys/types.h>
104 #include <sys/wait.h> 104 #include <sys/wait.h>
105 #include <signal.h> 105 #include <signal.h>
106 106
107 /* #include <dmalloc.h> */ 107 /* #include <dmalloc.h> */
108 108
109 #if 1 109 #if 1
110 #include "busybox.h" 110 #include "busybox.h"
111 #include "cmdedit.h" 111 #include "cmdedit.h"
112 #else 112 #else
113 #define applet_name "hush" 113 #define applet_name "hush"
114 #include "standalone.h" 114 #include "standalone.h"
115 #define hush_main main 115 #define hush_main main
116 #undef CONFIG_FEATURE_SH_FANCY_PROMPT 116 #undef CONFIG_FEATURE_SH_FANCY_PROMPT
117 #define BB_BANNER 117 #define BB_BANNER
118 #endif 118 #endif
119 #endif 119 #endif
120 #define SPECIAL_VAR_SYMBOL 03 120 #define SPECIAL_VAR_SYMBOL 03
121 #define SUBSTED_VAR_SYMBOL 04 121 #define SUBSTED_VAR_SYMBOL 04
122 #ifndef __U_BOOT__ 122 #ifndef __U_BOOT__
123 #define FLAG_EXIT_FROM_LOOP 1 123 #define FLAG_EXIT_FROM_LOOP 1
124 #define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */ 124 #define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */
125 #define FLAG_REPARSING (1 << 2) /* >= 2nd pass */ 125 #define FLAG_REPARSING (1 << 2) /* >= 2nd pass */
126 126
127 #endif 127 #endif
128 128
129 #ifdef __U_BOOT__ 129 #ifdef __U_BOOT__
130 DECLARE_GLOBAL_DATA_PTR; 130 DECLARE_GLOBAL_DATA_PTR;
131 131
132 #define EXIT_SUCCESS 0 132 #define EXIT_SUCCESS 0
133 #define EOF -1 133 #define EOF -1
134 #define syntax() syntax_err() 134 #define syntax() syntax_err()
135 #define xstrdup strdup 135 #define xstrdup strdup
136 #define error_msg printf 136 #define error_msg printf
137 #else 137 #else
138 typedef enum { 138 typedef enum {
139 REDIRECT_INPUT = 1, 139 REDIRECT_INPUT = 1,
140 REDIRECT_OVERWRITE = 2, 140 REDIRECT_OVERWRITE = 2,
141 REDIRECT_APPEND = 3, 141 REDIRECT_APPEND = 3,
142 REDIRECT_HEREIS = 4, 142 REDIRECT_HEREIS = 4,
143 REDIRECT_IO = 5 143 REDIRECT_IO = 5
144 } redir_type; 144 } redir_type;
145 145
146 /* The descrip member of this structure is only used to make debugging 146 /* The descrip member of this structure is only used to make debugging
147 * output pretty */ 147 * output pretty */
148 struct {int mode; int default_fd; char *descrip;} redir_table[] = { 148 struct {int mode; int default_fd; char *descrip;} redir_table[] = {
149 { 0, 0, "()" }, 149 { 0, 0, "()" },
150 { O_RDONLY, 0, "<" }, 150 { O_RDONLY, 0, "<" },
151 { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" }, 151 { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" },
152 { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" }, 152 { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
153 { O_RDONLY, -1, "<<" }, 153 { O_RDONLY, -1, "<<" },
154 { O_RDWR, 1, "<>" } 154 { O_RDWR, 1, "<>" }
155 }; 155 };
156 #endif 156 #endif
157 157
158 typedef enum { 158 typedef enum {
159 PIPE_SEQ = 1, 159 PIPE_SEQ = 1,
160 PIPE_AND = 2, 160 PIPE_AND = 2,
161 PIPE_OR = 3, 161 PIPE_OR = 3,
162 PIPE_BG = 4, 162 PIPE_BG = 4,
163 } pipe_style; 163 } pipe_style;
164 164
165 /* might eventually control execution */ 165 /* might eventually control execution */
166 typedef enum { 166 typedef enum {
167 RES_NONE = 0, 167 RES_NONE = 0,
168 RES_IF = 1, 168 RES_IF = 1,
169 RES_THEN = 2, 169 RES_THEN = 2,
170 RES_ELIF = 3, 170 RES_ELIF = 3,
171 RES_ELSE = 4, 171 RES_ELSE = 4,
172 RES_FI = 5, 172 RES_FI = 5,
173 RES_FOR = 6, 173 RES_FOR = 6,
174 RES_WHILE = 7, 174 RES_WHILE = 7,
175 RES_UNTIL = 8, 175 RES_UNTIL = 8,
176 RES_DO = 9, 176 RES_DO = 9,
177 RES_DONE = 10, 177 RES_DONE = 10,
178 RES_XXXX = 11, 178 RES_XXXX = 11,
179 RES_IN = 12, 179 RES_IN = 12,
180 RES_SNTX = 13 180 RES_SNTX = 13
181 } reserved_style; 181 } reserved_style;
182 #define FLAG_END (1<<RES_NONE) 182 #define FLAG_END (1<<RES_NONE)
183 #define FLAG_IF (1<<RES_IF) 183 #define FLAG_IF (1<<RES_IF)
184 #define FLAG_THEN (1<<RES_THEN) 184 #define FLAG_THEN (1<<RES_THEN)
185 #define FLAG_ELIF (1<<RES_ELIF) 185 #define FLAG_ELIF (1<<RES_ELIF)
186 #define FLAG_ELSE (1<<RES_ELSE) 186 #define FLAG_ELSE (1<<RES_ELSE)
187 #define FLAG_FI (1<<RES_FI) 187 #define FLAG_FI (1<<RES_FI)
188 #define FLAG_FOR (1<<RES_FOR) 188 #define FLAG_FOR (1<<RES_FOR)
189 #define FLAG_WHILE (1<<RES_WHILE) 189 #define FLAG_WHILE (1<<RES_WHILE)
190 #define FLAG_UNTIL (1<<RES_UNTIL) 190 #define FLAG_UNTIL (1<<RES_UNTIL)
191 #define FLAG_DO (1<<RES_DO) 191 #define FLAG_DO (1<<RES_DO)
192 #define FLAG_DONE (1<<RES_DONE) 192 #define FLAG_DONE (1<<RES_DONE)
193 #define FLAG_IN (1<<RES_IN) 193 #define FLAG_IN (1<<RES_IN)
194 #define FLAG_START (1<<RES_XXXX) 194 #define FLAG_START (1<<RES_XXXX)
195 195
196 /* This holds pointers to the various results of parsing */ 196 /* This holds pointers to the various results of parsing */
197 struct p_context { 197 struct p_context {
198 struct child_prog *child; 198 struct child_prog *child;
199 struct pipe *list_head; 199 struct pipe *list_head;
200 struct pipe *pipe; 200 struct pipe *pipe;
201 #ifndef __U_BOOT__ 201 #ifndef __U_BOOT__
202 struct redir_struct *pending_redirect; 202 struct redir_struct *pending_redirect;
203 #endif 203 #endif
204 reserved_style w; 204 reserved_style w;
205 int old_flag; /* for figuring out valid reserved words */ 205 int old_flag; /* for figuring out valid reserved words */
206 struct p_context *stack; 206 struct p_context *stack;
207 int type; /* define type of parser : ";$" common or special symbol */ 207 int type; /* define type of parser : ";$" common or special symbol */
208 /* How about quoting status? */ 208 /* How about quoting status? */
209 }; 209 };
210 210
211 #ifndef __U_BOOT__ 211 #ifndef __U_BOOT__
212 struct redir_struct { 212 struct redir_struct {
213 redir_type type; /* type of redirection */ 213 redir_type type; /* type of redirection */
214 int fd; /* file descriptor being redirected */ 214 int fd; /* file descriptor being redirected */
215 int dup; /* -1, or file descriptor being duplicated */ 215 int dup; /* -1, or file descriptor being duplicated */
216 struct redir_struct *next; /* pointer to the next redirect in the list */ 216 struct redir_struct *next; /* pointer to the next redirect in the list */
217 glob_t word; /* *word.gl_pathv is the filename */ 217 glob_t word; /* *word.gl_pathv is the filename */
218 }; 218 };
219 #endif 219 #endif
220 220
221 struct child_prog { 221 struct child_prog {
222 #ifndef __U_BOOT__ 222 #ifndef __U_BOOT__
223 pid_t pid; /* 0 if exited */ 223 pid_t pid; /* 0 if exited */
224 #endif 224 #endif
225 char **argv; /* program name and arguments */ 225 char **argv; /* program name and arguments */
226 /* was quoted when parsed; copy of struct o_string.nonnull field */ 226 /* was quoted when parsed; copy of struct o_string.nonnull field */
227 int *argv_nonnull; 227 int *argv_nonnull;
228 #ifdef __U_BOOT__ 228 #ifdef __U_BOOT__
229 int argc; /* number of program arguments */ 229 int argc; /* number of program arguments */
230 #endif 230 #endif
231 struct pipe *group; /* if non-NULL, first in group or subshell */ 231 struct pipe *group; /* if non-NULL, first in group or subshell */
232 #ifndef __U_BOOT__ 232 #ifndef __U_BOOT__
233 int subshell; /* flag, non-zero if group must be forked */ 233 int subshell; /* flag, non-zero if group must be forked */
234 struct redir_struct *redirects; /* I/O redirections */ 234 struct redir_struct *redirects; /* I/O redirections */
235 glob_t glob_result; /* result of parameter globbing */ 235 glob_t glob_result; /* result of parameter globbing */
236 int is_stopped; /* is the program currently running? */ 236 int is_stopped; /* is the program currently running? */
237 struct pipe *family; /* pointer back to the child's parent pipe */ 237 struct pipe *family; /* pointer back to the child's parent pipe */
238 #endif 238 #endif
239 int sp; /* number of SPECIAL_VAR_SYMBOL */ 239 int sp; /* number of SPECIAL_VAR_SYMBOL */
240 int type; 240 int type;
241 }; 241 };
242 242
243 struct pipe { 243 struct pipe {
244 #ifndef __U_BOOT__ 244 #ifndef __U_BOOT__
245 int jobid; /* job number */ 245 int jobid; /* job number */
246 #endif 246 #endif
247 int num_progs; /* total number of programs in job */ 247 int num_progs; /* total number of programs in job */
248 #ifndef __U_BOOT__ 248 #ifndef __U_BOOT__
249 int running_progs; /* number of programs running */ 249 int running_progs; /* number of programs running */
250 char *text; /* name of job */ 250 char *text; /* name of job */
251 char *cmdbuf; /* buffer various argv's point into */ 251 char *cmdbuf; /* buffer various argv's point into */
252 pid_t pgrp; /* process group ID for the job */ 252 pid_t pgrp; /* process group ID for the job */
253 #endif 253 #endif
254 struct child_prog *progs; /* array of commands in pipe */ 254 struct child_prog *progs; /* array of commands in pipe */
255 struct pipe *next; /* to track background commands */ 255 struct pipe *next; /* to track background commands */
256 #ifndef __U_BOOT__ 256 #ifndef __U_BOOT__
257 int stopped_progs; /* number of programs alive, but stopped */ 257 int stopped_progs; /* number of programs alive, but stopped */
258 int job_context; /* bitmask defining current context */ 258 int job_context; /* bitmask defining current context */
259 #endif 259 #endif
260 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ 260 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
261 reserved_style r_mode; /* supports if, for, while, until */ 261 reserved_style r_mode; /* supports if, for, while, until */
262 }; 262 };
263 263
264 #ifndef __U_BOOT__ 264 #ifndef __U_BOOT__
265 struct close_me { 265 struct close_me {
266 int fd; 266 int fd;
267 struct close_me *next; 267 struct close_me *next;
268 }; 268 };
269 #endif 269 #endif
270 270
271 struct variables { 271 struct variables {
272 char *name; 272 char *name;
273 char *value; 273 char *value;
274 int flg_export; 274 int flg_export;
275 int flg_read_only; 275 int flg_read_only;
276 struct variables *next; 276 struct variables *next;
277 }; 277 };
278 278
279 /* globals, connect us to the outside world 279 /* globals, connect us to the outside world
280 * the first three support $?, $#, and $1 */ 280 * the first three support $?, $#, and $1 */
281 #ifndef __U_BOOT__ 281 #ifndef __U_BOOT__
282 char **global_argv; 282 char **global_argv;
283 unsigned int global_argc; 283 unsigned int global_argc;
284 #endif 284 #endif
285 static unsigned int last_return_code; 285 static unsigned int last_return_code;
286 #ifndef __U_BOOT__ 286 #ifndef __U_BOOT__
287 extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ 287 extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
288 #endif 288 #endif
289 289
290 /* "globals" within this file */ 290 /* "globals" within this file */
291 static uchar *ifs; 291 static uchar *ifs;
292 static char map[256]; 292 static char map[256];
293 #ifndef __U_BOOT__ 293 #ifndef __U_BOOT__
294 static int fake_mode; 294 static int fake_mode;
295 static int interactive; 295 static int interactive;
296 static struct close_me *close_me_head; 296 static struct close_me *close_me_head;
297 static const char *cwd; 297 static const char *cwd;
298 static struct pipe *job_list; 298 static struct pipe *job_list;
299 static unsigned int last_bg_pid; 299 static unsigned int last_bg_pid;
300 static unsigned int last_jobid; 300 static unsigned int last_jobid;
301 static unsigned int shell_terminal; 301 static unsigned int shell_terminal;
302 static char *PS1; 302 static char *PS1;
303 static char *PS2; 303 static char *PS2;
304 struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; 304 struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
305 struct variables *top_vars = &shell_ver; 305 struct variables *top_vars = &shell_ver;
306 #else 306 #else
307 static int flag_repeat = 0; 307 static int flag_repeat = 0;
308 static int do_repeat = 0; 308 static int do_repeat = 0;
309 static struct variables *top_vars = NULL ; 309 static struct variables *top_vars = NULL ;
310 #endif /*__U_BOOT__ */ 310 #endif /*__U_BOOT__ */
311 311
312 #define B_CHUNK (100) 312 #define B_CHUNK (100)
313 #define B_NOSPAC 1 313 #define B_NOSPAC 1
314 314
315 typedef struct { 315 typedef struct {
316 char *data; 316 char *data;
317 int length; 317 int length;
318 int maxlen; 318 int maxlen;
319 int quote; 319 int quote;
320 int nonnull; 320 int nonnull;
321 } o_string; 321 } o_string;
322 #define NULL_O_STRING {NULL,0,0,0,0} 322 #define NULL_O_STRING {NULL,0,0,0,0}
323 /* used for initialization: 323 /* used for initialization:
324 o_string foo = NULL_O_STRING; */ 324 o_string foo = NULL_O_STRING; */
325 325
326 /* I can almost use ordinary FILE *. Is open_memstream() universally 326 /* I can almost use ordinary FILE *. Is open_memstream() universally
327 * available? Where is it documented? */ 327 * available? Where is it documented? */
328 struct in_str { 328 struct in_str {
329 const char *p; 329 const char *p;
330 #ifndef __U_BOOT__ 330 #ifndef __U_BOOT__
331 char peek_buf[2]; 331 char peek_buf[2];
332 #endif 332 #endif
333 int __promptme; 333 int __promptme;
334 int promptmode; 334 int promptmode;
335 #ifndef __U_BOOT__ 335 #ifndef __U_BOOT__
336 FILE *file; 336 FILE *file;
337 #endif 337 #endif
338 int (*get) (struct in_str *); 338 int (*get) (struct in_str *);
339 int (*peek) (struct in_str *); 339 int (*peek) (struct in_str *);
340 }; 340 };
341 #define b_getch(input) ((input)->get(input)) 341 #define b_getch(input) ((input)->get(input))
342 #define b_peek(input) ((input)->peek(input)) 342 #define b_peek(input) ((input)->peek(input))
343 343
344 #ifndef __U_BOOT__ 344 #ifndef __U_BOOT__
345 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" 345 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
346 346
347 struct built_in_command { 347 struct built_in_command {
348 char *cmd; /* name */ 348 char *cmd; /* name */
349 char *descr; /* description */ 349 char *descr; /* description */
350 int (*function) (struct child_prog *); /* function ptr */ 350 int (*function) (struct child_prog *); /* function ptr */
351 }; 351 };
352 #endif 352 #endif
353 353
354 /* define DEBUG_SHELL for debugging output (obviously ;-)) */ 354 /* define DEBUG_SHELL for debugging output (obviously ;-)) */
355 #if 0 355 #if 0
356 #define DEBUG_SHELL 356 #define DEBUG_SHELL
357 #endif 357 #endif
358 358
359 /* This should be in utility.c */ 359 /* This should be in utility.c */
360 #ifdef DEBUG_SHELL 360 #ifdef DEBUG_SHELL
361 #ifndef __U_BOOT__ 361 #ifndef __U_BOOT__
362 static void debug_printf(const char *format, ...) 362 static void debug_printf(const char *format, ...)
363 { 363 {
364 va_list args; 364 va_list args;
365 va_start(args, format); 365 va_start(args, format);
366 vfprintf(stderr, format, args); 366 vfprintf(stderr, format, args);
367 va_end(args); 367 va_end(args);
368 } 368 }
369 #else 369 #else
370 #define debug_printf(fmt,args...) printf (fmt ,##args) 370 #define debug_printf(fmt,args...) printf (fmt ,##args)
371 #endif 371 #endif
372 #else 372 #else
373 static inline void debug_printf(const char *format, ...) { } 373 static inline void debug_printf(const char *format, ...) { }
374 #endif 374 #endif
375 #define final_printf debug_printf 375 #define final_printf debug_printf
376 376
377 #ifdef __U_BOOT__ 377 #ifdef __U_BOOT__
378 static void syntax_err(void) { 378 static void syntax_err(void) {
379 printf("syntax error\n"); 379 printf("syntax error\n");
380 } 380 }
381 #else 381 #else
382 static void __syntax(char *file, int line) { 382 static void __syntax(char *file, int line) {
383 error_msg("syntax error %s:%d", file, line); 383 error_msg("syntax error %s:%d", file, line);
384 } 384 }
385 #define syntax() __syntax(__FILE__, __LINE__) 385 #define syntax() __syntax(__FILE__, __LINE__)
386 #endif 386 #endif
387 387
388 #ifdef __U_BOOT__ 388 #ifdef __U_BOOT__
389 static void *xmalloc(size_t size); 389 static void *xmalloc(size_t size);
390 static void *xrealloc(void *ptr, size_t size); 390 static void *xrealloc(void *ptr, size_t size);
391 #else 391 #else
392 /* Index of subroutines: */ 392 /* Index of subroutines: */
393 /* function prototypes for builtins */ 393 /* function prototypes for builtins */
394 static int builtin_cd(struct child_prog *child); 394 static int builtin_cd(struct child_prog *child);
395 static int builtin_env(struct child_prog *child); 395 static int builtin_env(struct child_prog *child);
396 static int builtin_eval(struct child_prog *child); 396 static int builtin_eval(struct child_prog *child);
397 static int builtin_exec(struct child_prog *child); 397 static int builtin_exec(struct child_prog *child);
398 static int builtin_exit(struct child_prog *child); 398 static int builtin_exit(struct child_prog *child);
399 static int builtin_export(struct child_prog *child); 399 static int builtin_export(struct child_prog *child);
400 static int builtin_fg_bg(struct child_prog *child); 400 static int builtin_fg_bg(struct child_prog *child);
401 static int builtin_help(struct child_prog *child); 401 static int builtin_help(struct child_prog *child);
402 static int builtin_jobs(struct child_prog *child); 402 static int builtin_jobs(struct child_prog *child);
403 static int builtin_pwd(struct child_prog *child); 403 static int builtin_pwd(struct child_prog *child);
404 static int builtin_read(struct child_prog *child); 404 static int builtin_read(struct child_prog *child);
405 static int builtin_set(struct child_prog *child); 405 static int builtin_set(struct child_prog *child);
406 static int builtin_shift(struct child_prog *child); 406 static int builtin_shift(struct child_prog *child);
407 static int builtin_source(struct child_prog *child); 407 static int builtin_source(struct child_prog *child);
408 static int builtin_umask(struct child_prog *child); 408 static int builtin_umask(struct child_prog *child);
409 static int builtin_unset(struct child_prog *child); 409 static int builtin_unset(struct child_prog *child);
410 static int builtin_not_written(struct child_prog *child); 410 static int builtin_not_written(struct child_prog *child);
411 #endif 411 #endif
412 /* o_string manipulation: */ 412 /* o_string manipulation: */
413 static int b_check_space(o_string *o, int len); 413 static int b_check_space(o_string *o, int len);
414 static int b_addchr(o_string *o, int ch); 414 static int b_addchr(o_string *o, int ch);
415 static void b_reset(o_string *o); 415 static void b_reset(o_string *o);
416 static int b_addqchr(o_string *o, int ch, int quote); 416 static int b_addqchr(o_string *o, int ch, int quote);
417 #ifndef __U_BOOT__ 417 #ifndef __U_BOOT__
418 static int b_adduint(o_string *o, unsigned int i); 418 static int b_adduint(o_string *o, unsigned int i);
419 #endif 419 #endif
420 /* in_str manipulations: */ 420 /* in_str manipulations: */
421 static int static_get(struct in_str *i); 421 static int static_get(struct in_str *i);
422 static int static_peek(struct in_str *i); 422 static int static_peek(struct in_str *i);
423 static int file_get(struct in_str *i); 423 static int file_get(struct in_str *i);
424 static int file_peek(struct in_str *i); 424 static int file_peek(struct in_str *i);
425 #ifndef __U_BOOT__ 425 #ifndef __U_BOOT__
426 static void setup_file_in_str(struct in_str *i, FILE *f); 426 static void setup_file_in_str(struct in_str *i, FILE *f);
427 #else 427 #else
428 static void setup_file_in_str(struct in_str *i); 428 static void setup_file_in_str(struct in_str *i);
429 #endif 429 #endif
430 static void setup_string_in_str(struct in_str *i, const char *s); 430 static void setup_string_in_str(struct in_str *i, const char *s);
431 #ifndef __U_BOOT__ 431 #ifndef __U_BOOT__
432 /* close_me manipulations: */ 432 /* close_me manipulations: */
433 static void mark_open(int fd); 433 static void mark_open(int fd);
434 static void mark_closed(int fd); 434 static void mark_closed(int fd);
435 static void close_all(void); 435 static void close_all(void);
436 #endif 436 #endif
437 /* "run" the final data structures: */ 437 /* "run" the final data structures: */
438 static char *indenter(int i); 438 static char *indenter(int i);
439 static int free_pipe_list(struct pipe *head, int indent); 439 static int free_pipe_list(struct pipe *head, int indent);
440 static int free_pipe(struct pipe *pi, int indent); 440 static int free_pipe(struct pipe *pi, int indent);
441 /* really run the final data structures: */ 441 /* really run the final data structures: */
442 #ifndef __U_BOOT__ 442 #ifndef __U_BOOT__
443 static int setup_redirects(struct child_prog *prog, int squirrel[]); 443 static int setup_redirects(struct child_prog *prog, int squirrel[]);
444 #endif 444 #endif
445 static int run_list_real(struct pipe *pi); 445 static int run_list_real(struct pipe *pi);
446 #ifndef __U_BOOT__ 446 #ifndef __U_BOOT__
447 static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn)); 447 static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn));
448 #endif 448 #endif
449 static int run_pipe_real(struct pipe *pi); 449 static int run_pipe_real(struct pipe *pi);
450 /* extended glob support: */ 450 /* extended glob support: */
451 #ifndef __U_BOOT__ 451 #ifndef __U_BOOT__
452 static int globhack(const char *src, int flags, glob_t *pglob); 452 static int globhack(const char *src, int flags, glob_t *pglob);
453 static int glob_needed(const char *s); 453 static int glob_needed(const char *s);
454 static int xglob(o_string *dest, int flags, glob_t *pglob); 454 static int xglob(o_string *dest, int flags, glob_t *pglob);
455 #endif 455 #endif
456 /* variable assignment: */ 456 /* variable assignment: */
457 static int is_assignment(const char *s); 457 static int is_assignment(const char *s);
458 /* data structure manipulation: */ 458 /* data structure manipulation: */
459 #ifndef __U_BOOT__ 459 #ifndef __U_BOOT__
460 static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); 460 static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
461 #endif 461 #endif
462 static void initialize_context(struct p_context *ctx); 462 static void initialize_context(struct p_context *ctx);
463 static int done_word(o_string *dest, struct p_context *ctx); 463 static int done_word(o_string *dest, struct p_context *ctx);
464 static int done_command(struct p_context *ctx); 464 static int done_command(struct p_context *ctx);
465 static int done_pipe(struct p_context *ctx, pipe_style type); 465 static int done_pipe(struct p_context *ctx, pipe_style type);
466 /* primary string parsing: */ 466 /* primary string parsing: */
467 #ifndef __U_BOOT__ 467 #ifndef __U_BOOT__
468 static int redirect_dup_num(struct in_str *input); 468 static int redirect_dup_num(struct in_str *input);
469 static int redirect_opt_num(o_string *o); 469 static int redirect_opt_num(o_string *o);
470 static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end); 470 static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end);
471 static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch); 471 static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch);
472 #endif 472 #endif
473 static char *lookup_param(char *src); 473 static char *lookup_param(char *src);
474 static char *make_string(char **inp, int *nonnull); 474 static char *make_string(char **inp, int *nonnull);
475 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input); 475 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
476 #ifndef __U_BOOT__ 476 #ifndef __U_BOOT__
477 static int parse_string(o_string *dest, struct p_context *ctx, const char *src); 477 static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
478 #endif 478 #endif
479 static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, int end_trigger); 479 static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, int end_trigger);
480 /* setup: */ 480 /* setup: */
481 static int parse_stream_outer(struct in_str *inp, int flag); 481 static int parse_stream_outer(struct in_str *inp, int flag);
482 #ifndef __U_BOOT__ 482 #ifndef __U_BOOT__
483 static int parse_string_outer(const char *s, int flag); 483 static int parse_string_outer(const char *s, int flag);
484 static int parse_file_outer(FILE *f); 484 static int parse_file_outer(FILE *f);
485 #endif 485 #endif
486 #ifndef __U_BOOT__ 486 #ifndef __U_BOOT__
487 /* job management: */ 487 /* job management: */
488 static int checkjobs(struct pipe* fg_pipe); 488 static int checkjobs(struct pipe* fg_pipe);
489 static void insert_bg_job(struct pipe *pi); 489 static void insert_bg_job(struct pipe *pi);
490 static void remove_bg_job(struct pipe *pi); 490 static void remove_bg_job(struct pipe *pi);
491 #endif 491 #endif
492 /* local variable support */ 492 /* local variable support */
493 static char **make_list_in(char **inp, char *name); 493 static char **make_list_in(char **inp, char *name);
494 static char *insert_var_value(char *inp); 494 static char *insert_var_value(char *inp);
495 static char *insert_var_value_sub(char *inp, int tag_subst); 495 static char *insert_var_value_sub(char *inp, int tag_subst);
496 496
497 #ifndef __U_BOOT__ 497 #ifndef __U_BOOT__
498 /* Table of built-in functions. They can be forked or not, depending on 498 /* Table of built-in functions. They can be forked or not, depending on
499 * context: within pipes, they fork. As simple commands, they do not. 499 * context: within pipes, they fork. As simple commands, they do not.
500 * When used in non-forking context, they can change global variables 500 * When used in non-forking context, they can change global variables
501 * in the parent shell process. If forked, of course they can not. 501 * in the parent shell process. If forked, of course they can not.
502 * For example, 'unset foo | whatever' will parse and run, but foo will 502 * For example, 'unset foo | whatever' will parse and run, but foo will
503 * still be set at the end. */ 503 * still be set at the end. */
504 static struct built_in_command bltins[] = { 504 static struct built_in_command bltins[] = {
505 {"bg", "Resume a job in the background", builtin_fg_bg}, 505 {"bg", "Resume a job in the background", builtin_fg_bg},
506 {"break", "Exit for, while or until loop", builtin_not_written}, 506 {"break", "Exit for, while or until loop", builtin_not_written},
507 {"cd", "Change working directory", builtin_cd}, 507 {"cd", "Change working directory", builtin_cd},
508 {"continue", "Continue for, while or until loop", builtin_not_written}, 508 {"continue", "Continue for, while or until loop", builtin_not_written},
509 {"env", "Print all environment variables", builtin_env}, 509 {"env", "Print all environment variables", builtin_env},
510 {"eval", "Construct and run shell command", builtin_eval}, 510 {"eval", "Construct and run shell command", builtin_eval},
511 {"exec", "Exec command, replacing this shell with the exec'd process", 511 {"exec", "Exec command, replacing this shell with the exec'd process",
512 builtin_exec}, 512 builtin_exec},
513 {"exit", "Exit from shell()", builtin_exit}, 513 {"exit", "Exit from shell()", builtin_exit},
514 {"export", "Set environment variable", builtin_export}, 514 {"export", "Set environment variable", builtin_export},
515 {"fg", "Bring job into the foreground", builtin_fg_bg}, 515 {"fg", "Bring job into the foreground", builtin_fg_bg},
516 {"jobs", "Lists the active jobs", builtin_jobs}, 516 {"jobs", "Lists the active jobs", builtin_jobs},
517 {"pwd", "Print current directory", builtin_pwd}, 517 {"pwd", "Print current directory", builtin_pwd},
518 {"read", "Input environment variable", builtin_read}, 518 {"read", "Input environment variable", builtin_read},
519 {"return", "Return from a function", builtin_not_written}, 519 {"return", "Return from a function", builtin_not_written},
520 {"set", "Set/unset shell local variables", builtin_set}, 520 {"set", "Set/unset shell local variables", builtin_set},
521 {"shift", "Shift positional parameters", builtin_shift}, 521 {"shift", "Shift positional parameters", builtin_shift},
522 {"trap", "Trap signals", builtin_not_written}, 522 {"trap", "Trap signals", builtin_not_written},
523 {"ulimit","Controls resource limits", builtin_not_written}, 523 {"ulimit","Controls resource limits", builtin_not_written},
524 {"umask","Sets file creation mask", builtin_umask}, 524 {"umask","Sets file creation mask", builtin_umask},
525 {"unset", "Unset environment variable", builtin_unset}, 525 {"unset", "Unset environment variable", builtin_unset},
526 {".", "Source-in and run commands in a file", builtin_source}, 526 {".", "Source-in and run commands in a file", builtin_source},
527 {"help", "List shell built-in commands", builtin_help}, 527 {"help", "List shell built-in commands", builtin_help},
528 {NULL, NULL, NULL} 528 {NULL, NULL, NULL}
529 }; 529 };
530 530
531 static const char *set_cwd(void) 531 static const char *set_cwd(void)
532 { 532 {
533 if(cwd==unknown) 533 if(cwd==unknown)
534 cwd = NULL; /* xgetcwd(arg) called free(arg) */ 534 cwd = NULL; /* xgetcwd(arg) called free(arg) */
535 cwd = xgetcwd((char *)cwd); 535 cwd = xgetcwd((char *)cwd);
536 if (!cwd) 536 if (!cwd)
537 cwd = unknown; 537 cwd = unknown;
538 return cwd; 538 return cwd;
539 } 539 }
540 540
541 /* built-in 'eval' handler */ 541 /* built-in 'eval' handler */
542 static int builtin_eval(struct child_prog *child) 542 static int builtin_eval(struct child_prog *child)
543 { 543 {
544 char *str = NULL; 544 char *str = NULL;
545 int rcode = EXIT_SUCCESS; 545 int rcode = EXIT_SUCCESS;
546 546
547 if (child->argv[1]) { 547 if (child->argv[1]) {
548 str = make_string(child->argv + 1); 548 str = make_string(child->argv + 1);
549 parse_string_outer(str, FLAG_EXIT_FROM_LOOP | 549 parse_string_outer(str, FLAG_EXIT_FROM_LOOP |
550 FLAG_PARSE_SEMICOLON); 550 FLAG_PARSE_SEMICOLON);
551 free(str); 551 free(str);
552 rcode = last_return_code; 552 rcode = last_return_code;
553 } 553 }
554 return rcode; 554 return rcode;
555 } 555 }
556 556
557 /* built-in 'cd <path>' handler */ 557 /* built-in 'cd <path>' handler */
558 static int builtin_cd(struct child_prog *child) 558 static int builtin_cd(struct child_prog *child)
559 { 559 {
560 char *newdir; 560 char *newdir;
561 if (child->argv[1] == NULL) 561 if (child->argv[1] == NULL)
562 newdir = getenv("HOME"); 562 newdir = getenv("HOME");
563 else 563 else
564 newdir = child->argv[1]; 564 newdir = child->argv[1];
565 if (chdir(newdir)) { 565 if (chdir(newdir)) {
566 printf("cd: %s: %s\n", newdir, strerror(errno)); 566 printf("cd: %s: %s\n", newdir, strerror(errno));
567 return EXIT_FAILURE; 567 return EXIT_FAILURE;
568 } 568 }
569 set_cwd(); 569 set_cwd();
570 return EXIT_SUCCESS; 570 return EXIT_SUCCESS;
571 } 571 }
572 572
573 /* built-in 'env' handler */ 573 /* built-in 'env' handler */
574 static int builtin_env(struct child_prog *dummy) 574 static int builtin_env(struct child_prog *dummy)
575 { 575 {
576 char **e = environ; 576 char **e = environ;
577 if (e == NULL) return EXIT_FAILURE; 577 if (e == NULL) return EXIT_FAILURE;
578 for (; *e; e++) { 578 for (; *e; e++) {
579 puts(*e); 579 puts(*e);
580 } 580 }
581 return EXIT_SUCCESS; 581 return EXIT_SUCCESS;
582 } 582 }
583 583
584 /* built-in 'exec' handler */ 584 /* built-in 'exec' handler */
585 static int builtin_exec(struct child_prog *child) 585 static int builtin_exec(struct child_prog *child)
586 { 586 {
587 if (child->argv[1] == NULL) 587 if (child->argv[1] == NULL)
588 return EXIT_SUCCESS; /* Really? */ 588 return EXIT_SUCCESS; /* Really? */
589 child->argv++; 589 child->argv++;
590 pseudo_exec(child); 590 pseudo_exec(child);
591 /* never returns */ 591 /* never returns */
592 } 592 }
593 593
594 /* built-in 'exit' handler */ 594 /* built-in 'exit' handler */
595 static int builtin_exit(struct child_prog *child) 595 static int builtin_exit(struct child_prog *child)
596 { 596 {
597 if (child->argv[1] == NULL) 597 if (child->argv[1] == NULL)
598 exit(last_return_code); 598 exit(last_return_code);
599 exit (atoi(child->argv[1])); 599 exit (atoi(child->argv[1]));
600 } 600 }
601 601
602 /* built-in 'export VAR=value' handler */ 602 /* built-in 'export VAR=value' handler */
603 static int builtin_export(struct child_prog *child) 603 static int builtin_export(struct child_prog *child)
604 { 604 {
605 int res = 0; 605 int res = 0;
606 char *name = child->argv[1]; 606 char *name = child->argv[1];
607 607
608 if (name == NULL) { 608 if (name == NULL) {
609 return (builtin_env(child)); 609 return (builtin_env(child));
610 } 610 }
611 611
612 name = strdup(name); 612 name = strdup(name);
613 613
614 if(name) { 614 if(name) {
615 char *value = strchr(name, '='); 615 char *value = strchr(name, '=');
616 616
617 if (!value) { 617 if (!value) {
618 char *tmp; 618 char *tmp;
619 /* They are exporting something without an =VALUE */ 619 /* They are exporting something without an =VALUE */
620 620
621 value = get_local_var(name); 621 value = get_local_var(name);
622 if (value) { 622 if (value) {
623 size_t ln = strlen(name); 623 size_t ln = strlen(name);
624 624
625 tmp = realloc(name, ln+strlen(value)+2); 625 tmp = realloc(name, ln+strlen(value)+2);
626 if(tmp==NULL) 626 if(tmp==NULL)
627 res = -1; 627 res = -1;
628 else { 628 else {
629 sprintf(tmp+ln, "=%s", value); 629 sprintf(tmp+ln, "=%s", value);
630 name = tmp; 630 name = tmp;
631 } 631 }
632 } else { 632 } else {
633 /* bash does not return an error when trying to export 633 /* bash does not return an error when trying to export
634 * an undefined variable. Do likewise. */ 634 * an undefined variable. Do likewise. */
635 res = 1; 635 res = 1;
636 } 636 }
637 } 637 }
638 } 638 }
639 if (res<0) 639 if (res<0)
640 perror_msg("export"); 640 perror_msg("export");
641 else if(res==0) 641 else if(res==0)
642 res = set_local_var(name, 1); 642 res = set_local_var(name, 1);
643 else 643 else
644 res = 0; 644 res = 0;
645 free(name); 645 free(name);
646 return res; 646 return res;
647 } 647 }
648 648
649 /* built-in 'fg' and 'bg' handler */ 649 /* built-in 'fg' and 'bg' handler */
650 static int builtin_fg_bg(struct child_prog *child) 650 static int builtin_fg_bg(struct child_prog *child)
651 { 651 {
652 int i, jobnum; 652 int i, jobnum;
653 struct pipe *pi=NULL; 653 struct pipe *pi=NULL;
654 654
655 if (!interactive) 655 if (!interactive)
656 return EXIT_FAILURE; 656 return EXIT_FAILURE;
657 /* If they gave us no args, assume they want the last backgrounded task */ 657 /* If they gave us no args, assume they want the last backgrounded task */
658 if (!child->argv[1]) { 658 if (!child->argv[1]) {
659 for (pi = job_list; pi; pi = pi->next) { 659 for (pi = job_list; pi; pi = pi->next) {
660 if (pi->jobid == last_jobid) { 660 if (pi->jobid == last_jobid) {
661 break; 661 break;
662 } 662 }
663 } 663 }
664 if (!pi) { 664 if (!pi) {
665 error_msg("%s: no current job", child->argv[0]); 665 error_msg("%s: no current job", child->argv[0]);
666 return EXIT_FAILURE; 666 return EXIT_FAILURE;
667 } 667 }
668 } else { 668 } else {
669 if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) { 669 if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
670 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]); 670 error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
671 return EXIT_FAILURE; 671 return EXIT_FAILURE;
672 } 672 }
673 for (pi = job_list; pi; pi = pi->next) { 673 for (pi = job_list; pi; pi = pi->next) {
674 if (pi->jobid == jobnum) { 674 if (pi->jobid == jobnum) {
675 break; 675 break;
676 } 676 }
677 } 677 }
678 if (!pi) { 678 if (!pi) {
679 error_msg("%s: %d: no such job", child->argv[0], jobnum); 679 error_msg("%s: %d: no such job", child->argv[0], jobnum);
680 return EXIT_FAILURE; 680 return EXIT_FAILURE;
681 } 681 }
682 } 682 }
683 683
684 if (*child->argv[0] == 'f') { 684 if (*child->argv[0] == 'f') {
685 /* Put the job into the foreground. */ 685 /* Put the job into the foreground. */
686 tcsetpgrp(shell_terminal, pi->pgrp); 686 tcsetpgrp(shell_terminal, pi->pgrp);
687 } 687 }
688 688
689 /* Restart the processes in the job */ 689 /* Restart the processes in the job */
690 for (i = 0; i < pi->num_progs; i++) 690 for (i = 0; i < pi->num_progs; i++)
691 pi->progs[i].is_stopped = 0; 691 pi->progs[i].is_stopped = 0;
692 692
693 if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) { 693 if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) {
694 if (i == ESRCH) { 694 if (i == ESRCH) {
695 remove_bg_job(pi); 695 remove_bg_job(pi);
696 } else { 696 } else {
697 perror_msg("kill (SIGCONT)"); 697 perror_msg("kill (SIGCONT)");
698 } 698 }
699 } 699 }
700 700
701 pi->stopped_progs = 0; 701 pi->stopped_progs = 0;
702 return EXIT_SUCCESS; 702 return EXIT_SUCCESS;
703 } 703 }
704 704
705 /* built-in 'help' handler */ 705 /* built-in 'help' handler */
706 static int builtin_help(struct child_prog *dummy) 706 static int builtin_help(struct child_prog *dummy)
707 { 707 {
708 struct built_in_command *x; 708 struct built_in_command *x;
709 709
710 printf("\nBuilt-in commands:\n"); 710 printf("\nBuilt-in commands:\n");
711 printf("-------------------\n"); 711 printf("-------------------\n");
712 for (x = bltins; x->cmd; x++) { 712 for (x = bltins; x->cmd; x++) {
713 if (x->descr==NULL) 713 if (x->descr==NULL)
714 continue; 714 continue;
715 printf("%s\t%s\n", x->cmd, x->descr); 715 printf("%s\t%s\n", x->cmd, x->descr);
716 } 716 }
717 printf("\n\n"); 717 printf("\n\n");
718 return EXIT_SUCCESS; 718 return EXIT_SUCCESS;
719 } 719 }
720 720
721 /* built-in 'jobs' handler */ 721 /* built-in 'jobs' handler */
722 static int builtin_jobs(struct child_prog *child) 722 static int builtin_jobs(struct child_prog *child)
723 { 723 {
724 struct pipe *job; 724 struct pipe *job;
725 char *status_string; 725 char *status_string;
726 726
727 for (job = job_list; job; job = job->next) { 727 for (job = job_list; job; job = job->next) {
728 if (job->running_progs == job->stopped_progs) 728 if (job->running_progs == job->stopped_progs)
729 status_string = "Stopped"; 729 status_string = "Stopped";
730 else 730 else
731 status_string = "Running"; 731 status_string = "Running";
732 732
733 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text); 733 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
734 } 734 }
735 return EXIT_SUCCESS; 735 return EXIT_SUCCESS;
736 } 736 }
737 737
738 738
739 /* built-in 'pwd' handler */ 739 /* built-in 'pwd' handler */
740 static int builtin_pwd(struct child_prog *dummy) 740 static int builtin_pwd(struct child_prog *dummy)
741 { 741 {
742 puts(set_cwd()); 742 puts(set_cwd());
743 return EXIT_SUCCESS; 743 return EXIT_SUCCESS;
744 } 744 }
745 745
746 /* built-in 'read VAR' handler */ 746 /* built-in 'read VAR' handler */
747 static int builtin_read(struct child_prog *child) 747 static int builtin_read(struct child_prog *child)
748 { 748 {
749 int res; 749 int res;
750 750
751 if (child->argv[1]) { 751 if (child->argv[1]) {
752 char string[BUFSIZ]; 752 char string[BUFSIZ];
753 char *var = 0; 753 char *var = 0;
754 754
755 string[0] = 0; /* In case stdin has only EOF */ 755 string[0] = 0; /* In case stdin has only EOF */
756 /* read string */ 756 /* read string */
757 fgets(string, sizeof(string), stdin); 757 fgets(string, sizeof(string), stdin);
758 chomp(string); 758 chomp(string);
759 var = malloc(strlen(child->argv[1])+strlen(string)+2); 759 var = malloc(strlen(child->argv[1])+strlen(string)+2);
760 if(var) { 760 if(var) {
761 sprintf(var, "%s=%s", child->argv[1], string); 761 sprintf(var, "%s=%s", child->argv[1], string);
762 res = set_local_var(var, 0); 762 res = set_local_var(var, 0);
763 } else 763 } else
764 res = -1; 764 res = -1;
765 if (res) 765 if (res)
766 fprintf(stderr, "read: %m\n"); 766 fprintf(stderr, "read: %m\n");
767 free(var); /* So not move up to avoid breaking errno */ 767 free(var); /* So not move up to avoid breaking errno */
768 return res; 768 return res;
769 } else { 769 } else {
770 do res=getchar(); while(res!='\n' && res!=EOF); 770 do res=getchar(); while(res!='\n' && res!=EOF);
771 return 0; 771 return 0;
772 } 772 }
773 } 773 }
774 774
775 /* built-in 'set VAR=value' handler */ 775 /* built-in 'set VAR=value' handler */
776 static int builtin_set(struct child_prog *child) 776 static int builtin_set(struct child_prog *child)
777 { 777 {
778 char *temp = child->argv[1]; 778 char *temp = child->argv[1];
779 struct variables *e; 779 struct variables *e;
780 780
781 if (temp == NULL) 781 if (temp == NULL)
782 for(e = top_vars; e; e=e->next) 782 for(e = top_vars; e; e=e->next)
783 printf("%s=%s\n", e->name, e->value); 783 printf("%s=%s\n", e->name, e->value);
784 else 784 else
785 set_local_var(temp, 0); 785 set_local_var(temp, 0);
786 786
787 return EXIT_SUCCESS; 787 return EXIT_SUCCESS;
788 } 788 }
789 789
790 790
791 /* Built-in 'shift' handler */ 791 /* Built-in 'shift' handler */
792 static int builtin_shift(struct child_prog *child) 792 static int builtin_shift(struct child_prog *child)
793 { 793 {
794 int n=1; 794 int n=1;
795 if (child->argv[1]) { 795 if (child->argv[1]) {
796 n=atoi(child->argv[1]); 796 n=atoi(child->argv[1]);
797 } 797 }
798 if (n>=0 && n<global_argc) { 798 if (n>=0 && n<global_argc) {
799 /* XXX This probably breaks $0 */ 799 /* XXX This probably breaks $0 */
800 global_argc -= n; 800 global_argc -= n;
801 global_argv += n; 801 global_argv += n;
802 return EXIT_SUCCESS; 802 return EXIT_SUCCESS;
803 } else { 803 } else {
804 return EXIT_FAILURE; 804 return EXIT_FAILURE;
805 } 805 }
806 } 806 }
807 807
808 /* Built-in '.' handler (read-in and execute commands from file) */ 808 /* Built-in '.' handler (read-in and execute commands from file) */
809 static int builtin_source(struct child_prog *child) 809 static int builtin_source(struct child_prog *child)
810 { 810 {
811 FILE *input; 811 FILE *input;
812 int status; 812 int status;
813 813
814 if (child->argv[1] == NULL) 814 if (child->argv[1] == NULL)
815 return EXIT_FAILURE; 815 return EXIT_FAILURE;
816 816
817 /* XXX search through $PATH is missing */ 817 /* XXX search through $PATH is missing */
818 input = fopen(child->argv[1], "r"); 818 input = fopen(child->argv[1], "r");
819 if (!input) { 819 if (!input) {
820 error_msg("Couldn't open file '%s'", child->argv[1]); 820 error_msg("Couldn't open file '%s'", child->argv[1]);
821 return EXIT_FAILURE; 821 return EXIT_FAILURE;
822 } 822 }
823 823
824 /* Now run the file */ 824 /* Now run the file */
825 /* XXX argv and argc are broken; need to save old global_argv 825 /* XXX argv and argc are broken; need to save old global_argv
826 * (pointer only is OK!) on this stack frame, 826 * (pointer only is OK!) on this stack frame,
827 * set global_argv=child->argv+1, recurse, and restore. */ 827 * set global_argv=child->argv+1, recurse, and restore. */
828 mark_open(fileno(input)); 828 mark_open(fileno(input));
829 status = parse_file_outer(input); 829 status = parse_file_outer(input);
830 mark_closed(fileno(input)); 830 mark_closed(fileno(input));
831 fclose(input); 831 fclose(input);
832 return (status); 832 return (status);
833 } 833 }
834 834
835 static int builtin_umask(struct child_prog *child) 835 static int builtin_umask(struct child_prog *child)
836 { 836 {
837 mode_t new_umask; 837 mode_t new_umask;
838 const char *arg = child->argv[1]; 838 const char *arg = child->argv[1];
839 char *end; 839 char *end;
840 if (arg) { 840 if (arg) {
841 new_umask=strtoul(arg, &end, 8); 841 new_umask=strtoul(arg, &end, 8);
842 if (*end!='\0' || end == arg) { 842 if (*end!='\0' || end == arg) {
843 return EXIT_FAILURE; 843 return EXIT_FAILURE;
844 } 844 }
845 } else { 845 } else {
846 printf("%.3o\n", (unsigned int) (new_umask=umask(0))); 846 printf("%.3o\n", (unsigned int) (new_umask=umask(0)));
847 } 847 }
848 umask(new_umask); 848 umask(new_umask);
849 return EXIT_SUCCESS; 849 return EXIT_SUCCESS;
850 } 850 }
851 851
852 /* built-in 'unset VAR' handler */ 852 /* built-in 'unset VAR' handler */
853 static int builtin_unset(struct child_prog *child) 853 static int builtin_unset(struct child_prog *child)
854 { 854 {
855 /* bash returned already true */ 855 /* bash returned already true */
856 unset_local_var(child->argv[1]); 856 unset_local_var(child->argv[1]);
857 return EXIT_SUCCESS; 857 return EXIT_SUCCESS;
858 } 858 }
859 859
860 static int builtin_not_written(struct child_prog *child) 860 static int builtin_not_written(struct child_prog *child)
861 { 861 {
862 printf("builtin_%s not written\n",child->argv[0]); 862 printf("builtin_%s not written\n",child->argv[0]);
863 return EXIT_FAILURE; 863 return EXIT_FAILURE;
864 } 864 }
865 #endif 865 #endif
866 866
867 static int b_check_space(o_string *o, int len) 867 static int b_check_space(o_string *o, int len)
868 { 868 {
869 /* It would be easy to drop a more restrictive policy 869 /* It would be easy to drop a more restrictive policy
870 * in here, such as setting a maximum string length */ 870 * in here, such as setting a maximum string length */
871 if (o->length + len > o->maxlen) { 871 if (o->length + len > o->maxlen) {
872 char *old_data = o->data; 872 char *old_data = o->data;
873 /* assert (data == NULL || o->maxlen != 0); */ 873 /* assert (data == NULL || o->maxlen != 0); */
874 o->maxlen += max(2*len, B_CHUNK); 874 o->maxlen += max(2*len, B_CHUNK);
875 o->data = realloc(o->data, 1 + o->maxlen); 875 o->data = realloc(o->data, 1 + o->maxlen);
876 if (o->data == NULL) { 876 if (o->data == NULL) {
877 free(old_data); 877 free(old_data);
878 } 878 }
879 } 879 }
880 return o->data == NULL; 880 return o->data == NULL;
881 } 881 }
882 882
883 static int b_addchr(o_string *o, int ch) 883 static int b_addchr(o_string *o, int ch)
884 { 884 {
885 debug_printf("b_addchr: %c %d %p\n", ch, o->length, o); 885 debug_printf("b_addchr: %c %d %p\n", ch, o->length, o);
886 if (b_check_space(o, 1)) return B_NOSPAC; 886 if (b_check_space(o, 1)) return B_NOSPAC;
887 o->data[o->length] = ch; 887 o->data[o->length] = ch;
888 o->length++; 888 o->length++;
889 o->data[o->length] = '\0'; 889 o->data[o->length] = '\0';
890 return 0; 890 return 0;
891 } 891 }
892 892
893 static void b_reset(o_string *o) 893 static void b_reset(o_string *o)
894 { 894 {
895 o->length = 0; 895 o->length = 0;
896 o->nonnull = 0; 896 o->nonnull = 0;
897 if (o->data != NULL) *o->data = '\0'; 897 if (o->data != NULL) *o->data = '\0';
898 } 898 }
899 899
900 static void b_free(o_string *o) 900 static void b_free(o_string *o)
901 { 901 {
902 b_reset(o); 902 b_reset(o);
903 free(o->data); 903 free(o->data);
904 o->data = NULL; 904 o->data = NULL;
905 o->maxlen = 0; 905 o->maxlen = 0;
906 } 906 }
907 907
908 /* My analysis of quoting semantics tells me that state information 908 /* My analysis of quoting semantics tells me that state information
909 * is associated with a destination, not a source. 909 * is associated with a destination, not a source.
910 */ 910 */
911 static int b_addqchr(o_string *o, int ch, int quote) 911 static int b_addqchr(o_string *o, int ch, int quote)
912 { 912 {
913 if (quote && strchr("*?[\\",ch)) { 913 if (quote && strchr("*?[\\",ch)) {
914 int rc; 914 int rc;
915 rc = b_addchr(o, '\\'); 915 rc = b_addchr(o, '\\');
916 if (rc) return rc; 916 if (rc) return rc;
917 } 917 }
918 return b_addchr(o, ch); 918 return b_addchr(o, ch);
919 } 919 }
920 920
921 #ifndef __U_BOOT__ 921 #ifndef __U_BOOT__
922 static int b_adduint(o_string *o, unsigned int i) 922 static int b_adduint(o_string *o, unsigned int i)
923 { 923 {
924 int r; 924 int r;
925 char *p = simple_itoa(i); 925 char *p = simple_itoa(i);
926 /* no escape checking necessary */ 926 /* no escape checking necessary */
927 do r=b_addchr(o, *p++); while (r==0 && *p); 927 do r=b_addchr(o, *p++); while (r==0 && *p);
928 return r; 928 return r;
929 } 929 }
930 #endif 930 #endif
931 931
932 static int static_get(struct in_str *i) 932 static int static_get(struct in_str *i)
933 { 933 {
934 int ch = *i->p++; 934 int ch = *i->p++;
935 if (ch=='\0') return EOF; 935 if (ch=='\0') return EOF;
936 return ch; 936 return ch;
937 } 937 }
938 938
939 static int static_peek(struct in_str *i) 939 static int static_peek(struct in_str *i)
940 { 940 {
941 return *i->p; 941 return *i->p;
942 } 942 }
943 943
944 #ifndef __U_BOOT__ 944 #ifndef __U_BOOT__
945 static inline void cmdedit_set_initial_prompt(void) 945 static inline void cmdedit_set_initial_prompt(void)
946 { 946 {
947 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT 947 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
948 PS1 = NULL; 948 PS1 = NULL;
949 #else 949 #else
950 PS1 = getenv("PS1"); 950 PS1 = getenv("PS1");
951 if(PS1==0) 951 if(PS1==0)
952 PS1 = "\\w \\$ "; 952 PS1 = "\\w \\$ ";
953 #endif 953 #endif
954 } 954 }
955 955
956 static inline void setup_prompt_string(int promptmode, char **prompt_str) 956 static inline void setup_prompt_string(int promptmode, char **prompt_str)
957 { 957 {
958 debug_printf("setup_prompt_string %d ",promptmode); 958 debug_printf("setup_prompt_string %d ",promptmode);
959 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT 959 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
960 /* Set up the prompt */ 960 /* Set up the prompt */
961 if (promptmode == 1) { 961 if (promptmode == 1) {
962 free(PS1); 962 free(PS1);
963 PS1=xmalloc(strlen(cwd)+4); 963 PS1=xmalloc(strlen(cwd)+4);
964 sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# "); 964 sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# ");
965 *prompt_str = PS1; 965 *prompt_str = PS1;
966 } else { 966 } else {
967 *prompt_str = PS2; 967 *prompt_str = PS2;
968 } 968 }
969 #else 969 #else
970 *prompt_str = (promptmode==1)? PS1 : PS2; 970 *prompt_str = (promptmode==1)? PS1 : PS2;
971 #endif 971 #endif
972 debug_printf("result %s\n",*prompt_str); 972 debug_printf("result %s\n",*prompt_str);
973 } 973 }
974 #endif 974 #endif
975 975
976 static void get_user_input(struct in_str *i) 976 static void get_user_input(struct in_str *i)
977 { 977 {
978 #ifndef __U_BOOT__ 978 #ifndef __U_BOOT__
979 char *prompt_str; 979 char *prompt_str;
980 static char the_command[BUFSIZ]; 980 static char the_command[BUFSIZ];
981 981
982 setup_prompt_string(i->promptmode, &prompt_str); 982 setup_prompt_string(i->promptmode, &prompt_str);
983 #ifdef CONFIG_FEATURE_COMMAND_EDITING 983 #ifdef CONFIG_FEATURE_COMMAND_EDITING
984 /* 984 /*
985 ** enable command line editing only while a command line 985 ** enable command line editing only while a command line
986 ** is actually being read; otherwise, we'll end up bequeathing 986 ** is actually being read; otherwise, we'll end up bequeathing
987 ** atexit() handlers and other unwanted stuff to our 987 ** atexit() handlers and other unwanted stuff to our
988 ** child processes (rob@sysgo.de) 988 ** child processes (rob@sysgo.de)
989 */ 989 */
990 cmdedit_read_input(prompt_str, the_command); 990 cmdedit_read_input(prompt_str, the_command);
991 #else 991 #else
992 fputs(prompt_str, stdout); 992 fputs(prompt_str, stdout);
993 fflush(stdout); 993 fflush(stdout);
994 the_command[0]=fgetc(i->file); 994 the_command[0]=fgetc(i->file);
995 the_command[1]='\0'; 995 the_command[1]='\0';
996 #endif 996 #endif
997 fflush(stdout); 997 fflush(stdout);
998 i->p = the_command; 998 i->p = the_command;
999 #else 999 #else
1000 int n; 1000 int n;
1001 static char the_command[CONFIG_SYS_CBSIZE + 1]; 1001 static char the_command[CONFIG_SYS_CBSIZE + 1];
1002 1002
1003 bootretry_reset_cmd_timeout(); 1003 bootretry_reset_cmd_timeout();
1004 i->__promptme = 1; 1004 i->__promptme = 1;
1005 if (i->promptmode == 1) { 1005 if (i->promptmode == 1) {
1006 n = cli_readline(CONFIG_SYS_PROMPT); 1006 n = cli_readline(CONFIG_SYS_PROMPT);
1007 } else { 1007 } else {
1008 n = cli_readline(CONFIG_SYS_PROMPT_HUSH_PS2); 1008 n = cli_readline(CONFIG_SYS_PROMPT_HUSH_PS2);
1009 } 1009 }
1010 #ifdef CONFIG_BOOT_RETRY_TIME 1010 #ifdef CONFIG_BOOT_RETRY_TIME
1011 if (n == -2) { 1011 if (n == -2) {
1012 puts("\nTimeout waiting for command\n"); 1012 puts("\nTimeout waiting for command\n");
1013 # ifdef CONFIG_RESET_TO_RETRY 1013 # ifdef CONFIG_RESET_TO_RETRY
1014 do_reset(NULL, 0, 0, NULL); 1014 do_reset(NULL, 0, 0, NULL);
1015 # else 1015 # else
1016 # error "This currently only works with CONFIG_RESET_TO_RETRY enabled" 1016 # error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
1017 # endif 1017 # endif
1018 } 1018 }
1019 #endif 1019 #endif
1020 if (n == -1 ) { 1020 if (n == -1 ) {
1021 flag_repeat = 0; 1021 flag_repeat = 0;
1022 i->__promptme = 0; 1022 i->__promptme = 0;
1023 } 1023 }
1024 n = strlen(console_buffer); 1024 n = strlen(console_buffer);
1025 console_buffer[n] = '\n'; 1025 console_buffer[n] = '\n';
1026 console_buffer[n+1]= '\0'; 1026 console_buffer[n+1]= '\0';
1027 if (had_ctrlc()) flag_repeat = 0; 1027 if (had_ctrlc()) flag_repeat = 0;
1028 clear_ctrlc(); 1028 clear_ctrlc();
1029 do_repeat = 0; 1029 do_repeat = 0;
1030 if (i->promptmode == 1) { 1030 if (i->promptmode == 1) {
1031 if (console_buffer[0] == '\n'&& flag_repeat == 0) { 1031 if (console_buffer[0] == '\n'&& flag_repeat == 0) {
1032 strcpy(the_command,console_buffer); 1032 strcpy(the_command,console_buffer);
1033 } 1033 }
1034 else { 1034 else {
1035 if (console_buffer[0] != '\n') { 1035 if (console_buffer[0] != '\n') {
1036 strcpy(the_command,console_buffer); 1036 strcpy(the_command,console_buffer);
1037 flag_repeat = 1; 1037 flag_repeat = 1;
1038 } 1038 }
1039 else { 1039 else {
1040 do_repeat = 1; 1040 do_repeat = 1;
1041 } 1041 }
1042 } 1042 }
1043 i->p = the_command; 1043 i->p = the_command;
1044 } 1044 }
1045 else { 1045 else {
1046 if (console_buffer[0] != '\n') { 1046 if (console_buffer[0] != '\n') {
1047 if (strlen(the_command) + strlen(console_buffer) 1047 if (strlen(the_command) + strlen(console_buffer)
1048 < CONFIG_SYS_CBSIZE) { 1048 < CONFIG_SYS_CBSIZE) {
1049 n = strlen(the_command); 1049 n = strlen(the_command);
1050 the_command[n-1] = ' '; 1050 the_command[n-1] = ' ';
1051 strcpy(&the_command[n],console_buffer); 1051 strcpy(&the_command[n],console_buffer);
1052 } 1052 }
1053 else { 1053 else {
1054 the_command[0] = '\n'; 1054 the_command[0] = '\n';
1055 the_command[1] = '\0'; 1055 the_command[1] = '\0';
1056 flag_repeat = 0; 1056 flag_repeat = 0;
1057 } 1057 }
1058 } 1058 }
1059 if (i->__promptme == 0) { 1059 if (i->__promptme == 0) {
1060 the_command[0] = '\n'; 1060 the_command[0] = '\n';
1061 the_command[1] = '\0'; 1061 the_command[1] = '\0';
1062 } 1062 }
1063 i->p = console_buffer; 1063 i->p = console_buffer;
1064 } 1064 }
1065 #endif 1065 #endif
1066 } 1066 }
1067 1067
1068 /* This is the magic location that prints prompts 1068 /* This is the magic location that prints prompts
1069 * and gets data back from the user */ 1069 * and gets data back from the user */
1070 static int file_get(struct in_str *i) 1070 static int file_get(struct in_str *i)
1071 { 1071 {
1072 int ch; 1072 int ch;
1073 1073
1074 ch = 0; 1074 ch = 0;
1075 /* If there is data waiting, eat it up */ 1075 /* If there is data waiting, eat it up */
1076 if (i->p && *i->p) { 1076 if (i->p && *i->p) {
1077 ch = *i->p++; 1077 ch = *i->p++;
1078 } else { 1078 } else {
1079 /* need to double check i->file because we might be doing something 1079 /* need to double check i->file because we might be doing something
1080 * more complicated by now, like sourcing or substituting. */ 1080 * more complicated by now, like sourcing or substituting. */
1081 #ifndef __U_BOOT__ 1081 #ifndef __U_BOOT__
1082 if (i->__promptme && interactive && i->file == stdin) { 1082 if (i->__promptme && interactive && i->file == stdin) {
1083 while(! i->p || (interactive && strlen(i->p)==0) ) { 1083 while(! i->p || (interactive && strlen(i->p)==0) ) {
1084 #else 1084 #else
1085 while(! i->p || strlen(i->p)==0 ) { 1085 while(! i->p || strlen(i->p)==0 ) {
1086 #endif 1086 #endif
1087 get_user_input(i); 1087 get_user_input(i);
1088 } 1088 }
1089 i->promptmode=2; 1089 i->promptmode=2;
1090 #ifndef __U_BOOT__ 1090 #ifndef __U_BOOT__
1091 i->__promptme = 0; 1091 i->__promptme = 0;
1092 #endif 1092 #endif
1093 if (i->p && *i->p) { 1093 if (i->p && *i->p) {
1094 ch = *i->p++; 1094 ch = *i->p++;
1095 } 1095 }
1096 #ifndef __U_BOOT__ 1096 #ifndef __U_BOOT__
1097 } else { 1097 } else {
1098 ch = fgetc(i->file); 1098 ch = fgetc(i->file);
1099 } 1099 }
1100 1100
1101 #endif 1101 #endif
1102 debug_printf("b_getch: got a %d\n", ch); 1102 debug_printf("b_getch: got a %d\n", ch);
1103 } 1103 }
1104 #ifndef __U_BOOT__ 1104 #ifndef __U_BOOT__
1105 if (ch == '\n') i->__promptme=1; 1105 if (ch == '\n') i->__promptme=1;
1106 #endif 1106 #endif
1107 return ch; 1107 return ch;
1108 } 1108 }
1109 1109
1110 /* All the callers guarantee this routine will never be 1110 /* All the callers guarantee this routine will never be
1111 * used right after a newline, so prompting is not needed. 1111 * used right after a newline, so prompting is not needed.
1112 */ 1112 */
1113 static int file_peek(struct in_str *i) 1113 static int file_peek(struct in_str *i)
1114 { 1114 {
1115 #ifndef __U_BOOT__ 1115 #ifndef __U_BOOT__
1116 if (i->p && *i->p) { 1116 if (i->p && *i->p) {
1117 #endif 1117 #endif
1118 return *i->p; 1118 return *i->p;
1119 #ifndef __U_BOOT__ 1119 #ifndef __U_BOOT__
1120 } else { 1120 } else {
1121 i->peek_buf[0] = fgetc(i->file); 1121 i->peek_buf[0] = fgetc(i->file);
1122 i->peek_buf[1] = '\0'; 1122 i->peek_buf[1] = '\0';
1123 i->p = i->peek_buf; 1123 i->p = i->peek_buf;
1124 debug_printf("b_peek: got a %d\n", *i->p); 1124 debug_printf("b_peek: got a %d\n", *i->p);
1125 return *i->p; 1125 return *i->p;
1126 } 1126 }
1127 #endif 1127 #endif
1128 } 1128 }
1129 1129
1130 #ifndef __U_BOOT__ 1130 #ifndef __U_BOOT__
1131 static void setup_file_in_str(struct in_str *i, FILE *f) 1131 static void setup_file_in_str(struct in_str *i, FILE *f)
1132 #else 1132 #else
1133 static void setup_file_in_str(struct in_str *i) 1133 static void setup_file_in_str(struct in_str *i)
1134 #endif 1134 #endif
1135 { 1135 {
1136 i->peek = file_peek; 1136 i->peek = file_peek;
1137 i->get = file_get; 1137 i->get = file_get;
1138 i->__promptme=1; 1138 i->__promptme=1;
1139 i->promptmode=1; 1139 i->promptmode=1;
1140 #ifndef __U_BOOT__ 1140 #ifndef __U_BOOT__
1141 i->file = f; 1141 i->file = f;
1142 #endif 1142 #endif
1143 i->p = NULL; 1143 i->p = NULL;
1144 } 1144 }
1145 1145
1146 static void setup_string_in_str(struct in_str *i, const char *s) 1146 static void setup_string_in_str(struct in_str *i, const char *s)
1147 { 1147 {
1148 i->peek = static_peek; 1148 i->peek = static_peek;
1149 i->get = static_get; 1149 i->get = static_get;
1150 i->__promptme=1; 1150 i->__promptme=1;
1151 i->promptmode=1; 1151 i->promptmode=1;
1152 i->p = s; 1152 i->p = s;
1153 } 1153 }
1154 1154
1155 #ifndef __U_BOOT__ 1155 #ifndef __U_BOOT__
1156 static void mark_open(int fd) 1156 static void mark_open(int fd)
1157 { 1157 {
1158 struct close_me *new = xmalloc(sizeof(struct close_me)); 1158 struct close_me *new = xmalloc(sizeof(struct close_me));
1159 new->fd = fd; 1159 new->fd = fd;
1160 new->next = close_me_head; 1160 new->next = close_me_head;
1161 close_me_head = new; 1161 close_me_head = new;
1162 } 1162 }
1163 1163
1164 static void mark_closed(int fd) 1164 static void mark_closed(int fd)
1165 { 1165 {
1166 struct close_me *tmp; 1166 struct close_me *tmp;
1167 if (close_me_head == NULL || close_me_head->fd != fd) 1167 if (close_me_head == NULL || close_me_head->fd != fd)
1168 error_msg_and_die("corrupt close_me"); 1168 error_msg_and_die("corrupt close_me");
1169 tmp = close_me_head; 1169 tmp = close_me_head;
1170 close_me_head = close_me_head->next; 1170 close_me_head = close_me_head->next;
1171 free(tmp); 1171 free(tmp);
1172 } 1172 }
1173 1173
1174 static void close_all(void) 1174 static void close_all(void)
1175 { 1175 {
1176 struct close_me *c; 1176 struct close_me *c;
1177 for (c=close_me_head; c; c=c->next) { 1177 for (c=close_me_head; c; c=c->next) {
1178 close(c->fd); 1178 close(c->fd);
1179 } 1179 }
1180 close_me_head = NULL; 1180 close_me_head = NULL;
1181 } 1181 }
1182 1182
1183 /* squirrel != NULL means we squirrel away copies of stdin, stdout, 1183 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
1184 * and stderr if they are redirected. */ 1184 * and stderr if they are redirected. */
1185 static int setup_redirects(struct child_prog *prog, int squirrel[]) 1185 static int setup_redirects(struct child_prog *prog, int squirrel[])
1186 { 1186 {
1187 int openfd, mode; 1187 int openfd, mode;
1188 struct redir_struct *redir; 1188 struct redir_struct *redir;
1189 1189
1190 for (redir=prog->redirects; redir; redir=redir->next) { 1190 for (redir=prog->redirects; redir; redir=redir->next) {
1191 if (redir->dup == -1 && redir->word.gl_pathv == NULL) { 1191 if (redir->dup == -1 && redir->word.gl_pathv == NULL) {
1192 /* something went wrong in the parse. Pretend it didn't happen */ 1192 /* something went wrong in the parse. Pretend it didn't happen */
1193 continue; 1193 continue;
1194 } 1194 }
1195 if (redir->dup == -1) { 1195 if (redir->dup == -1) {
1196 mode=redir_table[redir->type].mode; 1196 mode=redir_table[redir->type].mode;
1197 openfd = open(redir->word.gl_pathv[0], mode, 0666); 1197 openfd = open(redir->word.gl_pathv[0], mode, 0666);
1198 if (openfd < 0) { 1198 if (openfd < 0) {
1199 /* this could get lost if stderr has been redirected, but 1199 /* this could get lost if stderr has been redirected, but
1200 bash and ash both lose it as well (though zsh doesn't!) */ 1200 bash and ash both lose it as well (though zsh doesn't!) */
1201 perror_msg("error opening %s", redir->word.gl_pathv[0]); 1201 perror_msg("error opening %s", redir->word.gl_pathv[0]);
1202 return 1; 1202 return 1;
1203 } 1203 }
1204 } else { 1204 } else {
1205 openfd = redir->dup; 1205 openfd = redir->dup;
1206 } 1206 }
1207 1207
1208 if (openfd != redir->fd) { 1208 if (openfd != redir->fd) {
1209 if (squirrel && redir->fd < 3) { 1209 if (squirrel && redir->fd < 3) {
1210 squirrel[redir->fd] = dup(redir->fd); 1210 squirrel[redir->fd] = dup(redir->fd);
1211 } 1211 }
1212 if (openfd == -3) { 1212 if (openfd == -3) {
1213 close(openfd); 1213 close(openfd);
1214 } else { 1214 } else {
1215 dup2(openfd, redir->fd); 1215 dup2(openfd, redir->fd);
1216 if (redir->dup == -1) 1216 if (redir->dup == -1)
1217 close (openfd); 1217 close (openfd);
1218 } 1218 }
1219 } 1219 }
1220 } 1220 }
1221 return 0; 1221 return 0;
1222 } 1222 }
1223 1223
1224 static void restore_redirects(int squirrel[]) 1224 static void restore_redirects(int squirrel[])
1225 { 1225 {
1226 int i, fd; 1226 int i, fd;
1227 for (i=0; i<3; i++) { 1227 for (i=0; i<3; i++) {
1228 fd = squirrel[i]; 1228 fd = squirrel[i];
1229 if (fd != -1) { 1229 if (fd != -1) {
1230 /* No error checking. I sure wouldn't know what 1230 /* No error checking. I sure wouldn't know what
1231 * to do with an error if I found one! */ 1231 * to do with an error if I found one! */
1232 dup2(fd, i); 1232 dup2(fd, i);
1233 close(fd); 1233 close(fd);
1234 } 1234 }
1235 } 1235 }
1236 } 1236 }
1237 1237
1238 /* never returns */ 1238 /* never returns */
1239 /* XXX no exit() here. If you don't exec, use _exit instead. 1239 /* XXX no exit() here. If you don't exec, use _exit instead.
1240 * The at_exit handlers apparently confuse the calling process, 1240 * The at_exit handlers apparently confuse the calling process,
1241 * in particular stdin handling. Not sure why? */ 1241 * in particular stdin handling. Not sure why? */
1242 static void pseudo_exec(struct child_prog *child) 1242 static void pseudo_exec(struct child_prog *child)
1243 { 1243 {
1244 int i, rcode; 1244 int i, rcode;
1245 char *p; 1245 char *p;
1246 struct built_in_command *x; 1246 struct built_in_command *x;
1247 if (child->argv) { 1247 if (child->argv) {
1248 for (i=0; is_assignment(child->argv[i]); i++) { 1248 for (i=0; is_assignment(child->argv[i]); i++) {
1249 debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]); 1249 debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]);
1250 p = insert_var_value(child->argv[i]); 1250 p = insert_var_value(child->argv[i]);
1251 putenv(strdup(p)); 1251 putenv(strdup(p));
1252 if (p != child->argv[i]) free(p); 1252 if (p != child->argv[i]) free(p);
1253 } 1253 }
1254 child->argv+=i; /* XXX this hack isn't so horrible, since we are about 1254 child->argv+=i; /* XXX this hack isn't so horrible, since we are about
1255 to exit, and therefore don't need to keep data 1255 to exit, and therefore don't need to keep data
1256 structures consistent for free() use. */ 1256 structures consistent for free() use. */
1257 /* If a variable is assigned in a forest, and nobody listens, 1257 /* If a variable is assigned in a forest, and nobody listens,
1258 * was it ever really set? 1258 * was it ever really set?
1259 */ 1259 */
1260 if (child->argv[0] == NULL) { 1260 if (child->argv[0] == NULL) {
1261 _exit(EXIT_SUCCESS); 1261 _exit(EXIT_SUCCESS);
1262 } 1262 }
1263 1263
1264 /* 1264 /*
1265 * Check if the command matches any of the builtins. 1265 * Check if the command matches any of the builtins.
1266 * Depending on context, this might be redundant. But it's 1266 * Depending on context, this might be redundant. But it's
1267 * easier to waste a few CPU cycles than it is to figure out 1267 * easier to waste a few CPU cycles than it is to figure out
1268 * if this is one of those cases. 1268 * if this is one of those cases.
1269 */ 1269 */
1270 for (x = bltins; x->cmd; x++) { 1270 for (x = bltins; x->cmd; x++) {
1271 if (strcmp(child->argv[0], x->cmd) == 0 ) { 1271 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1272 debug_printf("builtin exec %s\n", child->argv[0]); 1272 debug_printf("builtin exec %s\n", child->argv[0]);
1273 rcode = x->function(child); 1273 rcode = x->function(child);
1274 fflush(stdout); 1274 fflush(stdout);
1275 _exit(rcode); 1275 _exit(rcode);
1276 } 1276 }
1277 } 1277 }
1278 1278
1279 /* Check if the command matches any busybox internal commands 1279 /* Check if the command matches any busybox internal commands
1280 * ("applets") here. 1280 * ("applets") here.
1281 * FIXME: This feature is not 100% safe, since 1281 * FIXME: This feature is not 100% safe, since
1282 * BusyBox is not fully reentrant, so we have no guarantee the things 1282 * BusyBox is not fully reentrant, so we have no guarantee the things
1283 * from the .bss are still zeroed, or that things from .data are still 1283 * from the .bss are still zeroed, or that things from .data are still
1284 * at their defaults. We could exec ourself from /proc/self/exe, but I 1284 * at their defaults. We could exec ourself from /proc/self/exe, but I
1285 * really dislike relying on /proc for things. We could exec ourself 1285 * really dislike relying on /proc for things. We could exec ourself
1286 * from global_argv[0], but if we are in a chroot, we may not be able 1286 * from global_argv[0], but if we are in a chroot, we may not be able
1287 * to find ourself... */ 1287 * to find ourself... */
1288 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL 1288 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
1289 { 1289 {
1290 int argc_l; 1290 int argc_l;
1291 char** argv_l=child->argv; 1291 char** argv_l=child->argv;
1292 char *name = child->argv[0]; 1292 char *name = child->argv[0];
1293 1293
1294 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN 1294 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
1295 /* Following discussions from November 2000 on the busybox mailing 1295 /* Following discussions from November 2000 on the busybox mailing
1296 * list, the default configuration, (without 1296 * list, the default configuration, (without
1297 * get_last_path_component()) lets the user force use of an 1297 * get_last_path_component()) lets the user force use of an
1298 * external command by specifying the full (with slashes) filename. 1298 * external command by specifying the full (with slashes) filename.
1299 * If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN then applets 1299 * If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN then applets
1300 * _aways_ override external commands, so if you want to run 1300 * _aways_ override external commands, so if you want to run
1301 * /bin/cat, it will use BusyBox cat even if /bin/cat exists on the 1301 * /bin/cat, it will use BusyBox cat even if /bin/cat exists on the
1302 * filesystem and is _not_ busybox. Some systems may want this, 1302 * filesystem and is _not_ busybox. Some systems may want this,
1303 * most do not. */ 1303 * most do not. */
1304 name = get_last_path_component(name); 1304 name = get_last_path_component(name);
1305 #endif 1305 #endif
1306 /* Count argc for use in a second... */ 1306 /* Count argc for use in a second... */
1307 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++); 1307 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);
1308 optind = 1; 1308 optind = 1;
1309 debug_printf("running applet %s\n", name); 1309 debug_printf("running applet %s\n", name);
1310 run_applet_by_name(name, argc_l, child->argv); 1310 run_applet_by_name(name, argc_l, child->argv);
1311 } 1311 }
1312 #endif 1312 #endif
1313 debug_printf("exec of %s\n",child->argv[0]); 1313 debug_printf("exec of %s\n",child->argv[0]);
1314 execvp(child->argv[0],child->argv); 1314 execvp(child->argv[0],child->argv);
1315 perror_msg("couldn't exec: %s",child->argv[0]); 1315 perror_msg("couldn't exec: %s",child->argv[0]);
1316 _exit(1); 1316 _exit(1);
1317 } else if (child->group) { 1317 } else if (child->group) {
1318 debug_printf("runtime nesting to group\n"); 1318 debug_printf("runtime nesting to group\n");
1319 interactive=0; /* crucial!!!! */ 1319 interactive=0; /* crucial!!!! */
1320 rcode = run_list_real(child->group); 1320 rcode = run_list_real(child->group);
1321 /* OK to leak memory by not calling free_pipe_list, 1321 /* OK to leak memory by not calling free_pipe_list,
1322 * since this process is about to exit */ 1322 * since this process is about to exit */
1323 _exit(rcode); 1323 _exit(rcode);
1324 } else { 1324 } else {
1325 /* Can happen. See what bash does with ">foo" by itself. */ 1325 /* Can happen. See what bash does with ">foo" by itself. */
1326 debug_printf("trying to pseudo_exec null command\n"); 1326 debug_printf("trying to pseudo_exec null command\n");
1327 _exit(EXIT_SUCCESS); 1327 _exit(EXIT_SUCCESS);
1328 } 1328 }
1329 } 1329 }
1330 1330
1331 static void insert_bg_job(struct pipe *pi) 1331 static void insert_bg_job(struct pipe *pi)
1332 { 1332 {
1333 struct pipe *thejob; 1333 struct pipe *thejob;
1334 1334
1335 /* Linear search for the ID of the job to use */ 1335 /* Linear search for the ID of the job to use */
1336 pi->jobid = 1; 1336 pi->jobid = 1;
1337 for (thejob = job_list; thejob; thejob = thejob->next) 1337 for (thejob = job_list; thejob; thejob = thejob->next)
1338 if (thejob->jobid >= pi->jobid) 1338 if (thejob->jobid >= pi->jobid)
1339 pi->jobid = thejob->jobid + 1; 1339 pi->jobid = thejob->jobid + 1;
1340 1340
1341 /* add thejob to the list of running jobs */ 1341 /* add thejob to the list of running jobs */
1342 if (!job_list) { 1342 if (!job_list) {
1343 thejob = job_list = xmalloc(sizeof(*thejob)); 1343 thejob = job_list = xmalloc(sizeof(*thejob));
1344 } else { 1344 } else {
1345 for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */; 1345 for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */;
1346 thejob->next = xmalloc(sizeof(*thejob)); 1346 thejob->next = xmalloc(sizeof(*thejob));
1347 thejob = thejob->next; 1347 thejob = thejob->next;
1348 } 1348 }
1349 1349
1350 /* physically copy the struct job */ 1350 /* physically copy the struct job */
1351 memcpy(thejob, pi, sizeof(struct pipe)); 1351 memcpy(thejob, pi, sizeof(struct pipe));
1352 thejob->next = NULL; 1352 thejob->next = NULL;
1353 thejob->running_progs = thejob->num_progs; 1353 thejob->running_progs = thejob->num_progs;
1354 thejob->stopped_progs = 0; 1354 thejob->stopped_progs = 0;
1355 thejob->text = xmalloc(BUFSIZ); /* cmdedit buffer size */ 1355 thejob->text = xmalloc(BUFSIZ); /* cmdedit buffer size */
1356 1356
1357 /*if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0]) */ 1357 /*if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0]) */
1358 { 1358 {
1359 char *bar=thejob->text; 1359 char *bar=thejob->text;
1360 char **foo=pi->progs[0].argv; 1360 char **foo=pi->progs[0].argv;
1361 while(foo && *foo) { 1361 while(foo && *foo) {
1362 bar += sprintf(bar, "%s ", *foo++); 1362 bar += sprintf(bar, "%s ", *foo++);
1363 } 1363 }
1364 } 1364 }
1365 1365
1366 /* we don't wait for background thejobs to return -- append it 1366 /* we don't wait for background thejobs to return -- append it
1367 to the list of backgrounded thejobs and leave it alone */ 1367 to the list of backgrounded thejobs and leave it alone */
1368 printf("[%d] %d\n", thejob->jobid, thejob->progs[0].pid); 1368 printf("[%d] %d\n", thejob->jobid, thejob->progs[0].pid);
1369 last_bg_pid = thejob->progs[0].pid; 1369 last_bg_pid = thejob->progs[0].pid;
1370 last_jobid = thejob->jobid; 1370 last_jobid = thejob->jobid;
1371 } 1371 }
1372 1372
1373 /* remove a backgrounded job */ 1373 /* remove a backgrounded job */
1374 static void remove_bg_job(struct pipe *pi) 1374 static void remove_bg_job(struct pipe *pi)
1375 { 1375 {
1376 struct pipe *prev_pipe; 1376 struct pipe *prev_pipe;
1377 1377
1378 if (pi == job_list) { 1378 if (pi == job_list) {
1379 job_list = pi->next; 1379 job_list = pi->next;
1380 } else { 1380 } else {
1381 prev_pipe = job_list; 1381 prev_pipe = job_list;
1382 while (prev_pipe->next != pi) 1382 while (prev_pipe->next != pi)
1383 prev_pipe = prev_pipe->next; 1383 prev_pipe = prev_pipe->next;
1384 prev_pipe->next = pi->next; 1384 prev_pipe->next = pi->next;
1385 } 1385 }
1386 if (job_list) 1386 if (job_list)
1387 last_jobid = job_list->jobid; 1387 last_jobid = job_list->jobid;
1388 else 1388 else
1389 last_jobid = 0; 1389 last_jobid = 0;
1390 1390
1391 pi->stopped_progs = 0; 1391 pi->stopped_progs = 0;
1392 free_pipe(pi, 0); 1392 free_pipe(pi, 0);
1393 free(pi); 1393 free(pi);
1394 } 1394 }
1395 1395
1396 /* Checks to see if any processes have exited -- if they 1396 /* Checks to see if any processes have exited -- if they
1397 have, figure out why and see if a job has completed */ 1397 have, figure out why and see if a job has completed */
1398 static int checkjobs(struct pipe* fg_pipe) 1398 static int checkjobs(struct pipe* fg_pipe)
1399 { 1399 {
1400 int attributes; 1400 int attributes;
1401 int status; 1401 int status;
1402 int prognum = 0; 1402 int prognum = 0;
1403 struct pipe *pi; 1403 struct pipe *pi;
1404 pid_t childpid; 1404 pid_t childpid;
1405 1405
1406 attributes = WUNTRACED; 1406 attributes = WUNTRACED;
1407 if (fg_pipe==NULL) { 1407 if (fg_pipe==NULL) {
1408 attributes |= WNOHANG; 1408 attributes |= WNOHANG;
1409 } 1409 }
1410 1410
1411 while ((childpid = waitpid(-1, &status, attributes)) > 0) { 1411 while ((childpid = waitpid(-1, &status, attributes)) > 0) {
1412 if (fg_pipe) { 1412 if (fg_pipe) {
1413 int i, rcode = 0; 1413 int i, rcode = 0;
1414 for (i=0; i < fg_pipe->num_progs; i++) { 1414 for (i=0; i < fg_pipe->num_progs; i++) {
1415 if (fg_pipe->progs[i].pid == childpid) { 1415 if (fg_pipe->progs[i].pid == childpid) {
1416 if (i==fg_pipe->num_progs-1) 1416 if (i==fg_pipe->num_progs-1)
1417 rcode=WEXITSTATUS(status); 1417 rcode=WEXITSTATUS(status);
1418 (fg_pipe->num_progs)--; 1418 (fg_pipe->num_progs)--;
1419 return(rcode); 1419 return(rcode);
1420 } 1420 }
1421 } 1421 }
1422 } 1422 }
1423 1423
1424 for (pi = job_list; pi; pi = pi->next) { 1424 for (pi = job_list; pi; pi = pi->next) {
1425 prognum = 0; 1425 prognum = 0;
1426 while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) { 1426 while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) {
1427 prognum++; 1427 prognum++;
1428 } 1428 }
1429 if (prognum < pi->num_progs) 1429 if (prognum < pi->num_progs)
1430 break; 1430 break;
1431 } 1431 }
1432 1432
1433 if(pi==NULL) { 1433 if(pi==NULL) {
1434 debug_printf("checkjobs: pid %d was not in our list!\n", childpid); 1434 debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
1435 continue; 1435 continue;
1436 } 1436 }
1437 1437
1438 if (WIFEXITED(status) || WIFSIGNALED(status)) { 1438 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1439 /* child exited */ 1439 /* child exited */
1440 pi->running_progs--; 1440 pi->running_progs--;
1441 pi->progs[prognum].pid = 0; 1441 pi->progs[prognum].pid = 0;
1442 1442
1443 if (!pi->running_progs) { 1443 if (!pi->running_progs) {
1444 printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text); 1444 printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text);
1445 remove_bg_job(pi); 1445 remove_bg_job(pi);
1446 } 1446 }
1447 } else { 1447 } else {
1448 /* child stopped */ 1448 /* child stopped */
1449 pi->stopped_progs++; 1449 pi->stopped_progs++;
1450 pi->progs[prognum].is_stopped = 1; 1450 pi->progs[prognum].is_stopped = 1;
1451 1451
1452 #if 0 1452 #if 0
1453 /* Printing this stuff is a pain, since it tends to 1453 /* Printing this stuff is a pain, since it tends to
1454 * overwrite the prompt an inconveinient moments. So 1454 * overwrite the prompt an inconveinient moments. So
1455 * don't do that. */ 1455 * don't do that. */
1456 if (pi->stopped_progs == pi->num_progs) { 1456 if (pi->stopped_progs == pi->num_progs) {
1457 printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text); 1457 printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
1458 } 1458 }
1459 #endif 1459 #endif
1460 } 1460 }
1461 } 1461 }
1462 1462
1463 if (childpid == -1 && errno != ECHILD) 1463 if (childpid == -1 && errno != ECHILD)
1464 perror_msg("waitpid"); 1464 perror_msg("waitpid");
1465 1465
1466 /* move the shell to the foreground */ 1466 /* move the shell to the foreground */
1467 /*if (interactive && tcsetpgrp(shell_terminal, getpgid(0))) */ 1467 /*if (interactive && tcsetpgrp(shell_terminal, getpgid(0))) */
1468 /* perror_msg("tcsetpgrp-2"); */ 1468 /* perror_msg("tcsetpgrp-2"); */
1469 return -1; 1469 return -1;
1470 } 1470 }
1471 1471
1472 /* Figure out our controlling tty, checking in order stderr, 1472 /* Figure out our controlling tty, checking in order stderr,
1473 * stdin, and stdout. If check_pgrp is set, also check that 1473 * stdin, and stdout. If check_pgrp is set, also check that
1474 * we belong to the foreground process group associated with 1474 * we belong to the foreground process group associated with
1475 * that tty. The value of shell_terminal is needed in order to call 1475 * that tty. The value of shell_terminal is needed in order to call
1476 * tcsetpgrp(shell_terminal, ...); */ 1476 * tcsetpgrp(shell_terminal, ...); */
1477 void controlling_tty(int check_pgrp) 1477 void controlling_tty(int check_pgrp)
1478 { 1478 {
1479 pid_t curpgrp; 1479 pid_t curpgrp;
1480 1480
1481 if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0 1481 if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
1482 && (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0 1482 && (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
1483 && (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0) 1483 && (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
1484 goto shell_terminal_error; 1484 goto shell_terminal_error;
1485 1485
1486 if (check_pgrp && curpgrp != getpgid(0)) 1486 if (check_pgrp && curpgrp != getpgid(0))
1487 goto shell_terminal_error; 1487 goto shell_terminal_error;
1488 1488
1489 return; 1489 return;
1490 1490
1491 shell_terminal_error: 1491 shell_terminal_error:
1492 shell_terminal = -1; 1492 shell_terminal = -1;
1493 return; 1493 return;
1494 } 1494 }
1495 #endif 1495 #endif
1496 1496
1497 /* run_pipe_real() starts all the jobs, but doesn't wait for anything 1497 /* run_pipe_real() starts all the jobs, but doesn't wait for anything
1498 * to finish. See checkjobs(). 1498 * to finish. See checkjobs().
1499 * 1499 *
1500 * return code is normally -1, when the caller has to wait for children 1500 * return code is normally -1, when the caller has to wait for children
1501 * to finish to determine the exit status of the pipe. If the pipe 1501 * to finish to determine the exit status of the pipe. If the pipe
1502 * is a simple builtin command, however, the action is done by the 1502 * is a simple builtin command, however, the action is done by the
1503 * time run_pipe_real returns, and the exit code is provided as the 1503 * time run_pipe_real returns, and the exit code is provided as the
1504 * return value. 1504 * return value.
1505 * 1505 *
1506 * The input of the pipe is always stdin, the output is always 1506 * The input of the pipe is always stdin, the output is always
1507 * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus, 1507 * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
1508 * because it tries to avoid running the command substitution in 1508 * because it tries to avoid running the command substitution in
1509 * subshell, when that is in fact necessary. The subshell process 1509 * subshell, when that is in fact necessary. The subshell process
1510 * now has its stdout directed to the input of the appropriate pipe, 1510 * now has its stdout directed to the input of the appropriate pipe,
1511 * so this routine is noticeably simpler. 1511 * so this routine is noticeably simpler.
1512 */ 1512 */
1513 static int run_pipe_real(struct pipe *pi) 1513 static int run_pipe_real(struct pipe *pi)
1514 { 1514 {
1515 int i; 1515 int i;
1516 #ifndef __U_BOOT__ 1516 #ifndef __U_BOOT__
1517 int nextin, nextout; 1517 int nextin, nextout;
1518 int pipefds[2]; /* pipefds[0] is for reading */ 1518 int pipefds[2]; /* pipefds[0] is for reading */
1519 struct child_prog *child; 1519 struct child_prog *child;
1520 struct built_in_command *x; 1520 struct built_in_command *x;
1521 char *p; 1521 char *p;
1522 # if __GNUC__ 1522 # if __GNUC__
1523 /* Avoid longjmp clobbering */ 1523 /* Avoid longjmp clobbering */
1524 (void) &i; 1524 (void) &i;
1525 (void) &nextin; 1525 (void) &nextin;
1526 (void) &nextout; 1526 (void) &nextout;
1527 (void) &child; 1527 (void) &child;
1528 # endif 1528 # endif
1529 #else 1529 #else
1530 int nextin; 1530 int nextin;
1531 int flag = do_repeat ? CMD_FLAG_REPEAT : 0; 1531 int flag = do_repeat ? CMD_FLAG_REPEAT : 0;
1532 struct child_prog *child; 1532 struct child_prog *child;
1533 char *p; 1533 char *p;
1534 # if __GNUC__ 1534 # if __GNUC__
1535 /* Avoid longjmp clobbering */ 1535 /* Avoid longjmp clobbering */
1536 (void) &i; 1536 (void) &i;
1537 (void) &nextin; 1537 (void) &nextin;
1538 (void) &child; 1538 (void) &child;
1539 # endif 1539 # endif
1540 #endif /* __U_BOOT__ */ 1540 #endif /* __U_BOOT__ */
1541 1541
1542 nextin = 0; 1542 nextin = 0;
1543 #ifndef __U_BOOT__ 1543 #ifndef __U_BOOT__
1544 pi->pgrp = -1; 1544 pi->pgrp = -1;
1545 #endif 1545 #endif
1546 1546
1547 /* Check if this is a simple builtin (not part of a pipe). 1547 /* Check if this is a simple builtin (not part of a pipe).
1548 * Builtins within pipes have to fork anyway, and are handled in 1548 * Builtins within pipes have to fork anyway, and are handled in
1549 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. 1549 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
1550 */ 1550 */
1551 if (pi->num_progs == 1) child = & (pi->progs[0]); 1551 if (pi->num_progs == 1) child = & (pi->progs[0]);
1552 #ifndef __U_BOOT__ 1552 #ifndef __U_BOOT__
1553 if (pi->num_progs == 1 && child->group && child->subshell == 0) { 1553 if (pi->num_progs == 1 && child->group && child->subshell == 0) {
1554 int squirrel[] = {-1, -1, -1}; 1554 int squirrel[] = {-1, -1, -1};
1555 int rcode; 1555 int rcode;
1556 debug_printf("non-subshell grouping\n"); 1556 debug_printf("non-subshell grouping\n");
1557 setup_redirects(child, squirrel); 1557 setup_redirects(child, squirrel);
1558 /* XXX could we merge code with following builtin case, 1558 /* XXX could we merge code with following builtin case,
1559 * by creating a pseudo builtin that calls run_list_real? */ 1559 * by creating a pseudo builtin that calls run_list_real? */
1560 rcode = run_list_real(child->group); 1560 rcode = run_list_real(child->group);
1561 restore_redirects(squirrel); 1561 restore_redirects(squirrel);
1562 #else 1562 #else
1563 if (pi->num_progs == 1 && child->group) { 1563 if (pi->num_progs == 1 && child->group) {
1564 int rcode; 1564 int rcode;
1565 debug_printf("non-subshell grouping\n"); 1565 debug_printf("non-subshell grouping\n");
1566 rcode = run_list_real(child->group); 1566 rcode = run_list_real(child->group);
1567 #endif 1567 #endif
1568 return rcode; 1568 return rcode;
1569 } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { 1569 } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
1570 for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } 1570 for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ }
1571 if (i!=0 && child->argv[i]==NULL) { 1571 if (i!=0 && child->argv[i]==NULL) {
1572 /* assignments, but no command: set the local environment */ 1572 /* assignments, but no command: set the local environment */
1573 for (i=0; child->argv[i]!=NULL; i++) { 1573 for (i=0; child->argv[i]!=NULL; i++) {
1574 1574
1575 /* Ok, this case is tricky. We have to decide if this is a 1575 /* Ok, this case is tricky. We have to decide if this is a
1576 * local variable, or an already exported variable. If it is 1576 * local variable, or an already exported variable. If it is
1577 * already exported, we have to export the new value. If it is 1577 * already exported, we have to export the new value. If it is
1578 * not exported, we need only set this as a local variable. 1578 * not exported, we need only set this as a local variable.
1579 * This junk is all to decide whether or not to export this 1579 * This junk is all to decide whether or not to export this
1580 * variable. */ 1580 * variable. */
1581 int export_me=0; 1581 int export_me=0;
1582 char *name, *value; 1582 char *name, *value;
1583 name = xstrdup(child->argv[i]); 1583 name = xstrdup(child->argv[i]);
1584 debug_printf("Local environment set: %s\n", name); 1584 debug_printf("Local environment set: %s\n", name);
1585 value = strchr(name, '='); 1585 value = strchr(name, '=');
1586 if (value) 1586 if (value)
1587 *value=0; 1587 *value=0;
1588 #ifndef __U_BOOT__ 1588 #ifndef __U_BOOT__
1589 if ( get_local_var(name)) { 1589 if ( get_local_var(name)) {
1590 export_me=1; 1590 export_me=1;
1591 } 1591 }
1592 #endif 1592 #endif
1593 free(name); 1593 free(name);
1594 p = insert_var_value(child->argv[i]); 1594 p = insert_var_value(child->argv[i]);
1595 set_local_var(p, export_me); 1595 set_local_var(p, export_me);
1596 if (p != child->argv[i]) free(p); 1596 if (p != child->argv[i]) free(p);
1597 } 1597 }
1598 return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */ 1598 return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */
1599 } 1599 }
1600 for (i = 0; is_assignment(child->argv[i]); i++) { 1600 for (i = 0; is_assignment(child->argv[i]); i++) {
1601 p = insert_var_value(child->argv[i]); 1601 p = insert_var_value(child->argv[i]);
1602 #ifndef __U_BOOT__ 1602 #ifndef __U_BOOT__
1603 putenv(strdup(p)); 1603 putenv(strdup(p));
1604 #else 1604 #else
1605 set_local_var(p, 0); 1605 set_local_var(p, 0);
1606 #endif 1606 #endif
1607 if (p != child->argv[i]) { 1607 if (p != child->argv[i]) {
1608 child->sp--; 1608 child->sp--;
1609 free(p); 1609 free(p);
1610 } 1610 }
1611 } 1611 }
1612 if (child->sp) { 1612 if (child->sp) {
1613 char * str = NULL; 1613 char * str = NULL;
1614 1614
1615 str = make_string(child->argv + i, 1615 str = make_string(child->argv + i,
1616 child->argv_nonnull + i); 1616 child->argv_nonnull + i);
1617 parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING); 1617 parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
1618 free(str); 1618 free(str);
1619 return last_return_code; 1619 return last_return_code;
1620 } 1620 }
1621 #ifndef __U_BOOT__ 1621 #ifndef __U_BOOT__
1622 for (x = bltins; x->cmd; x++) { 1622 for (x = bltins; x->cmd; x++) {
1623 if (strcmp(child->argv[i], x->cmd) == 0 ) { 1623 if (strcmp(child->argv[i], x->cmd) == 0 ) {
1624 int squirrel[] = {-1, -1, -1}; 1624 int squirrel[] = {-1, -1, -1};
1625 int rcode; 1625 int rcode;
1626 if (x->function == builtin_exec && child->argv[i+1]==NULL) { 1626 if (x->function == builtin_exec && child->argv[i+1]==NULL) {
1627 debug_printf("magic exec\n"); 1627 debug_printf("magic exec\n");
1628 setup_redirects(child,NULL); 1628 setup_redirects(child,NULL);
1629 return EXIT_SUCCESS; 1629 return EXIT_SUCCESS;
1630 } 1630 }
1631 debug_printf("builtin inline %s\n", child->argv[0]); 1631 debug_printf("builtin inline %s\n", child->argv[0]);
1632 /* XXX setup_redirects acts on file descriptors, not FILEs. 1632 /* XXX setup_redirects acts on file descriptors, not FILEs.
1633 * This is perfect for work that comes after exec(). 1633 * This is perfect for work that comes after exec().
1634 * Is it really safe for inline use? Experimentally, 1634 * Is it really safe for inline use? Experimentally,
1635 * things seem to work with glibc. */ 1635 * things seem to work with glibc. */
1636 setup_redirects(child, squirrel); 1636 setup_redirects(child, squirrel);
1637 1637
1638 child->argv += i; /* XXX horrible hack */ 1638 child->argv += i; /* XXX horrible hack */
1639 rcode = x->function(child); 1639 rcode = x->function(child);
1640 /* XXX restore hack so free() can work right */ 1640 /* XXX restore hack so free() can work right */
1641 child->argv -= i; 1641 child->argv -= i;
1642 restore_redirects(squirrel); 1642 restore_redirects(squirrel);
1643 } 1643 }
1644 return rcode; 1644 return rcode;
1645 } 1645 }
1646 #else 1646 #else
1647 /* check ";", because ,example , argv consist from 1647 /* check ";", because ,example , argv consist from
1648 * "help;flinfo" must not execute 1648 * "help;flinfo" must not execute
1649 */ 1649 */
1650 if (strchr(child->argv[i], ';')) { 1650 if (strchr(child->argv[i], ';')) {
1651 printf("Unknown command '%s' - try 'help' or use " 1651 printf("Unknown command '%s' - try 'help' or use "
1652 "'run' command\n", child->argv[i]); 1652 "'run' command\n", child->argv[i]);
1653 return -1; 1653 return -1;
1654 } 1654 }
1655 /* Process the command */ 1655 /* Process the command */
1656 return cmd_process(flag, child->argc, child->argv, 1656 return cmd_process(flag, child->argc, child->argv,
1657 &flag_repeat, NULL); 1657 &flag_repeat, NULL);
1658 #endif 1658 #endif
1659 } 1659 }
1660 #ifndef __U_BOOT__ 1660 #ifndef __U_BOOT__
1661 1661
1662 for (i = 0; i < pi->num_progs; i++) { 1662 for (i = 0; i < pi->num_progs; i++) {
1663 child = & (pi->progs[i]); 1663 child = & (pi->progs[i]);
1664 1664
1665 /* pipes are inserted between pairs of commands */ 1665 /* pipes are inserted between pairs of commands */
1666 if ((i + 1) < pi->num_progs) { 1666 if ((i + 1) < pi->num_progs) {
1667 if (pipe(pipefds)<0) perror_msg_and_die("pipe"); 1667 if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1668 nextout = pipefds[1]; 1668 nextout = pipefds[1];
1669 } else { 1669 } else {
1670 nextout=1; 1670 nextout=1;
1671 pipefds[0] = -1; 1671 pipefds[0] = -1;
1672 } 1672 }
1673 1673
1674 /* XXX test for failed fork()? */ 1674 /* XXX test for failed fork()? */
1675 if (!(child->pid = fork())) { 1675 if (!(child->pid = fork())) {
1676 /* Set the handling for job control signals back to the default. */ 1676 /* Set the handling for job control signals back to the default. */
1677 signal(SIGINT, SIG_DFL); 1677 signal(SIGINT, SIG_DFL);
1678 signal(SIGQUIT, SIG_DFL); 1678 signal(SIGQUIT, SIG_DFL);
1679 signal(SIGTERM, SIG_DFL); 1679 signal(SIGTERM, SIG_DFL);
1680 signal(SIGTSTP, SIG_DFL); 1680 signal(SIGTSTP, SIG_DFL);
1681 signal(SIGTTIN, SIG_DFL); 1681 signal(SIGTTIN, SIG_DFL);
1682 signal(SIGTTOU, SIG_DFL); 1682 signal(SIGTTOU, SIG_DFL);
1683 signal(SIGCHLD, SIG_DFL); 1683 signal(SIGCHLD, SIG_DFL);
1684 1684
1685 close_all(); 1685 close_all();
1686 1686
1687 if (nextin != 0) { 1687 if (nextin != 0) {
1688 dup2(nextin, 0); 1688 dup2(nextin, 0);
1689 close(nextin); 1689 close(nextin);
1690 } 1690 }
1691 if (nextout != 1) { 1691 if (nextout != 1) {
1692 dup2(nextout, 1); 1692 dup2(nextout, 1);
1693 close(nextout); 1693 close(nextout);
1694 } 1694 }
1695 if (pipefds[0]!=-1) { 1695 if (pipefds[0]!=-1) {
1696 close(pipefds[0]); /* opposite end of our output pipe */ 1696 close(pipefds[0]); /* opposite end of our output pipe */
1697 } 1697 }
1698 1698
1699 /* Like bash, explicit redirects override pipes, 1699 /* Like bash, explicit redirects override pipes,
1700 * and the pipe fd is available for dup'ing. */ 1700 * and the pipe fd is available for dup'ing. */
1701 setup_redirects(child,NULL); 1701 setup_redirects(child,NULL);
1702 1702
1703 if (interactive && pi->followup!=PIPE_BG) { 1703 if (interactive && pi->followup!=PIPE_BG) {
1704 /* If we (the child) win the race, put ourselves in the process 1704 /* If we (the child) win the race, put ourselves in the process
1705 * group whose leader is the first process in this pipe. */ 1705 * group whose leader is the first process in this pipe. */
1706 if (pi->pgrp < 0) { 1706 if (pi->pgrp < 0) {
1707 pi->pgrp = getpid(); 1707 pi->pgrp = getpid();
1708 } 1708 }
1709 if (setpgid(0, pi->pgrp) == 0) { 1709 if (setpgid(0, pi->pgrp) == 0) {
1710 tcsetpgrp(2, pi->pgrp); 1710 tcsetpgrp(2, pi->pgrp);
1711 } 1711 }
1712 } 1712 }
1713 1713
1714 pseudo_exec(child); 1714 pseudo_exec(child);
1715 } 1715 }
1716 1716
1717 1717
1718 /* put our child in the process group whose leader is the 1718 /* put our child in the process group whose leader is the
1719 first process in this pipe */ 1719 first process in this pipe */
1720 if (pi->pgrp < 0) { 1720 if (pi->pgrp < 0) {
1721 pi->pgrp = child->pid; 1721 pi->pgrp = child->pid;
1722 } 1722 }
1723 /* Don't check for errors. The child may be dead already, 1723 /* Don't check for errors. The child may be dead already,
1724 * in which case setpgid returns error code EACCES. */ 1724 * in which case setpgid returns error code EACCES. */
1725 setpgid(child->pid, pi->pgrp); 1725 setpgid(child->pid, pi->pgrp);
1726 1726
1727 if (nextin != 0) 1727 if (nextin != 0)
1728 close(nextin); 1728 close(nextin);
1729 if (nextout != 1) 1729 if (nextout != 1)
1730 close(nextout); 1730 close(nextout);
1731 1731
1732 /* If there isn't another process, nextin is garbage 1732 /* If there isn't another process, nextin is garbage
1733 but it doesn't matter */ 1733 but it doesn't matter */
1734 nextin = pipefds[0]; 1734 nextin = pipefds[0];
1735 } 1735 }
1736 #endif 1736 #endif
1737 return -1; 1737 return -1;
1738 } 1738 }
1739 1739
1740 static int run_list_real(struct pipe *pi) 1740 static int run_list_real(struct pipe *pi)
1741 { 1741 {
1742 char *save_name = NULL; 1742 char *save_name = NULL;
1743 char **list = NULL; 1743 char **list = NULL;
1744 char **save_list = NULL; 1744 char **save_list = NULL;
1745 struct pipe *rpipe; 1745 struct pipe *rpipe;
1746 int flag_rep = 0; 1746 int flag_rep = 0;
1747 #ifndef __U_BOOT__ 1747 #ifndef __U_BOOT__
1748 int save_num_progs; 1748 int save_num_progs;
1749 #endif 1749 #endif
1750 int rcode=0, flag_skip=1; 1750 int rcode=0, flag_skip=1;
1751 int flag_restore = 0; 1751 int flag_restore = 0;
1752 int if_code=0, next_if_code=0; /* need double-buffer to handle elif */ 1752 int if_code=0, next_if_code=0; /* need double-buffer to handle elif */
1753 reserved_style rmode, skip_more_in_this_rmode=RES_XXXX; 1753 reserved_style rmode, skip_more_in_this_rmode=RES_XXXX;
1754 /* check syntax for "for" */ 1754 /* check syntax for "for" */
1755 for (rpipe = pi; rpipe; rpipe = rpipe->next) { 1755 for (rpipe = pi; rpipe; rpipe = rpipe->next) {
1756 if ((rpipe->r_mode == RES_IN || 1756 if ((rpipe->r_mode == RES_IN ||
1757 rpipe->r_mode == RES_FOR) && 1757 rpipe->r_mode == RES_FOR) &&
1758 (rpipe->next == NULL)) { 1758 (rpipe->next == NULL)) {
1759 syntax(); 1759 syntax();
1760 #ifdef __U_BOOT__ 1760 #ifdef __U_BOOT__
1761 flag_repeat = 0; 1761 flag_repeat = 0;
1762 #endif 1762 #endif
1763 return 1; 1763 return 1;
1764 } 1764 }
1765 if ((rpipe->r_mode == RES_IN && 1765 if ((rpipe->r_mode == RES_IN &&
1766 (rpipe->next->r_mode == RES_IN && 1766 (rpipe->next->r_mode == RES_IN &&
1767 rpipe->next->progs->argv != NULL))|| 1767 rpipe->next->progs->argv != NULL))||
1768 (rpipe->r_mode == RES_FOR && 1768 (rpipe->r_mode == RES_FOR &&
1769 rpipe->next->r_mode != RES_IN)) { 1769 rpipe->next->r_mode != RES_IN)) {
1770 syntax(); 1770 syntax();
1771 #ifdef __U_BOOT__ 1771 #ifdef __U_BOOT__
1772 flag_repeat = 0; 1772 flag_repeat = 0;
1773 #endif 1773 #endif
1774 return 1; 1774 return 1;
1775 } 1775 }
1776 } 1776 }
1777 for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) { 1777 for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {
1778 if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL || 1778 if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL ||
1779 pi->r_mode == RES_FOR) { 1779 pi->r_mode == RES_FOR) {
1780 #ifdef __U_BOOT__ 1780 #ifdef __U_BOOT__
1781 /* check Ctrl-C */ 1781 /* check Ctrl-C */
1782 ctrlc(); 1782 ctrlc();
1783 if ((had_ctrlc())) { 1783 if ((had_ctrlc())) {
1784 return 1; 1784 return 1;
1785 } 1785 }
1786 #endif 1786 #endif
1787 flag_restore = 0; 1787 flag_restore = 0;
1788 if (!rpipe) { 1788 if (!rpipe) {
1789 flag_rep = 0; 1789 flag_rep = 0;
1790 rpipe = pi; 1790 rpipe = pi;
1791 } 1791 }
1792 } 1792 }
1793 rmode = pi->r_mode; 1793 rmode = pi->r_mode;
1794 debug_printf("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode); 1794 debug_printf("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode);
1795 if (rmode == skip_more_in_this_rmode && flag_skip) { 1795 if (rmode == skip_more_in_this_rmode && flag_skip) {
1796 if (pi->followup == PIPE_SEQ) flag_skip=0; 1796 if (pi->followup == PIPE_SEQ) flag_skip=0;
1797 continue; 1797 continue;
1798 } 1798 }
1799 flag_skip = 1; 1799 flag_skip = 1;
1800 skip_more_in_this_rmode = RES_XXXX; 1800 skip_more_in_this_rmode = RES_XXXX;
1801 if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code; 1801 if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code;
1802 if (rmode == RES_THEN && if_code) continue; 1802 if (rmode == RES_THEN && if_code) continue;
1803 if (rmode == RES_ELSE && !if_code) continue; 1803 if (rmode == RES_ELSE && !if_code) continue;
1804 if (rmode == RES_ELIF && !if_code) break; 1804 if (rmode == RES_ELIF && !if_code) break;
1805 if (rmode == RES_FOR && pi->num_progs) { 1805 if (rmode == RES_FOR && pi->num_progs) {
1806 if (!list) { 1806 if (!list) {
1807 /* if no variable values after "in" we skip "for" */ 1807 /* if no variable values after "in" we skip "for" */
1808 if (!pi->next->progs->argv) continue; 1808 if (!pi->next->progs->argv) continue;
1809 /* create list of variable values */ 1809 /* create list of variable values */
1810 list = make_list_in(pi->next->progs->argv, 1810 list = make_list_in(pi->next->progs->argv,
1811 pi->progs->argv[0]); 1811 pi->progs->argv[0]);
1812 save_list = list; 1812 save_list = list;
1813 save_name = pi->progs->argv[0]; 1813 save_name = pi->progs->argv[0];
1814 pi->progs->argv[0] = NULL; 1814 pi->progs->argv[0] = NULL;
1815 flag_rep = 1; 1815 flag_rep = 1;
1816 } 1816 }
1817 if (!(*list)) { 1817 if (!(*list)) {
1818 free(pi->progs->argv[0]); 1818 free(pi->progs->argv[0]);
1819 free(save_list); 1819 free(save_list);
1820 list = NULL; 1820 list = NULL;
1821 flag_rep = 0; 1821 flag_rep = 0;
1822 pi->progs->argv[0] = save_name; 1822 pi->progs->argv[0] = save_name;
1823 #ifndef __U_BOOT__ 1823 #ifndef __U_BOOT__
1824 pi->progs->glob_result.gl_pathv[0] = 1824 pi->progs->glob_result.gl_pathv[0] =
1825 pi->progs->argv[0]; 1825 pi->progs->argv[0];
1826 #endif 1826 #endif
1827 continue; 1827 continue;
1828 } else { 1828 } else {
1829 /* insert new value from list for variable */ 1829 /* insert new value from list for variable */
1830 if (pi->progs->argv[0]) 1830 if (pi->progs->argv[0])
1831 free(pi->progs->argv[0]); 1831 free(pi->progs->argv[0]);
1832 pi->progs->argv[0] = *list++; 1832 pi->progs->argv[0] = *list++;
1833 #ifndef __U_BOOT__ 1833 #ifndef __U_BOOT__
1834 pi->progs->glob_result.gl_pathv[0] = 1834 pi->progs->glob_result.gl_pathv[0] =
1835 pi->progs->argv[0]; 1835 pi->progs->argv[0];
1836 #endif 1836 #endif
1837 } 1837 }
1838 } 1838 }
1839 if (rmode == RES_IN) continue; 1839 if (rmode == RES_IN) continue;
1840 if (rmode == RES_DO) { 1840 if (rmode == RES_DO) {
1841 if (!flag_rep) continue; 1841 if (!flag_rep) continue;
1842 } 1842 }
1843 if (rmode == RES_DONE) { 1843 if (rmode == RES_DONE) {
1844 if (flag_rep) { 1844 if (flag_rep) {
1845 flag_restore = 1; 1845 flag_restore = 1;
1846 } else { 1846 } else {
1847 rpipe = NULL; 1847 rpipe = NULL;
1848 } 1848 }
1849 } 1849 }
1850 if (pi->num_progs == 0) continue; 1850 if (pi->num_progs == 0) continue;
1851 #ifndef __U_BOOT__ 1851 #ifndef __U_BOOT__
1852 save_num_progs = pi->num_progs; /* save number of programs */ 1852 save_num_progs = pi->num_progs; /* save number of programs */
1853 #endif 1853 #endif
1854 rcode = run_pipe_real(pi); 1854 rcode = run_pipe_real(pi);
1855 debug_printf("run_pipe_real returned %d\n",rcode); 1855 debug_printf("run_pipe_real returned %d\n",rcode);
1856 #ifndef __U_BOOT__ 1856 #ifndef __U_BOOT__
1857 if (rcode!=-1) { 1857 if (rcode!=-1) {
1858 /* We only ran a builtin: rcode was set by the return value 1858 /* We only ran a builtin: rcode was set by the return value
1859 * of run_pipe_real(), and we don't need to wait for anything. */ 1859 * of run_pipe_real(), and we don't need to wait for anything. */
1860 } else if (pi->followup==PIPE_BG) { 1860 } else if (pi->followup==PIPE_BG) {
1861 /* XXX check bash's behavior with nontrivial pipes */ 1861 /* XXX check bash's behavior with nontrivial pipes */
1862 /* XXX compute jobid */ 1862 /* XXX compute jobid */
1863 /* XXX what does bash do with attempts to background builtins? */ 1863 /* XXX what does bash do with attempts to background builtins? */
1864 insert_bg_job(pi); 1864 insert_bg_job(pi);
1865 rcode = EXIT_SUCCESS; 1865 rcode = EXIT_SUCCESS;
1866 } else { 1866 } else {
1867 if (interactive) { 1867 if (interactive) {
1868 /* move the new process group into the foreground */ 1868 /* move the new process group into the foreground */
1869 if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY) 1869 if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
1870 perror_msg("tcsetpgrp-3"); 1870 perror_msg("tcsetpgrp-3");
1871 rcode = checkjobs(pi); 1871 rcode = checkjobs(pi);
1872 /* move the shell to the foreground */ 1872 /* move the shell to the foreground */
1873 if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY) 1873 if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)
1874 perror_msg("tcsetpgrp-4"); 1874 perror_msg("tcsetpgrp-4");
1875 } else { 1875 } else {
1876 rcode = checkjobs(pi); 1876 rcode = checkjobs(pi);
1877 } 1877 }
1878 debug_printf("checkjobs returned %d\n",rcode); 1878 debug_printf("checkjobs returned %d\n",rcode);
1879 } 1879 }
1880 last_return_code=rcode; 1880 last_return_code=rcode;
1881 #else 1881 #else
1882 if (rcode < -1) { 1882 if (rcode < -1) {
1883 last_return_code = -rcode - 2; 1883 last_return_code = -rcode - 2;
1884 return -2; /* exit */ 1884 return -2; /* exit */
1885 } 1885 }
1886 last_return_code=(rcode == 0) ? 0 : 1; 1886 last_return_code=(rcode == 0) ? 0 : 1;
1887 #endif 1887 #endif
1888 #ifndef __U_BOOT__ 1888 #ifndef __U_BOOT__
1889 pi->num_progs = save_num_progs; /* restore number of programs */ 1889 pi->num_progs = save_num_progs; /* restore number of programs */
1890 #endif 1890 #endif
1891 if ( rmode == RES_IF || rmode == RES_ELIF ) 1891 if ( rmode == RES_IF || rmode == RES_ELIF )
1892 next_if_code=rcode; /* can be overwritten a number of times */ 1892 next_if_code=rcode; /* can be overwritten a number of times */
1893 if (rmode == RES_WHILE) 1893 if (rmode == RES_WHILE)
1894 flag_rep = !last_return_code; 1894 flag_rep = !last_return_code;
1895 if (rmode == RES_UNTIL) 1895 if (rmode == RES_UNTIL)
1896 flag_rep = last_return_code; 1896 flag_rep = last_return_code;
1897 if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) || 1897 if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
1898 (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) ) 1898 (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
1899 skip_more_in_this_rmode=rmode; 1899 skip_more_in_this_rmode=rmode;
1900 #ifndef __U_BOOT__ 1900 #ifndef __U_BOOT__
1901 checkjobs(NULL); 1901 checkjobs(NULL);
1902 #endif 1902 #endif
1903 } 1903 }
1904 return rcode; 1904 return rcode;
1905 } 1905 }
1906 1906
1907 /* broken, of course, but OK for testing */ 1907 /* broken, of course, but OK for testing */
1908 static char *indenter(int i) 1908 static char *indenter(int i)
1909 { 1909 {
1910 static char blanks[]=" "; 1910 static char blanks[]=" ";
1911 return &blanks[sizeof(blanks)-i-1]; 1911 return &blanks[sizeof(blanks)-i-1];
1912 } 1912 }
1913 1913
1914 /* return code is the exit status of the pipe */ 1914 /* return code is the exit status of the pipe */
1915 static int free_pipe(struct pipe *pi, int indent) 1915 static int free_pipe(struct pipe *pi, int indent)
1916 { 1916 {
1917 char **p; 1917 char **p;
1918 struct child_prog *child; 1918 struct child_prog *child;
1919 #ifndef __U_BOOT__ 1919 #ifndef __U_BOOT__
1920 struct redir_struct *r, *rnext; 1920 struct redir_struct *r, *rnext;
1921 #endif 1921 #endif
1922 int a, i, ret_code=0; 1922 int a, i, ret_code=0;
1923 char *ind = indenter(indent); 1923 char *ind = indenter(indent);
1924 1924
1925 #ifndef __U_BOOT__ 1925 #ifndef __U_BOOT__
1926 if (pi->stopped_progs > 0) 1926 if (pi->stopped_progs > 0)
1927 return ret_code; 1927 return ret_code;
1928 final_printf("%s run pipe: (pid %d)\n",ind,getpid()); 1928 final_printf("%s run pipe: (pid %d)\n",ind,getpid());
1929 #endif 1929 #endif
1930 for (i=0; i<pi->num_progs; i++) { 1930 for (i=0; i<pi->num_progs; i++) {
1931 child = &pi->progs[i]; 1931 child = &pi->progs[i];
1932 final_printf("%s command %d:\n",ind,i); 1932 final_printf("%s command %d:\n",ind,i);
1933 if (child->argv) { 1933 if (child->argv) {
1934 for (a=0,p=child->argv; *p; a++,p++) { 1934 for (a=0,p=child->argv; *p; a++,p++) {
1935 final_printf("%s argv[%d] = %s\n",ind,a,*p); 1935 final_printf("%s argv[%d] = %s\n",ind,a,*p);
1936 } 1936 }
1937 #ifndef __U_BOOT__ 1937 #ifndef __U_BOOT__
1938 globfree(&child->glob_result); 1938 globfree(&child->glob_result);
1939 #else 1939 #else
1940 for (a = 0; a < child->argc; a++) { 1940 for (a = 0; a < child->argc; a++) {
1941 free(child->argv[a]); 1941 free(child->argv[a]);
1942 } 1942 }
1943 free(child->argv); 1943 free(child->argv);
1944 free(child->argv_nonnull); 1944 free(child->argv_nonnull);
1945 child->argc = 0; 1945 child->argc = 0;
1946 #endif 1946 #endif
1947 child->argv=NULL; 1947 child->argv=NULL;
1948 } else if (child->group) { 1948 } else if (child->group) {
1949 #ifndef __U_BOOT__ 1949 #ifndef __U_BOOT__
1950 final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); 1950 final_printf("%s begin group (subshell:%d)\n",ind, child->subshell);
1951 #endif 1951 #endif
1952 ret_code = free_pipe_list(child->group,indent+3); 1952 ret_code = free_pipe_list(child->group,indent+3);
1953 final_printf("%s end group\n",ind); 1953 final_printf("%s end group\n",ind);
1954 } else { 1954 } else {
1955 final_printf("%s (nil)\n",ind); 1955 final_printf("%s (nil)\n",ind);
1956 } 1956 }
1957 #ifndef __U_BOOT__ 1957 #ifndef __U_BOOT__
1958 for (r=child->redirects; r; r=rnext) { 1958 for (r=child->redirects; r; r=rnext) {
1959 final_printf("%s redirect %d%s", ind, r->fd, redir_table[r->type].descrip); 1959 final_printf("%s redirect %d%s", ind, r->fd, redir_table[r->type].descrip);
1960 if (r->dup == -1) { 1960 if (r->dup == -1) {
1961 /* guard against the case >$FOO, where foo is unset or blank */ 1961 /* guard against the case >$FOO, where foo is unset or blank */
1962 if (r->word.gl_pathv) { 1962 if (r->word.gl_pathv) {
1963 final_printf(" %s\n", *r->word.gl_pathv); 1963 final_printf(" %s\n", *r->word.gl_pathv);
1964 globfree(&r->word); 1964 globfree(&r->word);
1965 } 1965 }
1966 } else { 1966 } else {
1967 final_printf("&%d\n", r->dup); 1967 final_printf("&%d\n", r->dup);
1968 } 1968 }
1969 rnext=r->next; 1969 rnext=r->next;
1970 free(r); 1970 free(r);
1971 } 1971 }
1972 child->redirects=NULL; 1972 child->redirects=NULL;
1973 #endif 1973 #endif
1974 } 1974 }
1975 free(pi->progs); /* children are an array, they get freed all at once */ 1975 free(pi->progs); /* children are an array, they get freed all at once */
1976 pi->progs=NULL; 1976 pi->progs=NULL;
1977 return ret_code; 1977 return ret_code;
1978 } 1978 }
1979 1979
1980 static int free_pipe_list(struct pipe *head, int indent) 1980 static int free_pipe_list(struct pipe *head, int indent)
1981 { 1981 {
1982 int rcode=0; /* if list has no members */ 1982 int rcode=0; /* if list has no members */
1983 struct pipe *pi, *next; 1983 struct pipe *pi, *next;
1984 char *ind = indenter(indent); 1984 char *ind = indenter(indent);
1985 for (pi=head; pi; pi=next) { 1985 for (pi=head; pi; pi=next) {
1986 final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); 1986 final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);
1987 rcode = free_pipe(pi, indent); 1987 rcode = free_pipe(pi, indent);
1988 final_printf("%s pipe followup code %d\n", ind, pi->followup); 1988 final_printf("%s pipe followup code %d\n", ind, pi->followup);
1989 next=pi->next; 1989 next=pi->next;
1990 pi->next=NULL; 1990 pi->next=NULL;
1991 free(pi); 1991 free(pi);
1992 } 1992 }
1993 return rcode; 1993 return rcode;
1994 } 1994 }
1995 1995
1996 /* Select which version we will use */ 1996 /* Select which version we will use */
1997 static int run_list(struct pipe *pi) 1997 static int run_list(struct pipe *pi)
1998 { 1998 {
1999 int rcode=0; 1999 int rcode=0;
2000 #ifndef __U_BOOT__ 2000 #ifndef __U_BOOT__
2001 if (fake_mode==0) { 2001 if (fake_mode==0) {
2002 #endif 2002 #endif
2003 rcode = run_list_real(pi); 2003 rcode = run_list_real(pi);
2004 #ifndef __U_BOOT__ 2004 #ifndef __U_BOOT__
2005 } 2005 }
2006 #endif 2006 #endif
2007 /* free_pipe_list has the side effect of clearing memory 2007 /* free_pipe_list has the side effect of clearing memory
2008 * In the long run that function can be merged with run_list_real, 2008 * In the long run that function can be merged with run_list_real,
2009 * but doing that now would hobble the debugging effort. */ 2009 * but doing that now would hobble the debugging effort. */
2010 free_pipe_list(pi,0); 2010 free_pipe_list(pi,0);
2011 return rcode; 2011 return rcode;
2012 } 2012 }
2013 2013
2014 /* The API for glob is arguably broken. This routine pushes a non-matching 2014 /* The API for glob is arguably broken. This routine pushes a non-matching
2015 * string into the output structure, removing non-backslashed backslashes. 2015 * string into the output structure, removing non-backslashed backslashes.
2016 * If someone can prove me wrong, by performing this function within the 2016 * If someone can prove me wrong, by performing this function within the
2017 * original glob(3) api, feel free to rewrite this routine into oblivion. 2017 * original glob(3) api, feel free to rewrite this routine into oblivion.
2018 * Return code (0 vs. GLOB_NOSPACE) matches glob(3). 2018 * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
2019 * XXX broken if the last character is '\\', check that before calling. 2019 * XXX broken if the last character is '\\', check that before calling.
2020 */ 2020 */
2021 #ifndef __U_BOOT__ 2021 #ifndef __U_BOOT__
2022 static int globhack(const char *src, int flags, glob_t *pglob) 2022 static int globhack(const char *src, int flags, glob_t *pglob)
2023 { 2023 {
2024 int cnt=0, pathc; 2024 int cnt=0, pathc;
2025 const char *s; 2025 const char *s;
2026 char *dest; 2026 char *dest;
2027 for (cnt=1, s=src; s && *s; s++) { 2027 for (cnt=1, s=src; s && *s; s++) {
2028 if (*s == '\\') s++; 2028 if (*s == '\\') s++;
2029 cnt++; 2029 cnt++;
2030 } 2030 }
2031 dest = malloc(cnt); 2031 dest = malloc(cnt);
2032 if (!dest) return GLOB_NOSPACE; 2032 if (!dest) return GLOB_NOSPACE;
2033 if (!(flags & GLOB_APPEND)) { 2033 if (!(flags & GLOB_APPEND)) {
2034 pglob->gl_pathv=NULL; 2034 pglob->gl_pathv=NULL;
2035 pglob->gl_pathc=0; 2035 pglob->gl_pathc=0;
2036 pglob->gl_offs=0; 2036 pglob->gl_offs=0;
2037 pglob->gl_offs=0; 2037 pglob->gl_offs=0;
2038 } 2038 }
2039 pathc = ++pglob->gl_pathc; 2039 pathc = ++pglob->gl_pathc;
2040 pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv)); 2040 pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv));
2041 if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; 2041 if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;
2042 pglob->gl_pathv[pathc-1]=dest; 2042 pglob->gl_pathv[pathc-1]=dest;
2043 pglob->gl_pathv[pathc]=NULL; 2043 pglob->gl_pathv[pathc]=NULL;
2044 for (s=src; s && *s; s++, dest++) { 2044 for (s=src; s && *s; s++, dest++) {
2045 if (*s == '\\') s++; 2045 if (*s == '\\') s++;
2046 *dest = *s; 2046 *dest = *s;
2047 } 2047 }
2048 *dest='\0'; 2048 *dest='\0';
2049 return 0; 2049 return 0;
2050 } 2050 }
2051 2051
2052 /* XXX broken if the last character is '\\', check that before calling */ 2052 /* XXX broken if the last character is '\\', check that before calling */
2053 static int glob_needed(const char *s) 2053 static int glob_needed(const char *s)
2054 { 2054 {
2055 for (; *s; s++) { 2055 for (; *s; s++) {
2056 if (*s == '\\') s++; 2056 if (*s == '\\') s++;
2057 if (strchr("*[?",*s)) return 1; 2057 if (strchr("*[?",*s)) return 1;
2058 } 2058 }
2059 return 0; 2059 return 0;
2060 } 2060 }
2061 2061
2062 #if 0 2062 #if 0
2063 static void globprint(glob_t *pglob) 2063 static void globprint(glob_t *pglob)
2064 { 2064 {
2065 int i; 2065 int i;
2066 debug_printf("glob_t at %p:\n", pglob); 2066 debug_printf("glob_t at %p:\n", pglob);
2067 debug_printf(" gl_pathc=%d gl_pathv=%p gl_offs=%d gl_flags=%d\n", 2067 debug_printf(" gl_pathc=%d gl_pathv=%p gl_offs=%d gl_flags=%d\n",
2068 pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags); 2068 pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags);
2069 for (i=0; i<pglob->gl_pathc; i++) 2069 for (i=0; i<pglob->gl_pathc; i++)
2070 debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i, 2070 debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i,
2071 pglob->gl_pathv[i], pglob->gl_pathv[i]); 2071 pglob->gl_pathv[i], pglob->gl_pathv[i]);
2072 } 2072 }
2073 #endif 2073 #endif
2074 2074
2075 static int xglob(o_string *dest, int flags, glob_t *pglob) 2075 static int xglob(o_string *dest, int flags, glob_t *pglob)
2076 { 2076 {
2077 int gr; 2077 int gr;
2078 2078
2079 /* short-circuit for null word */ 2079 /* short-circuit for null word */
2080 /* we can code this better when the debug_printf's are gone */ 2080 /* we can code this better when the debug_printf's are gone */
2081 if (dest->length == 0) { 2081 if (dest->length == 0) {
2082 if (dest->nonnull) { 2082 if (dest->nonnull) {
2083 /* bash man page calls this an "explicit" null */ 2083 /* bash man page calls this an "explicit" null */
2084 gr = globhack(dest->data, flags, pglob); 2084 gr = globhack(dest->data, flags, pglob);
2085 debug_printf("globhack returned %d\n",gr); 2085 debug_printf("globhack returned %d\n",gr);
2086 } else { 2086 } else {
2087 return 0; 2087 return 0;
2088 } 2088 }
2089 } else if (glob_needed(dest->data)) { 2089 } else if (glob_needed(dest->data)) {
2090 gr = glob(dest->data, flags, NULL, pglob); 2090 gr = glob(dest->data, flags, NULL, pglob);
2091 debug_printf("glob returned %d\n",gr); 2091 debug_printf("glob returned %d\n",gr);
2092 if (gr == GLOB_NOMATCH) { 2092 if (gr == GLOB_NOMATCH) {
2093 /* quote removal, or more accurately, backslash removal */ 2093 /* quote removal, or more accurately, backslash removal */
2094 gr = globhack(dest->data, flags, pglob); 2094 gr = globhack(dest->data, flags, pglob);
2095 debug_printf("globhack returned %d\n",gr); 2095 debug_printf("globhack returned %d\n",gr);
2096 } 2096 }
2097 } else { 2097 } else {
2098 gr = globhack(dest->data, flags, pglob); 2098 gr = globhack(dest->data, flags, pglob);
2099 debug_printf("globhack returned %d\n",gr); 2099 debug_printf("globhack returned %d\n",gr);
2100 } 2100 }
2101 if (gr == GLOB_NOSPACE) 2101 if (gr == GLOB_NOSPACE)
2102 error_msg_and_die("out of memory during glob"); 2102 error_msg_and_die("out of memory during glob");
2103 if (gr != 0) { /* GLOB_ABORTED ? */ 2103 if (gr != 0) { /* GLOB_ABORTED ? */
2104 error_msg("glob(3) error %d",gr); 2104 error_msg("glob(3) error %d",gr);
2105 } 2105 }
2106 /* globprint(glob_target); */ 2106 /* globprint(glob_target); */
2107 return gr; 2107 return gr;
2108 } 2108 }
2109 #endif 2109 #endif
2110 2110
2111 #ifdef __U_BOOT__ 2111 #ifdef __U_BOOT__
2112 static char *get_dollar_var(char ch); 2112 static char *get_dollar_var(char ch);
2113 #endif 2113 #endif
2114 2114
2115 /* This is used to get/check local shell variables */ 2115 /* This is used to get/check local shell variables */
2116 char *get_local_var(const char *s) 2116 char *get_local_var(const char *s)
2117 { 2117 {
2118 struct variables *cur; 2118 struct variables *cur;
2119 2119
2120 if (!s) 2120 if (!s)
2121 return NULL; 2121 return NULL;
2122 2122
2123 #ifdef __U_BOOT__ 2123 #ifdef __U_BOOT__
2124 if (*s == '$') 2124 if (*s == '$')
2125 return get_dollar_var(s[1]); 2125 return get_dollar_var(s[1]);
2126 #endif 2126 #endif
2127 2127
2128 for (cur = top_vars; cur; cur=cur->next) 2128 for (cur = top_vars; cur; cur=cur->next)
2129 if(strcmp(cur->name, s)==0) 2129 if(strcmp(cur->name, s)==0)
2130 return cur->value; 2130 return cur->value;
2131 return NULL; 2131 return NULL;
2132 } 2132 }
2133 2133
2134 /* This is used to set local shell variables 2134 /* This is used to set local shell variables
2135 flg_export==0 if only local (not exporting) variable 2135 flg_export==0 if only local (not exporting) variable
2136 flg_export==1 if "new" exporting environ 2136 flg_export==1 if "new" exporting environ
2137 flg_export>1 if current startup environ (not call putenv()) */ 2137 flg_export>1 if current startup environ (not call putenv()) */
2138 int set_local_var(const char *s, int flg_export) 2138 int set_local_var(const char *s, int flg_export)
2139 { 2139 {
2140 char *name, *value; 2140 char *name, *value;
2141 int result=0; 2141 int result=0;
2142 struct variables *cur; 2142 struct variables *cur;
2143 2143
2144 #ifdef __U_BOOT__ 2144 #ifdef __U_BOOT__
2145 /* might be possible! */ 2145 /* might be possible! */
2146 if (!isalpha(*s)) 2146 if (!isalpha(*s))
2147 return -1; 2147 return -1;
2148 #endif 2148 #endif
2149 2149
2150 name=strdup(s); 2150 name=strdup(s);
2151 2151
2152 #ifdef __U_BOOT__ 2152 #ifdef __U_BOOT__
2153 if (getenv(name) != NULL) { 2153 if (getenv(name) != NULL) {
2154 printf ("ERROR: " 2154 printf ("ERROR: "
2155 "There is a global environment variable with the same name.\n"); 2155 "There is a global environment variable with the same name.\n");
2156 free(name); 2156 free(name);
2157 return -1; 2157 return -1;
2158 } 2158 }
2159 #endif 2159 #endif
2160 /* Assume when we enter this function that we are already in 2160 /* Assume when we enter this function that we are already in
2161 * NAME=VALUE format. So the first order of business is to 2161 * NAME=VALUE format. So the first order of business is to
2162 * split 's' on the '=' into 'name' and 'value' */ 2162 * split 's' on the '=' into 'name' and 'value' */
2163 value = strchr(name, '='); 2163 value = strchr(name, '=');
2164 if (value == NULL && ++value == NULL) { 2164 if (value == NULL && ++value == NULL) {
2165 free(name); 2165 free(name);
2166 return -1; 2166 return -1;
2167 } 2167 }
2168 *value++ = 0; 2168 *value++ = 0;
2169 2169
2170 for(cur = top_vars; cur; cur = cur->next) { 2170 for(cur = top_vars; cur; cur = cur->next) {
2171 if(strcmp(cur->name, name)==0) 2171 if(strcmp(cur->name, name)==0)
2172 break; 2172 break;
2173 } 2173 }
2174 2174
2175 if(cur) { 2175 if(cur) {
2176 if(strcmp(cur->value, value)==0) { 2176 if(strcmp(cur->value, value)==0) {
2177 if(flg_export>0 && cur->flg_export==0) 2177 if(flg_export>0 && cur->flg_export==0)
2178 cur->flg_export=flg_export; 2178 cur->flg_export=flg_export;
2179 else 2179 else
2180 result++; 2180 result++;
2181 } else { 2181 } else {
2182 if(cur->flg_read_only) { 2182 if(cur->flg_read_only) {
2183 error_msg("%s: readonly variable", name); 2183 error_msg("%s: readonly variable", name);
2184 result = -1; 2184 result = -1;
2185 } else { 2185 } else {
2186 if(flg_export>0 || cur->flg_export>1) 2186 if(flg_export>0 || cur->flg_export>1)
2187 cur->flg_export=1; 2187 cur->flg_export=1;
2188 free(cur->value); 2188 free(cur->value);
2189 2189
2190 cur->value = strdup(value); 2190 cur->value = strdup(value);
2191 } 2191 }
2192 } 2192 }
2193 } else { 2193 } else {
2194 cur = malloc(sizeof(struct variables)); 2194 cur = malloc(sizeof(struct variables));
2195 if(!cur) { 2195 if(!cur) {
2196 result = -1; 2196 result = -1;
2197 } else { 2197 } else {
2198 cur->name = strdup(name); 2198 cur->name = strdup(name);
2199 if (cur->name == NULL) { 2199 if (cur->name == NULL) {
2200 free(cur); 2200 free(cur);
2201 result = -1; 2201 result = -1;
2202 } else { 2202 } else {
2203 struct variables *bottom = top_vars; 2203 struct variables *bottom = top_vars;
2204 cur->value = strdup(value); 2204 cur->value = strdup(value);
2205 cur->next = NULL; 2205 cur->next = NULL;
2206 cur->flg_export = flg_export; 2206 cur->flg_export = flg_export;
2207 cur->flg_read_only = 0; 2207 cur->flg_read_only = 0;
2208 while(bottom->next) bottom=bottom->next; 2208 while(bottom->next) bottom=bottom->next;
2209 bottom->next = cur; 2209 bottom->next = cur;
2210 } 2210 }
2211 } 2211 }
2212 } 2212 }
2213 2213
2214 #ifndef __U_BOOT__ 2214 #ifndef __U_BOOT__
2215 if(result==0 && cur->flg_export==1) { 2215 if(result==0 && cur->flg_export==1) {
2216 *(value-1) = '='; 2216 *(value-1) = '=';
2217 result = putenv(name); 2217 result = putenv(name);
2218 } else { 2218 } else {
2219 #endif 2219 #endif
2220 free(name); 2220 free(name);
2221 #ifndef __U_BOOT__ 2221 #ifndef __U_BOOT__
2222 if(result>0) /* equivalent to previous set */ 2222 if(result>0) /* equivalent to previous set */
2223 result = 0; 2223 result = 0;
2224 } 2224 }
2225 #endif 2225 #endif
2226 return result; 2226 return result;
2227 } 2227 }
2228 2228
2229 void unset_local_var(const char *name) 2229 void unset_local_var(const char *name)
2230 { 2230 {
2231 struct variables *cur; 2231 struct variables *cur;
2232 2232
2233 if (name) { 2233 if (name) {
2234 for (cur = top_vars; cur; cur=cur->next) { 2234 for (cur = top_vars; cur; cur=cur->next) {
2235 if(strcmp(cur->name, name)==0) 2235 if(strcmp(cur->name, name)==0)
2236 break; 2236 break;
2237 } 2237 }
2238 if (cur != NULL) { 2238 if (cur != NULL) {
2239 struct variables *next = top_vars; 2239 struct variables *next = top_vars;
2240 if(cur->flg_read_only) { 2240 if(cur->flg_read_only) {
2241 error_msg("%s: readonly variable", name); 2241 error_msg("%s: readonly variable", name);
2242 return; 2242 return;
2243 } else { 2243 } else {
2244 #ifndef __U_BOOT__ 2244 #ifndef __U_BOOT__
2245 if(cur->flg_export) 2245 if(cur->flg_export)
2246 unsetenv(cur->name); 2246 unsetenv(cur->name);
2247 #endif 2247 #endif
2248 free(cur->name); 2248 free(cur->name);
2249 free(cur->value); 2249 free(cur->value);
2250 while (next->next != cur) 2250 while (next->next != cur)
2251 next = next->next; 2251 next = next->next;
2252 next->next = cur->next; 2252 next->next = cur->next;
2253 } 2253 }
2254 free(cur); 2254 free(cur);
2255 } 2255 }
2256 } 2256 }
2257 } 2257 }
2258 2258
2259 static int is_assignment(const char *s) 2259 static int is_assignment(const char *s)
2260 { 2260 {
2261 if (s == NULL) 2261 if (s == NULL)
2262 return 0; 2262 return 0;
2263 2263
2264 if (!isalpha(*s)) return 0; 2264 if (!isalpha(*s)) return 0;
2265 ++s; 2265 ++s;
2266 while(isalnum(*s) || *s=='_') ++s; 2266 while(isalnum(*s) || *s=='_') ++s;
2267 return *s=='='; 2267 return *s=='=';
2268 } 2268 }
2269 2269
2270 #ifndef __U_BOOT__ 2270 #ifndef __U_BOOT__
2271 /* the src parameter allows us to peek forward to a possible &n syntax 2271 /* the src parameter allows us to peek forward to a possible &n syntax
2272 * for file descriptor duplication, e.g., "2>&1". 2272 * for file descriptor duplication, e.g., "2>&1".
2273 * Return code is 0 normally, 1 if a syntax error is detected in src. 2273 * Return code is 0 normally, 1 if a syntax error is detected in src.
2274 * Resource errors (in xmalloc) cause the process to exit */ 2274 * Resource errors (in xmalloc) cause the process to exit */
2275 static int setup_redirect(struct p_context *ctx, int fd, redir_type style, 2275 static int setup_redirect(struct p_context *ctx, int fd, redir_type style,
2276 struct in_str *input) 2276 struct in_str *input)
2277 { 2277 {
2278 struct child_prog *child=ctx->child; 2278 struct child_prog *child=ctx->child;
2279 struct redir_struct *redir = child->redirects; 2279 struct redir_struct *redir = child->redirects;
2280 struct redir_struct *last_redir=NULL; 2280 struct redir_struct *last_redir=NULL;
2281 2281
2282 /* Create a new redir_struct and drop it onto the end of the linked list */ 2282 /* Create a new redir_struct and drop it onto the end of the linked list */
2283 while(redir) { 2283 while(redir) {
2284 last_redir=redir; 2284 last_redir=redir;
2285 redir=redir->next; 2285 redir=redir->next;
2286 } 2286 }
2287 redir = xmalloc(sizeof(struct redir_struct)); 2287 redir = xmalloc(sizeof(struct redir_struct));
2288 redir->next=NULL; 2288 redir->next=NULL;
2289 redir->word.gl_pathv=NULL; 2289 redir->word.gl_pathv=NULL;
2290 if (last_redir) { 2290 if (last_redir) {
2291 last_redir->next=redir; 2291 last_redir->next=redir;
2292 } else { 2292 } else {
2293 child->redirects=redir; 2293 child->redirects=redir;
2294 } 2294 }
2295 2295
2296 redir->type=style; 2296 redir->type=style;
2297 redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ; 2297 redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ;
2298 2298
2299 debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip); 2299 debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip);
2300 2300
2301 /* Check for a '2>&1' type redirect */ 2301 /* Check for a '2>&1' type redirect */
2302 redir->dup = redirect_dup_num(input); 2302 redir->dup = redirect_dup_num(input);
2303 if (redir->dup == -2) return 1; /* syntax error */ 2303 if (redir->dup == -2) return 1; /* syntax error */
2304 if (redir->dup != -1) { 2304 if (redir->dup != -1) {
2305 /* Erik had a check here that the file descriptor in question 2305 /* Erik had a check here that the file descriptor in question
2306 * is legit; I postpone that to "run time" 2306 * is legit; I postpone that to "run time"
2307 * A "-" representation of "close me" shows up as a -3 here */ 2307 * A "-" representation of "close me" shows up as a -3 here */
2308 debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup); 2308 debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);
2309 } else { 2309 } else {
2310 /* We do _not_ try to open the file that src points to, 2310 /* We do _not_ try to open the file that src points to,
2311 * since we need to return and let src be expanded first. 2311 * since we need to return and let src be expanded first.
2312 * Set ctx->pending_redirect, so we know what to do at the 2312 * Set ctx->pending_redirect, so we know what to do at the
2313 * end of the next parsed word. 2313 * end of the next parsed word.
2314 */ 2314 */
2315 ctx->pending_redirect = redir; 2315 ctx->pending_redirect = redir;
2316 } 2316 }
2317 return 0; 2317 return 0;
2318 } 2318 }
2319 #endif 2319 #endif
2320 2320
2321 static struct pipe *new_pipe(void) 2321 static struct pipe *new_pipe(void)
2322 { 2322 {
2323 struct pipe *pi; 2323 struct pipe *pi;
2324 pi = xmalloc(sizeof(struct pipe)); 2324 pi = xmalloc(sizeof(struct pipe));
2325 pi->num_progs = 0; 2325 pi->num_progs = 0;
2326 pi->progs = NULL; 2326 pi->progs = NULL;
2327 pi->next = NULL; 2327 pi->next = NULL;
2328 pi->followup = 0; /* invalid */ 2328 pi->followup = 0; /* invalid */
2329 pi->r_mode = RES_NONE; 2329 pi->r_mode = RES_NONE;
2330 return pi; 2330 return pi;
2331 } 2331 }
2332 2332
2333 static void initialize_context(struct p_context *ctx) 2333 static void initialize_context(struct p_context *ctx)
2334 { 2334 {
2335 ctx->pipe=NULL; 2335 ctx->pipe=NULL;
2336 #ifndef __U_BOOT__ 2336 #ifndef __U_BOOT__
2337 ctx->pending_redirect=NULL; 2337 ctx->pending_redirect=NULL;
2338 #endif 2338 #endif
2339 ctx->child=NULL; 2339 ctx->child=NULL;
2340 ctx->list_head=new_pipe(); 2340 ctx->list_head=new_pipe();
2341 ctx->pipe=ctx->list_head; 2341 ctx->pipe=ctx->list_head;
2342 ctx->w=RES_NONE; 2342 ctx->w=RES_NONE;
2343 ctx->stack=NULL; 2343 ctx->stack=NULL;
2344 #ifdef __U_BOOT__ 2344 #ifdef __U_BOOT__
2345 ctx->old_flag=0; 2345 ctx->old_flag=0;
2346 #endif 2346 #endif
2347 done_command(ctx); /* creates the memory for working child */ 2347 done_command(ctx); /* creates the memory for working child */
2348 } 2348 }
2349 2349
2350 /* normal return is 0 2350 /* normal return is 0
2351 * if a reserved word is found, and processed, return 1 2351 * if a reserved word is found, and processed, return 1
2352 * should handle if, then, elif, else, fi, for, while, until, do, done. 2352 * should handle if, then, elif, else, fi, for, while, until, do, done.
2353 * case, function, and select are obnoxious, save those for later. 2353 * case, function, and select are obnoxious, save those for later.
2354 */ 2354 */
2355 struct reserved_combo { 2355 struct reserved_combo {
2356 char *literal; 2356 char *literal;
2357 int code; 2357 int code;
2358 long flag; 2358 long flag;
2359 }; 2359 };
2360 /* Mostly a list of accepted follow-up reserved words. 2360 /* Mostly a list of accepted follow-up reserved words.
2361 * FLAG_END means we are done with the sequence, and are ready 2361 * FLAG_END means we are done with the sequence, and are ready
2362 * to turn the compound list into a command. 2362 * to turn the compound list into a command.
2363 * FLAG_START means the word must start a new compound list. 2363 * FLAG_START means the word must start a new compound list.
2364 */ 2364 */
2365 static struct reserved_combo reserved_list[] = { 2365 static struct reserved_combo reserved_list[] = {
2366 { "if", RES_IF, FLAG_THEN | FLAG_START }, 2366 { "if", RES_IF, FLAG_THEN | FLAG_START },
2367 { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, 2367 { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
2368 { "elif", RES_ELIF, FLAG_THEN }, 2368 { "elif", RES_ELIF, FLAG_THEN },
2369 { "else", RES_ELSE, FLAG_FI }, 2369 { "else", RES_ELSE, FLAG_FI },
2370 { "fi", RES_FI, FLAG_END }, 2370 { "fi", RES_FI, FLAG_END },
2371 { "for", RES_FOR, FLAG_IN | FLAG_START }, 2371 { "for", RES_FOR, FLAG_IN | FLAG_START },
2372 { "while", RES_WHILE, FLAG_DO | FLAG_START }, 2372 { "while", RES_WHILE, FLAG_DO | FLAG_START },
2373 { "until", RES_UNTIL, FLAG_DO | FLAG_START }, 2373 { "until", RES_UNTIL, FLAG_DO | FLAG_START },
2374 { "in", RES_IN, FLAG_DO }, 2374 { "in", RES_IN, FLAG_DO },
2375 { "do", RES_DO, FLAG_DONE }, 2375 { "do", RES_DO, FLAG_DONE },
2376 { "done", RES_DONE, FLAG_END } 2376 { "done", RES_DONE, FLAG_END }
2377 }; 2377 };
2378 #define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo)) 2378 #define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo))
2379 2379
2380 static int reserved_word(o_string *dest, struct p_context *ctx) 2380 static int reserved_word(o_string *dest, struct p_context *ctx)
2381 { 2381 {
2382 struct reserved_combo *r; 2382 struct reserved_combo *r;
2383 for (r=reserved_list; 2383 for (r=reserved_list;
2384 r<reserved_list+NRES; r++) { 2384 r<reserved_list+NRES; r++) {
2385 if (strcmp(dest->data, r->literal) == 0) { 2385 if (strcmp(dest->data, r->literal) == 0) {
2386 debug_printf("found reserved word %s, code %d\n",r->literal,r->code); 2386 debug_printf("found reserved word %s, code %d\n",r->literal,r->code);
2387 if (r->flag & FLAG_START) { 2387 if (r->flag & FLAG_START) {
2388 struct p_context *new = xmalloc(sizeof(struct p_context)); 2388 struct p_context *new = xmalloc(sizeof(struct p_context));
2389 debug_printf("push stack\n"); 2389 debug_printf("push stack\n");
2390 if (ctx->w == RES_IN || ctx->w == RES_FOR) { 2390 if (ctx->w == RES_IN || ctx->w == RES_FOR) {
2391 syntax(); 2391 syntax();
2392 free(new); 2392 free(new);
2393 ctx->w = RES_SNTX; 2393 ctx->w = RES_SNTX;
2394 b_reset(dest); 2394 b_reset(dest);
2395 return 1; 2395 return 1;
2396 } 2396 }
2397 *new = *ctx; /* physical copy */ 2397 *new = *ctx; /* physical copy */
2398 initialize_context(ctx); 2398 initialize_context(ctx);
2399 ctx->stack=new; 2399 ctx->stack=new;
2400 } else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) { 2400 } else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
2401 syntax(); 2401 syntax();
2402 ctx->w = RES_SNTX; 2402 ctx->w = RES_SNTX;
2403 b_reset(dest); 2403 b_reset(dest);
2404 return 1; 2404 return 1;
2405 } 2405 }
2406 ctx->w=r->code; 2406 ctx->w=r->code;
2407 ctx->old_flag = r->flag; 2407 ctx->old_flag = r->flag;
2408 if (ctx->old_flag & FLAG_END) { 2408 if (ctx->old_flag & FLAG_END) {
2409 struct p_context *old; 2409 struct p_context *old;
2410 debug_printf("pop stack\n"); 2410 debug_printf("pop stack\n");
2411 done_pipe(ctx,PIPE_SEQ); 2411 done_pipe(ctx,PIPE_SEQ);
2412 old = ctx->stack; 2412 old = ctx->stack;
2413 old->child->group = ctx->list_head; 2413 old->child->group = ctx->list_head;
2414 #ifndef __U_BOOT__ 2414 #ifndef __U_BOOT__
2415 old->child->subshell = 0; 2415 old->child->subshell = 0;
2416 #endif 2416 #endif
2417 *ctx = *old; /* physical copy */ 2417 *ctx = *old; /* physical copy */
2418 free(old); 2418 free(old);
2419 } 2419 }
2420 b_reset (dest); 2420 b_reset (dest);
2421 return 1; 2421 return 1;
2422 } 2422 }
2423 } 2423 }
2424 return 0; 2424 return 0;
2425 } 2425 }
2426 2426
2427 /* normal return is 0. 2427 /* normal return is 0.
2428 * Syntax or xglob errors return 1. */ 2428 * Syntax or xglob errors return 1. */
2429 static int done_word(o_string *dest, struct p_context *ctx) 2429 static int done_word(o_string *dest, struct p_context *ctx)
2430 { 2430 {
2431 struct child_prog *child=ctx->child; 2431 struct child_prog *child=ctx->child;
2432 #ifndef __U_BOOT__ 2432 #ifndef __U_BOOT__
2433 glob_t *glob_target; 2433 glob_t *glob_target;
2434 int gr, flags = 0; 2434 int gr, flags = 0;
2435 #else 2435 #else
2436 char *str, *s; 2436 char *str, *s;
2437 int argc, cnt; 2437 int argc, cnt;
2438 #endif 2438 #endif
2439 2439
2440 debug_printf("done_word: %s %p\n", dest->data, child); 2440 debug_printf("done_word: %s %p\n", dest->data, child);
2441 if (dest->length == 0 && !dest->nonnull) { 2441 if (dest->length == 0 && !dest->nonnull) {
2442 debug_printf(" true null, ignored\n"); 2442 debug_printf(" true null, ignored\n");
2443 return 0; 2443 return 0;
2444 } 2444 }
2445 #ifndef __U_BOOT__ 2445 #ifndef __U_BOOT__
2446 if (ctx->pending_redirect) { 2446 if (ctx->pending_redirect) {
2447 glob_target = &ctx->pending_redirect->word; 2447 glob_target = &ctx->pending_redirect->word;
2448 } else { 2448 } else {
2449 #endif 2449 #endif
2450 if (child->group) { 2450 if (child->group) {
2451 syntax(); 2451 syntax();
2452 return 1; /* syntax error, groups and arglists don't mix */ 2452 return 1; /* syntax error, groups and arglists don't mix */
2453 } 2453 }
2454 if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) { 2454 if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
2455 debug_printf("checking %s for reserved-ness\n",dest->data); 2455 debug_printf("checking %s for reserved-ness\n",dest->data);
2456 if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX; 2456 if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX;
2457 } 2457 }
2458 #ifndef __U_BOOT__ 2458 #ifndef __U_BOOT__
2459 glob_target = &child->glob_result; 2459 glob_target = &child->glob_result;
2460 if (child->argv) flags |= GLOB_APPEND; 2460 if (child->argv) flags |= GLOB_APPEND;
2461 #else 2461 #else
2462 for (cnt = 1, s = dest->data; s && *s; s++) { 2462 for (cnt = 1, s = dest->data; s && *s; s++) {
2463 if (*s == '\\') s++; 2463 if (*s == '\\') s++;
2464 cnt++; 2464 cnt++;
2465 } 2465 }
2466 str = malloc(cnt); 2466 str = malloc(cnt);
2467 if (!str) return 1; 2467 if (!str) return 1;
2468 if ( child->argv == NULL) { 2468 if ( child->argv == NULL) {
2469 child->argc=0; 2469 child->argc=0;
2470 } 2470 }
2471 argc = ++child->argc; 2471 argc = ++child->argc;
2472 child->argv = realloc(child->argv, (argc+1)*sizeof(*child->argv)); 2472 child->argv = realloc(child->argv, (argc+1)*sizeof(*child->argv));
2473 if (child->argv == NULL) return 1; 2473 if (child->argv == NULL) return 1;
2474 child->argv_nonnull = realloc(child->argv_nonnull, 2474 child->argv_nonnull = realloc(child->argv_nonnull,
2475 (argc+1)*sizeof(*child->argv_nonnull)); 2475 (argc+1)*sizeof(*child->argv_nonnull));
2476 if (child->argv_nonnull == NULL) 2476 if (child->argv_nonnull == NULL)
2477 return 1; 2477 return 1;
2478 child->argv[argc-1]=str; 2478 child->argv[argc-1]=str;
2479 child->argv_nonnull[argc-1] = dest->nonnull; 2479 child->argv_nonnull[argc-1] = dest->nonnull;
2480 child->argv[argc]=NULL; 2480 child->argv[argc]=NULL;
2481 child->argv_nonnull[argc] = 0; 2481 child->argv_nonnull[argc] = 0;
2482 for (s = dest->data; s && *s; s++,str++) { 2482 for (s = dest->data; s && *s; s++,str++) {
2483 if (*s == '\\') s++; 2483 if (*s == '\\') s++;
2484 *str = *s; 2484 *str = *s;
2485 } 2485 }
2486 *str = '\0'; 2486 *str = '\0';
2487 #endif 2487 #endif
2488 #ifndef __U_BOOT__ 2488 #ifndef __U_BOOT__
2489 } 2489 }
2490 gr = xglob(dest, flags, glob_target); 2490 gr = xglob(dest, flags, glob_target);
2491 if (gr != 0) return 1; 2491 if (gr != 0) return 1;
2492 #endif 2492 #endif
2493 2493
2494 b_reset(dest); 2494 b_reset(dest);
2495 #ifndef __U_BOOT__ 2495 #ifndef __U_BOOT__
2496 if (ctx->pending_redirect) { 2496 if (ctx->pending_redirect) {
2497 ctx->pending_redirect=NULL; 2497 ctx->pending_redirect=NULL;
2498 if (glob_target->gl_pathc != 1) { 2498 if (glob_target->gl_pathc != 1) {
2499 error_msg("ambiguous redirect"); 2499 error_msg("ambiguous redirect");
2500 return 1; 2500 return 1;
2501 } 2501 }
2502 } else { 2502 } else {
2503 child->argv = glob_target->gl_pathv; 2503 child->argv = glob_target->gl_pathv;
2504 } 2504 }
2505 #endif 2505 #endif
2506 if (ctx->w == RES_FOR) { 2506 if (ctx->w == RES_FOR) {
2507 done_word(dest,ctx); 2507 done_word(dest,ctx);
2508 done_pipe(ctx,PIPE_SEQ); 2508 done_pipe(ctx,PIPE_SEQ);
2509 } 2509 }
2510 return 0; 2510 return 0;
2511 } 2511 }
2512 2512
2513 /* The only possible error here is out of memory, in which case 2513 /* The only possible error here is out of memory, in which case
2514 * xmalloc exits. */ 2514 * xmalloc exits. */
2515 static int done_command(struct p_context *ctx) 2515 static int done_command(struct p_context *ctx)
2516 { 2516 {
2517 /* The child is really already in the pipe structure, so 2517 /* The child is really already in the pipe structure, so
2518 * advance the pipe counter and make a new, null child. 2518 * advance the pipe counter and make a new, null child.
2519 * Only real trickiness here is that the uncommitted 2519 * Only real trickiness here is that the uncommitted
2520 * child structure, to which ctx->child points, is not 2520 * child structure, to which ctx->child points, is not
2521 * counted in pi->num_progs. */ 2521 * counted in pi->num_progs. */
2522 struct pipe *pi=ctx->pipe; 2522 struct pipe *pi=ctx->pipe;
2523 struct child_prog *prog=ctx->child; 2523 struct child_prog *prog=ctx->child;
2524 2524
2525 if (prog && prog->group == NULL 2525 if (prog && prog->group == NULL
2526 && prog->argv == NULL 2526 && prog->argv == NULL
2527 #ifndef __U_BOOT__ 2527 #ifndef __U_BOOT__
2528 && prog->redirects == NULL) { 2528 && prog->redirects == NULL) {
2529 #else 2529 #else
2530 ) { 2530 ) {
2531 #endif 2531 #endif
2532 debug_printf("done_command: skipping null command\n"); 2532 debug_printf("done_command: skipping null command\n");
2533 return 0; 2533 return 0;
2534 } else if (prog) { 2534 } else if (prog) {
2535 pi->num_progs++; 2535 pi->num_progs++;
2536 debug_printf("done_command: num_progs incremented to %d\n",pi->num_progs); 2536 debug_printf("done_command: num_progs incremented to %d\n",pi->num_progs);
2537 } else { 2537 } else {
2538 debug_printf("done_command: initializing\n"); 2538 debug_printf("done_command: initializing\n");
2539 } 2539 }
2540 pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1)); 2540 pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
2541 2541
2542 prog = pi->progs + pi->num_progs; 2542 prog = pi->progs + pi->num_progs;
2543 #ifndef __U_BOOT__ 2543 #ifndef __U_BOOT__
2544 prog->redirects = NULL; 2544 prog->redirects = NULL;
2545 #endif 2545 #endif
2546 prog->argv = NULL; 2546 prog->argv = NULL;
2547 prog->argv_nonnull = NULL; 2547 prog->argv_nonnull = NULL;
2548 #ifndef __U_BOOT__ 2548 #ifndef __U_BOOT__
2549 prog->is_stopped = 0; 2549 prog->is_stopped = 0;
2550 #endif 2550 #endif
2551 prog->group = NULL; 2551 prog->group = NULL;
2552 #ifndef __U_BOOT__ 2552 #ifndef __U_BOOT__
2553 prog->glob_result.gl_pathv = NULL; 2553 prog->glob_result.gl_pathv = NULL;
2554 prog->family = pi; 2554 prog->family = pi;
2555 #endif 2555 #endif
2556 prog->sp = 0; 2556 prog->sp = 0;
2557 ctx->child = prog; 2557 ctx->child = prog;
2558 prog->type = ctx->type; 2558 prog->type = ctx->type;
2559 2559
2560 /* but ctx->pipe and ctx->list_head remain unchanged */ 2560 /* but ctx->pipe and ctx->list_head remain unchanged */
2561 return 0; 2561 return 0;
2562 } 2562 }
2563 2563
2564 static int done_pipe(struct p_context *ctx, pipe_style type) 2564 static int done_pipe(struct p_context *ctx, pipe_style type)
2565 { 2565 {
2566 struct pipe *new_p; 2566 struct pipe *new_p;
2567 done_command(ctx); /* implicit closure of previous command */ 2567 done_command(ctx); /* implicit closure of previous command */
2568 debug_printf("done_pipe, type %d\n", type); 2568 debug_printf("done_pipe, type %d\n", type);
2569 ctx->pipe->followup = type; 2569 ctx->pipe->followup = type;
2570 ctx->pipe->r_mode = ctx->w; 2570 ctx->pipe->r_mode = ctx->w;
2571 new_p=new_pipe(); 2571 new_p=new_pipe();
2572 ctx->pipe->next = new_p; 2572 ctx->pipe->next = new_p;
2573 ctx->pipe = new_p; 2573 ctx->pipe = new_p;
2574 ctx->child = NULL; 2574 ctx->child = NULL;
2575 done_command(ctx); /* set up new pipe to accept commands */ 2575 done_command(ctx); /* set up new pipe to accept commands */
2576 return 0; 2576 return 0;
2577 } 2577 }
2578 2578
2579 #ifndef __U_BOOT__ 2579 #ifndef __U_BOOT__
2580 /* peek ahead in the in_str to find out if we have a "&n" construct, 2580 /* peek ahead in the in_str to find out if we have a "&n" construct,
2581 * as in "2>&1", that represents duplicating a file descriptor. 2581 * as in "2>&1", that represents duplicating a file descriptor.
2582 * returns either -2 (syntax error), -1 (no &), or the number found. 2582 * returns either -2 (syntax error), -1 (no &), or the number found.
2583 */ 2583 */
2584 static int redirect_dup_num(struct in_str *input) 2584 static int redirect_dup_num(struct in_str *input)
2585 { 2585 {
2586 int ch, d=0, ok=0; 2586 int ch, d=0, ok=0;
2587 ch = b_peek(input); 2587 ch = b_peek(input);
2588 if (ch != '&') return -1; 2588 if (ch != '&') return -1;
2589 2589
2590 b_getch(input); /* get the & */ 2590 b_getch(input); /* get the & */
2591 ch=b_peek(input); 2591 ch=b_peek(input);
2592 if (ch == '-') { 2592 if (ch == '-') {
2593 b_getch(input); 2593 b_getch(input);
2594 return -3; /* "-" represents "close me" */ 2594 return -3; /* "-" represents "close me" */
2595 } 2595 }
2596 while (isdigit(ch)) { 2596 while (isdigit(ch)) {
2597 d = d*10+(ch-'0'); 2597 d = d*10+(ch-'0');
2598 ok=1; 2598 ok=1;
2599 b_getch(input); 2599 b_getch(input);
2600 ch = b_peek(input); 2600 ch = b_peek(input);
2601 } 2601 }
2602 if (ok) return d; 2602 if (ok) return d;
2603 2603
2604 error_msg("ambiguous redirect"); 2604 error_msg("ambiguous redirect");
2605 return -2; 2605 return -2;
2606 } 2606 }
2607 2607
2608 /* If a redirect is immediately preceded by a number, that number is 2608 /* If a redirect is immediately preceded by a number, that number is
2609 * supposed to tell which file descriptor to redirect. This routine 2609 * supposed to tell which file descriptor to redirect. This routine
2610 * looks for such preceding numbers. In an ideal world this routine 2610 * looks for such preceding numbers. In an ideal world this routine
2611 * needs to handle all the following classes of redirects... 2611 * needs to handle all the following classes of redirects...
2612 * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo 2612 * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo
2613 * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo 2613 * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo
2614 * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo 2614 * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo
2615 * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo 2615 * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo
2616 * A -1 output from this program means no valid number was found, so the 2616 * A -1 output from this program means no valid number was found, so the
2617 * caller should use the appropriate default for this redirection. 2617 * caller should use the appropriate default for this redirection.
2618 */ 2618 */
2619 static int redirect_opt_num(o_string *o) 2619 static int redirect_opt_num(o_string *o)
2620 { 2620 {
2621 int num; 2621 int num;
2622 2622
2623 if (o->length==0) return -1; 2623 if (o->length==0) return -1;
2624 for(num=0; num<o->length; num++) { 2624 for(num=0; num<o->length; num++) {
2625 if (!isdigit(*(o->data+num))) { 2625 if (!isdigit(*(o->data+num))) {
2626 return -1; 2626 return -1;
2627 } 2627 }
2628 } 2628 }
2629 /* reuse num (and save an int) */ 2629 /* reuse num (and save an int) */
2630 num=atoi(o->data); 2630 num=atoi(o->data);
2631 b_reset(o); 2631 b_reset(o);
2632 return num; 2632 return num;
2633 } 2633 }
2634 2634
2635 FILE *generate_stream_from_list(struct pipe *head) 2635 FILE *generate_stream_from_list(struct pipe *head)
2636 { 2636 {
2637 FILE *pf; 2637 FILE *pf;
2638 #if 1 2638 #if 1
2639 int pid, channel[2]; 2639 int pid, channel[2];
2640 if (pipe(channel)<0) perror_msg_and_die("pipe"); 2640 if (pipe(channel)<0) perror_msg_and_die("pipe");
2641 pid=fork(); 2641 pid=fork();
2642 if (pid<0) { 2642 if (pid<0) {
2643 perror_msg_and_die("fork"); 2643 perror_msg_and_die("fork");
2644 } else if (pid==0) { 2644 } else if (pid==0) {
2645 close(channel[0]); 2645 close(channel[0]);
2646 if (channel[1] != 1) { 2646 if (channel[1] != 1) {
2647 dup2(channel[1],1); 2647 dup2(channel[1],1);
2648 close(channel[1]); 2648 close(channel[1]);
2649 } 2649 }
2650 #if 0 2650 #if 0
2651 #define SURROGATE "surrogate response" 2651 #define SURROGATE "surrogate response"
2652 write(1,SURROGATE,sizeof(SURROGATE)); 2652 write(1,SURROGATE,sizeof(SURROGATE));
2653 _exit(run_list(head)); 2653 _exit(run_list(head));
2654 #else 2654 #else
2655 _exit(run_list_real(head)); /* leaks memory */ 2655 _exit(run_list_real(head)); /* leaks memory */
2656 #endif 2656 #endif
2657 } 2657 }
2658 debug_printf("forked child %d\n",pid); 2658 debug_printf("forked child %d\n",pid);
2659 close(channel[1]); 2659 close(channel[1]);
2660 pf = fdopen(channel[0],"r"); 2660 pf = fdopen(channel[0],"r");
2661 debug_printf("pipe on FILE *%p\n",pf); 2661 debug_printf("pipe on FILE *%p\n",pf);
2662 #else 2662 #else
2663 free_pipe_list(head,0); 2663 free_pipe_list(head,0);
2664 pf=popen("echo surrogate response","r"); 2664 pf=popen("echo surrogate response","r");
2665 debug_printf("started fake pipe on FILE *%p\n",pf); 2665 debug_printf("started fake pipe on FILE *%p\n",pf);
2666 #endif 2666 #endif
2667 return pf; 2667 return pf;
2668 } 2668 }
2669 2669
2670 /* this version hacked for testing purposes */ 2670 /* this version hacked for testing purposes */
2671 /* return code is exit status of the process that is run. */ 2671 /* return code is exit status of the process that is run. */
2672 static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end) 2672 static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end)
2673 { 2673 {
2674 int retcode; 2674 int retcode;
2675 o_string result=NULL_O_STRING; 2675 o_string result=NULL_O_STRING;
2676 struct p_context inner; 2676 struct p_context inner;
2677 FILE *p; 2677 FILE *p;
2678 struct in_str pipe_str; 2678 struct in_str pipe_str;
2679 initialize_context(&inner); 2679 initialize_context(&inner);
2680 2680
2681 /* recursion to generate command */ 2681 /* recursion to generate command */
2682 retcode = parse_stream(&result, &inner, input, subst_end); 2682 retcode = parse_stream(&result, &inner, input, subst_end);
2683 if (retcode != 0) return retcode; /* syntax error or EOF */ 2683 if (retcode != 0) return retcode; /* syntax error or EOF */
2684 done_word(&result, &inner); 2684 done_word(&result, &inner);
2685 done_pipe(&inner, PIPE_SEQ); 2685 done_pipe(&inner, PIPE_SEQ);
2686 b_free(&result); 2686 b_free(&result);
2687 2687
2688 p=generate_stream_from_list(inner.list_head); 2688 p=generate_stream_from_list(inner.list_head);
2689 if (p==NULL) return 1; 2689 if (p==NULL) return 1;
2690 mark_open(fileno(p)); 2690 mark_open(fileno(p));
2691 setup_file_in_str(&pipe_str, p); 2691 setup_file_in_str(&pipe_str, p);
2692 2692
2693 /* now send results of command back into original context */ 2693 /* now send results of command back into original context */
2694 retcode = parse_stream(dest, ctx, &pipe_str, '\0'); 2694 retcode = parse_stream(dest, ctx, &pipe_str, '\0');
2695 /* XXX In case of a syntax error, should we try to kill the child? 2695 /* XXX In case of a syntax error, should we try to kill the child?
2696 * That would be tough to do right, so just read until EOF. */ 2696 * That would be tough to do right, so just read until EOF. */
2697 if (retcode == 1) { 2697 if (retcode == 1) {
2698 while (b_getch(&pipe_str)!=EOF) { /* discard */ }; 2698 while (b_getch(&pipe_str)!=EOF) { /* discard */ };
2699 } 2699 }
2700 2700
2701 debug_printf("done reading from pipe, pclose()ing\n"); 2701 debug_printf("done reading from pipe, pclose()ing\n");
2702 /* This is the step that wait()s for the child. Should be pretty 2702 /* This is the step that wait()s for the child. Should be pretty
2703 * safe, since we just read an EOF from its stdout. We could try 2703 * safe, since we just read an EOF from its stdout. We could try
2704 * to better, by using wait(), and keeping track of background jobs 2704 * to better, by using wait(), and keeping track of background jobs
2705 * at the same time. That would be a lot of work, and contrary 2705 * at the same time. That would be a lot of work, and contrary
2706 * to the KISS philosophy of this program. */ 2706 * to the KISS philosophy of this program. */
2707 mark_closed(fileno(p)); 2707 mark_closed(fileno(p));
2708 retcode=pclose(p); 2708 retcode=pclose(p);
2709 free_pipe_list(inner.list_head,0); 2709 free_pipe_list(inner.list_head,0);
2710 debug_printf("pclosed, retcode=%d\n",retcode); 2710 debug_printf("pclosed, retcode=%d\n",retcode);
2711 /* XXX this process fails to trim a single trailing newline */ 2711 /* XXX this process fails to trim a single trailing newline */
2712 return retcode; 2712 return retcode;
2713 } 2713 }
2714 2714
2715 static int parse_group(o_string *dest, struct p_context *ctx, 2715 static int parse_group(o_string *dest, struct p_context *ctx,
2716 struct in_str *input, int ch) 2716 struct in_str *input, int ch)
2717 { 2717 {
2718 int rcode, endch=0; 2718 int rcode, endch=0;
2719 struct p_context sub; 2719 struct p_context sub;
2720 struct child_prog *child = ctx->child; 2720 struct child_prog *child = ctx->child;
2721 if (child->argv) { 2721 if (child->argv) {
2722 syntax(); 2722 syntax();
2723 return 1; /* syntax error, groups and arglists don't mix */ 2723 return 1; /* syntax error, groups and arglists don't mix */
2724 } 2724 }
2725 initialize_context(&sub); 2725 initialize_context(&sub);
2726 switch(ch) { 2726 switch(ch) {
2727 case '(': endch=')'; child->subshell=1; break; 2727 case '(': endch=')'; child->subshell=1; break;
2728 case '{': endch='}'; break; 2728 case '{': endch='}'; break;
2729 default: syntax(); /* really logic error */ 2729 default: syntax(); /* really logic error */
2730 } 2730 }
2731 rcode=parse_stream(dest,&sub,input,endch); 2731 rcode=parse_stream(dest,&sub,input,endch);
2732 done_word(dest,&sub); /* finish off the final word in the subcontext */ 2732 done_word(dest,&sub); /* finish off the final word in the subcontext */
2733 done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ 2733 done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */
2734 child->group = sub.list_head; 2734 child->group = sub.list_head;
2735 return rcode; 2735 return rcode;
2736 /* child remains "open", available for possible redirects */ 2736 /* child remains "open", available for possible redirects */
2737 } 2737 }
2738 #endif 2738 #endif
2739 2739
2740 /* basically useful version until someone wants to get fancier, 2740 /* basically useful version until someone wants to get fancier,
2741 * see the bash man page under "Parameter Expansion" */ 2741 * see the bash man page under "Parameter Expansion" */
2742 static char *lookup_param(char *src) 2742 static char *lookup_param(char *src)
2743 { 2743 {
2744 char *p; 2744 char *p;
2745 char *sep; 2745 char *sep;
2746 char *default_val = NULL; 2746 char *default_val = NULL;
2747 int assign = 0; 2747 int assign = 0;
2748 int expand_empty = 0; 2748 int expand_empty = 0;
2749 2749
2750 if (!src) 2750 if (!src)
2751 return NULL; 2751 return NULL;
2752 2752
2753 sep = strchr(src, ':'); 2753 sep = strchr(src, ':');
2754 2754
2755 if (sep) { 2755 if (sep) {
2756 *sep = '\0'; 2756 *sep = '\0';
2757 if (*(sep + 1) == '-') 2757 if (*(sep + 1) == '-')
2758 default_val = sep+2; 2758 default_val = sep+2;
2759 if (*(sep + 1) == '=') { 2759 if (*(sep + 1) == '=') {
2760 default_val = sep+2; 2760 default_val = sep+2;
2761 assign = 1; 2761 assign = 1;
2762 } 2762 }
2763 if (*(sep + 1) == '+') { 2763 if (*(sep + 1) == '+') {
2764 default_val = sep+2; 2764 default_val = sep+2;
2765 expand_empty = 1; 2765 expand_empty = 1;
2766 } 2766 }
2767 } 2767 }
2768 2768
2769 p = getenv(src); 2769 p = getenv(src);
2770 if (!p) 2770 if (!p)
2771 p = get_local_var(src); 2771 p = get_local_var(src);
2772 2772
2773 if (!p || strlen(p) == 0) { 2773 if (!p || strlen(p) == 0) {
2774 p = default_val; 2774 p = default_val;
2775 if (assign) { 2775 if (assign) {
2776 char *var = malloc(strlen(src)+strlen(default_val)+2); 2776 char *var = malloc(strlen(src)+strlen(default_val)+2);
2777 if (var) { 2777 if (var) {
2778 sprintf(var, "%s=%s", src, default_val); 2778 sprintf(var, "%s=%s", src, default_val);
2779 set_local_var(var, 0); 2779 set_local_var(var, 0);
2780 } 2780 }
2781 free(var); 2781 free(var);
2782 } 2782 }
2783 } else if (expand_empty) { 2783 } else if (expand_empty) {
2784 p += strlen(p); 2784 p += strlen(p);
2785 } 2785 }
2786 2786
2787 if (sep) 2787 if (sep)
2788 *sep = ':'; 2788 *sep = ':';
2789 2789
2790 return p; 2790 return p;
2791 } 2791 }
2792 2792
2793 #ifdef __U_BOOT__ 2793 #ifdef __U_BOOT__
2794 static char *get_dollar_var(char ch) 2794 static char *get_dollar_var(char ch)
2795 { 2795 {
2796 static char buf[40]; 2796 static char buf[40];
2797 2797
2798 buf[0] = '\0'; 2798 buf[0] = '\0';
2799 switch (ch) { 2799 switch (ch) {
2800 case '?': 2800 case '?':
2801 sprintf(buf, "%u", (unsigned int)last_return_code); 2801 sprintf(buf, "%u", (unsigned int)last_return_code);
2802 break; 2802 break;
2803 default: 2803 default:
2804 return NULL; 2804 return NULL;
2805 } 2805 }
2806 return buf; 2806 return buf;
2807 } 2807 }
2808 #endif 2808 #endif
2809 2809
2810 /* return code: 0 for OK, 1 for syntax error */ 2810 /* return code: 0 for OK, 1 for syntax error */
2811 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input) 2811 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
2812 { 2812 {
2813 #ifndef __U_BOOT__ 2813 #ifndef __U_BOOT__
2814 int i, advance=0; 2814 int i, advance=0;
2815 #else 2815 #else
2816 int advance=0; 2816 int advance=0;
2817 #endif 2817 #endif
2818 #ifndef __U_BOOT__ 2818 #ifndef __U_BOOT__
2819 char sep[]=" "; 2819 char sep[]=" ";
2820 #endif 2820 #endif
2821 int ch = input->peek(input); /* first character after the $ */ 2821 int ch = input->peek(input); /* first character after the $ */
2822 debug_printf("handle_dollar: ch=%c\n",ch); 2822 debug_printf("handle_dollar: ch=%c\n",ch);
2823 if (isalpha(ch)) { 2823 if (isalpha(ch)) {
2824 b_addchr(dest, SPECIAL_VAR_SYMBOL); 2824 b_addchr(dest, SPECIAL_VAR_SYMBOL);
2825 ctx->child->sp++; 2825 ctx->child->sp++;
2826 while(ch=b_peek(input),isalnum(ch) || ch=='_') { 2826 while(ch=b_peek(input),isalnum(ch) || ch=='_') {
2827 b_getch(input); 2827 b_getch(input);
2828 b_addchr(dest,ch); 2828 b_addchr(dest,ch);
2829 } 2829 }
2830 b_addchr(dest, SPECIAL_VAR_SYMBOL); 2830 b_addchr(dest, SPECIAL_VAR_SYMBOL);
2831 #ifndef __U_BOOT__ 2831 #ifndef __U_BOOT__
2832 } else if (isdigit(ch)) { 2832 } else if (isdigit(ch)) {
2833 i = ch-'0'; /* XXX is $0 special? */ 2833 i = ch-'0'; /* XXX is $0 special? */
2834 if (i<global_argc) { 2834 if (i<global_argc) {
2835 parse_string(dest, ctx, global_argv[i]); /* recursion */ 2835 parse_string(dest, ctx, global_argv[i]); /* recursion */
2836 } 2836 }
2837 advance = 1; 2837 advance = 1;
2838 #endif 2838 #endif
2839 } else switch (ch) { 2839 } else switch (ch) {
2840 #ifndef __U_BOOT__ 2840 #ifndef __U_BOOT__
2841 case '$': 2841 case '$':
2842 b_adduint(dest,getpid()); 2842 b_adduint(dest,getpid());
2843 advance = 1; 2843 advance = 1;
2844 break; 2844 break;
2845 case '!': 2845 case '!':
2846 if (last_bg_pid > 0) b_adduint(dest, last_bg_pid); 2846 if (last_bg_pid > 0) b_adduint(dest, last_bg_pid);
2847 advance = 1; 2847 advance = 1;
2848 break; 2848 break;
2849 #endif 2849 #endif
2850 case '?': 2850 case '?':
2851 #ifndef __U_BOOT__ 2851 #ifndef __U_BOOT__
2852 b_adduint(dest,last_return_code); 2852 b_adduint(dest,last_return_code);
2853 #else 2853 #else
2854 ctx->child->sp++; 2854 ctx->child->sp++;
2855 b_addchr(dest, SPECIAL_VAR_SYMBOL); 2855 b_addchr(dest, SPECIAL_VAR_SYMBOL);
2856 b_addchr(dest, '$'); 2856 b_addchr(dest, '$');
2857 b_addchr(dest, '?'); 2857 b_addchr(dest, '?');
2858 b_addchr(dest, SPECIAL_VAR_SYMBOL); 2858 b_addchr(dest, SPECIAL_VAR_SYMBOL);
2859 #endif 2859 #endif
2860 advance = 1; 2860 advance = 1;
2861 break; 2861 break;
2862 #ifndef __U_BOOT__ 2862 #ifndef __U_BOOT__
2863 case '#': 2863 case '#':
2864 b_adduint(dest,global_argc ? global_argc-1 : 0); 2864 b_adduint(dest,global_argc ? global_argc-1 : 0);
2865 advance = 1; 2865 advance = 1;
2866 break; 2866 break;
2867 #endif 2867 #endif
2868 case '{': 2868 case '{':
2869 b_addchr(dest, SPECIAL_VAR_SYMBOL); 2869 b_addchr(dest, SPECIAL_VAR_SYMBOL);
2870 ctx->child->sp++; 2870 ctx->child->sp++;
2871 b_getch(input); 2871 b_getch(input);
2872 /* XXX maybe someone will try to escape the '}' */ 2872 /* XXX maybe someone will try to escape the '}' */
2873 while(ch=b_getch(input),ch!=EOF && ch!='}') { 2873 while(ch=b_getch(input),ch!=EOF && ch!='}') {
2874 b_addchr(dest,ch); 2874 b_addchr(dest,ch);
2875 } 2875 }
2876 if (ch != '}') { 2876 if (ch != '}') {
2877 syntax(); 2877 syntax();
2878 return 1; 2878 return 1;
2879 } 2879 }
2880 b_addchr(dest, SPECIAL_VAR_SYMBOL); 2880 b_addchr(dest, SPECIAL_VAR_SYMBOL);
2881 break; 2881 break;
2882 #ifndef __U_BOOT__ 2882 #ifndef __U_BOOT__
2883 case '(': 2883 case '(':
2884 b_getch(input); 2884 b_getch(input);
2885 process_command_subs(dest, ctx, input, ')'); 2885 process_command_subs(dest, ctx, input, ')');
2886 break; 2886 break;
2887 case '*': 2887 case '*':
2888 sep[0]=ifs[0]; 2888 sep[0]=ifs[0];
2889 for (i=1; i<global_argc; i++) { 2889 for (i=1; i<global_argc; i++) {
2890 parse_string(dest, ctx, global_argv[i]); 2890 parse_string(dest, ctx, global_argv[i]);
2891 if (i+1 < global_argc) parse_string(dest, ctx, sep); 2891 if (i+1 < global_argc) parse_string(dest, ctx, sep);
2892 } 2892 }
2893 break; 2893 break;
2894 case '@': 2894 case '@':
2895 case '-': 2895 case '-':
2896 case '_': 2896 case '_':
2897 /* still unhandled, but should be eventually */ 2897 /* still unhandled, but should be eventually */
2898 error_msg("unhandled syntax: $%c",ch); 2898 error_msg("unhandled syntax: $%c",ch);
2899 return 1; 2899 return 1;
2900 break; 2900 break;
2901 #endif 2901 #endif
2902 default: 2902 default:
2903 b_addqchr(dest,'$',dest->quote); 2903 b_addqchr(dest,'$',dest->quote);
2904 } 2904 }
2905 /* Eat the character if the flag was set. If the compiler 2905 /* Eat the character if the flag was set. If the compiler
2906 * is smart enough, we could substitute "b_getch(input);" 2906 * is smart enough, we could substitute "b_getch(input);"
2907 * for all the "advance = 1;" above, and also end up with 2907 * for all the "advance = 1;" above, and also end up with
2908 * a nice size-optimized program. Hah! That'll be the day. 2908 * a nice size-optimized program. Hah! That'll be the day.
2909 */ 2909 */
2910 if (advance) b_getch(input); 2910 if (advance) b_getch(input);
2911 return 0; 2911 return 0;
2912 } 2912 }
2913 2913
2914 #ifndef __U_BOOT__ 2914 #ifndef __U_BOOT__
2915 int parse_string(o_string *dest, struct p_context *ctx, const char *src) 2915 int parse_string(o_string *dest, struct p_context *ctx, const char *src)
2916 { 2916 {
2917 struct in_str foo; 2917 struct in_str foo;
2918 setup_string_in_str(&foo, src); 2918 setup_string_in_str(&foo, src);
2919 return parse_stream(dest, ctx, &foo, '\0'); 2919 return parse_stream(dest, ctx, &foo, '\0');
2920 } 2920 }
2921 #endif 2921 #endif
2922 2922
2923 /* return code is 0 for normal exit, 1 for syntax error */ 2923 /* return code is 0 for normal exit, 1 for syntax error */
2924 static int parse_stream(o_string *dest, struct p_context *ctx, 2924 static int parse_stream(o_string *dest, struct p_context *ctx,
2925 struct in_str *input, int end_trigger) 2925 struct in_str *input, int end_trigger)
2926 { 2926 {
2927 unsigned int ch, m; 2927 unsigned int ch, m;
2928 #ifndef __U_BOOT__ 2928 #ifndef __U_BOOT__
2929 int redir_fd; 2929 int redir_fd;
2930 redir_type redir_style; 2930 redir_type redir_style;
2931 #endif 2931 #endif
2932 int next; 2932 int next;
2933 2933
2934 /* Only double-quote state is handled in the state variable dest->quote. 2934 /* Only double-quote state is handled in the state variable dest->quote.
2935 * A single-quote triggers a bypass of the main loop until its mate is 2935 * A single-quote triggers a bypass of the main loop until its mate is
2936 * found. When recursing, quote state is passed in via dest->quote. */ 2936 * found. When recursing, quote state is passed in via dest->quote. */
2937 2937
2938 debug_printf("parse_stream, end_trigger=%d\n",end_trigger); 2938 debug_printf("parse_stream, end_trigger=%d\n",end_trigger);
2939 while ((ch=b_getch(input))!=EOF) { 2939 while ((ch=b_getch(input))!=EOF) {
2940 m = map[ch]; 2940 m = map[ch];
2941 #ifdef __U_BOOT__ 2941 #ifdef __U_BOOT__
2942 if (input->__promptme == 0) return 1; 2942 if (input->__promptme == 0) return 1;
2943 #endif 2943 #endif
2944 next = (ch == '\n') ? 0 : b_peek(input); 2944 next = (ch == '\n') ? 0 : b_peek(input);
2945 2945
2946 debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n", 2946 debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n",
2947 ch >= ' ' ? ch : '.', ch, m, 2947 ch >= ' ' ? ch : '.', ch, m,
2948 dest->quote, ctx->stack == NULL ? '*' : '.'); 2948 dest->quote, ctx->stack == NULL ? '*' : '.');
2949 2949
2950 if (m==0 || ((m==1 || m==2) && dest->quote)) { 2950 if (m==0 || ((m==1 || m==2) && dest->quote)) {
2951 b_addqchr(dest, ch, dest->quote); 2951 b_addqchr(dest, ch, dest->quote);
2952 } else { 2952 } else {
2953 if (m==2) { /* unquoted IFS */ 2953 if (m==2) { /* unquoted IFS */
2954 if (done_word(dest, ctx)) { 2954 if (done_word(dest, ctx)) {
2955 return 1; 2955 return 1;
2956 } 2956 }
2957 /* If we aren't performing a substitution, treat a newline as a 2957 /* If we aren't performing a substitution, treat a newline as a
2958 * command separator. */ 2958 * command separator. */
2959 if (end_trigger != '\0' && ch=='\n') 2959 if (end_trigger != '\0' && ch=='\n')
2960 done_pipe(ctx,PIPE_SEQ); 2960 done_pipe(ctx,PIPE_SEQ);
2961 } 2961 }
2962 if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) { 2962 if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
2963 debug_printf("leaving parse_stream (triggered)\n"); 2963 debug_printf("leaving parse_stream (triggered)\n");
2964 return 0; 2964 return 0;
2965 } 2965 }
2966 #if 0 2966 #if 0
2967 if (ch=='\n') { 2967 if (ch=='\n') {
2968 /* Yahoo! Time to run with it! */ 2968 /* Yahoo! Time to run with it! */
2969 done_pipe(ctx,PIPE_SEQ); 2969 done_pipe(ctx,PIPE_SEQ);
2970 run_list(ctx->list_head); 2970 run_list(ctx->list_head);
2971 initialize_context(ctx); 2971 initialize_context(ctx);
2972 } 2972 }
2973 #endif 2973 #endif
2974 if (m!=2) switch (ch) { 2974 if (m!=2) switch (ch) {
2975 case '#': 2975 case '#':
2976 if (dest->length == 0 && !dest->quote) { 2976 if (dest->length == 0 && !dest->quote) {
2977 while(ch=b_peek(input),ch!=EOF && ch!='\n') { b_getch(input); } 2977 while(ch=b_peek(input),ch!=EOF && ch!='\n') { b_getch(input); }
2978 } else { 2978 } else {
2979 b_addqchr(dest, ch, dest->quote); 2979 b_addqchr(dest, ch, dest->quote);
2980 } 2980 }
2981 break; 2981 break;
2982 case '\\': 2982 case '\\':
2983 if (next == EOF) { 2983 if (next == EOF) {
2984 syntax(); 2984 syntax();
2985 return 1; 2985 return 1;
2986 } 2986 }
2987 b_addqchr(dest, '\\', dest->quote); 2987 b_addqchr(dest, '\\', dest->quote);
2988 b_addqchr(dest, b_getch(input), dest->quote); 2988 b_addqchr(dest, b_getch(input), dest->quote);
2989 break; 2989 break;
2990 case '$': 2990 case '$':
2991 if (handle_dollar(dest, ctx, input)!=0) return 1; 2991 if (handle_dollar(dest, ctx, input)!=0) return 1;
2992 break; 2992 break;
2993 case '\'': 2993 case '\'':
2994 dest->nonnull = 1; 2994 dest->nonnull = 1;
2995 while(ch=b_getch(input),ch!=EOF && ch!='\'') { 2995 while(ch=b_getch(input),ch!=EOF && ch!='\'') {
2996 #ifdef __U_BOOT__ 2996 #ifdef __U_BOOT__
2997 if(input->__promptme == 0) return 1; 2997 if(input->__promptme == 0) return 1;
2998 #endif 2998 #endif
2999 b_addchr(dest,ch); 2999 b_addchr(dest,ch);
3000 } 3000 }
3001 if (ch==EOF) { 3001 if (ch==EOF) {
3002 syntax(); 3002 syntax();
3003 return 1; 3003 return 1;
3004 } 3004 }
3005 break; 3005 break;
3006 case '"': 3006 case '"':
3007 dest->nonnull = 1; 3007 dest->nonnull = 1;
3008 dest->quote = !dest->quote; 3008 dest->quote = !dest->quote;
3009 break; 3009 break;
3010 #ifndef __U_BOOT__ 3010 #ifndef __U_BOOT__
3011 case '`': 3011 case '`':
3012 process_command_subs(dest, ctx, input, '`'); 3012 process_command_subs(dest, ctx, input, '`');
3013 break; 3013 break;
3014 case '>': 3014 case '>':
3015 redir_fd = redirect_opt_num(dest); 3015 redir_fd = redirect_opt_num(dest);
3016 done_word(dest, ctx); 3016 done_word(dest, ctx);
3017 redir_style=REDIRECT_OVERWRITE; 3017 redir_style=REDIRECT_OVERWRITE;
3018 if (next == '>') { 3018 if (next == '>') {
3019 redir_style=REDIRECT_APPEND; 3019 redir_style=REDIRECT_APPEND;
3020 b_getch(input); 3020 b_getch(input);
3021 } else if (next == '(') { 3021 } else if (next == '(') {
3022 syntax(); /* until we support >(list) Process Substitution */ 3022 syntax(); /* until we support >(list) Process Substitution */
3023 return 1; 3023 return 1;
3024 } 3024 }
3025 setup_redirect(ctx, redir_fd, redir_style, input); 3025 setup_redirect(ctx, redir_fd, redir_style, input);
3026 break; 3026 break;
3027 case '<': 3027 case '<':
3028 redir_fd = redirect_opt_num(dest); 3028 redir_fd = redirect_opt_num(dest);
3029 done_word(dest, ctx); 3029 done_word(dest, ctx);
3030 redir_style=REDIRECT_INPUT; 3030 redir_style=REDIRECT_INPUT;
3031 if (next == '<') { 3031 if (next == '<') {
3032 redir_style=REDIRECT_HEREIS; 3032 redir_style=REDIRECT_HEREIS;
3033 b_getch(input); 3033 b_getch(input);
3034 } else if (next == '>') { 3034 } else if (next == '>') {
3035 redir_style=REDIRECT_IO; 3035 redir_style=REDIRECT_IO;
3036 b_getch(input); 3036 b_getch(input);
3037 } else if (next == '(') { 3037 } else if (next == '(') {
3038 syntax(); /* until we support <(list) Process Substitution */ 3038 syntax(); /* until we support <(list) Process Substitution */
3039 return 1; 3039 return 1;
3040 } 3040 }
3041 setup_redirect(ctx, redir_fd, redir_style, input); 3041 setup_redirect(ctx, redir_fd, redir_style, input);
3042 break; 3042 break;
3043 #endif 3043 #endif
3044 case ';': 3044 case ';':
3045 done_word(dest, ctx); 3045 done_word(dest, ctx);
3046 done_pipe(ctx,PIPE_SEQ); 3046 done_pipe(ctx,PIPE_SEQ);
3047 break; 3047 break;
3048 case '&': 3048 case '&':
3049 done_word(dest, ctx); 3049 done_word(dest, ctx);
3050 if (next=='&') { 3050 if (next=='&') {
3051 b_getch(input); 3051 b_getch(input);
3052 done_pipe(ctx,PIPE_AND); 3052 done_pipe(ctx,PIPE_AND);
3053 } else { 3053 } else {
3054 #ifndef __U_BOOT__ 3054 #ifndef __U_BOOT__
3055 done_pipe(ctx,PIPE_BG); 3055 done_pipe(ctx,PIPE_BG);
3056 #else 3056 #else
3057 syntax_err(); 3057 syntax_err();
3058 return 1; 3058 return 1;
3059 #endif 3059 #endif
3060 } 3060 }
3061 break; 3061 break;
3062 case '|': 3062 case '|':
3063 done_word(dest, ctx); 3063 done_word(dest, ctx);
3064 if (next=='|') { 3064 if (next=='|') {
3065 b_getch(input); 3065 b_getch(input);
3066 done_pipe(ctx,PIPE_OR); 3066 done_pipe(ctx,PIPE_OR);
3067 } else { 3067 } else {
3068 /* we could pick up a file descriptor choice here 3068 /* we could pick up a file descriptor choice here
3069 * with redirect_opt_num(), but bash doesn't do it. 3069 * with redirect_opt_num(), but bash doesn't do it.
3070 * "echo foo 2| cat" yields "foo 2". */ 3070 * "echo foo 2| cat" yields "foo 2". */
3071 #ifndef __U_BOOT__ 3071 #ifndef __U_BOOT__
3072 done_command(ctx); 3072 done_command(ctx);
3073 #else 3073 #else
3074 syntax_err(); 3074 syntax_err();
3075 return 1; 3075 return 1;
3076 #endif 3076 #endif
3077 } 3077 }
3078 break; 3078 break;
3079 #ifndef __U_BOOT__ 3079 #ifndef __U_BOOT__
3080 case '(': 3080 case '(':
3081 case '{': 3081 case '{':
3082 if (parse_group(dest, ctx, input, ch)!=0) return 1; 3082 if (parse_group(dest, ctx, input, ch)!=0) return 1;
3083 break; 3083 break;
3084 case ')': 3084 case ')':
3085 case '}': 3085 case '}':
3086 syntax(); /* Proper use of this character caught by end_trigger */ 3086 syntax(); /* Proper use of this character caught by end_trigger */
3087 return 1; 3087 return 1;
3088 break; 3088 break;
3089 #endif 3089 #endif
3090 case SUBSTED_VAR_SYMBOL: 3090 case SUBSTED_VAR_SYMBOL:
3091 dest->nonnull = 1; 3091 dest->nonnull = 1;
3092 while (ch = b_getch(input), ch != EOF && 3092 while (ch = b_getch(input), ch != EOF &&
3093 ch != SUBSTED_VAR_SYMBOL) { 3093 ch != SUBSTED_VAR_SYMBOL) {
3094 debug_printf("subst, pass=%d\n", ch); 3094 debug_printf("subst, pass=%d\n", ch);
3095 if (input->__promptme == 0) 3095 if (input->__promptme == 0)
3096 return 1; 3096 return 1;
3097 b_addchr(dest, ch); 3097 b_addchr(dest, ch);
3098 } 3098 }
3099 debug_printf("subst, term=%d\n", ch); 3099 debug_printf("subst, term=%d\n", ch);
3100 if (ch == EOF) { 3100 if (ch == EOF) {
3101 syntax(); 3101 syntax();
3102 return 1; 3102 return 1;
3103 } 3103 }
3104 break; 3104 break;
3105 default: 3105 default:
3106 syntax(); /* this is really an internal logic error */ 3106 syntax(); /* this is really an internal logic error */
3107 return 1; 3107 return 1;
3108 } 3108 }
3109 } 3109 }
3110 } 3110 }
3111 /* complain if quote? No, maybe we just finished a command substitution 3111 /* complain if quote? No, maybe we just finished a command substitution
3112 * that was quoted. Example: 3112 * that was quoted. Example:
3113 * $ echo "`cat foo` plus more" 3113 * $ echo "`cat foo` plus more"
3114 * and we just got the EOF generated by the subshell that ran "cat foo" 3114 * and we just got the EOF generated by the subshell that ran "cat foo"
3115 * The only real complaint is if we got an EOF when end_trigger != '\0', 3115 * The only real complaint is if we got an EOF when end_trigger != '\0',
3116 * that is, we were really supposed to get end_trigger, and never got 3116 * that is, we were really supposed to get end_trigger, and never got
3117 * one before the EOF. Can't use the standard "syntax error" return code, 3117 * one before the EOF. Can't use the standard "syntax error" return code,
3118 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */ 3118 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
3119 debug_printf("leaving parse_stream (EOF)\n"); 3119 debug_printf("leaving parse_stream (EOF)\n");
3120 if (end_trigger != '\0') return -1; 3120 if (end_trigger != '\0') return -1;
3121 return 0; 3121 return 0;
3122 } 3122 }
3123 3123
3124 static void mapset(const unsigned char *set, int code) 3124 static void mapset(const unsigned char *set, int code)
3125 { 3125 {
3126 const unsigned char *s; 3126 const unsigned char *s;
3127 for (s=set; *s; s++) map[*s] = code; 3127 for (s=set; *s; s++) map[*s] = code;
3128 } 3128 }
3129 3129
3130 static void update_ifs_map(void) 3130 static void update_ifs_map(void)
3131 { 3131 {
3132 /* char *ifs and char map[256] are both globals. */ 3132 /* char *ifs and char map[256] are both globals. */
3133 ifs = (uchar *)getenv("IFS"); 3133 ifs = (uchar *)getenv("IFS");
3134 if (ifs == NULL) ifs=(uchar *)" \t\n"; 3134 if (ifs == NULL) ifs=(uchar *)" \t\n";
3135 /* Precompute a list of 'flow through' behavior so it can be treated 3135 /* Precompute a list of 'flow through' behavior so it can be treated
3136 * quickly up front. Computation is necessary because of IFS. 3136 * quickly up front. Computation is necessary because of IFS.
3137 * Special case handling of IFS == " \t\n" is not implemented. 3137 * Special case handling of IFS == " \t\n" is not implemented.
3138 * The map[] array only really needs two bits each, and on most machines 3138 * The map[] array only really needs two bits each, and on most machines
3139 * that would be faster because of the reduced L1 cache footprint. 3139 * that would be faster because of the reduced L1 cache footprint.
3140 */ 3140 */
3141 memset(map,0,sizeof(map)); /* most characters flow through always */ 3141 memset(map,0,sizeof(map)); /* most characters flow through always */
3142 #ifndef __U_BOOT__ 3142 #ifndef __U_BOOT__
3143 mapset((uchar *)"\\$'\"`", 3); /* never flow through */ 3143 mapset((uchar *)"\\$'\"`", 3); /* never flow through */
3144 mapset((uchar *)"<>;&|(){}#", 1); /* flow through if quoted */ 3144 mapset((uchar *)"<>;&|(){}#", 1); /* flow through if quoted */
3145 #else 3145 #else
3146 { 3146 {
3147 uchar subst[2] = {SUBSTED_VAR_SYMBOL, 0}; 3147 uchar subst[2] = {SUBSTED_VAR_SYMBOL, 0};
3148 mapset(subst, 3); /* never flow through */ 3148 mapset(subst, 3); /* never flow through */
3149 } 3149 }
3150 mapset((uchar *)"\\$'\"", 3); /* never flow through */ 3150 mapset((uchar *)"\\$'\"", 3); /* never flow through */
3151 mapset((uchar *)";&|#", 1); /* flow through if quoted */ 3151 mapset((uchar *)";&|#", 1); /* flow through if quoted */
3152 #endif 3152 #endif
3153 mapset(ifs, 2); /* also flow through if quoted */ 3153 mapset(ifs, 2); /* also flow through if quoted */
3154 } 3154 }
3155 3155
3156 /* most recursion does not come through here, the exeception is 3156 /* most recursion does not come through here, the exeception is
3157 * from builtin_source() */ 3157 * from builtin_source() */
3158 static int parse_stream_outer(struct in_str *inp, int flag) 3158 static int parse_stream_outer(struct in_str *inp, int flag)
3159 { 3159 {
3160 3160
3161 struct p_context ctx; 3161 struct p_context ctx;
3162 o_string temp=NULL_O_STRING; 3162 o_string temp=NULL_O_STRING;
3163 int rcode; 3163 int rcode;
3164 #ifdef __U_BOOT__ 3164 #ifdef __U_BOOT__
3165 int code = 1; 3165 int code = 1;
3166 #endif 3166 #endif
3167 do { 3167 do {
3168 ctx.type = flag; 3168 ctx.type = flag;
3169 initialize_context(&ctx); 3169 initialize_context(&ctx);
3170 update_ifs_map(); 3170 update_ifs_map();
3171 if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";$&|", 0); 3171 if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";$&|", 0);
3172 inp->promptmode=1; 3172 inp->promptmode=1;
3173 rcode = parse_stream(&temp, &ctx, inp, 3173 rcode = parse_stream(&temp, &ctx, inp,
3174 flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n'); 3174 flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n');
3175 #ifdef __U_BOOT__ 3175 #ifdef __U_BOOT__
3176 if (rcode == 1) flag_repeat = 0; 3176 if (rcode == 1) flag_repeat = 0;
3177 #endif 3177 #endif
3178 if (rcode != 1 && ctx.old_flag != 0) { 3178 if (rcode != 1 && ctx.old_flag != 0) {
3179 syntax(); 3179 syntax();
3180 #ifdef __U_BOOT__ 3180 #ifdef __U_BOOT__
3181 flag_repeat = 0; 3181 flag_repeat = 0;
3182 #endif 3182 #endif
3183 } 3183 }
3184 if (rcode != 1 && ctx.old_flag == 0) { 3184 if (rcode != 1 && ctx.old_flag == 0) {
3185 done_word(&temp, &ctx); 3185 done_word(&temp, &ctx);
3186 done_pipe(&ctx,PIPE_SEQ); 3186 done_pipe(&ctx,PIPE_SEQ);
3187 #ifndef __U_BOOT__ 3187 #ifndef __U_BOOT__
3188 run_list(ctx.list_head); 3188 run_list(ctx.list_head);
3189 #else 3189 #else
3190 code = run_list(ctx.list_head); 3190 code = run_list(ctx.list_head);
3191 if (code == -2) { /* exit */ 3191 if (code == -2) { /* exit */
3192 b_free(&temp); 3192 b_free(&temp);
3193 code = 0; 3193 code = 0;
3194 /* XXX hackish way to not allow exit from main loop */ 3194 /* XXX hackish way to not allow exit from main loop */
3195 if (inp->peek == file_peek) { 3195 if (inp->peek == file_peek) {
3196 printf("exit not allowed from main input shell.\n"); 3196 printf("exit not allowed from main input shell.\n");
3197 continue; 3197 continue;
3198 } 3198 }
3199 break; 3199 break;
3200 } 3200 }
3201 if (code == -1) 3201 if (code == -1)
3202 flag_repeat = 0; 3202 flag_repeat = 0;
3203 #endif 3203 #endif
3204 } else { 3204 } else {
3205 if (ctx.old_flag != 0) { 3205 if (ctx.old_flag != 0) {
3206 free(ctx.stack); 3206 free(ctx.stack);
3207 b_reset(&temp); 3207 b_reset(&temp);
3208 } 3208 }
3209 #ifdef __U_BOOT__ 3209 #ifdef __U_BOOT__
3210 if (inp->__promptme == 0) printf("<INTERRUPT>\n"); 3210 if (inp->__promptme == 0) printf("<INTERRUPT>\n");
3211 inp->__promptme = 1; 3211 inp->__promptme = 1;
3212 #endif 3212 #endif
3213 temp.nonnull = 0; 3213 temp.nonnull = 0;
3214 temp.quote = 0; 3214 temp.quote = 0;
3215 inp->p = NULL; 3215 inp->p = NULL;
3216 free_pipe_list(ctx.list_head,0); 3216 free_pipe_list(ctx.list_head,0);
3217 } 3217 }
3218 b_free(&temp); 3218 b_free(&temp);
3219 /* loop on syntax errors, return on EOF */ 3219 /* loop on syntax errors, return on EOF */
3220 } while (rcode != 1 && !(flag & FLAG_EXIT_FROM_LOOP) && 3220 } while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP) &&
3221 (inp->peek != static_peek || b_peek(inp))); 3221 (inp->peek != static_peek || b_peek(inp)));
3222 #ifndef __U_BOOT__ 3222 #ifndef __U_BOOT__
3223 return 0; 3223 return 0;
3224 #else 3224 #else
3225 return (code != 0) ? 1 : 0; 3225 return (code != 0) ? 1 : 0;
3226 #endif /* __U_BOOT__ */ 3226 #endif /* __U_BOOT__ */
3227 } 3227 }
3228 3228
3229 #ifndef __U_BOOT__ 3229 #ifndef __U_BOOT__
3230 static int parse_string_outer(const char *s, int flag) 3230 static int parse_string_outer(const char *s, int flag)
3231 #else 3231 #else
3232 int parse_string_outer(const char *s, int flag) 3232 int parse_string_outer(const char *s, int flag)
3233 #endif /* __U_BOOT__ */ 3233 #endif /* __U_BOOT__ */
3234 { 3234 {
3235 struct in_str input; 3235 struct in_str input;
3236 #ifdef __U_BOOT__ 3236 #ifdef __U_BOOT__
3237 char *p = NULL; 3237 char *p = NULL;
3238 int rcode; 3238 int rcode;
3239 if (!s) 3239 if (!s)
3240 return 1; 3240 return 1;
3241 if (!*s) 3241 if (!*s)
3242 return 0; 3242 return 0;
3243 if (!(p = strchr(s, '\n')) || *++p) { 3243 if (!(p = strchr(s, '\n')) || *++p) {
3244 p = xmalloc(strlen(s) + 2); 3244 p = xmalloc(strlen(s) + 2);
3245 strcpy(p, s); 3245 strcpy(p, s);
3246 strcat(p, "\n"); 3246 strcat(p, "\n");
3247 setup_string_in_str(&input, p); 3247 setup_string_in_str(&input, p);
3248 rcode = parse_stream_outer(&input, flag); 3248 rcode = parse_stream_outer(&input, flag);
3249 free(p); 3249 free(p);
3250 return rcode; 3250 return rcode;
3251 } else { 3251 } else {
3252 #endif 3252 #endif
3253 setup_string_in_str(&input, s); 3253 setup_string_in_str(&input, s);
3254 return parse_stream_outer(&input, flag); 3254 return parse_stream_outer(&input, flag);
3255 #ifdef __U_BOOT__ 3255 #ifdef __U_BOOT__
3256 } 3256 }
3257 #endif 3257 #endif
3258 } 3258 }
3259 3259
3260 #ifndef __U_BOOT__ 3260 #ifndef __U_BOOT__
3261 static int parse_file_outer(FILE *f) 3261 static int parse_file_outer(FILE *f)
3262 #else 3262 #else
3263 int parse_file_outer(void) 3263 int parse_file_outer(void)
3264 #endif 3264 #endif
3265 { 3265 {
3266 int rcode; 3266 int rcode;
3267 struct in_str input; 3267 struct in_str input;
3268 #ifndef __U_BOOT__ 3268 #ifndef __U_BOOT__
3269 setup_file_in_str(&input, f); 3269 setup_file_in_str(&input, f);
3270 #else 3270 #else
3271 setup_file_in_str(&input); 3271 setup_file_in_str(&input);
3272 #endif 3272 #endif
3273 rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON); 3273 rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON);
3274 return rcode; 3274 return rcode;
3275 } 3275 }
3276 3276
3277 #ifdef __U_BOOT__ 3277 #ifdef __U_BOOT__
3278 #ifdef CONFIG_NEEDS_MANUAL_RELOC 3278 #ifdef CONFIG_NEEDS_MANUAL_RELOC
3279 static void u_boot_hush_reloc(void) 3279 static void u_boot_hush_reloc(void)
3280 { 3280 {
3281 unsigned long addr; 3281 unsigned long addr;
3282 struct reserved_combo *r; 3282 struct reserved_combo *r;
3283 3283
3284 for (r=reserved_list; r<reserved_list+NRES; r++) { 3284 for (r=reserved_list; r<reserved_list+NRES; r++) {
3285 addr = (ulong) (r->literal) + gd->reloc_off; 3285 addr = (ulong) (r->literal) + gd->reloc_off;
3286 r->literal = (char *)addr; 3286 r->literal = (char *)addr;
3287 } 3287 }
3288 } 3288 }
3289 #endif 3289 #endif
3290 3290
3291 int u_boot_hush_start(void) 3291 int u_boot_hush_start(void)
3292 { 3292 {
3293 if (top_vars == NULL) { 3293 if (top_vars == NULL) {
3294 top_vars = malloc(sizeof(struct variables)); 3294 top_vars = malloc(sizeof(struct variables));
3295 top_vars->name = "HUSH_VERSION"; 3295 top_vars->name = "HUSH_VERSION";
3296 top_vars->value = "0.01"; 3296 top_vars->value = "0.01";
3297 top_vars->next = NULL; 3297 top_vars->next = NULL;
3298 top_vars->flg_export = 0; 3298 top_vars->flg_export = 0;
3299 top_vars->flg_read_only = 1; 3299 top_vars->flg_read_only = 1;
3300 #ifdef CONFIG_NEEDS_MANUAL_RELOC 3300 #ifdef CONFIG_NEEDS_MANUAL_RELOC
3301 u_boot_hush_reloc(); 3301 u_boot_hush_reloc();
3302 #endif 3302 #endif
3303 } 3303 }
3304 return 0; 3304 return 0;
3305 } 3305 }
3306 3306
3307 static void *xmalloc(size_t size) 3307 static void *xmalloc(size_t size)
3308 { 3308 {
3309 void *p = NULL; 3309 void *p = NULL;
3310 3310
3311 if (!(p = malloc(size))) { 3311 if (!(p = malloc(size))) {
3312 printf("ERROR : memory not allocated\n"); 3312 printf("ERROR : memory not allocated\n");
3313 for(;;); 3313 for(;;);
3314 } 3314 }
3315 return p; 3315 return p;
3316 } 3316 }
3317 3317
3318 static void *xrealloc(void *ptr, size_t size) 3318 static void *xrealloc(void *ptr, size_t size)
3319 { 3319 {
3320 void *p = NULL; 3320 void *p = NULL;
3321 3321
3322 if (!(p = realloc(ptr, size))) { 3322 if (!(p = realloc(ptr, size))) {
3323 printf("ERROR : memory not allocated\n"); 3323 printf("ERROR : memory not allocated\n");
3324 for(;;); 3324 for(;;);
3325 } 3325 }
3326 return p; 3326 return p;
3327 } 3327 }
3328 #endif /* __U_BOOT__ */ 3328 #endif /* __U_BOOT__ */
3329 3329
3330 #ifndef __U_BOOT__ 3330 #ifndef __U_BOOT__
3331 /* Make sure we have a controlling tty. If we get started under a job 3331 /* Make sure we have a controlling tty. If we get started under a job
3332 * aware app (like bash for example), make sure we are now in charge so 3332 * aware app (like bash for example), make sure we are now in charge so
3333 * we don't fight over who gets the foreground */ 3333 * we don't fight over who gets the foreground */
3334 static void setup_job_control(void) 3334 static void setup_job_control(void)
3335 { 3335 {
3336 static pid_t shell_pgrp; 3336 static pid_t shell_pgrp;
3337 /* Loop until we are in the foreground. */ 3337 /* Loop until we are in the foreground. */
3338 while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ())) 3338 while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
3339 kill (- shell_pgrp, SIGTTIN); 3339 kill (- shell_pgrp, SIGTTIN);
3340 3340
3341 /* Ignore interactive and job-control signals. */ 3341 /* Ignore interactive and job-control signals. */
3342 signal(SIGINT, SIG_IGN); 3342 signal(SIGINT, SIG_IGN);
3343 signal(SIGQUIT, SIG_IGN); 3343 signal(SIGQUIT, SIG_IGN);
3344 signal(SIGTERM, SIG_IGN); 3344 signal(SIGTERM, SIG_IGN);
3345 signal(SIGTSTP, SIG_IGN); 3345 signal(SIGTSTP, SIG_IGN);
3346 signal(SIGTTIN, SIG_IGN); 3346 signal(SIGTTIN, SIG_IGN);
3347 signal(SIGTTOU, SIG_IGN); 3347 signal(SIGTTOU, SIG_IGN);
3348 signal(SIGCHLD, SIG_IGN); 3348 signal(SIGCHLD, SIG_IGN);
3349 3349
3350 /* Put ourselves in our own process group. */ 3350 /* Put ourselves in our own process group. */
3351 setsid(); 3351 setsid();
3352 shell_pgrp = getpid (); 3352 shell_pgrp = getpid ();
3353 setpgid (shell_pgrp, shell_pgrp); 3353 setpgid (shell_pgrp, shell_pgrp);
3354 3354
3355 /* Grab control of the terminal. */ 3355 /* Grab control of the terminal. */
3356 tcsetpgrp(shell_terminal, shell_pgrp); 3356 tcsetpgrp(shell_terminal, shell_pgrp);
3357 } 3357 }
3358 3358
3359 int hush_main(int argc, char * const *argv) 3359 int hush_main(int argc, char * const *argv)
3360 { 3360 {
3361 int opt; 3361 int opt;
3362 FILE *input; 3362 FILE *input;
3363 char **e = environ; 3363 char **e = environ;
3364 3364
3365 /* XXX what should these be while sourcing /etc/profile? */ 3365 /* XXX what should these be while sourcing /etc/profile? */
3366 global_argc = argc; 3366 global_argc = argc;
3367 global_argv = argv; 3367 global_argv = argv;
3368 3368
3369 /* (re?) initialize globals. Sometimes hush_main() ends up calling 3369 /* (re?) initialize globals. Sometimes hush_main() ends up calling
3370 * hush_main(), therefore we cannot rely on the BSS to zero out this 3370 * hush_main(), therefore we cannot rely on the BSS to zero out this
3371 * stuff. Reset these to 0 every time. */ 3371 * stuff. Reset these to 0 every time. */
3372 ifs = NULL; 3372 ifs = NULL;
3373 /* map[] is taken care of with call to update_ifs_map() */ 3373 /* map[] is taken care of with call to update_ifs_map() */
3374 fake_mode = 0; 3374 fake_mode = 0;
3375 interactive = 0; 3375 interactive = 0;
3376 close_me_head = NULL; 3376 close_me_head = NULL;
3377 last_bg_pid = 0; 3377 last_bg_pid = 0;
3378 job_list = NULL; 3378 job_list = NULL;
3379 last_jobid = 0; 3379 last_jobid = 0;
3380 3380
3381 /* Initialize some more globals to non-zero values */ 3381 /* Initialize some more globals to non-zero values */
3382 set_cwd(); 3382 set_cwd();
3383 #ifdef CONFIG_FEATURE_COMMAND_EDITING 3383 #ifdef CONFIG_FEATURE_COMMAND_EDITING
3384 cmdedit_set_initial_prompt(); 3384 cmdedit_set_initial_prompt();
3385 #else 3385 #else
3386 PS1 = NULL; 3386 PS1 = NULL;
3387 #endif 3387 #endif
3388 PS2 = "> "; 3388 PS2 = "> ";
3389 3389
3390 /* initialize our shell local variables with the values 3390 /* initialize our shell local variables with the values
3391 * currently living in the environment */ 3391 * currently living in the environment */
3392 if (e) { 3392 if (e) {
3393 for (; *e; e++) 3393 for (; *e; e++)
3394 set_local_var(*e, 2); /* without call putenv() */ 3394 set_local_var(*e, 2); /* without call putenv() */
3395 } 3395 }
3396 3396
3397 last_return_code=EXIT_SUCCESS; 3397 last_return_code=EXIT_SUCCESS;
3398 3398
3399 3399
3400 if (argv[0] && argv[0][0] == '-') { 3400 if (argv[0] && argv[0][0] == '-') {
3401 debug_printf("\nsourcing /etc/profile\n"); 3401 debug_printf("\nsourcing /etc/profile\n");
3402 if ((input = fopen("/etc/profile", "r")) != NULL) { 3402 if ((input = fopen("/etc/profile", "r")) != NULL) {
3403 mark_open(fileno(input)); 3403 mark_open(fileno(input));
3404 parse_file_outer(input); 3404 parse_file_outer(input);
3405 mark_closed(fileno(input)); 3405 mark_closed(fileno(input));
3406 fclose(input); 3406 fclose(input);
3407 } 3407 }
3408 } 3408 }
3409 input=stdin; 3409 input=stdin;
3410 3410
3411 while ((opt = getopt(argc, argv, "c:xif")) > 0) { 3411 while ((opt = getopt(argc, argv, "c:xif")) > 0) {
3412 switch (opt) { 3412 switch (opt) {
3413 case 'c': 3413 case 'c':
3414 { 3414 {
3415 global_argv = argv+optind; 3415 global_argv = argv+optind;
3416 global_argc = argc-optind; 3416 global_argc = argc-optind;
3417 opt = parse_string_outer(optarg, FLAG_PARSE_SEMICOLON); 3417 opt = parse_string_outer(optarg, FLAG_PARSE_SEMICOLON);
3418 goto final_return; 3418 goto final_return;
3419 } 3419 }
3420 break; 3420 break;
3421 case 'i': 3421 case 'i':
3422 interactive++; 3422 interactive++;
3423 break; 3423 break;
3424 case 'f': 3424 case 'f':
3425 fake_mode++; 3425 fake_mode++;
3426 break; 3426 break;
3427 default: 3427 default:
3428 #ifndef BB_VER 3428 #ifndef BB_VER
3429 fprintf(stderr, "Usage: sh [FILE]...\n" 3429 fprintf(stderr, "Usage: sh [FILE]...\n"
3430 " or: sh -c command [args]...\n\n"); 3430 " or: sh -c command [args]...\n\n");
3431 exit(EXIT_FAILURE); 3431 exit(EXIT_FAILURE);
3432 #else 3432 #else
3433 show_usage(); 3433 show_usage();
3434 #endif 3434 #endif
3435 } 3435 }
3436 } 3436 }
3437 /* A shell is interactive if the `-i' flag was given, or if all of 3437 /* A shell is interactive if the `-i' flag was given, or if all of
3438 * the following conditions are met: 3438 * the following conditions are met:
3439 * no -c command 3439 * no -c command
3440 * no arguments remaining or the -s flag given 3440 * no arguments remaining or the -s flag given
3441 * standard input is a terminal 3441 * standard input is a terminal
3442 * standard output is a terminal 3442 * standard output is a terminal
3443 * Refer to Posix.2, the description of the `sh' utility. */ 3443 * Refer to Posix.2, the description of the `sh' utility. */
3444 if (argv[optind]==NULL && input==stdin && 3444 if (argv[optind]==NULL && input==stdin &&
3445 isatty(fileno(stdin)) && isatty(fileno(stdout))) { 3445 isatty(fileno(stdin)) && isatty(fileno(stdout))) {
3446 interactive++; 3446 interactive++;
3447 } 3447 }
3448 3448
3449 debug_printf("\ninteractive=%d\n", interactive); 3449 debug_printf("\ninteractive=%d\n", interactive);
3450 if (interactive) { 3450 if (interactive) {
3451 /* Looks like they want an interactive shell */ 3451 /* Looks like they want an interactive shell */
3452 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 3452 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
3453 printf( "\n\n" BB_BANNER " hush - the humble shell v0.01 (testing)\n"); 3453 printf( "\n\n" BB_BANNER " hush - the humble shell v0.01 (testing)\n");
3454 printf( "Enter 'help' for a list of built-in commands.\n\n"); 3454 printf( "Enter 'help' for a list of built-in commands.\n\n");
3455 #endif 3455 #endif
3456 setup_job_control(); 3456 setup_job_control();
3457 } 3457 }
3458 3458
3459 if (argv[optind]==NULL) { 3459 if (argv[optind]==NULL) {
3460 opt=parse_file_outer(stdin); 3460 opt=parse_file_outer(stdin);
3461 goto final_return; 3461 goto final_return;
3462 } 3462 }
3463 3463
3464 debug_printf("\nrunning script '%s'\n", argv[optind]); 3464 debug_printf("\nrunning script '%s'\n", argv[optind]);
3465 global_argv = argv+optind; 3465 global_argv = argv+optind;
3466 global_argc = argc-optind; 3466 global_argc = argc-optind;
3467 input = xfopen(argv[optind], "r"); 3467 input = xfopen(argv[optind], "r");
3468 opt = parse_file_outer(input); 3468 opt = parse_file_outer(input);
3469 3469
3470 #ifdef CONFIG_FEATURE_CLEAN_UP 3470 #ifdef CONFIG_FEATURE_CLEAN_UP
3471 fclose(input); 3471 fclose(input);
3472 if (cwd && cwd != unknown) 3472 if (cwd && cwd != unknown)
3473 free((char*)cwd); 3473 free((char*)cwd);
3474 { 3474 {
3475 struct variables *cur, *tmp; 3475 struct variables *cur, *tmp;
3476 for(cur = top_vars; cur; cur = tmp) { 3476 for(cur = top_vars; cur; cur = tmp) {
3477 tmp = cur->next; 3477 tmp = cur->next;
3478 if (!cur->flg_read_only) { 3478 if (!cur->flg_read_only) {
3479 free(cur->name); 3479 free(cur->name);
3480 free(cur->value); 3480 free(cur->value);
3481 free(cur); 3481 free(cur);
3482 } 3482 }
3483 } 3483 }
3484 } 3484 }
3485 #endif 3485 #endif
3486 3486
3487 final_return: 3487 final_return:
3488 return(opt?opt:last_return_code); 3488 return(opt?opt:last_return_code);
3489 } 3489 }
3490 #endif 3490 #endif
3491 3491
3492 static char *insert_var_value(char *inp) 3492 static char *insert_var_value(char *inp)
3493 { 3493 {
3494 return insert_var_value_sub(inp, 0); 3494 return insert_var_value_sub(inp, 0);
3495 } 3495 }
3496 3496
3497 static char *insert_var_value_sub(char *inp, int tag_subst) 3497 static char *insert_var_value_sub(char *inp, int tag_subst)
3498 { 3498 {
3499 int res_str_len = 0; 3499 int res_str_len = 0;
3500 int len; 3500 int len;
3501 int done = 0; 3501 int done = 0;
3502 char *p, *p1, *res_str = NULL; 3502 char *p, *p1, *res_str = NULL;
3503 3503
3504 while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) { 3504 while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
3505 /* check the beginning of the string for normal charachters */ 3505 /* check the beginning of the string for normal charachters */
3506 if (p != inp) { 3506 if (p != inp) {
3507 /* copy any charachters to the result string */ 3507 /* copy any charachters to the result string */
3508 len = p - inp; 3508 len = p - inp;
3509 res_str = xrealloc(res_str, (res_str_len + len)); 3509 res_str = xrealloc(res_str, (res_str_len + len));
3510 strncpy((res_str + res_str_len), inp, len); 3510 strncpy((res_str + res_str_len), inp, len);
3511 res_str_len += len; 3511 res_str_len += len;
3512 } 3512 }
3513 inp = ++p; 3513 inp = ++p;
3514 /* find the ending marker */ 3514 /* find the ending marker */
3515 p = strchr(inp, SPECIAL_VAR_SYMBOL); 3515 p = strchr(inp, SPECIAL_VAR_SYMBOL);
3516 *p = '\0'; 3516 *p = '\0';
3517 /* look up the value to substitute */ 3517 /* look up the value to substitute */
3518 if ((p1 = lookup_param(inp))) { 3518 if ((p1 = lookup_param(inp))) {
3519 if (tag_subst) 3519 if (tag_subst)
3520 len = res_str_len + strlen(p1) + 2; 3520 len = res_str_len + strlen(p1) + 2;
3521 else 3521 else
3522 len = res_str_len + strlen(p1); 3522 len = res_str_len + strlen(p1);
3523 res_str = xrealloc(res_str, (1 + len)); 3523 res_str = xrealloc(res_str, (1 + len));
3524 if (tag_subst) { 3524 if (tag_subst) {
3525 /* 3525 /*
3526 * copy the variable value to the result 3526 * copy the variable value to the result
3527 * string 3527 * string
3528 */ 3528 */
3529 strcpy((res_str + res_str_len + 1), p1); 3529 strcpy((res_str + res_str_len + 1), p1);
3530 3530
3531 /* 3531 /*
3532 * mark the replaced text to be accepted as 3532 * mark the replaced text to be accepted as
3533 * is 3533 * is
3534 */ 3534 */
3535 res_str[res_str_len] = SUBSTED_VAR_SYMBOL; 3535 res_str[res_str_len] = SUBSTED_VAR_SYMBOL;
3536 res_str[res_str_len + 1 + strlen(p1)] = 3536 res_str[res_str_len + 1 + strlen(p1)] =
3537 SUBSTED_VAR_SYMBOL; 3537 SUBSTED_VAR_SYMBOL;
3538 } else 3538 } else
3539 /* 3539 /*
3540 * copy the variable value to the result 3540 * copy the variable value to the result
3541 * string 3541 * string
3542 */ 3542 */
3543 strcpy((res_str + res_str_len), p1); 3543 strcpy((res_str + res_str_len), p1);
3544 3544
3545 res_str_len = len; 3545 res_str_len = len;
3546 } 3546 }
3547 *p = SPECIAL_VAR_SYMBOL; 3547 *p = SPECIAL_VAR_SYMBOL;
3548 inp = ++p; 3548 inp = ++p;
3549 done = 1; 3549 done = 1;
3550 } 3550 }
3551 if (done) { 3551 if (done) {
3552 res_str = xrealloc(res_str, (1 + res_str_len + strlen(inp))); 3552 res_str = xrealloc(res_str, (1 + res_str_len + strlen(inp)));
3553 strcpy((res_str + res_str_len), inp); 3553 strcpy((res_str + res_str_len), inp);
3554 while ((p = strchr(res_str, '\n'))) { 3554 while ((p = strchr(res_str, '\n'))) {
3555 *p = ' '; 3555 *p = ' ';
3556 } 3556 }
3557 } 3557 }
3558 return (res_str == NULL) ? inp : res_str; 3558 return (res_str == NULL) ? inp : res_str;
3559 } 3559 }
3560 3560
3561 static char **make_list_in(char **inp, char *name) 3561 static char **make_list_in(char **inp, char *name)
3562 { 3562 {
3563 int len, i; 3563 int len, i;
3564 int name_len = strlen(name); 3564 int name_len = strlen(name);
3565 int n = 0; 3565 int n = 0;
3566 char **list; 3566 char **list;
3567 char *p1, *p2, *p3; 3567 char *p1, *p2, *p3;
3568 3568
3569 /* create list of variable values */ 3569 /* create list of variable values */
3570 list = xmalloc(sizeof(*list)); 3570 list = xmalloc(sizeof(*list));
3571 for (i = 0; inp[i]; i++) { 3571 for (i = 0; inp[i]; i++) {
3572 p3 = insert_var_value(inp[i]); 3572 p3 = insert_var_value(inp[i]);
3573 p1 = p3; 3573 p1 = p3;
3574 while (*p1) { 3574 while (*p1) {
3575 if (*p1 == ' ') { 3575 if (*p1 == ' ') {
3576 p1++; 3576 p1++;
3577 continue; 3577 continue;
3578 } 3578 }
3579 if ((p2 = strchr(p1, ' '))) { 3579 if ((p2 = strchr(p1, ' '))) {
3580 len = p2 - p1; 3580 len = p2 - p1;
3581 } else { 3581 } else {
3582 len = strlen(p1); 3582 len = strlen(p1);
3583 p2 = p1 + len; 3583 p2 = p1 + len;
3584 } 3584 }
3585 /* we use n + 2 in realloc for list,because we add 3585 /* we use n + 2 in realloc for list,because we add
3586 * new element and then we will add NULL element */ 3586 * new element and then we will add NULL element */
3587 list = xrealloc(list, sizeof(*list) * (n + 2)); 3587 list = xrealloc(list, sizeof(*list) * (n + 2));
3588 list[n] = xmalloc(2 + name_len + len); 3588 list[n] = xmalloc(2 + name_len + len);
3589 strcpy(list[n], name); 3589 strcpy(list[n], name);
3590 strcat(list[n], "="); 3590 strcat(list[n], "=");
3591 strncat(list[n], p1, len); 3591 strncat(list[n], p1, len);
3592 list[n++][name_len + len + 1] = '\0'; 3592 list[n++][name_len + len + 1] = '\0';
3593 p1 = p2; 3593 p1 = p2;
3594 } 3594 }
3595 if (p3 != inp[i]) free(p3); 3595 if (p3 != inp[i]) free(p3);
3596 } 3596 }
3597 list[n] = NULL; 3597 list[n] = NULL;
3598 return list; 3598 return list;
3599 } 3599 }
3600 3600
3601 /* 3601 /*
3602 * Make new string for parser 3602 * Make new string for parser
3603 * inp - array of argument strings to flatten 3603 * inp - array of argument strings to flatten
3604 * nonnull - indicates argument was quoted when originally parsed 3604 * nonnull - indicates argument was quoted when originally parsed
3605 */ 3605 */
3606 static char *make_string(char **inp, int *nonnull) 3606 static char *make_string(char **inp, int *nonnull)
3607 { 3607 {
3608 char *p; 3608 char *p;
3609 char *str = NULL; 3609 char *str = NULL;
3610 int n; 3610 int n;
3611 int len = 2; 3611 int len = 2;
3612 char *noeval_str; 3612 char *noeval_str;
3613 int noeval = 0; 3613 int noeval = 0;
3614 3614
3615 noeval_str = get_local_var("HUSH_NO_EVAL"); 3615 noeval_str = get_local_var("HUSH_NO_EVAL");
3616 if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0') 3616 if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0')
3617 noeval = 1; 3617 noeval = 1;
3618 for (n = 0; inp[n]; n++) { 3618 for (n = 0; inp[n]; n++) {
3619 p = insert_var_value_sub(inp[n], noeval); 3619 p = insert_var_value_sub(inp[n], noeval);
3620 str = xrealloc(str, (len + strlen(p) + (2 * nonnull[n]))); 3620 str = xrealloc(str, (len + strlen(p) + (2 * nonnull[n])));
3621 if (n) { 3621 if (n) {
3622 strcat(str, " "); 3622 strcat(str, " ");
3623 } else { 3623 } else {
3624 *str = '\0'; 3624 *str = '\0';
3625 } 3625 }
3626 if (nonnull[n]) 3626 if (nonnull[n])
3627 strcat(str, "'"); 3627 strcat(str, "'");
3628 strcat(str, p); 3628 strcat(str, p);
3629 if (nonnull[n]) 3629 if (nonnull[n])
3630 strcat(str, "'"); 3630 strcat(str, "'");
3631 len = strlen(str) + 3; 3631 len = strlen(str) + 3;
3632 if (p != inp[n]) free(p); 3632 if (p != inp[n]) free(p);
3633 } 3633 }
3634 len = strlen(str); 3634 len = strlen(str);
3635 *(str + len) = '\n'; 3635 *(str + len) = '\n';
3636 *(str + len + 1) = '\0'; 3636 *(str + len + 1) = '\0';
3637 return str; 3637 return str;
3638 } 3638 }
3639 3639
3640 #ifdef __U_BOOT__ 3640 #ifdef __U_BOOT__
3641 static int do_showvar(cmd_tbl_t *cmdtp, int flag, int argc, 3641 static int do_showvar(cmd_tbl_t *cmdtp, int flag, int argc,
3642 char * const argv[]) 3642 char * const argv[])
3643 { 3643 {
3644 int i, k; 3644 int i, k;
3645 int rcode = 0; 3645 int rcode = 0;
3646 struct variables *cur; 3646 struct variables *cur;
3647 3647
3648 if (argc == 1) { /* Print all env variables */ 3648 if (argc == 1) { /* Print all env variables */
3649 for (cur = top_vars; cur; cur = cur->next) { 3649 for (cur = top_vars; cur; cur = cur->next) {
3650 printf ("%s=%s\n", cur->name, cur->value); 3650 printf ("%s=%s\n", cur->name, cur->value);
3651 if (ctrlc ()) { 3651 if (ctrlc ()) {
3652 puts ("\n ** Abort\n"); 3652 puts ("\n ** Abort\n");
3653 return 1; 3653 return 1;
3654 } 3654 }
3655 } 3655 }
3656 return 0; 3656 return 0;
3657 } 3657 }
3658 for (i = 1; i < argc; ++i) { /* print single env variables */ 3658 for (i = 1; i < argc; ++i) { /* print single env variables */
3659 char *name = argv[i]; 3659 char *name = argv[i];
3660 3660
3661 k = -1; 3661 k = -1;
3662 for (cur = top_vars; cur; cur = cur->next) { 3662 for (cur = top_vars; cur; cur = cur->next) {
3663 if(strcmp (cur->name, name) == 0) { 3663 if(strcmp (cur->name, name) == 0) {
3664 k = 0; 3664 k = 0;
3665 printf ("%s=%s\n", cur->name, cur->value); 3665 printf ("%s=%s\n", cur->name, cur->value);
3666 } 3666 }
3667 if (ctrlc ()) { 3667 if (ctrlc ()) {
3668 puts ("\n ** Abort\n"); 3668 puts ("\n ** Abort\n");
3669 return 1; 3669 return 1;
3670 } 3670 }
3671 } 3671 }
3672 if (k < 0) { 3672 if (k < 0) {
3673 printf ("## Error: \"%s\" not defined\n", name); 3673 printf ("## Error: \"%s\" not defined\n", name);
3674 rcode ++; 3674 rcode ++;
3675 } 3675 }
3676 } 3676 }
3677 return rcode; 3677 return rcode;
3678 } 3678 }
3679 3679
3680 U_BOOT_CMD( 3680 U_BOOT_CMD(
3681 showvar, CONFIG_SYS_MAXARGS, 1, do_showvar, 3681 showvar, CONFIG_SYS_MAXARGS, 1, do_showvar,
3682 "print local hushshell variables", 3682 "print local hushshell variables",
3683 "\n - print values of all hushshell variables\n" 3683 "\n - print values of all hushshell variables\n"
3684 "showvar name ...\n" 3684 "showvar name ...\n"
3685 " - print value of hushshell variable 'name'" 3685 " - print value of hushshell variable 'name'"
3686 ); 3686 );
3687 3687
3688 #endif 3688 #endif
3689 /****************************************************************************/ 3689 /****************************************************************************/
3690 3690