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