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