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