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