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);
810 fprintf(stdout, "[%s@%s %s]%s",user, buf,
811 get_last_path_component(cwd), prompt);
816 if (!fgets(command, BUFSIZ - 2, source)) {
822 /* remove trailing newline */
823 command[strlen(command) - 1] = '\0';
828 #ifdef BB_FEATURE_SH_ENVIRONMENT
829 static char* itoa(register int i)
831 static char a[7]; /* Max 7 ints */
832 register char *b = a + sizeof(a) - 1;
840 *--b = '0' + (i % 10);
850 static void expand_argument(struct child_prog *prog, int *argcPtr,
851 int *argv_alloced_ptr)
853 int argc_l = *argcPtr;
854 int argv_alloced = *argv_alloced_ptr;
858 char *src, *dst, *var;
860 if (argc_l > 1) { /* cmd->glob_result is already initialized */
862 i = prog->glob_result.gl_pathc;
868 /* do shell variable substitution */
869 if(*prog->argv[argc_l - 1] == '$') {
870 if ((var = getenv(prog->argv[argc_l - 1] + 1))) {
871 prog->argv[argc_l - 1] = var;
873 #ifdef BB_FEATURE_SH_ENVIRONMENT
875 switch(*(prog->argv[argc_l - 1] + 1)) {
877 prog->argv[argc_l - 1] = itoa(last_return_code);
880 prog->argv[argc_l - 1] = itoa(getpid());
883 prog->argv[argc_l - 1] = itoa(argc-1);
887 *(prog->argv[argc_l - 1])='\0';
889 prog->argv[argc_l - 1] = itoa(last_bg_pid);
891 case '0':case '1':case '2':case '3':case '4':
892 case '5':case '6':case '7':case '8':case '9':
894 int index=*(prog->argv[argc_l - 1] + 1)-48;
896 *(prog->argv[argc_l - 1])='\0';
898 prog->argv[argc_l - 1] = argv[index];
907 if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){
908 rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result);
909 if (rc == GLOB_NOSPACE) {
910 error_msg("out of space during glob operation\n");
912 } else if (rc == GLOB_NOMATCH ||
913 (!rc && (prog->glob_result.gl_pathc - i) == 1 &&
914 strcmp(prog->argv[argc_l - 1],
915 prog->glob_result.gl_pathv[i]) == 0)) {
916 /* we need to remove whatever \ quoting is still present */
917 src = dst = prog->argv[argc_l - 1];
921 *dst++ = process_escape_sequence(&src);
929 argv_alloced += (prog->glob_result.gl_pathc - i);
930 prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv));
931 memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i,
932 sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i));
933 argc_l += (prog->glob_result.gl_pathc - i - 1);
936 src = dst = prog->argv[argc_l - 1];
940 *dst++ = process_escape_sequence(&src);
948 prog->glob_result.gl_pathc=0;
950 prog->glob_result.gl_pathv=NULL;
952 *argv_alloced_ptr = argv_alloced;
956 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
957 line). If a valid command is found, command_ptr is set to point to
958 the beginning of the next command (if the original command had more
959 then one job associated with it) or NULL if no more commands are
961 static int parse_command(char **command_ptr, struct job *job, int *inbg)
964 char *return_command = NULL;
965 char *src, *buf, *chptr;
972 struct child_prog *prog;
974 /* skip leading white space */
975 while (**command_ptr && isspace(**command_ptr))
978 /* this handles empty lines or leading '#' characters */
979 if (!**command_ptr || (**command_ptr == '#')) {
986 job->progs = xmalloc(sizeof(*job->progs));
988 /* We set the argv elements to point inside of this string. The
989 memory is freed by free_job(). Allocate twice the original
990 length in case we need to quote every single character.
992 Getting clean memory relieves us of the task of NULL
993 terminating things and makes the rest of this look a bit
994 cleaner (though it is, admittedly, a tad less efficient) */
995 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
999 prog->num_redirects = 0;
1000 prog->redirects = NULL;
1001 prog->free_glob = 0;
1002 prog->is_stopped = 0;
1006 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1007 prog->argv[0] = job->cmdbuf;
1011 while (*src && !done) {
1012 if (quote == *src) {
1018 error_msg("character expected after \\\n");
1023 /* in shell, "\'" should yield \' */
1024 if (*src != quote) {
1028 } else if (*src == '*' || *src == '?' || *src == '[' ||
1029 *src == ']') *buf++ = '\\';
1031 } else if (isspace(*src)) {
1032 if (*prog->argv[argc_l]) {
1034 /* +1 here leaves room for the NULL which ends argv */
1035 if ((argc_l + 1) == argv_alloced) {
1037 prog->argv = xrealloc(prog->argv,
1038 sizeof(*prog->argv) *
1041 expand_argument(prog, &argc_l, &argv_alloced);
1042 prog->argv[argc_l] = buf;
1051 case '#': /* comment */
1058 case '>': /* redirects */
1060 i = prog->num_redirects++;
1061 prog->redirects = xrealloc(prog->redirects,
1062 sizeof(*prog->redirects) *
1065 prog->redirects[i].fd = -1;
1066 if (buf != prog->argv[argc_l]) {
1067 /* the stuff before this character may be the file number
1069 prog->redirects[i].fd =
1070 strtol(prog->argv[argc_l], &chptr, 10);
1072 if (*chptr && *prog->argv[argc_l]) {
1074 expand_argument(prog, &argc_l, &argv_alloced);
1075 prog->argv[argc_l] = buf;
1079 if (prog->redirects[i].fd == -1) {
1081 prog->redirects[i].fd = 1;
1083 prog->redirects[i].fd = 0;
1086 if (*src++ == '>') {
1088 prog->redirects[i].type =
1089 REDIRECT_APPEND, src++;
1091 prog->redirects[i].type = REDIRECT_OVERWRITE;
1093 prog->redirects[i].type = REDIRECT_INPUT;
1096 /* This isn't POSIX sh compliant. Oh well. */
1098 while (isspace(*chptr))
1102 error_msg("file name expected after %c\n", *src);
1108 prog->redirects[i].filename = buf;
1109 while (*chptr && !isspace(*chptr))
1112 src = chptr - 1; /* we src++ later */
1113 prog->argv[argc_l] = ++buf;
1116 case '|': /* pipe */
1117 /* finish this command */
1118 if (*prog->argv[argc_l])
1121 error_msg("empty command in pipe\n");
1126 prog->argv[argc_l] = NULL;
1128 /* and start the next */
1130 job->progs = xrealloc(job->progs,
1131 sizeof(*job->progs) * job->num_progs);
1132 prog = job->progs + (job->num_progs - 1);
1133 prog->num_redirects = 0;
1134 prog->redirects = NULL;
1135 prog->free_glob = 0;
1136 prog->is_stopped = 0;
1141 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1142 prog->argv[0] = ++buf;
1145 while (*src && isspace(*src))
1149 error_msg("empty command in pipe\n");
1154 src--; /* we'll ++ it at the end of the loop */
1158 case '&': /* background */
1160 case ';': /* multiple commands */
1162 return_command = *command_ptr + (src - *command_ptr) + 1;
1165 #ifdef BB_FEATURE_SH_BACKTICKS
1167 /* Exec a backtick-ed command */
1169 char* charptr1=NULL, *charptr2;
1172 struct jobset njob_list = { NULL, NULL };
1176 ptr=strchr(++src, '`');
1178 fprintf(stderr, "Unmatched '`' in command\n");
1183 /* Make some space to hold just the backticked command */
1184 charptr1 = charptr2 = xmalloc(1+ptr-src);
1185 memcpy(charptr1, src, ptr-src);
1186 charptr1[ptr-src] = '\0';
1187 newjob = xmalloc(sizeof(struct job));
1188 newjob->job_list = &njob_list;
1189 /* Now parse and run the backticked command */
1190 if (!parse_command(&charptr1, newjob, inbg)
1191 && newjob->num_progs) {
1193 run_command(newjob, 0, pipefd);
1195 checkjobs(job->job_list);
1196 free_job(newjob); /* doesn't actually free newjob,
1197 looks like a memory leak */
1200 /* Make a copy of any stuff left over in the command
1201 * line after the second backtick */
1202 charptr2 = xmalloc(strlen(ptr)+1);
1203 memcpy(charptr2, ptr+1, strlen(ptr));
1206 /* Copy the output from the backtick-ed command into the
1207 * command line, making extra room as needed */
1209 charptr1 = xmalloc(BUFSIZ);
1210 while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1211 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1212 if (newsize > BUFSIZ) {
1213 *command_ptr=xrealloc(*command_ptr, newsize);
1215 memcpy(src, charptr1, size);
1223 /* Now paste into the *command_ptr all the stuff
1224 * leftover after the second backtick */
1225 memcpy(src, charptr2, strlen(charptr2)+1);
1228 /* Now recursively call parse_command to deal with the new
1229 * and improved version of the command line with the backtick
1230 * results expanded in place... */
1232 struct jobset *jl=job->job_list;
1236 return(parse_command(command_ptr, job, inbg));
1239 #endif // BB_FEATURE_SH_BACKTICKS
1244 /* This is currently a little broken... */
1245 #ifdef HANDLE_CONTINUATION_CHARS
1246 /* They fed us a continuation char, so continue reading stuff
1247 * on the next line, then tack that onto the end of the current
1251 printf("erik: found a continue char at EOL...\n");
1252 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1253 if (get_command(input, command)) {
1254 error_msg("character expected after \\\n");
1259 newsize = strlen(*command_ptr) + strlen(command) + 2;
1260 if (newsize > BUFSIZ) {
1261 printf("erik: doing realloc\n");
1262 *command_ptr=xrealloc(*command_ptr, newsize);
1264 printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1265 memcpy(--src, command, strlen(command));
1266 printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1270 error_msg("character expected after \\\n");
1276 if (*src == '*' || *src == '[' || *src == ']'
1277 || *src == '?') *buf++ = '\\';
1286 if (*prog->argv[argc_l]) {
1288 expand_argument(prog, &argc_l, &argv_alloced);
1294 prog->argv[argc_l] = NULL;
1296 if (!return_command) {
1297 job->text = xmalloc(strlen(*command_ptr) + 1);
1298 strcpy(job->text, *command_ptr);
1300 /* This leaves any trailing spaces, which is a bit sloppy */
1301 count = return_command - *command_ptr;
1302 job->text = xmalloc(count + 1);
1303 strncpy(job->text, *command_ptr, count);
1304 job->text[count] = '\0';
1307 *command_ptr = return_command;
1312 /* Run the child_prog, no matter what kind of command it uses.
1314 static int pseudo_exec(struct child_prog *child)
1316 struct built_in_command *x;
1317 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1318 struct BB_applet search_applet, *applet;
1321 /* Check if the command matches any of the non-forking builtins.
1322 * Depending on context, this might be redundant. But it's
1323 * easier to waste a few CPU cycles than it is to figure out
1324 * if this is one of those cases.
1326 for (x = bltins; x->cmd; x++) {
1327 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1328 exit(x->function(child));
1332 /* Check if the command matches any of the forking builtins. */
1333 for (x = bltins_forking; x->cmd; x++) {
1334 if (strcmp(child->argv[0], x->cmd) == 0) {
1336 exit (x->function(child));
1339 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1340 /* Check if the command matches any busybox internal
1341 * commands ("applets") here. Following discussions from
1342 * November 2000 on busybox@opensource.lineo.com, don't use
1343 * get_last_path_component(). This way explicit (with
1344 * slashes) filenames will never be interpreted as an
1345 * applet, just like with builtins. This way the user can
1346 * override an applet with an explicit filename reference.
1347 * The only downside to this change is that an explicit
1348 * /bin/foo invocation will fork and exec /bin/foo, even if
1349 * /bin/foo is a symlink to busybox.
1351 search_applet.name = child->argv[0];
1353 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1354 /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1355 * if you run /bin/cat, it will use BusyBox cat even if
1356 * /bin/cat exists on the filesystem and is _not_ busybox.
1357 * Some systems want this, others do not. Choose wisely. :-)
1359 search_applet.name = get_last_path_component(search_applet.name);
1362 /* Do a binary search to find the applet entry given the name. */
1363 applet = bsearch(&search_applet, applets, NUM_APPLETS,
1364 sizeof(struct BB_applet), applet_name_compare);
1365 if (applet != NULL) {
1367 char** argv=child->argv;
1368 for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1369 applet_name=applet->name;
1371 exit((*(applet->main)) (argc_l, child->argv));
1375 execvp(child->argv[0], child->argv);
1376 error_msg_and_die("%s: %s\n", child->argv[0],
1380 static void insert_job(struct job *newjob, int inbg)
1383 struct jobset *job_list=newjob->job_list;
1385 /* find the ID for thejob to use */
1387 for (thejob = job_list->head; thejob; thejob = thejob->next)
1388 if (thejob->jobid >= newjob->jobid)
1389 newjob->jobid = thejob->jobid + 1;
1391 /* add thejob to the list of running jobs */
1392 if (!job_list->head) {
1393 thejob = job_list->head = xmalloc(sizeof(*thejob));
1395 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1396 thejob->next = xmalloc(sizeof(*thejob));
1397 thejob = thejob->next;
1400 *thejob = *newjob; /* physically copy the struct job */
1401 thejob->next = NULL;
1402 thejob->running_progs = thejob->num_progs;
1403 thejob->stopped_progs = 0;
1406 /* we don't wait for background thejobs to return -- append it
1407 to the list of backgrounded thejobs and leave it alone */
1408 printf("[%d] %d\n", thejob->jobid,
1409 newjob->progs[newjob->num_progs - 1].pid);
1410 #ifdef BB_FEATURE_SH_ENVIRONMENT
1411 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1414 newjob->job_list->fg = thejob;
1416 /* move the new process group into the foreground */
1417 /* suppress messages when run from /linuxrc mag@sysgo.de */
1418 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1419 perror_msg("tcsetpgrp");
1423 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1425 /* struct job *thejob; */
1427 int nextin, nextout;
1428 int pipefds[2]; /* pipefd[0] is for reading */
1429 struct built_in_command *x;
1430 struct child_prog *child;
1432 nextin = 0, nextout = 1;
1433 for (i = 0; i < newjob->num_progs; i++) {
1434 child = & (newjob->progs[i]);
1436 if ((i + 1) < newjob->num_progs) {
1437 if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1438 nextout = pipefds[1];
1440 if (outpipe[1]!=-1) {
1441 nextout = outpipe[1];
1447 #ifdef BB_FEATURE_SH_ENVIRONMENT
1448 if (show_x_trace==TRUE) {
1451 for (j = 0; child->argv[j]; j++) {
1453 fputs(child->argv[j], stderr);
1455 fputc('\n', stderr);
1459 /* Check if the command matches any non-forking builtins,
1460 * but only if this is a simple command.
1461 * Non-forking builtins within pipes have to fork anyway,
1462 * and are handled in pseudo_exec. "echo foo | read bar"
1463 * is doomed to failure, and doesn't work on bash, either.
1465 if (newjob->num_progs == 1) {
1466 for (x = bltins; x->cmd; x++) {
1467 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1468 int squirrel[] = {-1, -1, -1};
1470 setup_redirects(child, squirrel);
1471 rcode = x->function(child);
1472 restore_redirects(squirrel);
1478 if (!(child->pid = fork())) {
1479 signal(SIGTTOU, SIG_DFL);
1481 if (outpipe[1]!=-1) {
1491 dup2(nextout, 2); /* Really? */
1496 /* explicit redirects override pipes */
1497 setup_redirects(child,NULL);
1501 if (outpipe[1]!=-1) {
1505 /* put our child in the process group whose leader is the
1506 first process in this pipe */
1507 setpgid(child->pid, newjob->progs[0].pid);
1513 /* If there isn't another process, nextin is garbage
1514 but it doesn't matter */
1515 nextin = pipefds[0];
1518 newjob->pgrp = newjob->progs[0].pid;
1520 insert_job(newjob, inbg);
1525 static int busy_loop(FILE * input)
1528 char *next_command = NULL;
1534 newjob.job_list = &job_list;
1535 newjob.job_context = DEFAULT_CONTEXT;
1537 /* save current owner of TTY so we can restore it on exit */
1538 parent_pgrp = tcgetpgrp(0);
1540 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1542 /* don't pay any attention to this signal; it just confuses
1543 things and isn't really meant for shells anyway */
1544 signal(SIGTTOU, SIG_IGN);
1548 /* no job is in the foreground */
1550 /* see if any background processes have exited */
1551 checkjobs(&job_list);
1553 if (!next_command) {
1554 if (get_command(input, command))
1556 next_command = command;
1559 if (!parse_command(&next_command, &newjob, &inbg) &&
1561 int pipefds[2] = {-1,-1};
1562 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1563 run_command(&newjob, inbg, pipefds);
1567 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1568 next_command = NULL;
1571 /* a job is running in the foreground; wait for it */
1573 while (!job_list.fg->progs[i].pid ||
1574 job_list.fg->progs[i].is_stopped == 1) i++;
1576 waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED);
1578 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1579 /* the child exited */
1580 job_list.fg->running_progs--;
1581 job_list.fg->progs[i].pid = 0;
1583 #ifdef BB_FEATURE_SH_ENVIRONMENT
1584 last_return_code=WEXITSTATUS(status);
1586 debug_printf("'%s' exited -- return code %d\n",
1587 job_list.fg->text, last_return_code);
1588 if (!job_list.fg->running_progs) {
1590 remove_job(&job_list, job_list.fg);
1594 /* the child was stopped */
1595 job_list.fg->stopped_progs++;
1596 job_list.fg->progs[i].is_stopped = 1;
1598 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1599 printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1600 "Stopped", job_list.fg->text);
1606 /* move the shell to the foreground */
1607 /* suppress messages when run from /linuxrc mag@sysgo.de */
1608 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1609 perror_msg("tcsetpgrp");
1615 /* return controlling TTY back to parent process group before exiting */
1616 if (tcsetpgrp(0, parent_pgrp))
1617 perror_msg("tcsetpgrp");
1619 /* return exit status if called with "-c" */
1620 if (input == NULL && WIFEXITED(status))
1621 return WEXITSTATUS(status);
1627 #ifdef BB_FEATURE_CLEAN_UP
1628 void free_memory(void)
1634 if (local_pending_command)
1635 free(local_pending_command);
1637 if (job_list.fg && !job_list.fg->running_progs) {
1638 remove_job(&job_list, job_list.fg);
1644 int shell_main(int argc_l, char **argv_l)
1646 int opt, interactive=FALSE;
1647 FILE *input = stdin;
1652 if (argv[0] && argv[0][0] == '-') {
1654 input = fopen("/etc/profile", "r");
1656 fprintf(stdout, "Couldn't open file '/etc/profile'\n");
1658 /* Now run the file */
1664 while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1668 if (local_pending_command != 0)
1669 error_msg_and_die("multiple -c arguments\n");
1670 local_pending_command = xstrdup(argv[optind]);
1674 #ifdef BB_FEATURE_SH_ENVIRONMENT
1676 show_x_trace = TRUE;
1686 /* A shell is interactive if the `-i' flag was given, or if all of
1687 * the following conditions are met:
1689 * no arguments remaining or the -s flag given
1690 * standard input is a terminal
1691 * standard output is a terminal
1692 * Refer to Posix.2, the description of the `sh' utility. */
1693 if (argv[optind]==NULL && input==stdin &&
1694 isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1697 if (interactive==TRUE) {
1698 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1699 /* Looks like they want an interactive shell */
1700 fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1701 fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
1702 } else if (local_pending_command==NULL) {
1703 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1704 input = xfopen(argv[optind], "r");
1707 /* initialize the cwd -- this is never freed...*/
1708 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1709 getcwd(cwd, sizeof(char)*MAX_LINE);
1711 #ifdef BB_FEATURE_CLEAN_UP
1712 atexit(free_memory);
1716 return (busy_loop(input));