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