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