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