1 /* vi: set sw=4 ts=4: */
3 * lash -- the BusyBox Lame-Ass SHell
5 * Copyright (C) 2000 by Lineo, inc.
6 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
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."
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.
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.
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
29 //This works pretty well now, and is now on by default.
30 #define BB_FEATURE_SH_ENVIRONMENT
32 //Backtick support has some problems, use at your own risk!
33 //#define BB_FEATURE_SH_BACKTICKS
35 //If, then, else, etc. support.. This should now behave basically
36 //like any other Bourne shell...
37 #define BB_FEATURE_SH_IF_EXPRESSIONS
39 /* This is currently a little broken... */
40 //#define HANDLE_CONTINUATION_CHARS
42 //For debugging/development on the shell only...
55 #include <sys/ioctl.h>
61 #define MAX_LINE 256 /* size of input buffer for cwd data */
62 #define MAX_READ 128 /* size of input buffer for `read' builtin */
63 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
64 extern size_t NUM_APPLETS;
67 enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
71 static const unsigned int DEFAULT_CONTEXT=0x1;
72 static const unsigned int IF_TRUE_CONTEXT=0x2;
73 static const unsigned int IF_FALSE_CONTEXT=0x4;
74 static const unsigned int THEN_EXP_CONTEXT=0x8;
75 static const unsigned int ELSE_EXP_CONTEXT=0x10;
76 unsigned int shell_context = 0;
81 struct job *head; /* head of list of running jobs */
82 struct job *fg; /* current foreground job */
86 enum redir_type type; /* type of redirection */
87 int fd; /* file descriptor being redirected */
88 char *filename; /* file to redirect fd to */
92 pid_t pid; /* 0 if exited */
93 char **argv; /* program name and arguments */
94 int num_redirects; /* elements in redirection array */
95 struct redir_struct *redirects; /* I/O redirects */
96 glob_t glob_result; /* result of parameter globbing */
97 int free_glob; /* should we globfree(&glob_result)? */
98 int is_stopped; /* is the program currently running? */
99 struct job *family; /* pointer back to the child's parent job */
103 int jobid; /* job number */
104 int num_progs; /* total number of programs in job */
105 int running_progs; /* number of programs running */
106 char *text; /* name of job */
107 char *cmdbuf; /* buffer various argv's point into */
108 pid_t pgrp; /* process group ID for the job */
109 struct child_prog *progs; /* array of programs in job */
110 struct job *next; /* to track background commands */
111 int stopped_progs; /* number of programs alive, but stopped */
112 unsigned int job_context; /* bitmask defining current context */
113 struct jobset *job_list;
116 struct built_in_command {
117 char *cmd; /* name */
118 char *descr; /* description */
119 int (*function) (struct child_prog *); /* function ptr */
122 /* function prototypes for builtins */
123 static int builtin_cd(struct child_prog *cmd);
124 static int builtin_env(struct child_prog *dummy);
125 static int builtin_exec(struct child_prog *cmd);
126 static int builtin_exit(struct child_prog *cmd);
127 static int builtin_fg_bg(struct child_prog *cmd);
128 static int builtin_help(struct child_prog *cmd);
129 static int builtin_jobs(struct child_prog *dummy);
130 static int builtin_pwd(struct child_prog *dummy);
131 static int builtin_export(struct child_prog *cmd);
132 static int builtin_source(struct child_prog *cmd);
133 static int builtin_unset(struct child_prog *cmd);
134 static int builtin_read(struct child_prog *cmd);
135 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
136 static int builtin_if(struct child_prog *cmd);
137 static int builtin_then(struct child_prog *cmd);
138 static int builtin_else(struct child_prog *cmd);
139 static int builtin_fi(struct child_prog *cmd);
140 /* function prototypes for shell stuff */
141 static int run_command_predicate(char *cmd);
145 /* function prototypes for shell stuff */
146 static void checkjobs(struct jobset *job_list);
147 static int get_command(FILE * source, char *command);
148 static int parse_command(char **command_ptr, struct job *job, int *inbg);
149 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
150 static int pseudo_exec(struct child_prog *cmd) __attribute__ ((noreturn));
151 static int busy_loop(FILE * input);
154 /* Table of built-in functions (these are non-forking builtins, meaning they
155 * can change global variables in the parent shell process but they will not
156 * work with pipes and redirects; 'unset foo | whatever' will not work) */
157 static struct built_in_command bltins[] = {
158 {"bg", "Resume a job in the background", builtin_fg_bg},
159 {"cd", "Change working directory", builtin_cd},
160 {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
161 {"exit", "Exit from shell()", builtin_exit},
162 {"fg", "Bring job into the foreground", builtin_fg_bg},
163 {"jobs", "Lists the active jobs", builtin_jobs},
164 {"export", "Set environment variable", builtin_export},
165 {"unset", "Unset environment variable", builtin_unset},
166 {"read", "Input environment variable", builtin_read},
167 {".", "Source-in and run commands in a file", builtin_source},
168 /* to do: add ulimit */
169 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
170 {"if", NULL, builtin_if},
171 {"then", NULL, builtin_then},
172 {"else", NULL, builtin_else},
173 {"fi", NULL, builtin_fi},
178 /* Table of forking built-in functions (things that fork cannot change global
179 * variables in the parent process, such as the current working directory) */
180 static struct built_in_command bltins_forking[] = {
181 {"env", "Print all environment variables", builtin_env},
182 {"pwd", "Print current directory", builtin_pwd},
183 {"help", "List shell built-in commands", builtin_help},
187 static char prompt[3];
189 static char *local_pending_command = NULL;
190 static char *prompt_str = NULL;
191 static struct jobset job_list = { NULL, NULL };
194 #ifdef BB_FEATURE_SH_ENVIRONMENT
195 static int last_bg_pid=-1;
196 static int last_return_code=-1;
197 static int show_x_trace=FALSE;
199 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
200 static char syntax_err[]="syntax error near unexpected token";
204 static inline void debug_printf(const char *format, ...)
207 va_start(args, format);
208 vfprintf(stderr, format, args);
212 static inline void debug_printf(const char *format, ...) { }
215 #ifdef BB_FEATURE_SH_COMMAND_EDITING
216 static inline void win_changed(int junk)
218 struct winsize win = { 0, 0, 0, 0 };
219 ioctl(0, TIOCGWINSZ, &win);
220 if (win.ws_col > 0) {
221 cmdedit_setwidth( win.ws_col - 1);
225 static inline void win_changed(int junk) {}
229 Most builtins need access to the struct child_prog that has
230 their arguments, previously coded as cmd->progs[0]. That coding
231 can exhibit a bug, if the builtin is not the first command in
232 a pipeline: "echo foo | exec sort" will attempt to exec foo.
234 builtin previous use notes
235 ------ ----------------- ---------
238 exec cmd->progs[0] squashed bug: didn't look for applets or forking builtins
240 fg_bg cmd->progs[0], job_list->head, job_list->fg
244 export cmd->progs[0] passes cmd, job_list to builtin_env(), which ignores them
248 if cmd->job_context, cmd->text
249 then cmd->job_context, cmd->text
250 else cmd->job_context, cmd->text
253 The use of cmd->text by if/then/else/fi is hopelessly hacky.
254 Would it work to increment cmd->progs[0]->argv and recurse,
255 somewhat like builtin_exec does?
257 I added "struct job *family;" to struct child_prog,
258 and switched API to builtin_foo(struct child_prog *child);
259 So cmd->text becomes child->family->text
260 cmd->job_context becomes child->family->job_context
261 cmd->progs[0] becomes *child
262 job_list becomes child->family->job_list
265 /* built-in 'cd <path>' handler */
266 static int builtin_cd(struct child_prog *child)
270 if (child->argv[1] == NULL)
271 newdir = getenv("HOME");
273 newdir = child->argv[1];
275 printf("cd: %s: %s\n", newdir, strerror(errno));
278 getcwd(cwd, sizeof(char)*MAX_LINE);
283 /* built-in 'env' handler */
284 static int builtin_env(struct child_prog *dummy)
288 for (e = environ; *e; e++) {
289 fprintf(stdout, "%s\n", *e);
294 /* built-in 'exec' handler */
295 static int builtin_exec(struct child_prog *child)
297 if (child->argv[1] == NULL)
298 return EXIT_SUCCESS; /* Really? */
304 /* built-in 'exit' handler */
305 static int builtin_exit(struct child_prog *child)
307 if (child->argv[1] == NULL)
310 exit (atoi(child->argv[1]));
313 /* built-in 'fg' and 'bg' handler */
314 static int builtin_fg_bg(struct child_prog *child)
317 struct job *job=NULL;
319 if (!child->argv[1] || child->argv[2]) {
320 error_msg("%s: exactly one argument is expected\n",
325 if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
326 error_msg("%s: bad argument '%s'\n",
327 child->argv[0], child->argv[1]);
331 for (job = child->family->job_list->head; job; job = job->next) {
332 if (job->jobid == jobNum) {
338 error_msg("%s: unknown job %d\n",
339 child->argv[0], jobNum);
343 if (*child->argv[0] == 'f') {
344 /* Make this job the foreground job */
345 /* suppress messages when run from /linuxrc mag@sysgo.de */
346 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
347 perror_msg("tcsetpgrp");
348 child->family->job_list->fg = job;
351 /* Restart the processes in the job */
352 for (i = 0; i < job->num_progs; i++)
353 job->progs[i].is_stopped = 0;
355 kill(-job->pgrp, SIGCONT);
357 job->stopped_progs = 0;
362 /* built-in 'help' handler */
363 static int builtin_help(struct child_prog *dummy)
365 struct built_in_command *x;
367 printf("\nBuilt-in commands:\n");
368 printf("-------------------\n");
369 for (x = bltins; x->cmd; x++) {
372 printf("%s\t%s\n", x->cmd, x->descr);
374 for (x = bltins_forking; x->cmd; x++) {
377 printf("%s\t%s\n", x->cmd, x->descr);
383 /* built-in 'jobs' handler */
384 static int builtin_jobs(struct child_prog *child)
389 for (job = child->family->job_list->head; job; job = job->next) {
390 if (job->running_progs == job->stopped_progs)
391 status_string = "Stopped";
393 status_string = "Running";
395 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
401 /* built-in 'pwd' handler */
402 static int builtin_pwd(struct child_prog *dummy)
404 getcwd(cwd, MAX_LINE);
405 fprintf(stdout, "%s\n", cwd);
409 /* built-in 'export VAR=value' handler */
410 static int builtin_export(struct child_prog *child)
414 if (child->argv[1] == NULL) {
415 return (builtin_env(child));
417 res = putenv(child->argv[1]);
419 fprintf(stderr, "export: %s\n", strerror(errno));
423 /* built-in 'read VAR' handler */
424 static int builtin_read(struct child_prog *child)
426 int res = 0, len, newlen;
428 char string[MAX_READ];
430 if (child->argv[1]) {
431 /* argument (VAR) given: put "VAR=" into buffer */
432 strcpy(string, child->argv[1]);
433 len = strlen(string);
436 fgets(&string[len], sizeof(string) - len, stdin); /* read string */
437 newlen = strlen(string);
439 string[--newlen] = '\0'; /* chomp trailing newline */
441 ** string should now contain "VAR=<value>"
442 ** copy it (putenv() won't do that, so we must make sure
443 ** the string resides in a static buffer!)
446 if((s = strdup(string)))
449 fprintf(stderr, "read: %s\n", strerror(errno));
452 fgets(string, sizeof(string), stdin);
457 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
458 /* Built-in handler for 'if' commands */
459 static int builtin_if(struct child_prog *child)
461 struct job *cmd = child->family;
463 char* charptr1=cmd->text+3; /* skip over the leading 'if ' */
465 /* Now run the 'if' command */
466 debug_printf( "job=%p entering builtin_if ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
467 status = run_command_predicate(charptr1);
468 debug_printf( "if test returned ");
470 debug_printf( "TRUE\n");
471 cmd->job_context |= IF_TRUE_CONTEXT;
473 debug_printf( "FALSE\n");
474 cmd->job_context |= IF_FALSE_CONTEXT;
476 debug_printf("job=%p builtin_if set job context to %x\n", cmd, cmd->job_context);
482 /* Built-in handler for 'then' (part of the 'if' command) */
483 static int builtin_then(struct child_prog *child)
485 struct job *cmd = child->family;
486 char* charptr1=cmd->text+5; /* skip over the leading 'then ' */
488 debug_printf( "job=%p entering builtin_then ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
489 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
490 shell_context = 0; /* Reset the shell's context on an error */
491 error_msg("%s `then'\n", syntax_err);
495 cmd->job_context |= THEN_EXP_CONTEXT;
496 debug_printf("job=%p builtin_then set job context to %x\n", cmd, cmd->job_context);
498 /* If the if result was FALSE, skip the 'then' stuff */
499 if (cmd->job_context & IF_FALSE_CONTEXT) {
503 /* Seems the if result was TRUE, so run the 'then' command */
504 debug_printf( "'then' now running '%s'\n", charptr1);
506 return(run_command_predicate(charptr1));
509 /* Built-in handler for 'else' (part of the 'if' command) */
510 static int builtin_else(struct child_prog *child)
512 struct job *cmd = child->family;
513 char* charptr1=cmd->text+5; /* skip over the leading 'else ' */
515 debug_printf( "job=%p entering builtin_else ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
517 if (! (cmd->job_context & THEN_EXP_CONTEXT)) {
518 shell_context = 0; /* Reset the shell's context on an error */
519 error_msg("%s `else'\n", syntax_err);
522 /* If the if result was TRUE, skip the 'else' stuff */
523 if (cmd->job_context & IF_TRUE_CONTEXT) {
527 cmd->job_context |= ELSE_EXP_CONTEXT;
528 debug_printf("job=%p builtin_else set job context to %x\n", cmd, cmd->job_context);
530 /* Now run the 'else' command */
531 debug_printf( "'else' now running '%s'\n", charptr1);
532 return(run_command_predicate(charptr1));
535 /* Built-in handler for 'fi' (part of the 'if' command) */
536 static int builtin_fi(struct child_prog *child)
538 struct job *cmd = child->family;
539 debug_printf( "job=%p entering builtin_fi ('%s')-- context=%d\n", cmd, "", cmd->job_context);
540 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
541 shell_context = 0; /* Reset the shell's context on an error */
542 error_msg("%s `fi'\n", syntax_err);
545 /* Clear out the if and then context bits */
546 cmd->job_context &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
547 debug_printf("job=%p builtin_fi set job context to %x\n", cmd, cmd->job_context);
553 /* Built-in '.' handler (read-in and execute commands from file) */
554 static int builtin_source(struct child_prog *child)
559 if (child->argv[1] == NULL)
562 input = fopen(child->argv[1], "r");
564 fprintf(stdout, "Couldn't open file '%s'\n", child->argv[1]);
568 /* Now run the file */
569 status = busy_loop(input);
574 /* built-in 'unset VAR' handler */
575 static int builtin_unset(struct child_prog *child)
577 if (child->argv[1] == NULL) {
578 fprintf(stdout, "unset: parameter required.\n");
581 unsetenv(child->argv[1]);
585 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
586 /* currently used by if/then/else.
588 * Reparsing the command line for this purpose is gross,
589 * incorrect, and fundamentally unfixable; in particular,
590 * think about what happens with command substitution.
591 * We really need to pull out the run, wait, return status
592 * functionality out of busy_loop so we can child->argv++
593 * and use that, without going back through parse_command.
595 static int run_command_predicate(char *cmd)
598 local_pending_command = xmalloc(n+1);
599 strncpy(local_pending_command, cmd, n);
600 local_pending_command[n]='\0';
601 return( busy_loop(NULL));
605 /* free up all memory from a job */
606 static void free_job(struct job *cmd)
610 for (i = 0; i < cmd->num_progs; i++) {
611 free(cmd->progs[i].argv);
612 if (cmd->progs[i].redirects)
613 free(cmd->progs[i].redirects);
614 if (cmd->progs[i].free_glob)
615 globfree(&cmd->progs[i].glob_result);
621 memset(cmd, 0, sizeof(struct job));
624 /* remove a job from the job_list */
625 static void remove_job(struct jobset *job_list, struct job *job)
630 if (job == job_list->head) {
631 job_list->head = job->next;
633 prevjob = job_list->head;
634 while (prevjob->next != job)
635 prevjob = prevjob->next;
636 prevjob->next = job->next;
642 /* Checks to see if any background processes have exited -- if they
643 have, figure out why and see if a job has completed */
644 static void checkjobs(struct jobset *job_list)
651 while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
652 for (job = job_list->head; job; job = job->next) {
654 while (prognum < job->num_progs &&
655 job->progs[prognum].pid != childpid) prognum++;
656 if (prognum < job->num_progs)
660 /* This happens on backticked commands */
664 if (WIFEXITED(status) || WIFSIGNALED(status)) {
666 job->running_progs--;
667 job->progs[prognum].pid = 0;
669 if (!job->running_progs) {
670 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
671 remove_job(job_list, job);
675 job->stopped_progs++;
676 job->progs[prognum].is_stopped = 1;
678 if (job->stopped_progs == job->num_progs) {
679 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
685 if (childpid == -1 && errno != ECHILD)
686 perror_msg("waitpid");
689 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
690 * and stderr if they are redirected. */
691 static int setup_redirects(struct child_prog *prog, int squirrel[])
696 struct redir_struct *redir = prog->redirects;
698 for (i = 0; i < prog->num_redirects; i++, redir++) {
699 switch (redir->type) {
703 case REDIRECT_OVERWRITE:
704 mode = O_WRONLY | O_CREAT | O_TRUNC;
706 case REDIRECT_APPEND:
707 mode = O_WRONLY | O_CREAT | O_APPEND;
711 openfd = open(redir->filename, mode, 0666);
713 /* this could get lost if stderr has been redirected, but
714 bash and ash both lose it as well (though zsh doesn't!) */
715 error_msg("error opening %s: %s\n", redir->filename,
720 if (openfd != redir->fd) {
721 if (squirrel && redir->fd < 3) {
722 squirrel[redir->fd] = dup(redir->fd);
724 dup2(openfd, redir->fd);
732 static void restore_redirects(int squirrel[])
735 for (i=0; i<3; i++) {
738 /* No error checking. I sure wouldn't know what
739 * to do with an error if I found one! */
746 static int get_command(FILE * source, char *command)
748 char user[9],buf[255],*s;
750 if (source == NULL) {
751 if (local_pending_command) {
752 /* a command specified (-c option): return it & mark it done */
753 strcpy(command, local_pending_command);
754 free(local_pending_command);
755 local_pending_command = NULL;
761 if (shell_context == 0) {
762 /* get User Name and setup prompt */
763 strcpy(prompt,( geteuid() != 0 ) ? "$ ":"# ");
764 my_getpwuid(user, geteuid());
767 gethostname(buf, 255);
768 s = strchr(buf, '.');
776 if (source == stdin) {
777 #ifdef BB_FEATURE_SH_COMMAND_EDITING
781 ** enable command line editing only while a command line
782 ** is actually being read; otherwise, we'll end up bequeathing
783 ** atexit() handlers and other unwanted stuff to our
784 ** child processes (rob@sysgo.de)
787 signal(SIGWINCH, win_changed);
788 debug_printf( "in get_command() -- job_context=%d\n", shell_context);
790 if (shell_context == 0) {
791 len=fprintf(stdout, "[%s@%s %s]%s", user, buf,
792 get_last_path_component(cwd), prompt);
794 len=fprintf(stdout, "%s", prompt);
797 prompt_str=(char*)xmalloc(sizeof(char)*(len+1));
798 if (shell_context == 0) {
799 sprintf(prompt_str, "[%s@%s %s]%s", user, buf,
800 get_last_path_component(cwd), prompt);
802 sprintf(prompt_str, "%s", prompt);
804 cmdedit_read_input(prompt_str, command);
807 signal(SIGWINCH, SIG_DFL);
813 while ((i>0) && (*(cwd+i)!='/') ) i--;
814 if (*(cwd+i)=='/') i++;
817 fprintf(stdout, "[%s@%s %s]%s",user, buf, (cwd+i), prompt);
822 if (!fgets(command, BUFSIZ - 2, source)) {
828 /* remove trailing newline */
829 command[strlen(command) - 1] = '\0';
834 #ifdef BB_FEATURE_SH_ENVIRONMENT
835 static char* itoa(register int i)
837 static char a[7]; /* Max 7 ints */
838 register char *b = a + sizeof(a) - 1;
846 *--b = '0' + (i % 10);
856 static void expand_argument(struct child_prog *prog, int *argcPtr,
857 int *argv_alloced_ptr)
859 int argc_l = *argcPtr;
860 int argv_alloced = *argv_alloced_ptr;
864 char *src, *dst, *var;
866 if (argc_l > 1) { /* cmd->glob_result is already initialized */
868 i = prog->glob_result.gl_pathc;
874 /* do shell variable substitution */
875 if(*prog->argv[argc_l - 1] == '$') {
876 if ((var = getenv(prog->argv[argc_l - 1] + 1))) {
877 prog->argv[argc_l - 1] = var;
879 #ifdef BB_FEATURE_SH_ENVIRONMENT
881 switch(*(prog->argv[argc_l - 1] + 1)) {
883 prog->argv[argc_l - 1] = itoa(last_return_code);
886 prog->argv[argc_l - 1] = itoa(getpid());
889 prog->argv[argc_l - 1] = itoa(argc-1);
893 *(prog->argv[argc_l - 1])='\0';
895 prog->argv[argc_l - 1] = itoa(last_bg_pid);
897 case '0':case '1':case '2':case '3':case '4':
898 case '5':case '6':case '7':case '8':case '9':
900 int index=*(prog->argv[argc_l - 1] + 1)-48;
902 *(prog->argv[argc_l - 1])='\0';
904 prog->argv[argc_l - 1] = argv[index];
913 if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){
914 rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result);
915 if (rc == GLOB_NOSPACE) {
916 error_msg("out of space during glob operation\n");
918 } else if (rc == GLOB_NOMATCH ||
919 (!rc && (prog->glob_result.gl_pathc - i) == 1 &&
920 strcmp(prog->argv[argc_l - 1],
921 prog->glob_result.gl_pathv[i]) == 0)) {
922 /* we need to remove whatever \ quoting is still present */
923 src = dst = prog->argv[argc_l - 1];
927 *dst++ = process_escape_sequence(&src);
935 argv_alloced += (prog->glob_result.gl_pathc - i);
936 prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv));
937 memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i,
938 sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i));
939 argc_l += (prog->glob_result.gl_pathc - i - 1);
942 src = dst = prog->argv[argc_l - 1];
946 *dst++ = process_escape_sequence(&src);
954 prog->glob_result.gl_pathc=0;
956 prog->glob_result.gl_pathv=NULL;
958 *argv_alloced_ptr = argv_alloced;
962 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
963 line). If a valid command is found, command_ptr is set to point to
964 the beginning of the next command (if the original command had more
965 then one job associated with it) or NULL if no more commands are
967 static int parse_command(char **command_ptr, struct job *job, int *inbg)
970 char *return_command = NULL;
971 char *src, *buf, *chptr;
978 struct child_prog *prog;
980 /* skip leading white space */
981 while (**command_ptr && isspace(**command_ptr))
984 /* this handles empty lines or leading '#' characters */
985 if (!**command_ptr || (**command_ptr == '#')) {
992 job->progs = xmalloc(sizeof(*job->progs));
994 /* We set the argv elements to point inside of this string. The
995 memory is freed by free_job(). Allocate twice the original
996 length in case we need to quote every single character.
998 Getting clean memory relieves us of the task of NULL
999 terminating things and makes the rest of this look a bit
1000 cleaner (though it is, admittedly, a tad less efficient) */
1001 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
1005 prog->num_redirects = 0;
1006 prog->redirects = NULL;
1007 prog->free_glob = 0;
1008 prog->is_stopped = 0;
1012 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1013 prog->argv[0] = job->cmdbuf;
1017 while (*src && !done) {
1018 if (quote == *src) {
1024 error_msg("character expected after \\\n");
1029 /* in shell, "\'" should yield \' */
1030 if (*src != quote) {
1034 } else if (*src == '*' || *src == '?' || *src == '[' ||
1035 *src == ']') *buf++ = '\\';
1037 } else if (isspace(*src)) {
1038 if (*prog->argv[argc_l]) {
1040 /* +1 here leaves room for the NULL which ends argv */
1041 if ((argc_l + 1) == argv_alloced) {
1043 prog->argv = xrealloc(prog->argv,
1044 sizeof(*prog->argv) *
1047 expand_argument(prog, &argc_l, &argv_alloced);
1048 prog->argv[argc_l] = buf;
1057 case '#': /* comment */
1064 case '>': /* redirects */
1066 i = prog->num_redirects++;
1067 prog->redirects = xrealloc(prog->redirects,
1068 sizeof(*prog->redirects) *
1071 prog->redirects[i].fd = -1;
1072 if (buf != prog->argv[argc_l]) {
1073 /* the stuff before this character may be the file number
1075 prog->redirects[i].fd =
1076 strtol(prog->argv[argc_l], &chptr, 10);
1078 if (*chptr && *prog->argv[argc_l]) {
1080 expand_argument(prog, &argc_l, &argv_alloced);
1081 prog->argv[argc_l] = buf;
1085 if (prog->redirects[i].fd == -1) {
1087 prog->redirects[i].fd = 1;
1089 prog->redirects[i].fd = 0;
1092 if (*src++ == '>') {
1094 prog->redirects[i].type =
1095 REDIRECT_APPEND, src++;
1097 prog->redirects[i].type = REDIRECT_OVERWRITE;
1099 prog->redirects[i].type = REDIRECT_INPUT;
1102 /* This isn't POSIX sh compliant. Oh well. */
1104 while (isspace(*chptr))
1108 error_msg("file name expected after %c\n", *src);
1114 prog->redirects[i].filename = buf;
1115 while (*chptr && !isspace(*chptr))
1118 src = chptr - 1; /* we src++ later */
1119 prog->argv[argc_l] = ++buf;
1122 case '|': /* pipe */
1123 /* finish this command */
1124 if (*prog->argv[argc_l])
1127 error_msg("empty command in pipe\n");
1132 prog->argv[argc_l] = NULL;
1134 /* and start the next */
1136 job->progs = xrealloc(job->progs,
1137 sizeof(*job->progs) * job->num_progs);
1138 prog = job->progs + (job->num_progs - 1);
1139 prog->num_redirects = 0;
1140 prog->redirects = NULL;
1141 prog->free_glob = 0;
1142 prog->is_stopped = 0;
1147 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1148 prog->argv[0] = ++buf;
1151 while (*src && isspace(*src))
1155 error_msg("empty command in pipe\n");
1160 src--; /* we'll ++ it at the end of the loop */
1164 case '&': /* background */
1166 case ';': /* multiple commands */
1168 return_command = *command_ptr + (src - *command_ptr) + 1;
1171 #ifdef BB_FEATURE_SH_BACKTICKS
1173 /* Exec a backtick-ed command */
1175 char* charptr1=NULL, *charptr2;
1178 struct jobset njob_list = { NULL, NULL };
1182 ptr=strchr(++src, '`');
1184 fprintf(stderr, "Unmatched '`' in command\n");
1189 /* Make some space to hold just the backticked command */
1190 charptr1 = charptr2 = xmalloc(1+ptr-src);
1191 memcpy(charptr1, src, ptr-src);
1192 charptr1[ptr-src] = '\0';
1193 newjob = xmalloc(sizeof(struct job));
1194 newjob->job_list = &njob_list;
1195 /* Now parse and run the backticked command */
1196 if (!parse_command(&charptr1, newjob, inbg)
1197 && newjob->num_progs) {
1199 run_command(newjob, 0, pipefd);
1201 checkjobs(job->job_list);
1202 free_job(newjob); /* doesn't actually free newjob,
1203 looks like a memory leak */
1206 /* Make a copy of any stuff left over in the command
1207 * line after the second backtick */
1208 charptr2 = xmalloc(strlen(ptr)+1);
1209 memcpy(charptr2, ptr+1, strlen(ptr));
1212 /* Copy the output from the backtick-ed command into the
1213 * command line, making extra room as needed */
1215 charptr1 = xmalloc(BUFSIZ);
1216 while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1217 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1218 if (newsize > BUFSIZ) {
1219 *command_ptr=xrealloc(*command_ptr, newsize);
1221 memcpy(src, charptr1, size);
1229 /* Now paste into the *command_ptr all the stuff
1230 * leftover after the second backtick */
1231 memcpy(src, charptr2, strlen(charptr2)+1);
1234 /* Now recursively call parse_command to deal with the new
1235 * and improved version of the command line with the backtick
1236 * results expanded in place... */
1238 struct jobset *jl=job->job_list;
1242 return(parse_command(command_ptr, job, inbg));
1245 #endif // BB_FEATURE_SH_BACKTICKS
1250 /* This is currently a little broken... */
1251 #ifdef HANDLE_CONTINUATION_CHARS
1252 /* They fed us a continuation char, so continue reading stuff
1253 * on the next line, then tack that onto the end of the current
1257 printf("erik: found a continue char at EOL...\n");
1258 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1259 if (get_command(input, command)) {
1260 error_msg("character expected after \\\n");
1265 newsize = strlen(*command_ptr) + strlen(command) + 2;
1266 if (newsize > BUFSIZ) {
1267 printf("erik: doing realloc\n");
1268 *command_ptr=xrealloc(*command_ptr, newsize);
1270 printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1271 memcpy(--src, command, strlen(command));
1272 printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1276 error_msg("character expected after \\\n");
1282 if (*src == '*' || *src == '[' || *src == ']'
1283 || *src == '?') *buf++ = '\\';
1292 if (*prog->argv[argc_l]) {
1294 expand_argument(prog, &argc_l, &argv_alloced);
1300 prog->argv[argc_l] = NULL;
1302 if (!return_command) {
1303 job->text = xmalloc(strlen(*command_ptr) + 1);
1304 strcpy(job->text, *command_ptr);
1306 /* This leaves any trailing spaces, which is a bit sloppy */
1307 count = return_command - *command_ptr;
1308 job->text = xmalloc(count + 1);
1309 strncpy(job->text, *command_ptr, count);
1310 job->text[count] = '\0';
1313 *command_ptr = return_command;
1318 /* Run the child_prog, no matter what kind of command it uses.
1320 static int pseudo_exec(struct child_prog *child)
1322 struct built_in_command *x;
1323 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1324 struct BB_applet search_applet, *applet;
1327 /* Check if the command matches any of the non-forking builtins.
1328 * Depending on context, this might be redundant. But it's
1329 * easier to waste a few CPU cycles than it is to figure out
1330 * if this is one of those cases.
1332 for (x = bltins; x->cmd; x++) {
1333 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1334 exit(x->function(child));
1338 /* Check if the command matches any of the forking builtins. */
1339 for (x = bltins_forking; x->cmd; x++) {
1340 if (strcmp(child->argv[0], x->cmd) == 0) {
1342 exit (x->function(child));
1345 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1346 /* Check if the command matches any busybox internal
1347 * commands ("applets") here. Following discussions from
1348 * November 2000 on busybox@opensource.lineo.com, don't use
1349 * get_last_path_component(). This way explicit (with
1350 * slashes) filenames will never be interpreted as an
1351 * applet, just like with builtins. This way the user can
1352 * override an applet with an explicit filename reference.
1353 * The only downside to this change is that an explicit
1354 * /bin/foo invocation will fork and exec /bin/foo, even if
1355 * /bin/foo is a symlink to busybox.
1357 search_applet.name = child->argv[0];
1359 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1360 /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1361 * if you run /bin/cat, it will use BusyBox cat even if
1362 * /bin/cat exists on the filesystem and is _not_ busybox.
1363 * Some systems want this, others do not. Choose wisely. :-)
1365 search_applet.name = get_last_path_component(search_applet.name);
1368 /* Do a binary search to find the applet entry given the name. */
1369 applet = bsearch(&search_applet, applets, NUM_APPLETS,
1370 sizeof(struct BB_applet), applet_name_compare);
1371 if (applet != NULL) {
1373 char** argv=child->argv;
1374 for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1375 applet_name=applet->name;
1377 exit((*(applet->main)) (argc_l, child->argv));
1381 execvp(child->argv[0], child->argv);
1382 error_msg_and_die("%s: %s\n", child->argv[0],
1386 static void insert_job(struct job *newjob, int inbg)
1389 struct jobset *job_list=newjob->job_list;
1391 /* find the ID for thejob to use */
1393 for (thejob = job_list->head; thejob; thejob = thejob->next)
1394 if (thejob->jobid >= newjob->jobid)
1395 newjob->jobid = thejob->jobid + 1;
1397 /* add thejob to the list of running jobs */
1398 if (!job_list->head) {
1399 thejob = job_list->head = xmalloc(sizeof(*thejob));
1401 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1402 thejob->next = xmalloc(sizeof(*thejob));
1403 thejob = thejob->next;
1406 *thejob = *newjob; /* physically copy the struct job */
1407 thejob->next = NULL;
1408 thejob->running_progs = thejob->num_progs;
1409 thejob->stopped_progs = 0;
1412 /* we don't wait for background thejobs to return -- append it
1413 to the list of backgrounded thejobs and leave it alone */
1414 printf("[%d] %d\n", thejob->jobid,
1415 newjob->progs[newjob->num_progs - 1].pid);
1416 #ifdef BB_FEATURE_SH_ENVIRONMENT
1417 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1420 newjob->job_list->fg = thejob;
1422 /* move the new process group into the foreground */
1423 /* suppress messages when run from /linuxrc mag@sysgo.de */
1424 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1425 perror_msg("tcsetpgrp");
1429 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1431 /* struct job *thejob; */
1433 int nextin, nextout;
1434 int pipefds[2]; /* pipefd[0] is for reading */
1435 struct built_in_command *x;
1436 struct child_prog *child;
1438 nextin = 0, nextout = 1;
1439 for (i = 0; i < newjob->num_progs; i++) {
1440 child = & (newjob->progs[i]);
1442 if ((i + 1) < newjob->num_progs) {
1443 if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1444 nextout = pipefds[1];
1446 if (outpipe[1]!=-1) {
1447 nextout = outpipe[1];
1453 #ifdef BB_FEATURE_SH_ENVIRONMENT
1454 if (show_x_trace==TRUE) {
1457 for (j = 0; child->argv[j]; j++) {
1459 fputs(child->argv[j], stderr);
1461 fputc('\n', stderr);
1465 /* Check if the command matches any non-forking builtins,
1466 * but only if this is a simple command.
1467 * Non-forking builtins within pipes have to fork anyway,
1468 * and are handled in pseudo_exec. "echo foo | read bar"
1469 * is doomed to failure, and doesn't work on bash, either.
1471 if (newjob->num_progs == 1) {
1472 for (x = bltins; x->cmd; x++) {
1473 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1474 int squirrel[] = {-1, -1, -1};
1476 setup_redirects(child, squirrel);
1477 rcode = x->function(child);
1478 restore_redirects(squirrel);
1484 if (!(child->pid = fork())) {
1485 signal(SIGTTOU, SIG_DFL);
1487 if (outpipe[1]!=-1) {
1497 dup2(nextout, 2); /* Really? */
1502 /* explicit redirects override pipes */
1503 setup_redirects(child,NULL);
1507 if (outpipe[1]!=-1) {
1511 /* put our child in the process group whose leader is the
1512 first process in this pipe */
1513 setpgid(child->pid, newjob->progs[0].pid);
1519 /* If there isn't another process, nextin is garbage
1520 but it doesn't matter */
1521 nextin = pipefds[0];
1524 newjob->pgrp = newjob->progs[0].pid;
1526 insert_job(newjob, inbg);
1531 static int busy_loop(FILE * input)
1534 char *next_command = NULL;
1540 newjob.job_list = &job_list;
1541 newjob.job_context = DEFAULT_CONTEXT;
1543 /* save current owner of TTY so we can restore it on exit */
1544 parent_pgrp = tcgetpgrp(0);
1546 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1548 /* don't pay any attention to this signal; it just confuses
1549 things and isn't really meant for shells anyway */
1550 signal(SIGTTOU, SIG_IGN);
1554 /* no job is in the foreground */
1556 /* see if any background processes have exited */
1557 checkjobs(&job_list);
1559 if (!next_command) {
1560 if (get_command(input, command))
1562 next_command = command;
1565 if (!parse_command(&next_command, &newjob, &inbg) &&
1567 int pipefds[2] = {-1,-1};
1568 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1569 run_command(&newjob, inbg, pipefds);
1573 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1574 next_command = NULL;
1577 /* a job is running in the foreground; wait for it */
1579 while (!job_list.fg->progs[i].pid ||
1580 job_list.fg->progs[i].is_stopped == 1) i++;
1582 waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED);
1584 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1585 /* the child exited */
1586 job_list.fg->running_progs--;
1587 job_list.fg->progs[i].pid = 0;
1589 #ifdef BB_FEATURE_SH_ENVIRONMENT
1590 last_return_code=WEXITSTATUS(status);
1592 debug_printf("'%s' exited -- return code %d\n",
1593 job_list.fg->text, last_return_code);
1594 if (!job_list.fg->running_progs) {
1596 remove_job(&job_list, job_list.fg);
1600 /* the child was stopped */
1601 job_list.fg->stopped_progs++;
1602 job_list.fg->progs[i].is_stopped = 1;
1604 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1605 printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1606 "Stopped", job_list.fg->text);
1612 /* move the shell to the foreground */
1613 /* suppress messages when run from /linuxrc mag@sysgo.de */
1614 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1615 perror_msg("tcsetpgrp");
1621 /* return controlling TTY back to parent process group before exiting */
1622 if (tcsetpgrp(0, parent_pgrp))
1623 perror_msg("tcsetpgrp");
1625 /* return exit status if called with "-c" */
1626 if (input == NULL && WIFEXITED(status))
1627 return WEXITSTATUS(status);
1633 #ifdef BB_FEATURE_CLEAN_UP
1634 void free_memory(void)
1640 if (local_pending_command)
1641 free(local_pending_command);
1643 if (job_list.fg && !job_list.fg->running_progs) {
1644 remove_job(&job_list, job_list.fg);
1650 int shell_main(int argc_l, char **argv_l)
1652 int opt, interactive=FALSE;
1653 FILE *input = stdin;
1658 if (argv[0] && argv[0][0] == '-') {
1660 input = fopen("/etc/profile", "r");
1662 fprintf(stdout, "Couldn't open file '/etc/profile'\n");
1664 /* Now run the file */
1670 while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1674 if (local_pending_command != 0)
1675 error_msg_and_die("multiple -c arguments\n");
1676 local_pending_command = xstrdup(argv[optind]);
1680 #ifdef BB_FEATURE_SH_ENVIRONMENT
1682 show_x_trace = TRUE;
1692 /* A shell is interactive if the `-i' flag was given, or if all of
1693 * the following conditions are met:
1695 * no arguments remaining or the -s flag given
1696 * standard input is a terminal
1697 * standard output is a terminal
1698 * Refer to Posix.2, the description of the `sh' utility. */
1699 if (argv[optind]==NULL && input==stdin &&
1700 isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1703 if (interactive==TRUE) {
1704 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1705 /* Looks like they want an interactive shell */
1706 fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1707 fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
1708 } else if (local_pending_command==NULL) {
1709 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1710 input = xfopen(argv[optind], "r");
1713 /* initialize the cwd -- this is never freed...*/
1714 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1715 getcwd(cwd, sizeof(char)*MAX_LINE);
1717 #ifdef BB_FEATURE_CLEAN_UP
1718 atexit(free_memory);
1722 return (busy_loop(input));