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