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