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