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