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