b8ddc87c18a4f9bfc30579e7d56ca2d4a5b0d871
[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 not on by default.
30 #define BB_FEATURE_SH_ENVIRONMENT
31 //
32 //Backtick support has some problems, use at your own risk!
33 //#define BB_FEATURE_SH_BACKTICKS
34 //
35 //If, then, else, etc. support..  This should now behave basically
36 //like any other Bourne shell...
37 //#define BB_FEATURE_SH_IF_EXPRESSIONS
38 //
39 /* This is currently a little broken... */
40 //#define HANDLE_CONTINUATION_CHARS
41 //
42 //For debugging/development on the shell only...
43 //#define DEBUG_SHELL
44
45
46 #include "busybox.h"
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <ctype.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <glob.h>
53 #include <signal.h>
54 #include <string.h>
55 #include <sys/ioctl.h>
56 #include <sys/wait.h>
57 #include <unistd.h>
58 #include <getopt.h>
59 #include "cmdedit.h"
60
61 #define MAX_LINE        256     /* size of input buffer for cwd data */
62 #define MAX_READ        128     /* size of input buffer for `read' builtin */
63 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
64 extern size_t NUM_APPLETS;
65
66
67 enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
68         REDIRECT_APPEND
69 };
70
71 static const unsigned int DEFAULT_CONTEXT=0x1;
72 static const unsigned int IF_TRUE_CONTEXT=0x2;
73 static const unsigned int IF_FALSE_CONTEXT=0x4;
74 static const unsigned int THEN_EXP_CONTEXT=0x8;
75 static const unsigned int ELSE_EXP_CONTEXT=0x10;
76 unsigned int shell_context = 0;
77
78
79
80 struct jobset {
81         struct job *head;                       /* head of list of running jobs */
82         struct job *fg;                         /* current foreground job */
83 };
84
85 struct redir_struct {
86         enum redir_type type;   /* type of redirection */
87         int fd;                                         /* file descriptor being redirected */
88         char *filename;                         /* file to redirect fd to */
89 };
90
91 struct child_prog {
92         pid_t pid;                                      /* 0 if exited */
93         char **argv;                            /* program name and arguments */
94         int num_redirects;                      /* elements in redirection array */
95         struct redir_struct *redirects; /* I/O redirects */
96         glob_t glob_result;                     /* result of parameter globbing */
97         int free_glob;                          /* should we globfree(&glob_result)? */
98         int is_stopped;                         /* is the program currently running? */
99         struct job *family;                     /* pointer back to the child's parent job */
100 };
101
102 struct job {
103         int jobid;                                      /* job number */
104         int num_progs;                          /* total number of programs in job */
105         int running_progs;                      /* number of programs running */
106         char *text;                                     /* name of job */
107         char *cmdbuf;                           /* buffer various argv's point into */
108         pid_t pgrp;                                     /* process group ID for the job */
109         struct child_prog *progs;       /* array of programs in job */
110         struct job *next;                       /* to track background commands */
111         int stopped_progs;                      /* number of programs alive, but stopped */
112         unsigned int job_context;       /* bitmask defining current context */
113         struct jobset *job_list;
114 };
115
116 struct built_in_command {
117         char *cmd;                                      /* name */
118         char *descr;                            /* description */
119         int (*function) (struct child_prog *);  /* function ptr */
120 };
121
122 /* function prototypes for builtins */
123 static int builtin_cd(struct child_prog *cmd);
124 static int builtin_env(struct child_prog *dummy);
125 static int builtin_exec(struct child_prog *cmd);
126 static int builtin_exit(struct child_prog *cmd);
127 static int builtin_fg_bg(struct child_prog *cmd);
128 static int builtin_help(struct child_prog *cmd);
129 static int builtin_jobs(struct child_prog *dummy);
130 static int builtin_pwd(struct child_prog *dummy);
131 static int builtin_export(struct child_prog *cmd);
132 static int builtin_source(struct child_prog *cmd);
133 static int builtin_unset(struct child_prog *cmd);
134 static int builtin_read(struct child_prog *cmd);
135 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
136 static int builtin_if(struct child_prog *cmd);
137 static int builtin_then(struct child_prog *cmd);
138 static int builtin_else(struct child_prog *cmd);
139 static int builtin_fi(struct child_prog *cmd);
140 /* function prototypes for shell stuff */
141 static int run_command_predicate(char *cmd);
142 #endif
143
144
145 /* function prototypes for shell stuff */
146 static void checkjobs(struct jobset *job_list);
147 static int get_command(FILE * source, char *command);
148 static int parse_command(char **command_ptr, struct job *job, int *inbg);
149 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
150 static int pseudo_exec(struct child_prog *cmd) __attribute__ ((noreturn));
151 static int busy_loop(FILE * input);
152
153
154 /* Table of built-in functions (these are non-forking builtins, meaning they
155  * can change global variables in the parent shell process but they will not
156  * work with pipes and redirects; 'unset foo | whatever' will not work) */
157 static struct built_in_command bltins[] = {
158         {"bg", "Resume a job in the background", builtin_fg_bg},
159         {"cd", "Change working directory", builtin_cd},
160         {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
161         {"exit", "Exit from shell()", builtin_exit},
162         {"fg", "Bring job into the foreground", builtin_fg_bg},
163         {"jobs", "Lists the active jobs", builtin_jobs},
164         {"export", "Set environment variable", builtin_export},
165         {"unset", "Unset environment variable", builtin_unset},
166         {"read", "Input environment variable", builtin_read},
167         {".", "Source-in and run commands in a file", builtin_source},
168         /* to do: add ulimit */
169 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
170         {"if", NULL, builtin_if},
171         {"then", NULL, builtin_then},
172         {"else", NULL, builtin_else},
173         {"fi", NULL, builtin_fi},
174 #endif
175         {NULL, NULL, NULL}
176 };
177
178 /* Table of forking built-in functions (things that fork cannot change global
179  * variables in the parent process, such as the current working directory) */
180 static struct built_in_command bltins_forking[] = {
181         {"env", "Print all environment variables", builtin_env},
182         {"pwd", "Print current directory", builtin_pwd},
183         {"help", "List shell built-in commands", builtin_help},
184         {NULL, NULL, NULL}
185 };
186
187 static char prompt[3];
188 static char *cwd;
189 static char *local_pending_command = NULL;
190 static char *prompt_str = NULL;
191 static struct jobset job_list = { NULL, NULL };
192 static int argc;
193 static char **argv;
194 #ifdef BB_FEATURE_SH_ENVIRONMENT
195 static int last_bg_pid=-1;
196 static int last_return_code=-1;
197 static int show_x_trace=FALSE;
198 #endif
199 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
200 static char syntax_err[]="syntax error near unexpected token";
201 #endif
202
203 #ifdef DEBUG_SHELL
204 static inline void debug_printf(const char *format, ...)
205 {
206         va_list args;
207         va_start(args, format);
208         vfprintf(stderr, format, args);
209         va_end(args);
210 }
211 #else
212 static inline void debug_printf(const char *format, ...) { }
213 #endif
214
215 #ifdef BB_FEATURE_SH_COMMAND_EDITING
216 static inline void win_changed(int junk)
217 {
218         struct winsize win = { 0, 0, 0, 0 };
219         ioctl(0, TIOCGWINSZ, &win);
220         if (win.ws_col > 0) {
221                 cmdedit_setwidth( win.ws_col - 1);
222         }
223 }
224 #else
225 static inline void win_changed(int junk) {}
226 #endif
227
228 /*
229         Most builtins need access to the struct child_prog that has
230         their arguments, previously coded as cmd->progs[0].  That coding
231         can exhibit a bug, if the builtin is not the first command in
232         a pipeline: "echo foo | exec sort" will attempt to exec foo.
233
234 builtin   previous use      notes
235 ------ -----------------  ---------
236 cd      cmd->progs[0]
237 env     0
238 exec    cmd->progs[0]  squashed bug: didn't look for applets or forking builtins
239 exit    cmd->progs[0]
240 fg_bg   cmd->progs[0], job_list->head, job_list->fg
241 help    0
242 jobs    job_list->head
243 pwd     0
244 export  cmd->progs[0]  passes cmd, job_list to builtin_env(), which ignores them
245 source  cmd->progs[0]
246 unset   cmd->progs[0]
247 read    cmd->progs[0]
248 if      cmd->job_context,  cmd->text
249 then    cmd->job_context,  cmd->text
250 else    cmd->job_context,  cmd->text
251 fi      cmd->job_context
252
253 The use of cmd->text by if/then/else/fi is hopelessly hacky.
254 Would it work to increment cmd->progs[0]->argv and recurse,
255 somewhat like builtin_exec does?
256
257 I added "struct job *family;" to struct child_prog,
258 and switched API to builtin_foo(struct child_prog *child);
259 So   cmd->text        becomes  child->family->text
260      cmd->job_context  becomes  child->family->job_context
261      cmd->progs[0]    becomes  *child
262      job_list          becomes  child->family->job_list
263  */
264
265 /* built-in 'cd <path>' handler */
266 static int builtin_cd(struct child_prog *child)
267 {
268         char *newdir;
269
270         if (child->argv[1] == NULL)
271                 newdir = getenv("HOME");
272         else
273                 newdir = child->argv[1];
274         if (chdir(newdir)) {
275                 printf("cd: %s: %s\n", newdir, strerror(errno));
276                 return EXIT_FAILURE;
277         }
278         getcwd(cwd, sizeof(char)*MAX_LINE);
279
280         return EXIT_SUCCESS;
281 }
282
283 /* built-in 'env' handler */
284 static int builtin_env(struct child_prog *dummy)
285 {
286         char **e;
287
288         for (e = environ; *e; e++) {
289                 fprintf(stdout, "%s\n", *e);
290         }
291         return (0);
292 }
293
294 /* built-in 'exec' handler */
295 static int builtin_exec(struct child_prog *child)
296 {
297         if (child->argv[1] == NULL)
298                 return EXIT_SUCCESS;   /* Really? */
299         child->argv++;
300         pseudo_exec(child);
301         /* never returns */
302 }
303
304 /* built-in 'exit' handler */
305 static int builtin_exit(struct child_prog *child)
306 {
307         if (child->argv[1] == NULL)
308                 exit(EXIT_SUCCESS);
309
310         exit (atoi(child->argv[1]));
311 }
312
313 /* built-in 'fg' and 'bg' handler */
314 static int builtin_fg_bg(struct child_prog *child)
315 {
316         int i, jobNum;
317         struct job *job=NULL;
318         
319
320                 if (!child->argv[1] || child->argv[2]) {
321                         error_msg("%s: exactly one argument is expected\n",
322                                         child->argv[0]);
323                         return EXIT_FAILURE;
324                 }
325                 if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
326                         error_msg("%s: bad argument '%s'\n",
327                                         child->argv[0], child->argv[1]);
328                         return EXIT_FAILURE;
329                 }
330                 for (job = child->family->job_list->head; job; job = job->next) {
331                         if (job->jobid == jobNum) {
332                                 break;
333                         }
334                 }
335
336         if (!job) {
337                 error_msg("%s: unknown job %d\n",
338                                 child->argv[0], jobNum);
339                 return EXIT_FAILURE;
340         }
341
342         if (*child->argv[0] == 'f') {
343                 /* Make this job the foreground job */
344                 /* suppress messages when run from /linuxrc mag@sysgo.de */
345                 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
346                         perror("tcsetpgrp"); 
347                 child->family->job_list->fg = job;
348         }
349
350         /* Restart the processes in the job */
351         for (i = 0; i < job->num_progs; i++)
352                 job->progs[i].is_stopped = 0;
353
354         kill(-job->pgrp, SIGCONT);
355
356         job->stopped_progs = 0;
357
358         return EXIT_SUCCESS;
359 }
360
361 /* built-in 'help' handler */
362 static int builtin_help(struct child_prog *dummy)
363 {
364         struct built_in_command *x;
365
366         printf("\nBuilt-in commands:\n");
367         printf("-------------------\n");
368         for (x = bltins; x->cmd; x++) {
369                 if (x->descr==NULL)
370                         continue;
371                 printf("%s\t%s\n", x->cmd, x->descr);
372         }
373         for (x = bltins_forking; x->cmd; x++) {
374                 if (x->descr==NULL)
375                         continue;
376                 printf("%s\t%s\n", x->cmd, x->descr);
377         }
378         printf("\n\n");
379         return EXIT_SUCCESS;
380 }
381
382 /* built-in 'jobs' handler */
383 static int builtin_jobs(struct child_prog *child)
384 {
385         struct job *job;
386         char *status_string;
387
388         for (job = child->family->job_list->head; job; job = job->next) {
389                 if (job->running_progs == job->stopped_progs)
390                         status_string = "Stopped";
391                 else
392                         status_string = "Running";
393
394                 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
395         }
396         return EXIT_SUCCESS;
397 }
398
399
400 /* built-in 'pwd' handler */
401 static int builtin_pwd(struct child_prog *dummy)
402 {
403         getcwd(cwd, MAX_LINE);
404         fprintf(stdout, "%s\n", cwd);
405         return EXIT_SUCCESS;
406 }
407
408 /* built-in 'export VAR=value' handler */
409 static int builtin_export(struct child_prog *child)
410 {
411         int res;
412
413         if (child->argv[1] == NULL) {
414                 return (builtin_env(child));
415         }
416         res = putenv(child->argv[1]);
417         if (res)
418                 fprintf(stderr, "export: %s\n", strerror(errno));
419         return (res);
420 }
421
422 /* built-in 'read VAR' handler */
423 static int builtin_read(struct child_prog *child)
424 {
425         int res = 0, len, newlen;
426         char *s;
427         char string[MAX_READ];
428
429         if (child->argv[1]) {
430                 /* argument (VAR) given: put "VAR=" into buffer */
431                 strcpy(string, child->argv[1]);
432                 len = strlen(string);
433                 string[len++] = '=';
434                 string[len]   = '\0';
435                 fgets(&string[len], sizeof(string) - len, stdin);       /* read string */
436                 newlen = strlen(string);
437                 if(newlen > len)
438                         string[--newlen] = '\0';        /* chomp trailing newline */
439                 /*
440                 ** string should now contain "VAR=<value>"
441                 ** copy it (putenv() won't do that, so we must make sure
442                 ** the string resides in a static buffer!)
443                 */
444                 res = -1;
445                 if((s = strdup(string)))
446                         res = putenv(s);
447                 if (res)
448                         fprintf(stderr, "read: %s\n", strerror(errno));
449         }
450         else
451                 fgets(string, sizeof(string), stdin);
452
453         return (res);
454 }
455
456 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
457 /* Built-in handler for 'if' commands */
458 static int builtin_if(struct child_prog *child)
459 {
460         struct job *cmd = child->family;
461         int status;
462         char* charptr1=cmd->text+3; /* skip over the leading 'if ' */
463
464         /* Now run the 'if' command */
465         debug_printf( "job=%p entering builtin_if ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
466         status = run_command_predicate(charptr1);
467         debug_printf( "if test returned ");
468         if (status == 0) {
469                 debug_printf( "TRUE\n");
470                 cmd->job_context |= IF_TRUE_CONTEXT;
471         } else {
472                 debug_printf( "FALSE\n");
473                 cmd->job_context |= IF_FALSE_CONTEXT;
474         }
475         debug_printf("job=%p builtin_if set job context to %x\n", cmd, cmd->job_context);
476         shell_context++;
477
478         return status;
479 }
480
481 /* Built-in handler for 'then' (part of the 'if' command) */
482 static int builtin_then(struct child_prog *child)
483 {
484         struct job *cmd = child->family;
485         char* charptr1=cmd->text+5; /* skip over the leading 'then ' */
486
487         debug_printf( "job=%p entering builtin_then ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
488         if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
489                 shell_context = 0; /* Reset the shell's context on an error */
490                 error_msg("%s `then'\n", syntax_err);
491                 return EXIT_FAILURE;
492         }
493
494         cmd->job_context |= THEN_EXP_CONTEXT;
495         debug_printf("job=%p builtin_then set job context to %x\n", cmd, cmd->job_context);
496
497         /* If the if result was FALSE, skip the 'then' stuff */
498         if (cmd->job_context & IF_FALSE_CONTEXT) {
499                 return EXIT_SUCCESS;
500         }
501
502         /* Seems the if result was TRUE, so run the 'then' command */
503         debug_printf( "'then' now running '%s'\n", charptr1);
504
505         return(run_command_predicate(charptr1));
506 }
507
508 /* Built-in handler for 'else' (part of the 'if' command) */
509 static int builtin_else(struct child_prog *child)
510 {
511         struct job *cmd = child->family;
512         char* charptr1=cmd->text+5; /* skip over the leading 'else ' */
513
514         debug_printf( "job=%p entering builtin_else ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
515
516         if (! (cmd->job_context & THEN_EXP_CONTEXT)) {
517                 shell_context = 0; /* Reset the shell's context on an error */
518                 error_msg("%s `else'\n", syntax_err);
519                 return EXIT_FAILURE;
520         }
521         /* If the if result was TRUE, skip the 'else' stuff */
522         if (cmd->job_context & IF_TRUE_CONTEXT) {
523                 return EXIT_SUCCESS;
524         }
525
526         cmd->job_context |= ELSE_EXP_CONTEXT;
527         debug_printf("job=%p builtin_else set job context to %x\n", child->family, cmd->job_context);
528
529         /* Now run the 'else' command */
530         debug_printf( "'else' now running '%s'\n", charptr1);
531         return(run_command_predicate(charptr1));
532 }
533
534 /* Built-in handler for 'fi' (part of the 'if' command) */
535 static int builtin_fi(struct child_prog *child)
536 {
537         struct job *cmd = child->family;
538         debug_printf( "job=%p entering builtin_fi ('%s')-- context=%d\n", cmd, "", cmd->job_context);
539         if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
540                 shell_context = 0; /* Reset the shell's context on an error */
541                 error_msg("%s `fi'\n", syntax_err);
542                 return EXIT_FAILURE;
543         }
544         /* Clear out the if and then context bits */
545         cmd->job_context &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
546         debug_printf("job=%p builtin_fi set job context to %x\n", cmd, cmd->job_context);
547         shell_context--;
548         return EXIT_SUCCESS;
549 }
550 #endif
551
552 /* Built-in '.' handler (read-in and execute commands from file) */
553 static int builtin_source(struct child_prog *child)
554 {
555         FILE *input;
556         int status;
557
558         if (child->argv[1] == NULL)
559                 return EXIT_FAILURE;
560
561         input = fopen(child->argv[1], "r");
562         if (!input) {
563                 fprintf(stdout, "Couldn't open file '%s'\n", child->argv[1]);
564                 return EXIT_FAILURE;
565         }
566
567         /* Now run the file */
568         status = busy_loop(input);
569         fclose(input);
570         return (status);
571 }
572
573 /* built-in 'unset VAR' handler */
574 static int builtin_unset(struct child_prog *child)
575 {
576         if (child->argv[1] == NULL) {
577                 fprintf(stdout, "unset: parameter required.\n");
578                 return EXIT_FAILURE;
579         }
580         unsetenv(child->argv[1]);
581         return EXIT_SUCCESS;
582 }
583
584 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
585 /* currently used by if/then/else.
586  * Needlessly (?) forks and reparses the command line.
587  * But pseudo_exec on the pre-parsed args doesn't have the
588  * "fork, stick around until the child exits, and find it's return code"
589  * functionality.  The fork is not needed if the predicate is
590  * non-forking builtin, and maybe not even if it's a forking builtin.
591  * applets pretty clearly need the fork.
592  */
593 static int run_command_predicate(char *cmd)
594 {
595         int n=strlen(cmd);
596         local_pending_command = xmalloc(n+1);
597         strncpy(local_pending_command, cmd, n); 
598         local_pending_command[n]='\0';
599         return( busy_loop(NULL));
600 }
601 #endif
602
603 /* free up all memory from a job */
604 static void free_job(struct job *cmd)
605 {
606         int i;
607
608         for (i = 0; i < cmd->num_progs; i++) {
609                 free(cmd->progs[i].argv);
610                 if (cmd->progs[i].redirects)
611                         free(cmd->progs[i].redirects);
612                 if (cmd->progs[i].free_glob)
613                         globfree(&cmd->progs[i].glob_result);
614         }
615         free(cmd->progs);
616         if (cmd->text)
617                 free(cmd->text);
618         free(cmd->cmdbuf);
619         memset(cmd, 0, sizeof(struct job));
620 }
621
622 /* remove a job from the job_list */
623 static void remove_job(struct jobset *job_list, struct job *job)
624 {
625         struct job *prevjob;
626
627         free_job(job);
628         if (job == job_list->head) {
629                 job_list->head = job->next;
630         } else {
631                 prevjob = job_list->head;
632                 while (prevjob->next != job)
633                         prevjob = prevjob->next;
634                 prevjob->next = job->next;
635         }
636
637         free(job);
638 }
639
640 /* Checks to see if any background processes have exited -- if they 
641    have, figure out why and see if a job has completed */
642 static void checkjobs(struct jobset *job_list)
643 {
644         struct job *job;
645         pid_t childpid;
646         int status;
647         int prognum = 0;
648
649         while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
650                 for (job = job_list->head; job; job = job->next) {
651                         prognum = 0;
652                         while (prognum < job->num_progs &&
653                                    job->progs[prognum].pid != childpid) prognum++;
654                         if (prognum < job->num_progs)
655                                 break;
656                 }
657
658                 /* This happens on backticked commands */
659                 if(job==NULL)
660                         return;
661
662                 if (WIFEXITED(status) || WIFSIGNALED(status)) {
663                         /* child exited */
664                         job->running_progs--;
665                         job->progs[prognum].pid = 0;
666
667                         if (!job->running_progs) {
668                                 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
669                                 remove_job(job_list, job);
670                         }
671                 } else {
672                         /* child stopped */
673                         job->stopped_progs++;
674                         job->progs[prognum].is_stopped = 1;
675
676                         if (job->stopped_progs == job->num_progs) {
677                                 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
678                                            job->text);
679                         }
680                 }
681         }
682
683         if (childpid == -1 && errno != ECHILD)
684                 perror("waitpid");
685 }
686
687 static int setup_redirects(struct child_prog *prog)
688 {
689         int i;
690         int openfd;
691         int mode = O_RDONLY;
692         struct redir_struct *redir = prog->redirects;
693
694         for (i = 0; i < prog->num_redirects; i++, redir++) {
695                 switch (redir->type) {
696                 case REDIRECT_INPUT:
697                         mode = O_RDONLY;
698                         break;
699                 case REDIRECT_OVERWRITE:
700                         mode = O_WRONLY | O_CREAT | O_TRUNC;
701                         break;
702                 case REDIRECT_APPEND:
703                         mode = O_WRONLY | O_CREAT | O_APPEND;
704                         break;
705                 }
706
707                 openfd = open(redir->filename, mode, 0666);
708                 if (openfd < 0) {
709                         /* this could get lost if stderr has been redirected, but
710                            bash and ash both lose it as well (though zsh doesn't!) */
711                         error_msg("error opening %s: %s\n", redir->filename,
712                                         strerror(errno));
713                         return 1;
714                 }
715
716                 if (openfd != redir->fd) {
717                         dup2(openfd, redir->fd);
718                         close(openfd);
719                 }
720         }
721
722         return 0;
723 }
724
725
726 static int get_command(FILE * source, char *command)
727 {
728         char user[9],buf[255],*s;
729         
730         if (source == NULL) {
731                 if (local_pending_command) {
732                         /* a command specified (-c option): return it & mark it done */
733                         strcpy(command, local_pending_command);
734                         free(local_pending_command);
735                         local_pending_command = NULL;
736                         return 0;
737                 }
738                 return 1;
739         }
740
741         if (shell_context == 0) {
742                 /* get User Name and setup prompt */
743                 strcpy(prompt,( geteuid() != 0 ) ? "$ ":"# ");
744                 my_getpwuid(user, geteuid());
745                 
746                 /* get HostName */
747                 gethostname(buf, 255);
748                 s = strchr(buf, '.');
749                 if (s) {
750                         *s = 0;
751                 }
752         } else {
753                 strcpy(prompt,"> ");
754         }
755         
756         if (source == stdin) {
757 #ifdef BB_FEATURE_SH_COMMAND_EDITING
758                 int len;
759
760                 /*
761                 ** enable command line editing only while a command line
762                 ** is actually being read; otherwise, we'll end up bequeathing
763                 ** atexit() handlers and other unwanted stuff to our
764                 ** child processes (rob@sysgo.de)
765                 */
766                 cmdedit_init();
767                 signal(SIGWINCH, win_changed);
768                 debug_printf( "in get_command() -- job_context=%d\n", shell_context);
769                 fflush(stdout);
770                 if (shell_context == 0) {
771                         len=fprintf(stdout, "[%s@%s %s]%s", user, buf, 
772                                         get_last_path_component(cwd), prompt);
773                 } else {
774                         len=fprintf(stdout, "%s", prompt);
775                 }
776                 fflush(stdout);
777                 prompt_str=(char*)xmalloc(sizeof(char)*(len+1));
778                 if (shell_context == 0) {
779                         sprintf(prompt_str, "[%s@%s %s]%s", user, buf, 
780                                         get_last_path_component(cwd), prompt);
781                 } else {
782                         sprintf(prompt_str, "%s", prompt);
783                 }
784                 cmdedit_read_input(prompt_str, command);
785                 free( prompt_str);
786                 cmdedit_terminate();
787                 signal(SIGWINCH, SIG_DFL);
788                 return 0;
789 #else
790                 i=strlen(cwd);
791                 i--;
792                 if (i>1){
793                         while ((i>0) && (*(cwd+i)!='/') ) i--;
794                         if (*(cwd+i)=='/') i++;
795                 }
796                 
797                 fprintf(stdout, "[%s@%s %s]%s",user, buf, (cwd+i), prompt);
798                 fflush(stdout);
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 forking builtins.
1308          * XXX It would probably be wise to check for non-forking builtins
1309          * here as well, since in some context the non-forking path
1310          * is disabled or bypassed.  See comment in run_command.
1311          */
1312         for (x = bltins_forking; x->cmd; x++) {
1313                 if (strcmp(child->argv[0], x->cmd) == 0) {
1314                         applet_name=x->cmd;
1315                         exit (x->function(child));
1316                 }
1317         }
1318 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1319         /* Check if the command matches any busybox internal
1320          * commands ("applets") here.  Following discussions from
1321          * November 2000 on busybox@opensource.lineo.com, don't use
1322          * get_last_path_component().  This way explicit (with
1323          * slashes) filenames will never be interpreted as an
1324          * applet, just like with builtins.  This way the user can
1325          * override an applet with an explicit filename reference.
1326          * The only downside to this change is that an explicit
1327          * /bin/foo invocation will fork and exec /bin/foo, even if
1328          * /bin/foo is a symlink to busybox.
1329          */
1330         search_applet.name = child->argv[0];
1331
1332 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1333         /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1334          * if you run /bin/cat, it will use BusyBox cat even if 
1335          * /bin/cat exists on the filesystem and is _not_ busybox.
1336          * Some systems want this, others do not.  Choose wisely.  :-)
1337          */
1338         search_applet.name = get_last_path_component(search_applet.name);
1339 #endif
1340
1341         /* Do a binary search to find the applet entry given the name. */
1342         applet = bsearch(&search_applet, applets, NUM_APPLETS,
1343                         sizeof(struct BB_applet), applet_name_compare);
1344         if (applet != NULL) {
1345                 int argc_l;
1346                 char** argv=child->argv;
1347                 for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1348                 applet_name=applet->name;
1349                 optind = 1;
1350                 exit((*(applet->main)) (argc_l, child->argv));
1351         }
1352 #endif
1353
1354         execvp(child->argv[0], child->argv);
1355         error_msg_and_die("%s: %s\n", child->argv[0],
1356                         strerror(errno));
1357 }
1358
1359 static void insert_job(struct job *newjob, int inbg)
1360 {
1361         struct job *thejob;
1362         struct jobset *job_list=newjob->job_list;
1363
1364         /* find the ID for thejob to use */
1365         newjob->jobid = 1;
1366         for (thejob = job_list->head; thejob; thejob = thejob->next)
1367                 if (thejob->jobid >= newjob->jobid)
1368                         newjob->jobid = thejob->jobid + 1;
1369
1370         /* add thejob to the list of running jobs */
1371         if (!job_list->head) {
1372                 thejob = job_list->head = xmalloc(sizeof(*thejob));
1373         } else {
1374                 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1375                 thejob->next = xmalloc(sizeof(*thejob));
1376                 thejob = thejob->next;
1377         }
1378
1379         *thejob = *newjob;   /* physically copy the struct job */
1380         thejob->next = NULL;
1381         thejob->running_progs = thejob->num_progs;
1382         thejob->stopped_progs = 0;
1383
1384         if (inbg) {
1385                 /* we don't wait for background thejobs to return -- append it 
1386                    to the list of backgrounded thejobs and leave it alone */
1387                 printf("[%d] %d\n", thejob->jobid,
1388                            newjob->progs[newjob->num_progs - 1].pid);
1389 #ifdef BB_FEATURE_SH_ENVIRONMENT
1390                 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1391 #endif
1392         } else {
1393                 newjob->job_list->fg = thejob;
1394
1395                 /* move the new process group into the foreground */
1396                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1397                 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1398                         perror("tcsetpgrp");
1399         }
1400 }
1401
1402 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1403 {
1404         /* struct job *thejob; */
1405         int i;
1406         int nextin, nextout;
1407         int pipefds[2];                         /* pipefd[0] is for reading */
1408         struct built_in_command *x;
1409         struct child_prog *child;
1410
1411         nextin = 0, nextout = 1;
1412         for (i = 0; i < newjob->num_progs; i++) {
1413                 child = & (newjob->progs[i]);
1414
1415                 if ((i + 1) < newjob->num_progs) {
1416                         if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1417                         nextout = pipefds[1];
1418                 } else {
1419                         if (outpipe[1]!=-1) {
1420                                 nextout = outpipe[1];
1421                         } else {
1422                                 nextout = 1;
1423                         }
1424                 }
1425
1426 #ifdef BB_FEATURE_SH_ENVIRONMENT
1427                 if (show_x_trace==TRUE) {
1428                         int j;
1429                         fputc('+', stderr);
1430                         for (j = 0; child->argv[j]; j++) {
1431                                 fputc(' ', stderr);
1432                                 fputs(child->argv[j], stderr);
1433                         }
1434                         fputc('\n', stderr);
1435                 }
1436 #endif
1437
1438                 /* Check if the command matches any non-forking builtins.
1439                  * XXX should probably skip this test, and fork anyway, if
1440                  * there redirects of some kind demand forking to work right.
1441                  * pseudo_exec would then need to handle the non-forking command
1442                  * in a forked context.
1443                  */
1444                 for (x = bltins; x->cmd; x++) {
1445                         if (strcmp(child->argv[0], x->cmd) == 0 ) {
1446                                 return(x->function(child));
1447                         }
1448                 }
1449
1450                 if (!(child->pid = fork())) {
1451                         signal(SIGTTOU, SIG_DFL);
1452
1453                         if (outpipe[1]!=-1) {
1454                                 close(outpipe[0]);
1455                         }
1456                         if (nextin != 0) {
1457                                 dup2(nextin, 0);
1458                                 close(nextin);
1459                         }
1460
1461                         if (nextout != 1) {
1462                                 dup2(nextout, 1);
1463                                 dup2(nextout, 2);  /* Really? */
1464                                 close(nextout);
1465                                 close(pipefds[0]);
1466                         }
1467
1468                         /* explicit redirects override pipes */
1469                         setup_redirects(child);
1470
1471                         pseudo_exec(child);
1472                 }
1473                 if (outpipe[1]!=-1) {
1474                         close(outpipe[1]);
1475                 }
1476
1477                 /* put our child in the process group whose leader is the
1478                    first process in this pipe */
1479                 setpgid(child->pid, newjob->progs[0].pid);
1480                 if (nextin != 0)
1481                         close(nextin);
1482                 if (nextout != 1)
1483                         close(nextout);
1484
1485                 /* If there isn't another process, nextin is garbage 
1486                    but it doesn't matter */
1487                 nextin = pipefds[0];
1488         }
1489
1490         newjob->pgrp = newjob->progs[0].pid;
1491
1492         insert_job(newjob, inbg);
1493
1494         return 0;
1495 }
1496
1497 static int busy_loop(FILE * input)
1498 {
1499         char *command;
1500         char *next_command = NULL;
1501         struct job newjob;
1502         pid_t  parent_pgrp;
1503         int i;
1504         int inbg;
1505         int status;
1506         newjob.job_list = &job_list;
1507         newjob.job_context = DEFAULT_CONTEXT;
1508
1509         /* save current owner of TTY so we can restore it on exit */
1510         parent_pgrp = tcgetpgrp(0);
1511
1512         command = (char *) xcalloc(BUFSIZ, sizeof(char));
1513
1514         /* don't pay any attention to this signal; it just confuses 
1515            things and isn't really meant for shells anyway */
1516         signal(SIGTTOU, SIG_IGN);
1517
1518         while (1) {
1519                 if (!job_list.fg) {
1520                         /* no job is in the foreground */
1521
1522                         /* see if any background processes have exited */
1523                         checkjobs(&job_list);
1524
1525                         if (!next_command) {
1526                                 if (get_command(input, command))
1527                                         break;
1528                                 next_command = command;
1529                         }
1530
1531                         if (!parse_command(&next_command, &newjob, &inbg) &&
1532                                 newjob.num_progs) {
1533                                 int pipefds[2] = {-1,-1};
1534                                 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1535                                 run_command(&newjob, inbg, pipefds);
1536                         }
1537                         else {
1538                                 free(command);
1539                                 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1540                                 next_command = NULL;
1541                         }
1542                 } else {
1543                         /* a job is running in the foreground; wait for it */
1544                         i = 0;
1545                         while (!job_list.fg->progs[i].pid ||
1546                                    job_list.fg->progs[i].is_stopped == 1) i++;
1547
1548                         waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED);
1549
1550                         if (WIFEXITED(status) || WIFSIGNALED(status)) {
1551                                 /* the child exited */
1552                                 job_list.fg->running_progs--;
1553                                 job_list.fg->progs[i].pid = 0;
1554
1555 #ifdef BB_FEATURE_SH_ENVIRONMENT
1556                                 last_return_code=WEXITSTATUS(status);
1557 #endif
1558                                 debug_printf("'%s' exited -- return code %d\n",
1559                                                 job_list.fg->text, last_return_code);
1560                                 if (!job_list.fg->running_progs) {
1561                                         /* child exited */
1562                                         remove_job(&job_list, job_list.fg);
1563                                         job_list.fg = NULL;
1564                                 }
1565                         } else {
1566                                 /* the child was stopped */
1567                                 job_list.fg->stopped_progs++;
1568                                 job_list.fg->progs[i].is_stopped = 1;
1569
1570                                 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1571                                         printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1572                                                    "Stopped", job_list.fg->text);
1573                                         job_list.fg = NULL;
1574                                 }
1575                         }
1576
1577                         if (!job_list.fg) {
1578                                 /* move the shell to the foreground */
1579                                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1580                                 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1581                                         perror("tcsetpgrp"); 
1582                         }
1583                 }
1584         }
1585         free(command);
1586
1587         /* return controlling TTY back to parent process group before exiting */
1588         if (tcsetpgrp(0, parent_pgrp))
1589                 perror("tcsetpgrp");
1590
1591         /* return exit status if called with "-c" */
1592         if (input == NULL && WIFEXITED(status))
1593                 return WEXITSTATUS(status);
1594         
1595         return 0;
1596 }
1597
1598
1599 #ifdef BB_FEATURE_CLEAN_UP
1600 void free_memory(void)
1601 {
1602         if (prompt_str)
1603                 free(prompt_str);
1604         if (cwd)
1605                 free(cwd);
1606         if (local_pending_command)
1607                 free(local_pending_command);
1608
1609         if (job_list.fg && !job_list.fg->running_progs) {
1610                 remove_job(&job_list, job_list.fg);
1611         }
1612 }
1613 #endif
1614
1615
1616 int shell_main(int argc_l, char **argv_l)
1617 {
1618         int opt, interactive=FALSE;
1619         FILE *input = stdin;
1620         argc = argc_l;
1621         argv = argv_l;
1622
1623
1624         if (argv[0] && argv[0][0] == '-') {
1625                   FILE *input;
1626                   input = fopen("/etc/profile", "r");
1627                   if (!input) {
1628                           fprintf(stdout, "Couldn't open file '/etc/profile'\n");
1629                   } else {
1630                           /* Now run the file */
1631                           busy_loop(input);
1632                           fclose(input);
1633                   }
1634         }
1635
1636         while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1637                 switch (opt) {
1638                         case 'c':
1639                                 input = NULL;
1640                                 if (local_pending_command != 0)
1641                                         error_msg_and_die("multiple -c arguments\n");
1642                                 local_pending_command = xstrdup(argv[optind]);
1643                                 optind++;
1644                                 argv = argv+optind;
1645                                 break;
1646 #ifdef BB_FEATURE_SH_ENVIRONMENT
1647                         case 'x':
1648                                 show_x_trace = TRUE;
1649                                 break;
1650 #endif
1651                         case 'i':
1652                                 interactive = TRUE;
1653                                 break;
1654                         default:
1655                                 usage(shell_usage);
1656                 }
1657         }
1658         /* A shell is interactive if the `-i' flag was given, or if all of
1659          * the following conditions are met:
1660          *        no -c command
1661          *    no arguments remaining or the -s flag given
1662          *    standard input is a terminal
1663          *    standard output is a terminal
1664          *    Refer to Posix.2, the description of the `sh' utility. */
1665         if (argv[optind]==NULL && input==stdin &&
1666                         isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1667                 interactive=TRUE;
1668         }
1669         if (interactive==TRUE) {
1670                 //fprintf(stdout, "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1671                 /* Looks like they want an interactive shell */
1672                 fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1673                 fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
1674         } else if (local_pending_command==NULL) {
1675                 //fprintf(stdout, "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1676                 input = xfopen(argv[optind], "r");
1677         }
1678
1679         /* initialize the cwd -- this is never freed...*/
1680         cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1681         getcwd(cwd, sizeof(char)*MAX_LINE);
1682
1683 #ifdef BB_FEATURE_CLEAN_UP
1684         atexit(free_memory);
1685 #endif
1686
1687         win_changed(0);
1688         return (busy_loop(input));
1689 }