Revert multibuild.pl change.
[oweals/busybox.git] / lash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * lash -- the BusyBox Lame-Ass SHell
4  *
5  * Copyright (C) 1999,2000,2001 by Lineo, inc.
6  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7  *
8  * Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is
9  * under the following liberal license: "We have placed this source code in the
10  * public domain. Use it in any project, free or commercial."
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  *
26  */
27
28 /* The parsing engine of this program is officially at a dead-end.
29  * Future work in that direction should move to the work posted
30  * at http://doolittle.faludi.com/~larry/parser.html .
31  * A start on the integration of that work with the rest of sh.c
32  * is at http://codepoet.org/sh.c .
33  */
34 //
35 //This works pretty well now, and is now on by default.
36 #define BB_FEATURE_SH_ENVIRONMENT
37 //
38 //Backtick support has some problems, use at your own risk!
39 //#define BB_FEATURE_SH_BACKTICKS
40 //
41 //If, then, else, etc. support..  This should now behave basically
42 //like any other Bourne shell...
43 #define BB_FEATURE_SH_IF_EXPRESSIONS
44 //
45 /* This is currently a little broken... */
46 //#define HANDLE_CONTINUATION_CHARS
47 //
48 //For debugging/development on the shell only...
49 //#define DEBUG_SHELL
50
51
52 #include "busybox.h"
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <ctype.h>
56 #include <errno.h>
57 #include <fcntl.h>
58 #include <glob.h>
59 #include <signal.h>
60 #include <string.h>
61 #include <sys/ioctl.h>
62 #include <sys/wait.h>
63 #include <unistd.h>
64 #include <getopt.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_init();
858                 cmdedit_read_input(prompt_str, command);
859                 free(prompt_str);
860                 cmdedit_terminate();
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         /* do shell variable substitution */
921         if(*prog->argv[argc_l - 1] == '$') {
922                 if ((var = getenv(prog->argv[argc_l - 1] + 1))) {
923                         prog->argv[argc_l - 1] = var;
924                 } 
925 #ifdef BB_FEATURE_SH_ENVIRONMENT
926                 else {
927                         switch(*(prog->argv[argc_l - 1] + 1)) {
928                                 case '?':
929                                         prog->argv[argc_l - 1] = itoa(last_return_code);
930                                         break;
931                                 case '$':
932                                         prog->argv[argc_l - 1] = itoa(getpid());
933                                         break;
934                                 case '#':
935                                         prog->argv[argc_l - 1] = itoa(argc-1);
936                                         break;
937                                 case '!':
938                                         if (last_bg_pid==-1)
939                                                 *(prog->argv[argc_l - 1])='\0';
940                                         else
941                                                 prog->argv[argc_l - 1] = itoa(last_bg_pid);
942                                         break;
943                                 case '0':case '1':case '2':case '3':case '4':
944                                 case '5':case '6':case '7':case '8':case '9':
945                                         {
946                                                 int index=*(prog->argv[argc_l - 1] + 1)-48;
947                                                 if (index >= argc) {
948                                                         *(prog->argv[argc_l - 1])='\0';
949                                                 } else {
950                                                         prog->argv[argc_l - 1] = argv[index];
951                                                 }
952                                         }
953                                         break;
954                         }
955                 }
956 #endif
957         }
958
959         if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){
960                 rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result);
961                 if (rc == GLOB_NOSPACE) {
962                         error_msg("out of space during glob operation");
963                         return;
964                 } else if (rc == GLOB_NOMATCH ||
965                            (!rc && (prog->glob_result.gl_pathc - i) == 1 &&
966                                 strcmp(prog->argv[argc_l - 1],
967                                                 prog->glob_result.gl_pathv[i]) == 0)) {
968                         /* we need to remove whatever \ quoting is still present */
969                         src = dst = prog->argv[argc_l - 1];
970                         while (*src) {
971                                 if (*src == '\\') {
972                                         src++; 
973                                         *dst++ = process_escape_sequence(&src);
974                                 } else { 
975                                         *dst++ = *src;
976                                         src++;
977                                 }
978                         }
979                         *dst = '\0';
980                 } else if (!rc) {
981                         argv_alloced += (prog->glob_result.gl_pathc - i);
982                         prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv));
983                         memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i,
984                                    sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i));
985                         argc_l += (prog->glob_result.gl_pathc - i - 1);
986                 }
987         }else{
988                         src = dst = prog->argv[argc_l - 1];
989                         while (*src) {
990                                 if (*src == '\\') {
991                                         src++; 
992                                         *dst++ = process_escape_sequence(&src);
993                                 } else { 
994                                         *dst++ = *src;
995                                         src++;
996                                 }
997                         }
998                         *dst = '\0';
999                         
1000                         prog->glob_result.gl_pathc=0;
1001                         if (flags==0)
1002                                 prog->glob_result.gl_pathv=NULL;
1003         }
1004         *argv_alloced_ptr = argv_alloced;
1005         *argcPtr = argc_l;
1006 }
1007
1008 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
1009    line). If a valid command is found, command_ptr is set to point to
1010    the beginning of the next command (if the original command had more 
1011    then one job associated with it) or NULL if no more commands are 
1012    present. */
1013 static int parse_command(char **command_ptr, struct job *job, int *inbg)
1014 {
1015         char *command;
1016         char *return_command = NULL;
1017         char *src, *buf, *chptr;
1018         int argc_l = 0;
1019         int done = 0;
1020         int argv_alloced;
1021         int i;
1022         char quote = '\0';
1023         int count;
1024         struct child_prog *prog;
1025
1026         /* skip leading white space */
1027         while (**command_ptr && isspace(**command_ptr))
1028                 (*command_ptr)++;
1029
1030         /* this handles empty lines or leading '#' characters */
1031         if (!**command_ptr || (**command_ptr == '#')) {
1032                 job->num_progs=0;
1033                 return 0;
1034         }
1035
1036         *inbg = 0;
1037         job->num_progs = 1;
1038         job->progs = xmalloc(sizeof(*job->progs));
1039
1040         /* We set the argv elements to point inside of this string. The 
1041            memory is freed by free_job(). Allocate twice the original
1042            length in case we need to quote every single character.
1043
1044            Getting clean memory relieves us of the task of NULL 
1045            terminating things and makes the rest of this look a bit 
1046            cleaner (though it is, admittedly, a tad less efficient) */
1047         job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
1048         job->text = NULL;
1049
1050         prog = job->progs;
1051         prog->num_redirects = 0;
1052         prog->redirects = NULL;
1053         prog->free_glob = 0;
1054         prog->is_stopped = 0;
1055         prog->family = job;
1056
1057         argv_alloced = 5;
1058         prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1059         prog->argv[0] = job->cmdbuf;
1060
1061         buf = command;
1062         src = *command_ptr;
1063         while (*src && !done) {
1064                 if (quote == *src) {
1065                         quote = '\0';
1066                 } else if (quote) {
1067                         if (*src == '\\') {
1068                                 src++;
1069                                 if (!*src) {
1070                                         error_msg("character expected after \\");
1071                                         free_job(job);
1072                                         return 1;
1073                                 }
1074
1075                                 /* in shell, "\'" should yield \' */
1076                                 if (*src != quote) {
1077                                         *buf++ = '\\';
1078                                         *buf++ = '\\';
1079                                 }
1080                         } else if (*src == '*' || *src == '?' || *src == '[' ||
1081                                            *src == ']') *buf++ = '\\';
1082                         *buf++ = *src;
1083                 } else if (isspace(*src)) {
1084                         if (*prog->argv[argc_l]) {
1085                                 buf++, argc_l++;
1086                                 /* +1 here leaves room for the NULL which ends argv */
1087                                 if ((argc_l + 1) == argv_alloced) {
1088                                         argv_alloced += 5;
1089                                         prog->argv = xrealloc(prog->argv,
1090                                                                                   sizeof(*prog->argv) *
1091                                                                                   argv_alloced);
1092                                 }
1093                                 expand_argument(prog, &argc_l, &argv_alloced);
1094                                 prog->argv[argc_l] = buf;
1095                         }
1096                 } else
1097                         switch (*src) {
1098                         case '"':
1099                         case '\'':
1100                                 quote = *src;
1101                                 break;
1102
1103                         case '#':                       /* comment */
1104                                 if (*(src-1)== '$')
1105                                         *buf++ = *src;
1106                                 else
1107                                         done = 1;
1108                                 break;
1109
1110                         case '>':                       /* redirects */
1111                         case '<':
1112                                 i = prog->num_redirects++;
1113                                 prog->redirects = xrealloc(prog->redirects,
1114                                                                                           sizeof(*prog->redirects) *
1115                                                                                           (i + 1));
1116
1117                                 prog->redirects[i].fd = -1;
1118                                 if (buf != prog->argv[argc_l]) {
1119                                         /* the stuff before this character may be the file number 
1120                                            being redirected */
1121                                         prog->redirects[i].fd =
1122                                                 strtol(prog->argv[argc_l], &chptr, 10);
1123
1124                                         if (*chptr && *prog->argv[argc_l]) {
1125                                                 buf++, argc_l++;
1126                                                 expand_argument(prog, &argc_l, &argv_alloced);
1127                                                 prog->argv[argc_l] = buf;
1128                                         }
1129                                 }
1130
1131                                 if (prog->redirects[i].fd == -1) {
1132                                         if (*src == '>')
1133                                                 prog->redirects[i].fd = 1;
1134                                         else
1135                                                 prog->redirects[i].fd = 0;
1136                                 }
1137
1138                                 if (*src++ == '>') {
1139                                         if (*src == '>')
1140                                                 prog->redirects[i].type =
1141                                                         REDIRECT_APPEND, src++;
1142                                         else
1143                                                 prog->redirects[i].type = REDIRECT_OVERWRITE;
1144                                 } else {
1145                                         prog->redirects[i].type = REDIRECT_INPUT;
1146                                 }
1147
1148                                 /* This isn't POSIX sh compliant. Oh well. */
1149                                 chptr = src;
1150                                 while (isspace(*chptr))
1151                                         chptr++;
1152
1153                                 if (!*chptr) {
1154                                         error_msg("file name expected after %c", *src);
1155                                         free_job(job);
1156                                         job->num_progs=0;
1157                                         return 1;
1158                                 }
1159
1160                                 prog->redirects[i].filename = buf;
1161                                 while (*chptr && !isspace(*chptr))
1162                                         *buf++ = *chptr++;
1163
1164                                 src = chptr - 1;        /* we src++ later */
1165                                 prog->argv[argc_l] = ++buf;
1166                                 break;
1167
1168                         case '|':                       /* pipe */
1169                                 /* finish this command */
1170                                 if (*prog->argv[argc_l])
1171                                         argc_l++;
1172                                 if (!argc_l) {
1173                                         error_msg("empty command in pipe");
1174                                         free_job(job);
1175                                         job->num_progs=0;
1176                                         return 1;
1177                                 }
1178                                 prog->argv[argc_l] = NULL;
1179
1180                                 /* and start the next */
1181                                 job->num_progs++;
1182                                 job->progs = xrealloc(job->progs,
1183                                                                           sizeof(*job->progs) * job->num_progs);
1184                                 prog = job->progs + (job->num_progs - 1);
1185                                 prog->num_redirects = 0;
1186                                 prog->redirects = NULL;
1187                                 prog->free_glob = 0;
1188                                 prog->is_stopped = 0;
1189                                 prog->family = job;
1190                                 argc_l = 0;
1191
1192                                 argv_alloced = 5;
1193                                 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1194                                 prog->argv[0] = ++buf;
1195
1196                                 src++;
1197                                 while (*src && isspace(*src))
1198                                         src++;
1199
1200                                 if (!*src) {
1201                                         error_msg("empty command in pipe");
1202                                         free_job(job);
1203                                         job->num_progs=0;
1204                                         return 1;
1205                                 }
1206                                 src--;                  /* we'll ++ it at the end of the loop */
1207
1208                                 break;
1209
1210                         case '&':                       /* background */
1211                                 *inbg = 1;
1212                         case ';':                       /* multiple commands */
1213                                 done = 1;
1214                                 return_command = *command_ptr + (src - *command_ptr) + 1;
1215                                 break;
1216
1217 #ifdef BB_FEATURE_SH_BACKTICKS
1218                         case '`':
1219                                 /* Exec a backtick-ed command */
1220                                 /* Besides any previous brokenness, I have not
1221                                  * updated backtick handling for close_me support.
1222                                  * I don't know if it needs it or not.  -- LRD */
1223                                 {
1224                                         char* charptr1=NULL, *charptr2;
1225                                         char* ptr=NULL;
1226                                         struct job *newjob;
1227                                         struct jobset njob_list = { NULL, NULL };
1228                                         int pipefd[2];
1229                                         int size;
1230
1231                                         ptr=strchr(++src, '`');
1232                                         if (ptr==NULL) {
1233                                                 fprintf(stderr, "Unmatched '`' in command\n");
1234                                                 free_job(job);
1235                                                 return 1;
1236                                         }
1237
1238                                         /* Make some space to hold just the backticked command */
1239                                         charptr1 = charptr2 = xmalloc(1+ptr-src);
1240                                         memcpy(charptr1, src, ptr-src);
1241                                         charptr1[ptr-src] = '\0';
1242                                         newjob = xmalloc(sizeof(struct job));
1243                                         newjob->job_list = &njob_list;
1244                                         /* Now parse and run the backticked command */
1245                                         if (!parse_command(&charptr1, newjob, inbg) 
1246                                                         && newjob->num_progs) {
1247                                                 pipe(pipefd);
1248                                                 run_command(newjob, 0, pipefd);
1249                                         }
1250                                         checkjobs(job->job_list);
1251                                         free_job(newjob);  /* doesn't actually free newjob,
1252                                                              looks like a memory leak */
1253                                         free(charptr2);
1254                                         
1255                                         /* Make a copy of any stuff left over in the command 
1256                                          * line after the second backtick */
1257                                         charptr2 = xmalloc(strlen(ptr)+1);
1258                                         memcpy(charptr2, ptr+1, strlen(ptr));
1259
1260
1261                                         /* Copy the output from the backtick-ed command into the
1262                                          * command line, making extra room as needed  */
1263                                         --src;
1264                                         charptr1 = xmalloc(BUFSIZ);
1265                                         while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1266                                                 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1267                                                 if (newsize > BUFSIZ) {
1268                                                         *command_ptr=xrealloc(*command_ptr, newsize);
1269                                                 }
1270                                                 memcpy(src, charptr1, size); 
1271                                                 src+=size;
1272                                         }
1273                                         free(charptr1);
1274                                         close(pipefd[0]);
1275                                         if (*(src-1)=='\n')
1276                                                 --src;
1277
1278                                         /* Now paste into the *command_ptr all the stuff 
1279                                          * leftover after the second backtick */
1280                                         memcpy(src, charptr2, strlen(charptr2)+1);
1281                                         free(charptr2);
1282
1283                                         /* Now recursively call parse_command to deal with the new
1284                                          * and improved version of the command line with the backtick
1285                                          * results expanded in place... */
1286                                         {
1287                                                 struct jobset *jl=job->job_list;
1288                                                 free_job(job);
1289                                                 job->job_list = jl;
1290                                         }
1291                                         return(parse_command(command_ptr, job, inbg));
1292                                 }
1293                                 break;
1294 #endif // BB_FEATURE_SH_BACKTICKS
1295
1296                         case '\\':
1297                                 src++;
1298                                 if (!*src) {
1299 /* This is currently a little broken... */
1300 #ifdef HANDLE_CONTINUATION_CHARS
1301                                         /* They fed us a continuation char, so continue reading stuff
1302                                          * on the next line, then tack that onto the end of the current
1303                                          * command */
1304                                         char *command;
1305                                         int newsize;
1306                                         printf("erik: found a continue char at EOL...\n");
1307                                         command = (char *) xcalloc(BUFSIZ, sizeof(char));
1308                                         if (get_command(input, command)) {
1309                                                 error_msg("character expected after \\");
1310                                                 free(command);
1311                                                 free_job(job);
1312                                                 return 1;
1313                                         }
1314                                         newsize = strlen(*command_ptr) + strlen(command) + 2;
1315                                         if (newsize > BUFSIZ) {
1316                                                 printf("erik: doing realloc\n");
1317                                                 *command_ptr=xrealloc(*command_ptr, newsize);
1318                                         }
1319                                         printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1320                                         memcpy(--src, command, strlen(command)); 
1321                                         printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1322                                         free(command);
1323                                         break;
1324 #else
1325                                         error_msg("character expected after \\");
1326                                         free(command);
1327                                         free_job(job);
1328                                         return 1;
1329 #endif
1330                                 }
1331                                 if (*src == '*' || *src == '[' || *src == ']'
1332                                         || *src == '?') *buf++ = '\\';
1333                                 /* fallthrough */
1334                         default:
1335                                 *buf++ = *src;
1336                         }
1337
1338                 src++;
1339         }
1340
1341         if (*prog->argv[argc_l]) {
1342                 argc_l++;
1343                 expand_argument(prog, &argc_l, &argv_alloced);
1344         }
1345         if (!argc_l) {
1346                 free_job(job);
1347                 return 0;
1348         }
1349         prog->argv[argc_l] = NULL;
1350
1351         if (!return_command) {
1352                 job->text = xmalloc(strlen(*command_ptr) + 1);
1353                 strcpy(job->text, *command_ptr);
1354         } else {
1355                 /* This leaves any trailing spaces, which is a bit sloppy */
1356                 count = return_command - *command_ptr;
1357                 job->text = xmalloc(count + 1);
1358                 strncpy(job->text, *command_ptr, count);
1359                 job->text[count] = '\0';
1360         }
1361
1362         *command_ptr = return_command;
1363         
1364         return 0;
1365 }
1366
1367 /* Run the child_prog, no matter what kind of command it uses.
1368  */
1369 static int pseudo_exec(struct child_prog *child)
1370 {
1371         struct built_in_command *x;
1372 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1373         char *name;
1374 #endif
1375
1376         /* Check if the command matches any of the non-forking builtins.
1377          * Depending on context, this might be redundant.  But it's
1378          * easier to waste a few CPU cycles than it is to figure out
1379          * if this is one of those cases.
1380          */
1381         for (x = bltins; x->cmd; x++) {
1382                 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1383                         exit(x->function(child));
1384                 }
1385         }
1386
1387         /* Check if the command matches any of the forking builtins. */
1388         for (x = bltins_forking; x->cmd; x++) {
1389                 if (strcmp(child->argv[0], x->cmd) == 0) {
1390                         applet_name=x->cmd;
1391                         exit (x->function(child));
1392                 }
1393         }
1394 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1395         /* Check if the command matches any busybox internal
1396          * commands ("applets") here.  Following discussions from
1397          * November 2000 on busybox@opensource.lineo.com, don't use
1398          * get_last_path_component().  This way explicit (with
1399          * slashes) filenames will never be interpreted as an
1400          * applet, just like with builtins.  This way the user can
1401          * override an applet with an explicit filename reference.
1402          * The only downside to this change is that an explicit
1403          * /bin/foo invocation will fork and exec /bin/foo, even if
1404          * /bin/foo is a symlink to busybox.
1405          */
1406         name = child->argv[0];
1407
1408 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1409         /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1410          * if you run /bin/cat, it will use BusyBox cat even if 
1411          * /bin/cat exists on the filesystem and is _not_ busybox.
1412          * Some systems want this, others do not.  Choose wisely.  :-)
1413          */
1414         name = get_last_path_component(name);
1415 #endif
1416
1417         {
1418             char** argv=child->argv;
1419             int argc_l;
1420             for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1421             optind = 1;
1422             run_applet_by_name(name, argc_l, child->argv);
1423         }
1424 #endif
1425
1426         execvp(child->argv[0], child->argv);
1427         perror_msg_and_die("%s", child->argv[0]);
1428 }
1429
1430 static void insert_job(struct job *newjob, int inbg)
1431 {
1432         struct job *thejob;
1433         struct jobset *job_list=newjob->job_list;
1434
1435         /* find the ID for thejob to use */
1436         newjob->jobid = 1;
1437         for (thejob = job_list->head; thejob; thejob = thejob->next)
1438                 if (thejob->jobid >= newjob->jobid)
1439                         newjob->jobid = thejob->jobid + 1;
1440
1441         /* add thejob to the list of running jobs */
1442         if (!job_list->head) {
1443                 thejob = job_list->head = xmalloc(sizeof(*thejob));
1444         } else {
1445                 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1446                 thejob->next = xmalloc(sizeof(*thejob));
1447                 thejob = thejob->next;
1448         }
1449
1450         *thejob = *newjob;   /* physically copy the struct job */
1451         thejob->next = NULL;
1452         thejob->running_progs = thejob->num_progs;
1453         thejob->stopped_progs = 0;
1454
1455         if (inbg) {
1456                 /* we don't wait for background thejobs to return -- append it 
1457                    to the list of backgrounded thejobs and leave it alone */
1458                 printf("[%d] %d\n", thejob->jobid,
1459                            newjob->progs[newjob->num_progs - 1].pid);
1460 #ifdef BB_FEATURE_SH_ENVIRONMENT
1461                 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1462 #endif
1463         } else {
1464                 newjob->job_list->fg = thejob;
1465
1466                 /* move the new process group into the foreground */
1467                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1468                 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1469                         perror_msg("tcsetpgrp");
1470         }
1471 }
1472
1473 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1474 {
1475         /* struct job *thejob; */
1476         int i;
1477         int nextin, nextout;
1478         int pipefds[2];                         /* pipefd[0] is for reading */
1479         struct built_in_command *x;
1480         struct child_prog *child;
1481
1482         nextin = 0, nextout = 1;
1483         for (i = 0; i < newjob->num_progs; i++) {
1484                 child = & (newjob->progs[i]);
1485
1486                 if ((i + 1) < newjob->num_progs) {
1487                         if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1488                         nextout = pipefds[1];
1489                 } else {
1490                         if (outpipe[1]!=-1) {
1491                                 nextout = outpipe[1];
1492                         } else {
1493                                 nextout = 1;
1494                         }
1495                 }
1496
1497 #ifdef BB_FEATURE_SH_ENVIRONMENT
1498                 if (show_x_trace==TRUE) {
1499                         int j;
1500                         fputc('+', stderr);
1501                         for (j = 0; child->argv[j]; j++) {
1502                                 fputc(' ', stderr);
1503                                 fputs(child->argv[j], stderr);
1504                         }
1505                         fputc('\n', stderr);
1506                 }
1507 #endif
1508
1509                 /* Check if the command matches any non-forking builtins,
1510                  * but only if this is a simple command.
1511                  * Non-forking builtins within pipes have to fork anyway,
1512                  * and are handled in pseudo_exec.  "echo foo | read bar"
1513                  * is doomed to failure, and doesn't work on bash, either.
1514                  */
1515                 if (newjob->num_progs == 1) {
1516                         for (x = bltins; x->cmd; x++) {
1517                                 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1518                                         int squirrel[] = {-1, -1, -1};
1519                                         int rcode;
1520                                         setup_redirects(child, squirrel);
1521                                         rcode = x->function(child);
1522                                         restore_redirects(squirrel);
1523                                         return rcode;
1524                                 }
1525                         }
1526                 }
1527
1528                 if (!(child->pid = fork())) {
1529                         signal(SIGTTOU, SIG_DFL);
1530
1531                         close_all();
1532
1533                         if (outpipe[1]!=-1) {
1534                                 close(outpipe[0]);
1535                         }
1536                         if (nextin != 0) {
1537                                 dup2(nextin, 0);
1538                                 close(nextin);
1539                         }
1540
1541                         if (nextout != 1) {
1542                                 dup2(nextout, 1);
1543                                 dup2(nextout, 2);  /* Really? */
1544                                 close(nextout);
1545                                 close(pipefds[0]);
1546                         }
1547
1548                         /* explicit redirects override pipes */
1549                         setup_redirects(child,NULL);
1550
1551                         pseudo_exec(child);
1552                 }
1553                 if (outpipe[1]!=-1) {
1554                         close(outpipe[1]);
1555                 }
1556
1557                 /* put our child in the process group whose leader is the
1558                    first process in this pipe */
1559                 setpgid(child->pid, newjob->progs[0].pid);
1560                 if (nextin != 0)
1561                         close(nextin);
1562                 if (nextout != 1)
1563                         close(nextout);
1564
1565                 /* If there isn't another process, nextin is garbage 
1566                    but it doesn't matter */
1567                 nextin = pipefds[0];
1568         }
1569
1570         newjob->pgrp = newjob->progs[0].pid;
1571
1572         insert_job(newjob, inbg);
1573
1574         return 0;
1575 }
1576
1577 static int busy_loop(FILE * input)
1578 {
1579         char *command;
1580         char *next_command = NULL;
1581         struct job newjob;
1582         pid_t  parent_pgrp;
1583         int i;
1584         int inbg;
1585         int status;
1586         newjob.job_list = &job_list;
1587         newjob.job_context = DEFAULT_CONTEXT;
1588
1589         /* save current owner of TTY so we can restore it on exit */
1590         parent_pgrp = tcgetpgrp(0);
1591
1592         command = (char *) xcalloc(BUFSIZ, sizeof(char));
1593
1594         /* don't pay any attention to this signal; it just confuses 
1595            things and isn't really meant for shells anyway */
1596         signal(SIGTTOU, SIG_IGN);
1597
1598         while (1) {
1599                 if (!job_list.fg) {
1600                         /* no job is in the foreground */
1601
1602                         /* see if any background processes have exited */
1603                         checkjobs(&job_list);
1604
1605                         if (!next_command) {
1606                                 if (get_command(input, command))
1607                                         break;
1608                                 next_command = command;
1609                         }
1610
1611                         if (!parse_command(&next_command, &newjob, &inbg) &&
1612                                 newjob.num_progs) {
1613                                 int pipefds[2] = {-1,-1};
1614                                 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1615                                 run_command(&newjob, inbg, pipefds);
1616                         }
1617                         else {
1618                                 free(command);
1619                                 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1620                                 next_command = NULL;
1621                         }
1622                 } else {
1623                         /* a job is running in the foreground; wait for it */
1624                         i = 0;
1625                         while (!job_list.fg->progs[i].pid ||
1626                                    job_list.fg->progs[i].is_stopped == 1) i++;
1627
1628                         if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0)
1629                                 perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid);
1630
1631                         if (WIFEXITED(status) || WIFSIGNALED(status)) {
1632                                 /* the child exited */
1633                                 job_list.fg->running_progs--;
1634                                 job_list.fg->progs[i].pid = 0;
1635
1636 #ifdef BB_FEATURE_SH_ENVIRONMENT
1637                                 last_return_code=WEXITSTATUS(status);
1638 #endif
1639                                 debug_printf("'%s' exited -- return code %d\n",
1640                                                 job_list.fg->text, last_return_code);
1641                                 if (!job_list.fg->running_progs) {
1642                                         /* child exited */
1643                                         remove_job(&job_list, job_list.fg);
1644                                         job_list.fg = NULL;
1645                                 }
1646                         } else {
1647                                 /* the child was stopped */
1648                                 job_list.fg->stopped_progs++;
1649                                 job_list.fg->progs[i].is_stopped = 1;
1650
1651                                 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1652                                         printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1653                                                    "Stopped", job_list.fg->text);
1654                                         job_list.fg = NULL;
1655                                 }
1656                         }
1657
1658                         if (!job_list.fg) {
1659                                 /* move the shell to the foreground */
1660                                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1661                                 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1662                                         perror_msg("tcsetpgrp"); 
1663                         }
1664                 }
1665         }
1666         free(command);
1667
1668         /* return controlling TTY back to parent process group before exiting */
1669         if (tcsetpgrp(0, parent_pgrp))
1670                 perror_msg("tcsetpgrp");
1671
1672         /* return exit status if called with "-c" */
1673         if (input == NULL && WIFEXITED(status))
1674                 return WEXITSTATUS(status);
1675         
1676         return 0;
1677 }
1678
1679
1680 #ifdef BB_FEATURE_CLEAN_UP
1681 void free_memory(void)
1682 {
1683         if (cwd)
1684                 free(cwd);
1685         if (local_pending_command)
1686                 free(local_pending_command);
1687
1688         if (job_list.fg && !job_list.fg->running_progs) {
1689                 remove_job(&job_list, job_list.fg);
1690         }
1691 }
1692 #endif
1693
1694
1695 int shell_main(int argc_l, char **argv_l)
1696 {
1697         int opt, interactive=FALSE;
1698         FILE *input = stdin;
1699         argc = argc_l;
1700         argv = argv_l;
1701
1702         shell_context = 0;
1703         cwd=NULL;
1704 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1705         /* These variables need re-initializing when recursing */
1706         local_pending_command = NULL;
1707         job_list.head = NULL;
1708         job_list.fg = NULL;
1709 #ifdef BB_FEATURE_SH_ENVIRONMENT
1710         last_bg_pid=-1;
1711         last_return_code=-1;
1712         show_x_trace=FALSE;
1713 #endif
1714 #endif
1715
1716         if (argv[0] && argv[0][0] == '-') {
1717                 FILE *prof_input;
1718                 prof_input = fopen("/etc/profile", "r");
1719                 if (!prof_input) {
1720                         printf( "Couldn't open file '/etc/profile'\n");
1721                 } else {
1722                         int tmp_fd = fileno(prof_input);
1723                         mark_open(tmp_fd);      
1724                         /* Now run the file */
1725                         busy_loop(prof_input);
1726                         fclose(prof_input);
1727                         mark_closed(tmp_fd);
1728                 }
1729         }
1730
1731         while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1732                 switch (opt) {
1733                         case 'c':
1734                                 input = NULL;
1735                                 if (local_pending_command != 0)
1736                                         error_msg_and_die("multiple -c arguments");
1737                                 local_pending_command = xstrdup(argv[optind]);
1738                                 optind++;
1739                                 argv = argv+optind;
1740                                 break;
1741 #ifdef BB_FEATURE_SH_ENVIRONMENT
1742                         case 'x':
1743                                 show_x_trace = TRUE;
1744                                 break;
1745 #endif
1746                         case 'i':
1747                                 interactive = TRUE;
1748                                 break;
1749                         default:
1750                                 show_usage();
1751                 }
1752         }
1753         /* A shell is interactive if the `-i' flag was given, or if all of
1754          * the following conditions are met:
1755          *        no -c command
1756          *    no arguments remaining or the -s flag given
1757          *    standard input is a terminal
1758          *    standard output is a terminal
1759          *    Refer to Posix.2, the description of the `sh' utility. */
1760         if (argv[optind]==NULL && input==stdin &&
1761                         isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1762                 interactive=TRUE;
1763         }
1764         if (interactive==TRUE) {
1765                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1766                 /* Looks like they want an interactive shell */
1767                 printf( "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1768                 printf( "Enter 'help' for a list of built-in commands.\n\n");
1769         } else if (local_pending_command==NULL) {
1770                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1771                 input = xfopen(argv[optind], "r");
1772                 mark_open(fileno(input));  /* be lazy, never mark this closed */
1773         }
1774
1775         /* initialize the cwd -- this is never freed...*/
1776         cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1777         getcwd(cwd, sizeof(char)*MAX_LINE);
1778
1779 #ifdef BB_FEATURE_CLEAN_UP
1780         atexit(free_memory);
1781 #endif
1782
1783         return (busy_loop(input));
1784 }