Add in 'trim' routine. Fix up sh.c so it works when wordexp
[oweals/busybox.git] / lash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * lash -- the BusyBox Lame-Ass SHell
4  *
5  * Copyright (C) 1999,2000,2001 by Lineo, inc.
6  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7  *
8  * Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is
9  * under the following liberal license: "We have placed this source code in the
10  * public domain. Use it in any project, free or commercial."
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  *
26  */
27
28 /* The parsing engine of this program is officially at a dead-end.
29  * Future work in that direction should move to the work posted
30  * at http://doolittle.faludi.com/~larry/parser.html .
31  * A start on the integration of that work with the rest of sh.c
32  * is at http://codepoet.org/sh.c .
33  */
34 //
35 //This works pretty well now, and is now on by default.
36 #define BB_FEATURE_SH_ENVIRONMENT
37 //
38 //Backtick support has some problems, use at your own risk!
39 //#define BB_FEATURE_SH_BACKTICKS
40 //
41 //If, then, else, etc. support..  This should now behave basically
42 //like any other Bourne shell...
43 #define BB_FEATURE_SH_IF_EXPRESSIONS
44 //
45 /* This is currently a little broken... */
46 //#define HANDLE_CONTINUATION_CHARS
47 //
48 //For debugging/development on the shell only...
49 //#define DEBUG_SHELL
50
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <ctype.h>
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <signal.h>
58 #include <string.h>
59 #include <sys/ioctl.h>
60 #include <sys/wait.h>
61 #include <unistd.h>
62 #include <getopt.h>
63
64 #if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) 
65 #include <wordexp.h>
66 #define expand_t        wordexp_t
67 #undef BB_FEATURE_SH_BACKTICKS
68 #else
69 #include <glob.h>
70 #define expand_t        glob_t
71 #endif  
72 #include "busybox.h"
73 #include "cmdedit.h"
74
75
76 static const int MAX_LINE = 256;        /* size of input buffer for cwd data */
77 static const int MAX_READ = 128;        /* size of input buffer for `read' builtin */
78 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
79
80
81 enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
82         REDIRECT_APPEND
83 };
84
85 static const unsigned int DEFAULT_CONTEXT=0x1;
86 static const unsigned int IF_TRUE_CONTEXT=0x2;
87 static const unsigned int IF_FALSE_CONTEXT=0x4;
88 static const unsigned int THEN_EXP_CONTEXT=0x8;
89 static const unsigned int ELSE_EXP_CONTEXT=0x10;
90
91
92 struct jobset {
93         struct job *head;                       /* head of list of running jobs */
94         struct job *fg;                         /* current foreground job */
95 };
96
97 struct redir_struct {
98         enum redir_type type;   /* type of redirection */
99         int fd;                                         /* file descriptor being redirected */
100         char *filename;                         /* file to redirect fd to */
101 };
102
103 struct child_prog {
104         pid_t pid;                                      /* 0 if exited */
105         char **argv;                            /* program name and arguments */
106         int num_redirects;                      /* elements in redirection array */
107         struct redir_struct *redirects; /* I/O redirects */
108         int is_stopped;                         /* is the program currently running? */
109         struct job *family;                     /* pointer back to the child's parent job */
110 };
111
112 struct job {
113         int jobid;                                      /* job number */
114         int num_progs;                          /* total number of programs in job */
115         int running_progs;                      /* number of programs running */
116         char *text;                                     /* name of job */
117         char *cmdbuf;                           /* buffer various argv's point into */
118         pid_t pgrp;                                     /* process group ID for the job */
119         struct child_prog *progs;       /* array of programs in job */
120         struct job *next;                       /* to track background commands */
121         int stopped_progs;                      /* number of programs alive, but stopped */
122         unsigned int job_context;       /* bitmask defining current context */
123         struct jobset *job_list;
124 };
125
126 struct built_in_command {
127         char *cmd;                                      /* name */
128         char *descr;                            /* description */
129         int (*function) (struct child_prog *);  /* function ptr */
130 };
131
132 struct close_me {
133         int fd;
134         struct close_me *next;
135 };
136
137 /* function prototypes for builtins */
138 static int builtin_cd(struct child_prog *cmd);
139 static int builtin_env(struct child_prog *dummy);
140 static int builtin_exec(struct child_prog *cmd);
141 static int builtin_exit(struct child_prog *cmd);
142 static int builtin_fg_bg(struct child_prog *cmd);
143 static int builtin_help(struct child_prog *cmd);
144 static int builtin_jobs(struct child_prog *dummy);
145 static int builtin_pwd(struct child_prog *dummy);
146 static int builtin_export(struct child_prog *cmd);
147 static int builtin_source(struct child_prog *cmd);
148 static int builtin_unset(struct child_prog *cmd);
149 static int builtin_read(struct child_prog *cmd);
150 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
151 static int builtin_if(struct child_prog *cmd);
152 static int builtin_then(struct child_prog *cmd);
153 static int builtin_else(struct child_prog *cmd);
154 static int builtin_fi(struct child_prog *cmd);
155 /* function prototypes for shell stuff */
156 static int run_command_predicate(char *cmd);
157 #endif
158
159
160 /* function prototypes for shell stuff */
161 static void mark_open(int fd);
162 static void mark_closed(int fd);
163 static void close_all(void);
164 static void checkjobs(struct jobset *job_list);
165 static int get_command(FILE * source, char *command);
166 static int parse_command(char **command_ptr, struct job *job, int *inbg);
167 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
168 static int pseudo_exec(struct child_prog *cmd) __attribute__ ((noreturn));
169 static int busy_loop(FILE * input);
170
171
172 /* Table of built-in functions (these are non-forking builtins, meaning they
173  * can change global variables in the parent shell process but they will not
174  * work with pipes and redirects; 'unset foo | whatever' will not work) */
175 static struct built_in_command bltins[] = {
176         {"bg", "Resume a job in the background", builtin_fg_bg},
177         {"cd", "Change working directory", builtin_cd},
178         {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
179         {"exit", "Exit from shell()", builtin_exit},
180         {"fg", "Bring job into the foreground", builtin_fg_bg},
181         {"jobs", "Lists the active jobs", builtin_jobs},
182         {"export", "Set environment variable", builtin_export},
183         {"unset", "Unset environment variable", builtin_unset},
184         {"read", "Input environment variable", builtin_read},
185         {".", "Source-in and run commands in a file", builtin_source},
186         /* to do: add ulimit */
187 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
188         {"if", NULL, builtin_if},
189         {"then", NULL, builtin_then},
190         {"else", NULL, builtin_else},
191         {"fi", NULL, builtin_fi},
192 #endif
193         {NULL, NULL, NULL}
194 };
195
196 /* Table of forking built-in functions (things that fork cannot change global
197  * variables in the parent process, such as the current working directory) */
198 static struct built_in_command bltins_forking[] = {
199         {"env", "Print all environment variables", builtin_env},
200         {"pwd", "Print current directory", builtin_pwd},
201         {"help", "List shell built-in commands", builtin_help},
202         {NULL, NULL, NULL}
203 };
204
205
206 /* Variables we export */
207 unsigned int shell_context;  /* Used in cmdedit.c to reset the
208                                                                 context when someone hits ^C */
209
210
211 /* Globals that are static to this file */
212 static char *cwd;
213 static char *local_pending_command = NULL;
214 static struct jobset job_list = { NULL, NULL };
215 static int argc;
216 static char **argv;
217 static struct close_me *close_me_head;
218 #ifdef BB_FEATURE_SH_ENVIRONMENT
219 static int last_bg_pid;
220 static int last_return_code;
221 static int show_x_trace;
222 #endif
223 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
224 static char syntax_err[]="syntax error near unexpected token";
225 #endif
226
227 #ifdef DEBUG_SHELL
228 static inline void debug_printf(const char *format, ...)
229 {
230         va_list args;
231         va_start(args, format);
232         vfprintf(stderr, format, args);
233         va_end(args);
234 }
235 #else
236 static inline void debug_printf(const char *format, ...) { }
237 #endif
238
239 /*
240         Most builtins need access to the struct child_prog that has
241         their arguments, previously coded as cmd->progs[0].  That coding
242         can exhibit a bug, if the builtin is not the first command in
243         a pipeline: "echo foo | exec sort" will attempt to exec foo.
244
245 builtin   previous use      notes
246 ------ -----------------  ---------
247 cd      cmd->progs[0]
248 env     0
249 exec    cmd->progs[0]  squashed bug: didn't look for applets or forking builtins
250 exit    cmd->progs[0]
251 fg_bg   cmd->progs[0], job_list->head, job_list->fg
252 help    0
253 jobs    job_list->head
254 pwd     0
255 export  cmd->progs[0]  passes cmd, job_list to builtin_env(), which ignores them
256 source  cmd->progs[0]
257 unset   cmd->progs[0]
258 read    cmd->progs[0]
259 if      cmd->job_context,  cmd->text
260 then    cmd->job_context,  cmd->text
261 else    cmd->job_context,  cmd->text
262 fi      cmd->job_context
263
264 The use of cmd->text by if/then/else/fi is hopelessly hacky.
265 Would it work to increment cmd->progs[0]->argv and recurse,
266 somewhat like builtin_exec does?
267
268 I added "struct job *family;" to struct child_prog,
269 and switched API to builtin_foo(struct child_prog *child);
270 So   cmd->text        becomes  child->family->text
271      cmd->job_context  becomes  child->family->job_context
272      cmd->progs[0]    becomes  *child
273      job_list          becomes  child->family->job_list
274  */
275
276 /* built-in 'cd <path>' handler */
277 static int builtin_cd(struct child_prog *child)
278 {
279         char *newdir;
280
281         if (child->argv[1] == NULL)
282                 newdir = getenv("HOME");
283         else
284                 newdir = child->argv[1];
285         if (chdir(newdir)) {
286                 printf("cd: %s: %s\n", newdir, strerror(errno));
287                 return EXIT_FAILURE;
288         }
289         getcwd(cwd, sizeof(char)*MAX_LINE);
290
291         return EXIT_SUCCESS;
292 }
293
294 /* built-in 'env' handler */
295 static int builtin_env(struct child_prog *dummy)
296 {
297         char **e;
298
299         for (e = environ; *e; e++) {
300                 printf( "%s\n", *e);
301         }
302         return (0);
303 }
304
305 /* built-in 'exec' handler */
306 static int builtin_exec(struct child_prog *child)
307 {
308         if (child->argv[1] == NULL)
309                 return EXIT_SUCCESS;   /* Really? */
310         child->argv++;
311         close_all();
312         pseudo_exec(child);
313         /* never returns */
314 }
315
316 /* built-in 'exit' handler */
317 static int builtin_exit(struct child_prog *child)
318 {
319         if (child->argv[1] == NULL)
320                 exit(EXIT_SUCCESS);
321
322         exit (atoi(child->argv[1]));
323 }
324
325 /* built-in 'fg' and 'bg' handler */
326 static int builtin_fg_bg(struct child_prog *child)
327 {
328         int i, jobNum;
329         struct job *job=NULL;
330         
331         if (!child->argv[1] || child->argv[2]) {
332                 error_msg("%s: exactly one argument is expected",
333                                 child->argv[0]);
334                 return EXIT_FAILURE;
335         }
336
337         if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
338                 error_msg("%s: bad argument '%s'",
339                                 child->argv[0], child->argv[1]);
340                 return EXIT_FAILURE;
341         }
342
343         for (job = child->family->job_list->head; job; job = job->next) {
344                 if (job->jobid == jobNum) {
345                         break;
346                 }
347         }
348
349         if (!job) {
350                 error_msg("%s: unknown job %d",
351                                 child->argv[0], jobNum);
352                 return EXIT_FAILURE;
353         }
354
355         if (*child->argv[0] == 'f') {
356                 /* Make this job the foreground job */
357                 /* suppress messages when run from /linuxrc mag@sysgo.de */
358                 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
359                         perror_msg("tcsetpgrp"); 
360                 child->family->job_list->fg = job;
361         }
362
363         /* Restart the processes in the job */
364         for (i = 0; i < job->num_progs; i++)
365                 job->progs[i].is_stopped = 0;
366
367         kill(-job->pgrp, SIGCONT);
368
369         job->stopped_progs = 0;
370
371         return EXIT_SUCCESS;
372 }
373
374 /* built-in 'help' handler */
375 static int builtin_help(struct child_prog *dummy)
376 {
377         struct built_in_command *x;
378
379         printf("\nBuilt-in commands:\n");
380         printf("-------------------\n");
381         for (x = bltins; x->cmd; x++) {
382                 if (x->descr==NULL)
383                         continue;
384                 printf("%s\t%s\n", x->cmd, x->descr);
385         }
386         for (x = bltins_forking; x->cmd; x++) {
387                 if (x->descr==NULL)
388                         continue;
389                 printf("%s\t%s\n", x->cmd, x->descr);
390         }
391         printf("\n\n");
392         return EXIT_SUCCESS;
393 }
394
395 /* built-in 'jobs' handler */
396 static int builtin_jobs(struct child_prog *child)
397 {
398         struct job *job;
399         char *status_string;
400
401         for (job = child->family->job_list->head; job; job = job->next) {
402                 if (job->running_progs == job->stopped_progs)
403                         status_string = "Stopped";
404                 else
405                         status_string = "Running";
406
407                 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
408         }
409         return EXIT_SUCCESS;
410 }
411
412
413 /* built-in 'pwd' handler */
414 static int builtin_pwd(struct child_prog *dummy)
415 {
416         getcwd(cwd, MAX_LINE);
417         printf( "%s\n", cwd);
418         return EXIT_SUCCESS;
419 }
420
421 /* built-in 'export VAR=value' handler */
422 static int builtin_export(struct child_prog *child)
423 {
424         int res;
425
426         if (child->argv[1] == NULL) {
427                 return (builtin_env(child));
428         }
429         res = putenv(child->argv[1]);
430         if (res)
431                 fprintf(stderr, "export: %s\n", strerror(errno));
432         return (res);
433 }
434
435 /* built-in 'read VAR' handler */
436 static int builtin_read(struct child_prog *child)
437 {
438         int res = 0, len, newlen;
439         char *s;
440         char string[MAX_READ];
441
442         if (child->argv[1]) {
443                 /* argument (VAR) given: put "VAR=" into buffer */
444                 strcpy(string, child->argv[1]);
445                 len = strlen(string);
446                 string[len++] = '=';
447                 string[len]   = '\0';
448                 fgets(&string[len], sizeof(string) - len, stdin);       /* read string */
449                 newlen = strlen(string);
450                 if(newlen > len)
451                         string[--newlen] = '\0';        /* chomp trailing newline */
452                 /*
453                 ** string should now contain "VAR=<value>"
454                 ** copy it (putenv() won't do that, so we must make sure
455                 ** the string resides in a static buffer!)
456                 */
457                 res = -1;
458                 if((s = strdup(string)))
459                         res = putenv(s);
460                 if (res)
461                         fprintf(stderr, "read: %s\n", strerror(errno));
462         }
463         else
464                 fgets(string, sizeof(string), stdin);
465
466         return (res);
467 }
468
469 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
470 /* Built-in handler for 'if' commands */
471 static int builtin_if(struct child_prog *child)
472 {
473         struct job *cmd = child->family;
474         int status;
475         char* charptr1=cmd->text+3; /* skip over the leading 'if ' */
476
477         /* Now run the 'if' command */
478         debug_printf( "job=%p entering builtin_if ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
479         status = run_command_predicate(charptr1);
480         debug_printf( "if test returned ");
481         if (status == 0) {
482                 debug_printf( "TRUE\n");
483                 cmd->job_context |= IF_TRUE_CONTEXT;
484         } else {
485                 debug_printf( "FALSE\n");
486                 cmd->job_context |= IF_FALSE_CONTEXT;
487         }
488         debug_printf("job=%p builtin_if set job context to %x\n", cmd, cmd->job_context);
489         shell_context++;
490
491         return status;
492 }
493
494 /* Built-in handler for 'then' (part of the 'if' command) */
495 static int builtin_then(struct child_prog *child)
496 {
497         struct job *cmd = child->family;
498         char* charptr1=cmd->text+5; /* skip over the leading 'then ' */
499
500         debug_printf( "job=%p entering builtin_then ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
501         if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
502                 shell_context = 0; /* Reset the shell's context on an error */
503                 error_msg("%s `then'", syntax_err);
504                 return EXIT_FAILURE;
505         }
506
507         cmd->job_context |= THEN_EXP_CONTEXT;
508         debug_printf("job=%p builtin_then set job context to %x\n", cmd, cmd->job_context);
509
510         /* If the if result was FALSE, skip the 'then' stuff */
511         if (cmd->job_context & IF_FALSE_CONTEXT) {
512                 return EXIT_SUCCESS;
513         }
514
515         /* Seems the if result was TRUE, so run the 'then' command */
516         debug_printf( "'then' now running '%s'\n", charptr1);
517
518         return(run_command_predicate(charptr1));
519 }
520
521 /* Built-in handler for 'else' (part of the 'if' command) */
522 static int builtin_else(struct child_prog *child)
523 {
524         struct job *cmd = child->family;
525         char* charptr1=cmd->text+5; /* skip over the leading 'else ' */
526
527         debug_printf( "job=%p entering builtin_else ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
528
529         if (! (cmd->job_context & THEN_EXP_CONTEXT)) {
530                 shell_context = 0; /* Reset the shell's context on an error */
531                 error_msg("%s `else'", syntax_err);
532                 return EXIT_FAILURE;
533         }
534         /* If the if result was TRUE, skip the 'else' stuff */
535         if (cmd->job_context & IF_TRUE_CONTEXT) {
536                 return EXIT_SUCCESS;
537         }
538
539         cmd->job_context |= ELSE_EXP_CONTEXT;
540         debug_printf("job=%p builtin_else set job context to %x\n", cmd, cmd->job_context);
541
542         /* Now run the 'else' command */
543         debug_printf( "'else' now running '%s'\n", charptr1);
544         return(run_command_predicate(charptr1));
545 }
546
547 /* Built-in handler for 'fi' (part of the 'if' command) */
548 static int builtin_fi(struct child_prog *child)
549 {
550         struct job *cmd = child->family;
551         debug_printf( "job=%p entering builtin_fi ('%s')-- context=%d\n", cmd, "", cmd->job_context);
552         if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
553                 shell_context = 0; /* Reset the shell's context on an error */
554                 error_msg("%s `fi'", syntax_err);
555                 return EXIT_FAILURE;
556         }
557         /* Clear out the if and then context bits */
558         cmd->job_context &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
559         debug_printf("job=%p builtin_fi set job context to %x\n", cmd, cmd->job_context);
560         shell_context--;
561         return EXIT_SUCCESS;
562 }
563 #endif
564
565 /* Built-in '.' handler (read-in and execute commands from file) */
566 static int builtin_source(struct child_prog *child)
567 {
568         FILE *input;
569         int status;
570         int fd;
571
572         if (child->argv[1] == NULL)
573                 return EXIT_FAILURE;
574
575         input = fopen(child->argv[1], "r");
576         if (!input) {
577                 printf( "Couldn't open file '%s'\n", child->argv[1]);
578                 return EXIT_FAILURE;
579         }
580
581         fd=fileno(input);
582         mark_open(fd);
583         /* Now run the file */
584         status = busy_loop(input);
585         fclose(input);
586         mark_closed(fd);
587         return (status);
588 }
589
590 /* built-in 'unset VAR' handler */
591 static int builtin_unset(struct child_prog *child)
592 {
593         if (child->argv[1] == NULL) {
594                 printf( "unset: parameter required.\n");
595                 return EXIT_FAILURE;
596         }
597         unsetenv(child->argv[1]);
598         return EXIT_SUCCESS;
599 }
600
601 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
602 /* currently used by if/then/else.
603  *
604  * Reparsing the command line for this purpose is gross,
605  * incorrect, and fundamentally unfixable; in particular,
606  * think about what happens with command substitution.
607  * We really need to pull out the run, wait, return status
608  * functionality out of busy_loop so we can child->argv++
609  * and use that, without going back through parse_command.
610  */
611 static int run_command_predicate(char *cmd)
612 {
613         int n=strlen(cmd);
614         local_pending_command = xmalloc(n+1);
615         strncpy(local_pending_command, cmd, n); 
616         local_pending_command[n]='\0';
617         return( busy_loop(NULL));
618 }
619 #endif
620
621 static void mark_open(int fd)
622 {
623         struct close_me *new = xmalloc(sizeof(struct close_me));
624         new->fd = fd;
625         new->next = close_me_head;
626         close_me_head = new;
627 }
628
629 static void mark_closed(int fd)
630 {
631         struct close_me *tmp;
632         if (close_me_head == NULL || close_me_head->fd != fd)
633                 error_msg_and_die("corrupt close_me");
634         tmp = close_me_head;
635         close_me_head = close_me_head->next;
636         free(tmp);
637 }
638
639 static void close_all()
640 {
641         struct close_me *c, *tmp;
642         for (c=close_me_head; c; c=tmp) {
643                 close(c->fd);
644                 tmp=c->next;
645                 free(c);
646         }
647         close_me_head = NULL;
648 }
649
650
651 /* free up all memory from a job */
652 static void free_job(struct job *cmd)
653 {
654         int i;
655
656         for (i = 0; i < cmd->num_progs; i++) {
657                 free(cmd->progs[i].argv);
658                 if (cmd->progs[i].redirects)
659                         free(cmd->progs[i].redirects);
660         }
661         free(cmd->progs);
662         if (cmd->text)
663                 free(cmd->text);
664         free(cmd->cmdbuf);
665         memset(cmd, 0, sizeof(struct job));
666 }
667
668 /* remove a job from the job_list */
669 static void remove_job(struct jobset *job_list, struct job *job)
670 {
671         struct job *prevjob;
672
673         free_job(job);
674         if (job == job_list->head) {
675                 job_list->head = job->next;
676         } else {
677                 prevjob = job_list->head;
678                 while (prevjob->next != job)
679                         prevjob = prevjob->next;
680                 prevjob->next = job->next;
681         }
682
683         free(job);
684 }
685
686 /* Checks to see if any background processes have exited -- if they 
687    have, figure out why and see if a job has completed */
688 static void checkjobs(struct jobset *job_list)
689 {
690         struct job *job;
691         pid_t childpid;
692         int status;
693         int prognum = 0;
694
695         while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
696                 for (job = job_list->head; job; job = job->next) {
697                         prognum = 0;
698                         while (prognum < job->num_progs &&
699                                    job->progs[prognum].pid != childpid) prognum++;
700                         if (prognum < job->num_progs)
701                                 break;
702                 }
703
704                 /* This happens on backticked commands */
705                 if(job==NULL)
706                         return;
707
708                 if (WIFEXITED(status) || WIFSIGNALED(status)) {
709                         /* child exited */
710                         job->running_progs--;
711                         job->progs[prognum].pid = 0;
712
713                         if (!job->running_progs) {
714                                 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
715                                 remove_job(job_list, job);
716                         }
717                 } else {
718                         /* child stopped */
719                         job->stopped_progs++;
720                         job->progs[prognum].is_stopped = 1;
721
722                         if (job->stopped_progs == job->num_progs) {
723                                 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
724                                            job->text);
725                         }
726                 }
727         }
728
729         if (childpid == -1 && errno != ECHILD)
730                 perror_msg("waitpid");
731 }
732
733 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
734  * and stderr if they are redirected. */
735 static int setup_redirects(struct child_prog *prog, int squirrel[])
736 {
737         int i;
738         int openfd;
739         int mode = O_RDONLY;
740         struct redir_struct *redir = prog->redirects;
741
742         for (i = 0; i < prog->num_redirects; i++, redir++) {
743                 switch (redir->type) {
744                 case REDIRECT_INPUT:
745                         mode = O_RDONLY;
746                         break;
747                 case REDIRECT_OVERWRITE:
748                         mode = O_WRONLY | O_CREAT | O_TRUNC;
749                         break;
750                 case REDIRECT_APPEND:
751                         mode = O_WRONLY | O_CREAT | O_APPEND;
752                         break;
753                 }
754
755                 openfd = open(redir->filename, mode, 0666);
756                 if (openfd < 0) {
757                         /* this could get lost if stderr has been redirected, but
758                            bash and ash both lose it as well (though zsh doesn't!) */
759                         error_msg("error opening %s: %s", redir->filename,
760                                         strerror(errno));
761                         return 1;
762                 }
763
764                 if (openfd != redir->fd) {
765                         if (squirrel && redir->fd < 3) {
766                                 squirrel[redir->fd] = dup(redir->fd);
767                         }
768                         dup2(openfd, redir->fd);
769                         close(openfd);
770                 }
771         }
772
773         return 0;
774 }
775
776 static void restore_redirects(int squirrel[])
777 {
778         int i, fd;
779         for (i=0; i<3; i++) {
780                 fd = squirrel[i];
781                 if (fd != -1) {
782                         /* No error checking.  I sure wouldn't know what
783                          * to do with an error if I found one! */
784                         dup2(fd, i);
785                         close(fd);
786                 }
787         }
788 }
789
790 #if defined(BB_FEATURE_SH_SIMPLE_PROMPT)
791 static char* setup_prompt_string(int state)
792 {
793        char prompt_str[BUFSIZ];
794
795        /* Set up the prompt */
796        if (state == 0) {
797                /* simple prompt */
798                sprintf(prompt_str, "%s %s", cwd, ( geteuid() != 0 ) ?  "$ ":"# ");
799        } else {
800                strcpy(prompt_str,"> ");
801        }
802
803        return(strdup(prompt_str));  /* Must free this memory */
804 }
805
806 #else
807
808 static char* setup_prompt_string(int state)
809 {
810         char user[9],buf[255],*s;
811         char prompt[3];
812         char prompt_str[BUFSIZ];
813
814         /* Set up the prompt */
815         if (state == 0) {
816                 /* get User Name and setup prompt */
817                 strcpy(prompt,( geteuid() != 0 ) ? "$ ":"# ");
818                 my_getpwuid(user, geteuid());
819
820                 /* get HostName */
821                 gethostname(buf, 255);
822                 s = strchr(buf, '.');
823                 if (s) {
824                         *s = 0;
825                 }
826         } else {
827                 strcpy(prompt,"> ");
828         }
829
830         if (state == 0) {
831                 snprintf(prompt_str, BUFSIZ-1, "[%s@%s %s]%s", user, buf, 
832                                 get_last_path_component(cwd), prompt);
833         } else {
834                 sprintf(prompt_str, "%s", prompt);
835         }
836         return(strdup(prompt_str));  /* Must free this memory */
837 }
838
839 #endif 
840
841 static int get_command(FILE * source, char *command)
842 {
843         char *prompt_str;
844
845         if (source == NULL) {
846                 if (local_pending_command) {
847                         /* a command specified (-c option): return it & mark it done */
848                         strcpy(command, local_pending_command);
849                         free(local_pending_command);
850                         local_pending_command = NULL;
851                         return 0;
852                 }
853                 return 1;
854         }
855
856         if (source == stdin) {
857                 prompt_str = setup_prompt_string(shell_context);
858
859 #ifdef BB_FEATURE_SH_COMMAND_EDITING
860                 /*
861                 ** enable command line editing only while a command line
862                 ** is actually being read; otherwise, we'll end up bequeathing
863                 ** atexit() handlers and other unwanted stuff to our
864                 ** child processes (rob@sysgo.de)
865                 */
866                 cmdedit_read_input(prompt_str, command);
867                 cmdedit_terminate();
868                 free(prompt_str);
869                 return 0;
870 #else
871                 fputs(prompt_str, stdout);
872                 free(prompt_str);
873 #endif
874         }
875
876         if (!fgets(command, BUFSIZ - 2, source)) {
877                 if (source == stdin)
878                         printf("\n");
879                 return 1;
880         }
881
882         /* remove trailing newline */
883         chomp(command);
884
885         return 0;
886 }
887
888 #ifdef BB_FEATURE_SH_ENVIRONMENT
889 static char* itoa(register int i)
890 {
891         static char a[7]; /* Max 7 ints */
892         register char *b = a + sizeof(a) - 1;
893         int   sign = (i < 0);
894
895         if (sign)
896                 i = -i;
897         *b = 0;
898         do
899         {
900                 *--b = '0' + (i % 10);
901                 i /= 10;
902         }
903         while (i);
904         if (sign)
905                 *--b = '-';
906         return b;
907 }
908 #endif  
909
910 static int expand_arguments(char *command)
911 {
912 #ifdef BB_FEATURE_SH_ENVIRONMENT
913         expand_t expand_result;
914         char *src, *dst, *var;
915         int i=0, length, total_length=0, retval;
916 #endif
917
918         /* get rid of the terminating \n */
919         chomp(command);
920
921 #ifdef BB_FEATURE_SH_ENVIRONMENT
922
923
924 #if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) 
925         /* This first part uses wordexp() which is a wonderful C lib 
926          * function which expands nearly everything.  */ 
927         retval = wordexp (command, &expand_result, 0);
928         if (retval == WRDE_NOSPACE) {
929                 /* Mem may have been allocated... */
930                 wordfree (&expand_result);
931                 error_msg("out of space during expansion");
932                 return FALSE;
933         }
934         if (retval < 0) {
935                 /* Some other error.  */
936                 error_msg("syntax error");
937                 return FALSE;
938         }
939         
940         /* Convert from char** (one word per string) to a simple char*,
941          * but don't overflow command which is BUFSIZ in length */
942         *command = '\0';
943         while (i < expand_result.we_wordc && total_length < BUFSIZ) {
944                 length=strlen(expand_result.we_wordv[i])+1;
945                 if (BUFSIZ-total_length-length <= 0) {
946                         error_msg("out of space during expansion");
947                         return FALSE;
948                 }
949                 strcat(command+total_length, expand_result.we_wordv[i++]);
950                 strcat(command+total_length, " ");
951                 total_length+=length;
952         }
953         wordfree (&expand_result);
954 #else
955
956         /* Ok.  They don't have glibc and they don't have uClibc.  Chances are
957          * about 100% they don't have wordexp(), so instead, the best we can do is
958          * use glob, which is better then nothing, but certainly not perfect */
959
960         /* It turns out that glob is very stupid.  We have to feed it
961          * one word at a time since it can't cope with a full string. 
962          * Here we convert command (char*) into cmd (char**, one word 
963          * per string) */
964         {
965         
966                 int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE;
967                 char * tmpcmd;
968                 /* We need a clean copy, so strsep can mess up the copy while
969                  * we write stuff into the original in a minute */
970                 char * cmd = strdup(command);
971                 for (tmpcmd = cmd; (tmpcmd = strsep(&cmd, " \t")) != NULL;) {
972                         if (*tmpcmd == '\0')
973                                 break;
974                         retval = glob(tmpcmd, flags, NULL, &expand_result);
975                         /* We can't haveGLOB_APPEND on the first glob call,  
976                          * so put it there now */
977                         if (! (flags & GLOB_APPEND) ) 
978                                 flags |= GLOB_APPEND;
979
980                         if (retval == GLOB_NOSPACE) {
981                                 /* Mem may have been allocated... */
982                                 globfree (&expand_result);
983                                 error_msg("out of space during expansion");
984                                 return FALSE;
985                         }
986                         if (retval == GLOB_ABORTED || retval == GLOB_NOSYS) {
987                                 /* Some other error.  */
988                                 error_msg("syntax error");
989                                 return FALSE;
990                         }
991
992                         /* Convert from char** (one word per string) to a simple char*,
993                          * but don't overflow command which is BUFSIZ in length */
994                         *command = '\0';
995                         if ( expand_result.gl_pathc > 1) {
996                                 while (i < expand_result.gl_pathc && total_length < BUFSIZ) {
997                                         length=strlen(expand_result.gl_pathv[i])+1;
998                                         if (BUFSIZ-total_length-length <= 0) {
999                                                 error_msg("out of space during expansion");
1000                                                 return FALSE;
1001                                         }
1002                                         strcat(command+total_length, expand_result.gl_pathv[i++]);
1003                                         strcat(command+total_length, " ");
1004                                         total_length+=length;
1005                                 }
1006                         }
1007                 }
1008
1009                 free(cmd);
1010                 globfree (&expand_result);
1011         }
1012         
1013 #endif  
1014         
1015         /* FIXME -- this routine (which is only used when folks
1016          * don't have a C library with wordexp) needs a bit of help
1017          * to handle things like 'echo $PATH$0' */
1018         
1019         /* Now do the shell variable substitutions which 
1020          * wordexp can't do for us, namely $? and $! */
1021         src = command;
1022         while((dst = strchr(src,'$')) != NULL){
1023                 /* Ok -- got a $ -- now clean up any trailing mess */
1024                 trim(dst);
1025                 if (!(var = getenv(dst + 1))) {
1026                         switch(*(dst+1)) {
1027                                 case '?':
1028                                         var = itoa(last_return_code);
1029                                         break;
1030                                 case '!':
1031                                         if (last_bg_pid==-1)
1032                                                 *(var)='\0';
1033                                         else
1034                                                 var = itoa(last_bg_pid);
1035                                         break;
1036                                 /* Everything else like $$, $#, $[0-9], etc should all be
1037                                  * expanded by wordexp(), so we can in theory skip that stuff
1038                                  * here, but just to be on the safe side (i.e. since uClibc
1039                                  * wordexp doesn't do this stuff yet), lets leave it in for
1040                                  * now. */
1041                                 case '$':
1042                                         var = itoa(getpid());
1043                                         break;
1044                                 case '#':
1045                                         var = itoa(argc-1);
1046                                         break;
1047                                 case '0':case '1':case '2':case '3':case '4':
1048                                 case '5':case '6':case '7':case '8':case '9':
1049                                         {
1050                                                 int index=*(dst + 1)-48;
1051                                                 if (index >= argc) {
1052                                                         var='\0';
1053                                                 } else {
1054                                                         var = argv[index];
1055                                                 }
1056                                         }
1057                                         break;
1058
1059                         }
1060                 }
1061                 if (var) {
1062                         int subst_len = strlen(var);
1063                         char *next_dst;
1064                         if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?")) == NULL) {
1065                                 next_dst = dst;
1066                         }
1067                         src = (char*)xrealloc(src, strlen(src) - strlen(next_dst)+strlen(var)+1);
1068                         /* Move stuff to the end of the string to accommodate filling 
1069                          * the created gap with the new stuff */
1070                         memmove(dst+subst_len, next_dst+1, subst_len); 
1071                         /* Now copy in the new stuff */
1072                         strncpy(dst, var, subst_len+1);
1073                         src = dst;
1074                         src++;
1075                 } else {
1076                         /* Seems we got an un-expandable variable.  So delete it. */
1077                         char *next_dst;
1078                         if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?")) != NULL) {
1079                                 /* Move stuff to the end of the string to accommodate filling 
1080                                  * the created gap with the new stuff */
1081                                 memmove(dst, next_dst,  next_dst-dst); 
1082                         }
1083                 }
1084         }
1085
1086
1087
1088
1089 #endif  
1090         return TRUE;
1091 }
1092
1093 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
1094    line). If a valid command is found, command_ptr is set to point to
1095    the beginning of the next command (if the original command had more 
1096    then one job associated with it) or NULL if no more commands are 
1097    present. */
1098 static int parse_command(char **command_ptr, struct job *job, int *inbg)
1099 {
1100         char *command;
1101         char *return_command = NULL;
1102         char *src, *buf, *chptr;
1103         int argc_l = 0;
1104         int done = 0;
1105         int argv_alloced;
1106         int i;
1107         char quote = '\0';
1108         int count;
1109         struct child_prog *prog;
1110
1111         /* skip leading white space */
1112         while (**command_ptr && isspace(**command_ptr))
1113                 (*command_ptr)++;
1114
1115         /* this handles empty lines or leading '#' characters */
1116         if (!**command_ptr || (**command_ptr == '#')) {
1117                 job->num_progs=0;
1118                 return 0;
1119         }
1120
1121         *inbg = 0;
1122         job->num_progs = 1;
1123         job->progs = xmalloc(sizeof(*job->progs));
1124
1125         /* We set the argv elements to point inside of this string. The 
1126            memory is freed by free_job(). Allocate twice the original
1127            length in case we need to quote every single character.
1128
1129            Getting clean memory relieves us of the task of NULL 
1130            terminating things and makes the rest of this look a bit 
1131            cleaner (though it is, admittedly, a tad less efficient) */
1132         job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
1133         job->text = NULL;
1134
1135         prog = job->progs;
1136         prog->num_redirects = 0;
1137         prog->redirects = NULL;
1138         prog->is_stopped = 0;
1139         prog->family = job;
1140
1141         argv_alloced = 5;
1142         prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1143         prog->argv[0] = job->cmdbuf;
1144
1145         buf = command;
1146         src = *command_ptr;
1147         while (*src && !done) {
1148                 if (quote == *src) {
1149                         quote = '\0';
1150                 } else if (quote) {
1151                         if (*src == '\\') {
1152                                 src++;
1153                                 if (!*src) {
1154                                         error_msg("character expected after \\");
1155                                         free_job(job);
1156                                         return 1;
1157                                 }
1158
1159                                 /* in shell, "\'" should yield \' */
1160                                 if (*src != quote) {
1161                                         *buf++ = '\\';
1162                                         *buf++ = '\\';
1163                                 }
1164                         } else if (*src == '*' || *src == '?' || *src == '[' ||
1165                                            *src == ']') *buf++ = '\\';
1166                         *buf++ = *src;
1167                 } else if (isspace(*src)) {
1168                         if (*prog->argv[argc_l]) {
1169                                 buf++, argc_l++;
1170                                 /* +1 here leaves room for the NULL which ends argv */
1171                                 if ((argc_l + 1) == argv_alloced) {
1172                                         argv_alloced += 5;
1173                                         prog->argv = xrealloc(prog->argv,
1174                                                                                   sizeof(*prog->argv) *
1175                                                                                   argv_alloced);
1176                                 }
1177                                 prog->argv[argc_l] = buf;
1178                         }
1179                 } else
1180                         switch (*src) {
1181                         case '"':
1182                         case '\'':
1183                                 quote = *src;
1184                                 break;
1185
1186                         case '#':                       /* comment */
1187                                 if (*(src-1)== '$')
1188                                         *buf++ = *src;
1189                                 else
1190                                         done = 1;
1191                                 break;
1192
1193                         case '>':                       /* redirects */
1194                         case '<':
1195                                 i = prog->num_redirects++;
1196                                 prog->redirects = xrealloc(prog->redirects,
1197                                                                                           sizeof(*prog->redirects) *
1198                                                                                           (i + 1));
1199
1200                                 prog->redirects[i].fd = -1;
1201                                 if (buf != prog->argv[argc_l]) {
1202                                         /* the stuff before this character may be the file number 
1203                                            being redirected */
1204                                         prog->redirects[i].fd =
1205                                                 strtol(prog->argv[argc_l], &chptr, 10);
1206
1207                                         if (*chptr && *prog->argv[argc_l]) {
1208                                                 buf++, argc_l++;
1209                                                 prog->argv[argc_l] = buf;
1210                                         }
1211                                 }
1212
1213                                 if (prog->redirects[i].fd == -1) {
1214                                         if (*src == '>')
1215                                                 prog->redirects[i].fd = 1;
1216                                         else
1217                                                 prog->redirects[i].fd = 0;
1218                                 }
1219
1220                                 if (*src++ == '>') {
1221                                         if (*src == '>')
1222                                                 prog->redirects[i].type =
1223                                                         REDIRECT_APPEND, src++;
1224                                         else
1225                                                 prog->redirects[i].type = REDIRECT_OVERWRITE;
1226                                 } else {
1227                                         prog->redirects[i].type = REDIRECT_INPUT;
1228                                 }
1229
1230                                 /* This isn't POSIX sh compliant. Oh well. */
1231                                 chptr = src;
1232                                 while (isspace(*chptr))
1233                                         chptr++;
1234
1235                                 if (!*chptr) {
1236                                         error_msg("file name expected after %c", *src);
1237                                         free_job(job);
1238                                         job->num_progs=0;
1239                                         return 1;
1240                                 }
1241
1242                                 prog->redirects[i].filename = buf;
1243                                 while (*chptr && !isspace(*chptr))
1244                                         *buf++ = *chptr++;
1245
1246                                 src = chptr - 1;        /* we src++ later */
1247                                 prog->argv[argc_l] = ++buf;
1248                                 break;
1249
1250                         case '|':                       /* pipe */
1251                                 /* finish this command */
1252                                 if (*prog->argv[argc_l])
1253                                         argc_l++;
1254                                 if (!argc_l) {
1255                                         error_msg("empty command in pipe");
1256                                         free_job(job);
1257                                         job->num_progs=0;
1258                                         return 1;
1259                                 }
1260                                 prog->argv[argc_l] = NULL;
1261
1262                                 /* and start the next */
1263                                 job->num_progs++;
1264                                 job->progs = xrealloc(job->progs,
1265                                                                           sizeof(*job->progs) * job->num_progs);
1266                                 prog = job->progs + (job->num_progs - 1);
1267                                 prog->num_redirects = 0;
1268                                 prog->redirects = NULL;
1269                                 prog->is_stopped = 0;
1270                                 prog->family = job;
1271                                 argc_l = 0;
1272
1273                                 argv_alloced = 5;
1274                                 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1275                                 prog->argv[0] = ++buf;
1276
1277                                 src++;
1278                                 while (*src && isspace(*src))
1279                                         src++;
1280
1281                                 if (!*src) {
1282                                         error_msg("empty command in pipe");
1283                                         free_job(job);
1284                                         job->num_progs=0;
1285                                         return 1;
1286                                 }
1287                                 src--;                  /* we'll ++ it at the end of the loop */
1288
1289                                 break;
1290
1291                         case '&':                       /* background */
1292                                 *inbg = 1;
1293                         case ';':                       /* multiple commands */
1294                                 done = 1;
1295                                 return_command = *command_ptr + (src - *command_ptr) + 1;
1296                                 break;
1297
1298 #ifdef BB_FEATURE_SH_BACKTICKS
1299                         case '`':
1300                                 /* Exec a backtick-ed command */
1301                                 /* Besides any previous brokenness, I have not
1302                                  * updated backtick handling for close_me support.
1303                                  * I don't know if it needs it or not.  -- LRD */
1304                                 {
1305                                         char* charptr1=NULL, *charptr2;
1306                                         char* ptr=NULL;
1307                                         struct job *newjob;
1308                                         struct jobset njob_list = { NULL, NULL };
1309                                         int pipefd[2];
1310                                         int size;
1311
1312                                         ptr=strchr(++src, '`');
1313                                         if (ptr==NULL) {
1314                                                 fprintf(stderr, "Unmatched '`' in command\n");
1315                                                 free_job(job);
1316                                                 return 1;
1317                                         }
1318
1319                                         /* Make some space to hold just the backticked command */
1320                                         charptr1 = charptr2 = xmalloc(1+ptr-src);
1321                                         memcpy(charptr1, src, ptr-src);
1322                                         charptr1[ptr-src] = '\0';
1323                                         newjob = xmalloc(sizeof(struct job));
1324                                         newjob->job_list = &njob_list;
1325                                         /* Now parse and run the backticked command */
1326                                         if (!parse_command(&charptr1, newjob, inbg) 
1327                                                         && newjob->num_progs) {
1328                                                 pipe(pipefd);
1329                                                 run_command(newjob, 0, pipefd);
1330                                         }
1331                                         checkjobs(job->job_list);
1332                                         free_job(newjob);  /* doesn't actually free newjob,
1333                                                              looks like a memory leak */
1334                                         free(charptr2);
1335                                         
1336                                         /* Make a copy of any stuff left over in the command 
1337                                          * line after the second backtick */
1338                                         charptr2 = xmalloc(strlen(ptr)+1);
1339                                         memcpy(charptr2, ptr+1, strlen(ptr));
1340
1341
1342                                         /* Copy the output from the backtick-ed command into the
1343                                          * command line, making extra room as needed  */
1344                                         --src;
1345                                         charptr1 = xmalloc(BUFSIZ);
1346                                         while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1347                                                 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1348                                                 if (newsize > BUFSIZ) {
1349                                                         *command_ptr=xrealloc(*command_ptr, newsize);
1350                                                 }
1351                                                 memcpy(src, charptr1, size); 
1352                                                 src+=size;
1353                                         }
1354                                         free(charptr1);
1355                                         close(pipefd[0]);
1356                                         if (*(src-1)=='\n')
1357                                                 --src;
1358
1359                                         /* Now paste into the *command_ptr all the stuff 
1360                                          * leftover after the second backtick */
1361                                         memcpy(src, charptr2, strlen(charptr2)+1);
1362                                         free(charptr2);
1363
1364                                         /* Now recursively call parse_command to deal with the new
1365                                          * and improved version of the command line with the backtick
1366                                          * results expanded in place... */
1367                                         {
1368                                                 struct jobset *jl=job->job_list;
1369                                                 free_job(job);
1370                                                 job->job_list = jl;
1371                                         }
1372                                         return(parse_command(command_ptr, job, inbg));
1373                                 }
1374                                 break;
1375 #endif // BB_FEATURE_SH_BACKTICKS
1376
1377                         case '\\':
1378                                 src++;
1379                                 if (!*src) {
1380 /* This is currently a little broken... */
1381 #ifdef HANDLE_CONTINUATION_CHARS
1382                                         /* They fed us a continuation char, so continue reading stuff
1383                                          * on the next line, then tack that onto the end of the current
1384                                          * command */
1385                                         char *command;
1386                                         int newsize;
1387                                         printf("erik: found a continue char at EOL...\n");
1388                                         command = (char *) xcalloc(BUFSIZ, sizeof(char));
1389                                         if (get_command(input, command)) {
1390                                                 error_msg("character expected after \\");
1391                                                 free(command);
1392                                                 free_job(job);
1393                                                 return 1;
1394                                         }
1395                                         newsize = strlen(*command_ptr) + strlen(command) + 2;
1396                                         if (newsize > BUFSIZ) {
1397                                                 printf("erik: doing realloc\n");
1398                                                 *command_ptr=xrealloc(*command_ptr, newsize);
1399                                         }
1400                                         printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1401                                         memcpy(--src, command, strlen(command)); 
1402                                         printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1403                                         free(command);
1404                                         break;
1405 #else
1406                                         error_msg("character expected after \\");
1407                                         free(command);
1408                                         free_job(job);
1409                                         return 1;
1410 #endif
1411                                 }
1412                                 if (*src == '*' || *src == '[' || *src == ']'
1413                                         || *src == '?') *buf++ = '\\';
1414                                 /* fallthrough */
1415                         default:
1416                                 *buf++ = *src;
1417                         }
1418
1419                 src++;
1420         }
1421
1422         if (*prog->argv[argc_l]) {
1423                 argc_l++;
1424         }
1425         if (!argc_l) {
1426                 free_job(job);
1427                 return 0;
1428         }
1429         prog->argv[argc_l] = NULL;
1430
1431         if (!return_command) {
1432                 job->text = xmalloc(strlen(*command_ptr) + 1);
1433                 strcpy(job->text, *command_ptr);
1434         } else {
1435                 /* This leaves any trailing spaces, which is a bit sloppy */
1436                 count = return_command - *command_ptr;
1437                 job->text = xmalloc(count + 1);
1438                 strncpy(job->text, *command_ptr, count);
1439                 job->text[count] = '\0';
1440         }
1441
1442         *command_ptr = return_command;
1443         
1444         return 0;
1445 }
1446
1447 /* Run the child_prog, no matter what kind of command it uses.
1448  */
1449 static int pseudo_exec(struct child_prog *child)
1450 {
1451         struct built_in_command *x;
1452 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1453         char *name;
1454 #endif
1455
1456         /* Check if the command matches any of the non-forking builtins.
1457          * Depending on context, this might be redundant.  But it's
1458          * easier to waste a few CPU cycles than it is to figure out
1459          * if this is one of those cases.
1460          */
1461         for (x = bltins; x->cmd; x++) {
1462                 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1463                         exit(x->function(child));
1464                 }
1465         }
1466
1467         /* Check if the command matches any of the forking builtins. */
1468         for (x = bltins_forking; x->cmd; x++) {
1469                 if (strcmp(child->argv[0], x->cmd) == 0) {
1470                         applet_name=x->cmd;
1471                         exit (x->function(child));
1472                 }
1473         }
1474 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1475         /* Check if the command matches any busybox internal
1476          * commands ("applets") here.  Following discussions from
1477          * November 2000 on busybox@opensource.lineo.com, don't use
1478          * get_last_path_component().  This way explicit (with
1479          * slashes) filenames will never be interpreted as an
1480          * applet, just like with builtins.  This way the user can
1481          * override an applet with an explicit filename reference.
1482          * The only downside to this change is that an explicit
1483          * /bin/foo invocation will fork and exec /bin/foo, even if
1484          * /bin/foo is a symlink to busybox.
1485          */
1486         name = child->argv[0];
1487
1488 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1489         /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1490          * if you run /bin/cat, it will use BusyBox cat even if 
1491          * /bin/cat exists on the filesystem and is _not_ busybox.
1492          * Some systems want this, others do not.  Choose wisely.  :-)
1493          */
1494         name = get_last_path_component(name);
1495 #endif
1496
1497         {
1498             char** argv=child->argv;
1499             int argc_l;
1500             for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1501             optind = 1;
1502             run_applet_by_name(name, argc_l, child->argv);
1503         }
1504 #endif
1505
1506         execvp(child->argv[0], child->argv);
1507         perror_msg_and_die("%s", child->argv[0]);
1508 }
1509
1510 static void insert_job(struct job *newjob, int inbg)
1511 {
1512         struct job *thejob;
1513         struct jobset *job_list=newjob->job_list;
1514
1515         /* find the ID for thejob to use */
1516         newjob->jobid = 1;
1517         for (thejob = job_list->head; thejob; thejob = thejob->next)
1518                 if (thejob->jobid >= newjob->jobid)
1519                         newjob->jobid = thejob->jobid + 1;
1520
1521         /* add thejob to the list of running jobs */
1522         if (!job_list->head) {
1523                 thejob = job_list->head = xmalloc(sizeof(*thejob));
1524         } else {
1525                 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1526                 thejob->next = xmalloc(sizeof(*thejob));
1527                 thejob = thejob->next;
1528         }
1529
1530         *thejob = *newjob;   /* physically copy the struct job */
1531         thejob->next = NULL;
1532         thejob->running_progs = thejob->num_progs;
1533         thejob->stopped_progs = 0;
1534
1535         if (inbg) {
1536                 /* we don't wait for background thejobs to return -- append it 
1537                    to the list of backgrounded thejobs and leave it alone */
1538                 printf("[%d] %d\n", thejob->jobid,
1539                            newjob->progs[newjob->num_progs - 1].pid);
1540 #ifdef BB_FEATURE_SH_ENVIRONMENT
1541                 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1542 #endif
1543         } else {
1544                 newjob->job_list->fg = thejob;
1545
1546                 /* move the new process group into the foreground */
1547                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1548                 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1549                         perror_msg("tcsetpgrp");
1550         }
1551 }
1552
1553 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1554 {
1555         /* struct job *thejob; */
1556         int i;
1557         int nextin, nextout;
1558         int pipefds[2];                         /* pipefd[0] is for reading */
1559         struct built_in_command *x;
1560         struct child_prog *child;
1561
1562         nextin = 0, nextout = 1;
1563         for (i = 0; i < newjob->num_progs; i++) {
1564                 child = & (newjob->progs[i]);
1565
1566                 if ((i + 1) < newjob->num_progs) {
1567                         if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1568                         nextout = pipefds[1];
1569                 } else {
1570                         if (outpipe[1]!=-1) {
1571                                 nextout = outpipe[1];
1572                         } else {
1573                                 nextout = 1;
1574                         }
1575                 }
1576
1577 #ifdef BB_FEATURE_SH_ENVIRONMENT
1578                 if (show_x_trace==TRUE) {
1579                         int j;
1580                         fputc('+', stderr);
1581                         for (j = 0; child->argv[j]; j++) {
1582                                 fputc(' ', stderr);
1583                                 fputs(child->argv[j], stderr);
1584                         }
1585                         fputc('\n', stderr);
1586                 }
1587 #endif
1588
1589                 /* Check if the command matches any non-forking builtins,
1590                  * but only if this is a simple command.
1591                  * Non-forking builtins within pipes have to fork anyway,
1592                  * and are handled in pseudo_exec.  "echo foo | read bar"
1593                  * is doomed to failure, and doesn't work on bash, either.
1594                  */
1595                 if (newjob->num_progs == 1) {
1596                         for (x = bltins; x->cmd; x++) {
1597                                 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1598                                         int squirrel[] = {-1, -1, -1};
1599                                         int rcode;
1600                                         setup_redirects(child, squirrel);
1601                                         rcode = x->function(child);
1602                                         restore_redirects(squirrel);
1603                                         return rcode;
1604                                 }
1605                         }
1606                 }
1607
1608                 if (!(child->pid = fork())) {
1609                         signal(SIGTTOU, SIG_DFL);
1610
1611                         close_all();
1612
1613                         if (outpipe[1]!=-1) {
1614                                 close(outpipe[0]);
1615                         }
1616                         if (nextin != 0) {
1617                                 dup2(nextin, 0);
1618                                 close(nextin);
1619                         }
1620
1621                         if (nextout != 1) {
1622                                 dup2(nextout, 1);
1623                                 dup2(nextout, 2);  /* Really? */
1624                                 close(nextout);
1625                                 close(pipefds[0]);
1626                         }
1627
1628                         /* explicit redirects override pipes */
1629                         setup_redirects(child,NULL);
1630
1631                         pseudo_exec(child);
1632                 }
1633                 if (outpipe[1]!=-1) {
1634                         close(outpipe[1]);
1635                 }
1636
1637                 /* put our child in the process group whose leader is the
1638                    first process in this pipe */
1639                 setpgid(child->pid, newjob->progs[0].pid);
1640                 if (nextin != 0)
1641                         close(nextin);
1642                 if (nextout != 1)
1643                         close(nextout);
1644
1645                 /* If there isn't another process, nextin is garbage 
1646                    but it doesn't matter */
1647                 nextin = pipefds[0];
1648         }
1649
1650         newjob->pgrp = newjob->progs[0].pid;
1651
1652         insert_job(newjob, inbg);
1653
1654         return 0;
1655 }
1656
1657 static int busy_loop(FILE * input)
1658 {
1659         char *command;
1660         char *next_command = NULL;
1661         struct job newjob;
1662         pid_t  parent_pgrp;
1663         int i;
1664         int inbg;
1665         int status;
1666         newjob.job_list = &job_list;
1667         newjob.job_context = DEFAULT_CONTEXT;
1668
1669         /* save current owner of TTY so we can restore it on exit */
1670         parent_pgrp = tcgetpgrp(0);
1671
1672         command = (char *) xcalloc(BUFSIZ, sizeof(char));
1673
1674         /* don't pay any attention to this signal; it just confuses 
1675            things and isn't really meant for shells anyway */
1676         signal(SIGTTOU, SIG_IGN);
1677
1678         while (1) {
1679                 if (!job_list.fg) {
1680                         /* no job is in the foreground */
1681
1682                         /* see if any background processes have exited */
1683                         checkjobs(&job_list);
1684
1685                         if (!next_command) {
1686                                 if (get_command(input, command))
1687                                         break;
1688                                 next_command = command;
1689                         }
1690
1691                         if (expand_arguments(next_command) == FALSE) {
1692                                 free(command);
1693                                 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1694                                 next_command = NULL;
1695                                 continue;
1696                         }
1697
1698                         if (!parse_command(&next_command, &newjob, &inbg) &&
1699                                 newjob.num_progs) {
1700                                 int pipefds[2] = {-1,-1};
1701                                 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1702                                 run_command(&newjob, inbg, pipefds);
1703                         }
1704                         else {
1705                                 free(command);
1706                                 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1707                                 next_command = NULL;
1708                         }
1709                 } else {
1710                         /* a job is running in the foreground; wait for it */
1711                         i = 0;
1712                         while (!job_list.fg->progs[i].pid ||
1713                                    job_list.fg->progs[i].is_stopped == 1) i++;
1714
1715                         if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0)
1716                                 perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid);
1717
1718                         if (WIFEXITED(status) || WIFSIGNALED(status)) {
1719                                 /* the child exited */
1720                                 job_list.fg->running_progs--;
1721                                 job_list.fg->progs[i].pid = 0;
1722
1723 #ifdef BB_FEATURE_SH_ENVIRONMENT
1724                                 last_return_code=WEXITSTATUS(status);
1725 #endif
1726                                 debug_printf("'%s' exited -- return code %d\n",
1727                                                 job_list.fg->text, last_return_code);
1728                                 if (!job_list.fg->running_progs) {
1729                                         /* child exited */
1730                                         remove_job(&job_list, job_list.fg);
1731                                         job_list.fg = NULL;
1732                                 }
1733                         } else {
1734                                 /* the child was stopped */
1735                                 job_list.fg->stopped_progs++;
1736                                 job_list.fg->progs[i].is_stopped = 1;
1737
1738                                 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1739                                         printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1740                                                    "Stopped", job_list.fg->text);
1741                                         job_list.fg = NULL;
1742                                 }
1743                         }
1744
1745                         if (!job_list.fg) {
1746                                 /* move the shell to the foreground */
1747                                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1748                                 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1749                                         perror_msg("tcsetpgrp"); 
1750                         }
1751                 }
1752         }
1753         free(command);
1754
1755         /* return controlling TTY back to parent process group before exiting */
1756         if (tcsetpgrp(0, parent_pgrp))
1757                 perror_msg("tcsetpgrp");
1758
1759         /* return exit status if called with "-c" */
1760         if (input == NULL && WIFEXITED(status))
1761                 return WEXITSTATUS(status);
1762         
1763         return 0;
1764 }
1765
1766
1767 #ifdef BB_FEATURE_CLEAN_UP
1768 void free_memory(void)
1769 {
1770         if (cwd)
1771                 free(cwd);
1772         if (local_pending_command)
1773                 free(local_pending_command);
1774
1775         if (job_list.fg && !job_list.fg->running_progs) {
1776                 remove_job(&job_list, job_list.fg);
1777         }
1778 }
1779 #endif
1780
1781
1782 int shell_main(int argc_l, char **argv_l)
1783 {
1784         int opt, interactive=FALSE;
1785         FILE *input = stdin;
1786         argc = argc_l;
1787         argv = argv_l;
1788
1789         /* These variables need re-initializing when recursing */
1790         shell_context = 0;
1791         cwd=NULL;
1792         local_pending_command = NULL;
1793         close_me_head = NULL;
1794         job_list.head = NULL;
1795         job_list.fg = NULL;
1796 #ifdef BB_FEATURE_SH_ENVIRONMENT
1797         last_bg_pid=1;
1798         last_return_code=1;
1799         show_x_trace=FALSE;
1800 #endif
1801
1802         if (argv[0] && argv[0][0] == '-') {
1803                 FILE *prof_input;
1804                 prof_input = fopen("/etc/profile", "r");
1805                 if (!prof_input) {
1806                         printf( "Couldn't open file '/etc/profile'\n");
1807                 } else {
1808                         int tmp_fd = fileno(prof_input);
1809                         mark_open(tmp_fd);      
1810                         /* Now run the file */
1811                         busy_loop(prof_input);
1812                         fclose(prof_input);
1813                         mark_closed(tmp_fd);
1814                 }
1815         }
1816
1817         while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1818                 switch (opt) {
1819                         case 'c':
1820                                 input = NULL;
1821                                 if (local_pending_command != 0)
1822                                         error_msg_and_die("multiple -c arguments");
1823                                 local_pending_command = xstrdup(argv[optind]);
1824                                 optind++;
1825                                 argv = argv+optind;
1826                                 break;
1827 #ifdef BB_FEATURE_SH_ENVIRONMENT
1828                         case 'x':
1829                                 show_x_trace = TRUE;
1830                                 break;
1831 #endif
1832                         case 'i':
1833                                 interactive = TRUE;
1834                                 break;
1835                         default:
1836                                 show_usage();
1837                 }
1838         }
1839         /* A shell is interactive if the `-i' flag was given, or if all of
1840          * the following conditions are met:
1841          *        no -c command
1842          *    no arguments remaining or the -s flag given
1843          *    standard input is a terminal
1844          *    standard output is a terminal
1845          *    Refer to Posix.2, the description of the `sh' utility. */
1846         if (argv[optind]==NULL && input==stdin &&
1847                         isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1848                 interactive=TRUE;
1849         }
1850         if (interactive==TRUE) {
1851                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1852                 /* Looks like they want an interactive shell */
1853                 printf( "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1854                 printf( "Enter 'help' for a list of built-in commands.\n\n");
1855         } else if (local_pending_command==NULL) {
1856                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1857                 input = xfopen(argv[optind], "r");
1858                 mark_open(fileno(input));  /* be lazy, never mark this closed */
1859         }
1860
1861         /* initialize the cwd -- this is never freed...*/
1862         cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1863         getcwd(cwd, sizeof(char)*MAX_LINE);
1864
1865 #ifdef BB_FEATURE_CLEAN_UP
1866         atexit(free_memory);
1867 #endif
1868
1869         return (busy_loop(input));
1870 }