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