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;
79 struct job *head; /* head of list of running jobs */
80 struct job *fg; /* current foreground job */
84 enum redir_type type; /* type of redirection */
85 int fd; /* file descriptor being redirected */
86 char *filename; /* file to redirect fd to */
90 pid_t pid; /* 0 if exited */
91 char **argv; /* program name and arguments */
92 int num_redirects; /* elements in redirection array */
93 struct redir_struct *redirects; /* I/O redirects */
94 glob_t glob_result; /* result of parameter globbing */
95 int free_glob; /* should we globfree(&glob_result)? */
96 int is_stopped; /* is the program currently running? */
97 struct job *family; /* pointer back to the child's parent job */
101 int jobid; /* job number */
102 int num_progs; /* total number of programs in job */
103 int running_progs; /* number of programs running */
104 char *text; /* name of job */
105 char *cmdbuf; /* buffer various argv's point into */
106 pid_t pgrp; /* process group ID for the job */
107 struct child_prog *progs; /* array of programs in job */
108 struct job *next; /* to track background commands */
109 int stopped_progs; /* number of programs alive, but stopped */
110 unsigned int job_context; /* bitmask defining current context */
111 struct jobset *job_list;
114 struct built_in_command {
115 char *cmd; /* name */
116 char *descr; /* description */
117 int (*function) (struct child_prog *); /* function ptr */
120 /* function prototypes for builtins */
121 static int builtin_cd(struct child_prog *cmd);
122 static int builtin_env(struct child_prog *dummy);
123 static int builtin_exec(struct child_prog *cmd);
124 static int builtin_exit(struct child_prog *cmd);
125 static int builtin_fg_bg(struct child_prog *cmd);
126 static int builtin_help(struct child_prog *cmd);
127 static int builtin_jobs(struct child_prog *dummy);
128 static int builtin_pwd(struct child_prog *dummy);
129 static int builtin_export(struct child_prog *cmd);
130 static int builtin_source(struct child_prog *cmd);
131 static int builtin_unset(struct child_prog *cmd);
132 static int builtin_read(struct child_prog *cmd);
133 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
134 static int builtin_if(struct child_prog *cmd);
135 static int builtin_then(struct child_prog *cmd);
136 static int builtin_else(struct child_prog *cmd);
137 static int builtin_fi(struct child_prog *cmd);
138 /* function prototypes for shell stuff */
139 static int run_command_predicate(char *cmd);
143 /* function prototypes for shell stuff */
144 static void checkjobs(struct jobset *job_list);
145 static int get_command(FILE * source, char *command);
146 static int parse_command(char **command_ptr, struct job *job, int *inbg);
147 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
148 static int pseudo_exec(struct child_prog *cmd) __attribute__ ((noreturn));
149 static int busy_loop(FILE * input);
152 /* Table of built-in functions (these are non-forking builtins, meaning they
153 * can change global variables in the parent shell process but they will not
154 * work with pipes and redirects; 'unset foo | whatever' will not work) */
155 static struct built_in_command bltins[] = {
156 {"bg", "Resume a job in the background", builtin_fg_bg},
157 {"cd", "Change working directory", builtin_cd},
158 {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
159 {"exit", "Exit from shell()", builtin_exit},
160 {"fg", "Bring job into the foreground", builtin_fg_bg},
161 {"jobs", "Lists the active jobs", builtin_jobs},
162 {"export", "Set environment variable", builtin_export},
163 {"unset", "Unset environment variable", builtin_unset},
164 {"read", "Input environment variable", builtin_read},
165 {".", "Source-in and run commands in a file", builtin_source},
166 /* to do: add ulimit */
167 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
168 {"if", NULL, builtin_if},
169 {"then", NULL, builtin_then},
170 {"else", NULL, builtin_else},
171 {"fi", NULL, builtin_fi},
176 /* Table of forking built-in functions (things that fork cannot change global
177 * variables in the parent process, such as the current working directory) */
178 static struct built_in_command bltins_forking[] = {
179 {"env", "Print all environment variables", builtin_env},
180 {"pwd", "Print current directory", builtin_pwd},
181 {"help", "List shell built-in commands", builtin_help},
186 /* Variables we export */
187 unsigned int shell_context; /* Used in cmdedit.c to reset the
188 context when someone hits ^C */
191 /* Globals that are static to this file */
193 static char *local_pending_command;
194 static struct jobset job_list = { NULL, NULL };
197 #ifdef BB_FEATURE_SH_ENVIRONMENT
198 static int last_bg_pid=-1;
199 static int last_return_code=-1;
200 static int show_x_trace=FALSE;
202 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
203 static char syntax_err[]="syntax error near unexpected token";
207 static inline void debug_printf(const char *format, ...)
210 va_start(args, format);
211 vfprintf(stderr, format, args);
215 static inline void debug_printf(const char *format, ...) { }
219 Most builtins need access to the struct child_prog that has
220 their arguments, previously coded as cmd->progs[0]. That coding
221 can exhibit a bug, if the builtin is not the first command in
222 a pipeline: "echo foo | exec sort" will attempt to exec foo.
224 builtin previous use notes
225 ------ ----------------- ---------
228 exec cmd->progs[0] squashed bug: didn't look for applets or forking builtins
230 fg_bg cmd->progs[0], job_list->head, job_list->fg
234 export cmd->progs[0] passes cmd, job_list to builtin_env(), which ignores them
238 if cmd->job_context, cmd->text
239 then cmd->job_context, cmd->text
240 else cmd->job_context, cmd->text
243 The use of cmd->text by if/then/else/fi is hopelessly hacky.
244 Would it work to increment cmd->progs[0]->argv and recurse,
245 somewhat like builtin_exec does?
247 I added "struct job *family;" to struct child_prog,
248 and switched API to builtin_foo(struct child_prog *child);
249 So cmd->text becomes child->family->text
250 cmd->job_context becomes child->family->job_context
251 cmd->progs[0] becomes *child
252 job_list becomes child->family->job_list
255 /* built-in 'cd <path>' handler */
256 static int builtin_cd(struct child_prog *child)
260 if (child->argv[1] == NULL)
261 newdir = getenv("HOME");
263 newdir = child->argv[1];
265 printf("cd: %s: %s\n", newdir, strerror(errno));
268 getcwd(cwd, sizeof(char)*MAX_LINE);
273 /* built-in 'env' handler */
274 static int builtin_env(struct child_prog *dummy)
278 for (e = environ; *e; e++) {
279 fprintf(stdout, "%s\n", *e);
284 /* built-in 'exec' handler */
285 static int builtin_exec(struct child_prog *child)
287 if (child->argv[1] == NULL)
288 return EXIT_SUCCESS; /* Really? */
294 /* built-in 'exit' handler */
295 static int builtin_exit(struct child_prog *child)
297 if (child->argv[1] == NULL)
300 exit (atoi(child->argv[1]));
303 /* built-in 'fg' and 'bg' handler */
304 static int builtin_fg_bg(struct child_prog *child)
307 struct job *job=NULL;
309 if (!child->argv[1] || child->argv[2]) {
310 error_msg("%s: exactly one argument is expected\n",
315 if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
316 error_msg("%s: bad argument '%s'\n",
317 child->argv[0], child->argv[1]);
321 for (job = child->family->job_list->head; job; job = job->next) {
322 if (job->jobid == jobNum) {
328 error_msg("%s: unknown job %d\n",
329 child->argv[0], jobNum);
333 if (*child->argv[0] == 'f') {
334 /* Make this job the foreground job */
335 /* suppress messages when run from /linuxrc mag@sysgo.de */
336 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
337 perror_msg("tcsetpgrp");
338 child->family->job_list->fg = job;
341 /* Restart the processes in the job */
342 for (i = 0; i < job->num_progs; i++)
343 job->progs[i].is_stopped = 0;
345 kill(-job->pgrp, SIGCONT);
347 job->stopped_progs = 0;
352 /* built-in 'help' handler */
353 static int builtin_help(struct child_prog *dummy)
355 struct built_in_command *x;
357 printf("\nBuilt-in commands:\n");
358 printf("-------------------\n");
359 for (x = bltins; x->cmd; x++) {
362 printf("%s\t%s\n", x->cmd, x->descr);
364 for (x = bltins_forking; x->cmd; x++) {
367 printf("%s\t%s\n", x->cmd, x->descr);
373 /* built-in 'jobs' handler */
374 static int builtin_jobs(struct child_prog *child)
379 for (job = child->family->job_list->head; job; job = job->next) {
380 if (job->running_progs == job->stopped_progs)
381 status_string = "Stopped";
383 status_string = "Running";
385 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
391 /* built-in 'pwd' handler */
392 static int builtin_pwd(struct child_prog *dummy)
394 getcwd(cwd, MAX_LINE);
395 fprintf(stdout, "%s\n", cwd);
399 /* built-in 'export VAR=value' handler */
400 static int builtin_export(struct child_prog *child)
404 if (child->argv[1] == NULL) {
405 return (builtin_env(child));
407 res = putenv(child->argv[1]);
409 fprintf(stderr, "export: %s\n", strerror(errno));
413 /* built-in 'read VAR' handler */
414 static int builtin_read(struct child_prog *child)
416 int res = 0, len, newlen;
418 char string[MAX_READ];
420 if (child->argv[1]) {
421 /* argument (VAR) given: put "VAR=" into buffer */
422 strcpy(string, child->argv[1]);
423 len = strlen(string);
426 fgets(&string[len], sizeof(string) - len, stdin); /* read string */
427 newlen = strlen(string);
429 string[--newlen] = '\0'; /* chomp trailing newline */
431 ** string should now contain "VAR=<value>"
432 ** copy it (putenv() won't do that, so we must make sure
433 ** the string resides in a static buffer!)
436 if((s = strdup(string)))
439 fprintf(stderr, "read: %s\n", strerror(errno));
442 fgets(string, sizeof(string), stdin);
447 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
448 /* Built-in handler for 'if' commands */
449 static int builtin_if(struct child_prog *child)
451 struct job *cmd = child->family;
453 char* charptr1=cmd->text+3; /* skip over the leading 'if ' */
455 /* Now run the 'if' command */
456 debug_printf( "job=%p entering builtin_if ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
457 status = run_command_predicate(charptr1);
458 debug_printf( "if test returned ");
460 debug_printf( "TRUE\n");
461 cmd->job_context |= IF_TRUE_CONTEXT;
463 debug_printf( "FALSE\n");
464 cmd->job_context |= IF_FALSE_CONTEXT;
466 debug_printf("job=%p builtin_if set job context to %x\n", cmd, cmd->job_context);
472 /* Built-in handler for 'then' (part of the 'if' command) */
473 static int builtin_then(struct child_prog *child)
475 struct job *cmd = child->family;
476 char* charptr1=cmd->text+5; /* skip over the leading 'then ' */
478 debug_printf( "job=%p entering builtin_then ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
479 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
480 shell_context = 0; /* Reset the shell's context on an error */
481 error_msg("%s `then'\n", syntax_err);
485 cmd->job_context |= THEN_EXP_CONTEXT;
486 debug_printf("job=%p builtin_then set job context to %x\n", cmd, cmd->job_context);
488 /* If the if result was FALSE, skip the 'then' stuff */
489 if (cmd->job_context & IF_FALSE_CONTEXT) {
493 /* Seems the if result was TRUE, so run the 'then' command */
494 debug_printf( "'then' now running '%s'\n", charptr1);
496 return(run_command_predicate(charptr1));
499 /* Built-in handler for 'else' (part of the 'if' command) */
500 static int builtin_else(struct child_prog *child)
502 struct job *cmd = child->family;
503 char* charptr1=cmd->text+5; /* skip over the leading 'else ' */
505 debug_printf( "job=%p entering builtin_else ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
507 if (! (cmd->job_context & THEN_EXP_CONTEXT)) {
508 shell_context = 0; /* Reset the shell's context on an error */
509 error_msg("%s `else'\n", syntax_err);
512 /* If the if result was TRUE, skip the 'else' stuff */
513 if (cmd->job_context & IF_TRUE_CONTEXT) {
517 cmd->job_context |= ELSE_EXP_CONTEXT;
518 debug_printf("job=%p builtin_else set job context to %x\n", cmd, cmd->job_context);
520 /* Now run the 'else' command */
521 debug_printf( "'else' now running '%s'\n", charptr1);
522 return(run_command_predicate(charptr1));
525 /* Built-in handler for 'fi' (part of the 'if' command) */
526 static int builtin_fi(struct child_prog *child)
528 struct job *cmd = child->family;
529 debug_printf( "job=%p entering builtin_fi ('%s')-- context=%d\n", cmd, "", cmd->job_context);
530 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
531 shell_context = 0; /* Reset the shell's context on an error */
532 error_msg("%s `fi'\n", syntax_err);
535 /* Clear out the if and then context bits */
536 cmd->job_context &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
537 debug_printf("job=%p builtin_fi set job context to %x\n", cmd, cmd->job_context);
543 /* Built-in '.' handler (read-in and execute commands from file) */
544 static int builtin_source(struct child_prog *child)
549 if (child->argv[1] == NULL)
552 input = fopen(child->argv[1], "r");
554 fprintf(stdout, "Couldn't open file '%s'\n", child->argv[1]);
558 /* Now run the file */
559 status = busy_loop(input);
564 /* built-in 'unset VAR' handler */
565 static int builtin_unset(struct child_prog *child)
567 if (child->argv[1] == NULL) {
568 fprintf(stdout, "unset: parameter required.\n");
571 unsetenv(child->argv[1]);
575 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
576 /* currently used by if/then/else.
578 * Reparsing the command line for this purpose is gross,
579 * incorrect, and fundamentally unfixable; in particular,
580 * think about what happens with command substitution.
581 * We really need to pull out the run, wait, return status
582 * functionality out of busy_loop so we can child->argv++
583 * and use that, without going back through parse_command.
585 static int run_command_predicate(char *cmd)
588 local_pending_command = xmalloc(n+1);
589 strncpy(local_pending_command, cmd, n);
590 local_pending_command[n]='\0';
591 return( busy_loop(NULL));
595 /* free up all memory from a job */
596 static void free_job(struct job *cmd)
600 for (i = 0; i < cmd->num_progs; i++) {
601 free(cmd->progs[i].argv);
602 if (cmd->progs[i].redirects)
603 free(cmd->progs[i].redirects);
604 if (cmd->progs[i].free_glob)
605 globfree(&cmd->progs[i].glob_result);
611 memset(cmd, 0, sizeof(struct job));
614 /* remove a job from the job_list */
615 static void remove_job(struct jobset *job_list, struct job *job)
620 if (job == job_list->head) {
621 job_list->head = job->next;
623 prevjob = job_list->head;
624 while (prevjob->next != job)
625 prevjob = prevjob->next;
626 prevjob->next = job->next;
632 /* Checks to see if any background processes have exited -- if they
633 have, figure out why and see if a job has completed */
634 static void checkjobs(struct jobset *job_list)
641 while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
642 for (job = job_list->head; job; job = job->next) {
644 while (prognum < job->num_progs &&
645 job->progs[prognum].pid != childpid) prognum++;
646 if (prognum < job->num_progs)
650 /* This happens on backticked commands */
654 if (WIFEXITED(status) || WIFSIGNALED(status)) {
656 job->running_progs--;
657 job->progs[prognum].pid = 0;
659 if (!job->running_progs) {
660 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
661 remove_job(job_list, job);
665 job->stopped_progs++;
666 job->progs[prognum].is_stopped = 1;
668 if (job->stopped_progs == job->num_progs) {
669 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
675 if (childpid == -1 && errno != ECHILD)
676 perror_msg("waitpid");
679 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
680 * and stderr if they are redirected. */
681 static int setup_redirects(struct child_prog *prog, int squirrel[])
686 struct redir_struct *redir = prog->redirects;
688 for (i = 0; i < prog->num_redirects; i++, redir++) {
689 switch (redir->type) {
693 case REDIRECT_OVERWRITE:
694 mode = O_WRONLY | O_CREAT | O_TRUNC;
696 case REDIRECT_APPEND:
697 mode = O_WRONLY | O_CREAT | O_APPEND;
701 openfd = open(redir->filename, mode, 0666);
703 /* this could get lost if stderr has been redirected, but
704 bash and ash both lose it as well (though zsh doesn't!) */
705 error_msg("error opening %s: %s\n", redir->filename,
710 if (openfd != redir->fd) {
711 if (squirrel && redir->fd < 3) {
712 squirrel[redir->fd] = dup(redir->fd);
714 dup2(openfd, redir->fd);
722 static void restore_redirects(int squirrel[])
725 for (i=0; i<3; i++) {
728 /* No error checking. I sure wouldn't know what
729 * to do with an error if I found one! */
736 static char* setup_prompt_string(int state)
738 char user[9],buf[255],*s;
740 char prompt_str[BUFSIZ];
742 /* Set up the prompt */
744 /* get User Name and setup prompt */
745 strcpy(prompt,( geteuid() != 0 ) ? "$ ":"# ");
746 my_getpwuid(user, geteuid());
749 gethostname(buf, 255);
750 s = strchr(buf, '.');
759 snprintf(prompt_str, BUFSIZ-1, "[%s@%s %s]%s", user, buf,
760 get_last_path_component(cwd), prompt);
762 sprintf(prompt_str, "%s", prompt);
764 return(strdup(prompt_str)); /* Must free this memory */
767 static int get_command(FILE * source, char *command)
771 if (source == NULL) {
772 if (local_pending_command) {
773 /* a command specified (-c option): return it & mark it done */
774 strcpy(command, local_pending_command);
775 free(local_pending_command);
776 local_pending_command = NULL;
782 if (source == stdin) {
783 prompt_str = setup_prompt_string(shell_context);
785 #ifdef BB_FEATURE_SH_COMMAND_EDITING
787 ** enable command line editing only while a command line
788 ** is actually being read; otherwise, we'll end up bequeathing
789 ** atexit() handlers and other unwanted stuff to our
790 ** child processes (rob@sysgo.de)
793 cmdedit_read_input(prompt_str, command);
798 fprintf(stdout, "%s", prompt_str);
802 if (!fgets(command, BUFSIZ - 2, source)) {
808 /* remove trailing newline */
809 command[strlen(command) - 1] = '\0';
814 #ifdef BB_FEATURE_SH_ENVIRONMENT
815 static char* itoa(register int i)
817 static char a[7]; /* Max 7 ints */
818 register char *b = a + sizeof(a) - 1;
826 *--b = '0' + (i % 10);
836 static void expand_argument(struct child_prog *prog, int *argcPtr,
837 int *argv_alloced_ptr)
839 int argc_l = *argcPtr;
840 int argv_alloced = *argv_alloced_ptr;
844 char *src, *dst, *var;
846 if (argc_l > 1) { /* cmd->glob_result is already initialized */
848 i = prog->glob_result.gl_pathc;
854 /* do shell variable substitution */
855 if(*prog->argv[argc_l - 1] == '$') {
856 if ((var = getenv(prog->argv[argc_l - 1] + 1))) {
857 prog->argv[argc_l - 1] = var;
859 #ifdef BB_FEATURE_SH_ENVIRONMENT
861 switch(*(prog->argv[argc_l - 1] + 1)) {
863 prog->argv[argc_l - 1] = itoa(last_return_code);
866 prog->argv[argc_l - 1] = itoa(getpid());
869 prog->argv[argc_l - 1] = itoa(argc-1);
873 *(prog->argv[argc_l - 1])='\0';
875 prog->argv[argc_l - 1] = itoa(last_bg_pid);
877 case '0':case '1':case '2':case '3':case '4':
878 case '5':case '6':case '7':case '8':case '9':
880 int index=*(prog->argv[argc_l - 1] + 1)-48;
882 *(prog->argv[argc_l - 1])='\0';
884 prog->argv[argc_l - 1] = argv[index];
893 if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){
894 rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result);
895 if (rc == GLOB_NOSPACE) {
896 error_msg("out of space during glob operation\n");
898 } else if (rc == GLOB_NOMATCH ||
899 (!rc && (prog->glob_result.gl_pathc - i) == 1 &&
900 strcmp(prog->argv[argc_l - 1],
901 prog->glob_result.gl_pathv[i]) == 0)) {
902 /* we need to remove whatever \ quoting is still present */
903 src = dst = prog->argv[argc_l - 1];
907 *dst++ = process_escape_sequence(&src);
915 argv_alloced += (prog->glob_result.gl_pathc - i);
916 prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv));
917 memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i,
918 sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i));
919 argc_l += (prog->glob_result.gl_pathc - i - 1);
922 src = dst = prog->argv[argc_l - 1];
926 *dst++ = process_escape_sequence(&src);
934 prog->glob_result.gl_pathc=0;
936 prog->glob_result.gl_pathv=NULL;
938 *argv_alloced_ptr = argv_alloced;
942 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
943 line). If a valid command is found, command_ptr is set to point to
944 the beginning of the next command (if the original command had more
945 then one job associated with it) or NULL if no more commands are
947 static int parse_command(char **command_ptr, struct job *job, int *inbg)
950 char *return_command = NULL;
951 char *src, *buf, *chptr;
958 struct child_prog *prog;
960 /* skip leading white space */
961 while (**command_ptr && isspace(**command_ptr))
964 /* this handles empty lines or leading '#' characters */
965 if (!**command_ptr || (**command_ptr == '#')) {
972 job->progs = xmalloc(sizeof(*job->progs));
974 /* We set the argv elements to point inside of this string. The
975 memory is freed by free_job(). Allocate twice the original
976 length in case we need to quote every single character.
978 Getting clean memory relieves us of the task of NULL
979 terminating things and makes the rest of this look a bit
980 cleaner (though it is, admittedly, a tad less efficient) */
981 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
985 prog->num_redirects = 0;
986 prog->redirects = NULL;
988 prog->is_stopped = 0;
992 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
993 prog->argv[0] = job->cmdbuf;
997 while (*src && !done) {
1004 error_msg("character expected after \\\n");
1009 /* in shell, "\'" should yield \' */
1010 if (*src != quote) {
1014 } else if (*src == '*' || *src == '?' || *src == '[' ||
1015 *src == ']') *buf++ = '\\';
1017 } else if (isspace(*src)) {
1018 if (*prog->argv[argc_l]) {
1020 /* +1 here leaves room for the NULL which ends argv */
1021 if ((argc_l + 1) == argv_alloced) {
1023 prog->argv = xrealloc(prog->argv,
1024 sizeof(*prog->argv) *
1027 expand_argument(prog, &argc_l, &argv_alloced);
1028 prog->argv[argc_l] = buf;
1037 case '#': /* comment */
1044 case '>': /* redirects */
1046 i = prog->num_redirects++;
1047 prog->redirects = xrealloc(prog->redirects,
1048 sizeof(*prog->redirects) *
1051 prog->redirects[i].fd = -1;
1052 if (buf != prog->argv[argc_l]) {
1053 /* the stuff before this character may be the file number
1055 prog->redirects[i].fd =
1056 strtol(prog->argv[argc_l], &chptr, 10);
1058 if (*chptr && *prog->argv[argc_l]) {
1060 expand_argument(prog, &argc_l, &argv_alloced);
1061 prog->argv[argc_l] = buf;
1065 if (prog->redirects[i].fd == -1) {
1067 prog->redirects[i].fd = 1;
1069 prog->redirects[i].fd = 0;
1072 if (*src++ == '>') {
1074 prog->redirects[i].type =
1075 REDIRECT_APPEND, src++;
1077 prog->redirects[i].type = REDIRECT_OVERWRITE;
1079 prog->redirects[i].type = REDIRECT_INPUT;
1082 /* This isn't POSIX sh compliant. Oh well. */
1084 while (isspace(*chptr))
1088 error_msg("file name expected after %c\n", *src);
1094 prog->redirects[i].filename = buf;
1095 while (*chptr && !isspace(*chptr))
1098 src = chptr - 1; /* we src++ later */
1099 prog->argv[argc_l] = ++buf;
1102 case '|': /* pipe */
1103 /* finish this command */
1104 if (*prog->argv[argc_l])
1107 error_msg("empty command in pipe\n");
1112 prog->argv[argc_l] = NULL;
1114 /* and start the next */
1116 job->progs = xrealloc(job->progs,
1117 sizeof(*job->progs) * job->num_progs);
1118 prog = job->progs + (job->num_progs - 1);
1119 prog->num_redirects = 0;
1120 prog->redirects = NULL;
1121 prog->free_glob = 0;
1122 prog->is_stopped = 0;
1127 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1128 prog->argv[0] = ++buf;
1131 while (*src && isspace(*src))
1135 error_msg("empty command in pipe\n");
1140 src--; /* we'll ++ it at the end of the loop */
1144 case '&': /* background */
1146 case ';': /* multiple commands */
1148 return_command = *command_ptr + (src - *command_ptr) + 1;
1151 #ifdef BB_FEATURE_SH_BACKTICKS
1153 /* Exec a backtick-ed command */
1155 char* charptr1=NULL, *charptr2;
1158 struct jobset njob_list = { NULL, NULL };
1162 ptr=strchr(++src, '`');
1164 fprintf(stderr, "Unmatched '`' in command\n");
1169 /* Make some space to hold just the backticked command */
1170 charptr1 = charptr2 = xmalloc(1+ptr-src);
1171 memcpy(charptr1, src, ptr-src);
1172 charptr1[ptr-src] = '\0';
1173 newjob = xmalloc(sizeof(struct job));
1174 newjob->job_list = &njob_list;
1175 /* Now parse and run the backticked command */
1176 if (!parse_command(&charptr1, newjob, inbg)
1177 && newjob->num_progs) {
1179 run_command(newjob, 0, pipefd);
1181 checkjobs(job->job_list);
1182 free_job(newjob); /* doesn't actually free newjob,
1183 looks like a memory leak */
1186 /* Make a copy of any stuff left over in the command
1187 * line after the second backtick */
1188 charptr2 = xmalloc(strlen(ptr)+1);
1189 memcpy(charptr2, ptr+1, strlen(ptr));
1192 /* Copy the output from the backtick-ed command into the
1193 * command line, making extra room as needed */
1195 charptr1 = xmalloc(BUFSIZ);
1196 while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1197 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1198 if (newsize > BUFSIZ) {
1199 *command_ptr=xrealloc(*command_ptr, newsize);
1201 memcpy(src, charptr1, size);
1209 /* Now paste into the *command_ptr all the stuff
1210 * leftover after the second backtick */
1211 memcpy(src, charptr2, strlen(charptr2)+1);
1214 /* Now recursively call parse_command to deal with the new
1215 * and improved version of the command line with the backtick
1216 * results expanded in place... */
1218 struct jobset *jl=job->job_list;
1222 return(parse_command(command_ptr, job, inbg));
1225 #endif // BB_FEATURE_SH_BACKTICKS
1230 /* This is currently a little broken... */
1231 #ifdef HANDLE_CONTINUATION_CHARS
1232 /* They fed us a continuation char, so continue reading stuff
1233 * on the next line, then tack that onto the end of the current
1237 printf("erik: found a continue char at EOL...\n");
1238 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1239 if (get_command(input, command)) {
1240 error_msg("character expected after \\\n");
1245 newsize = strlen(*command_ptr) + strlen(command) + 2;
1246 if (newsize > BUFSIZ) {
1247 printf("erik: doing realloc\n");
1248 *command_ptr=xrealloc(*command_ptr, newsize);
1250 printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1251 memcpy(--src, command, strlen(command));
1252 printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1256 error_msg("character expected after \\\n");
1262 if (*src == '*' || *src == '[' || *src == ']'
1263 || *src == '?') *buf++ = '\\';
1272 if (*prog->argv[argc_l]) {
1274 expand_argument(prog, &argc_l, &argv_alloced);
1280 prog->argv[argc_l] = NULL;
1282 if (!return_command) {
1283 job->text = xmalloc(strlen(*command_ptr) + 1);
1284 strcpy(job->text, *command_ptr);
1286 /* This leaves any trailing spaces, which is a bit sloppy */
1287 count = return_command - *command_ptr;
1288 job->text = xmalloc(count + 1);
1289 strncpy(job->text, *command_ptr, count);
1290 job->text[count] = '\0';
1293 *command_ptr = return_command;
1298 /* Run the child_prog, no matter what kind of command it uses.
1300 static int pseudo_exec(struct child_prog *child)
1302 struct built_in_command *x;
1303 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1304 struct BB_applet search_applet, *applet;
1307 /* Check if the command matches any of the non-forking builtins.
1308 * Depending on context, this might be redundant. But it's
1309 * easier to waste a few CPU cycles than it is to figure out
1310 * if this is one of those cases.
1312 for (x = bltins; x->cmd; x++) {
1313 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1314 exit(x->function(child));
1318 /* Check if the command matches any of the forking builtins. */
1319 for (x = bltins_forking; x->cmd; x++) {
1320 if (strcmp(child->argv[0], x->cmd) == 0) {
1322 exit (x->function(child));
1325 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1326 /* Check if the command matches any busybox internal
1327 * commands ("applets") here. Following discussions from
1328 * November 2000 on busybox@opensource.lineo.com, don't use
1329 * get_last_path_component(). This way explicit (with
1330 * slashes) filenames will never be interpreted as an
1331 * applet, just like with builtins. This way the user can
1332 * override an applet with an explicit filename reference.
1333 * The only downside to this change is that an explicit
1334 * /bin/foo invocation will fork and exec /bin/foo, even if
1335 * /bin/foo is a symlink to busybox.
1337 search_applet.name = child->argv[0];
1339 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1340 /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1341 * if you run /bin/cat, it will use BusyBox cat even if
1342 * /bin/cat exists on the filesystem and is _not_ busybox.
1343 * Some systems want this, others do not. Choose wisely. :-)
1345 search_applet.name = get_last_path_component(search_applet.name);
1348 /* Do a binary search to find the applet entry given the name. */
1349 applet = bsearch(&search_applet, applets, NUM_APPLETS,
1350 sizeof(struct BB_applet), applet_name_compare);
1351 if (applet != NULL) {
1353 char** argv=child->argv;
1354 for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1355 applet_name=applet->name;
1357 exit((*(applet->main)) (argc_l, child->argv));
1361 execvp(child->argv[0], child->argv);
1362 error_msg_and_die("%s: %s\n", child->argv[0],
1366 static void insert_job(struct job *newjob, int inbg)
1369 struct jobset *job_list=newjob->job_list;
1371 /* find the ID for thejob to use */
1373 for (thejob = job_list->head; thejob; thejob = thejob->next)
1374 if (thejob->jobid >= newjob->jobid)
1375 newjob->jobid = thejob->jobid + 1;
1377 /* add thejob to the list of running jobs */
1378 if (!job_list->head) {
1379 thejob = job_list->head = xmalloc(sizeof(*thejob));
1381 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1382 thejob->next = xmalloc(sizeof(*thejob));
1383 thejob = thejob->next;
1386 *thejob = *newjob; /* physically copy the struct job */
1387 thejob->next = NULL;
1388 thejob->running_progs = thejob->num_progs;
1389 thejob->stopped_progs = 0;
1392 /* we don't wait for background thejobs to return -- append it
1393 to the list of backgrounded thejobs and leave it alone */
1394 printf("[%d] %d\n", thejob->jobid,
1395 newjob->progs[newjob->num_progs - 1].pid);
1396 #ifdef BB_FEATURE_SH_ENVIRONMENT
1397 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1400 newjob->job_list->fg = thejob;
1402 /* move the new process group into the foreground */
1403 /* suppress messages when run from /linuxrc mag@sysgo.de */
1404 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1405 perror_msg("tcsetpgrp");
1409 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1411 /* struct job *thejob; */
1413 int nextin, nextout;
1414 int pipefds[2]; /* pipefd[0] is for reading */
1415 struct built_in_command *x;
1416 struct child_prog *child;
1418 nextin = 0, nextout = 1;
1419 for (i = 0; i < newjob->num_progs; i++) {
1420 child = & (newjob->progs[i]);
1422 if ((i + 1) < newjob->num_progs) {
1423 if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1424 nextout = pipefds[1];
1426 if (outpipe[1]!=-1) {
1427 nextout = outpipe[1];
1433 #ifdef BB_FEATURE_SH_ENVIRONMENT
1434 if (show_x_trace==TRUE) {
1437 for (j = 0; child->argv[j]; j++) {
1439 fputs(child->argv[j], stderr);
1441 fputc('\n', stderr);
1445 /* Check if the command matches any non-forking builtins,
1446 * but only if this is a simple command.
1447 * Non-forking builtins within pipes have to fork anyway,
1448 * and are handled in pseudo_exec. "echo foo | read bar"
1449 * is doomed to failure, and doesn't work on bash, either.
1451 if (newjob->num_progs == 1) {
1452 for (x = bltins; x->cmd; x++) {
1453 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1454 int squirrel[] = {-1, -1, -1};
1456 setup_redirects(child, squirrel);
1457 rcode = x->function(child);
1458 restore_redirects(squirrel);
1464 if (!(child->pid = fork())) {
1465 signal(SIGTTOU, SIG_DFL);
1467 if (outpipe[1]!=-1) {
1477 dup2(nextout, 2); /* Really? */
1482 /* explicit redirects override pipes */
1483 setup_redirects(child,NULL);
1487 if (outpipe[1]!=-1) {
1491 /* put our child in the process group whose leader is the
1492 first process in this pipe */
1493 setpgid(child->pid, newjob->progs[0].pid);
1499 /* If there isn't another process, nextin is garbage
1500 but it doesn't matter */
1501 nextin = pipefds[0];
1504 newjob->pgrp = newjob->progs[0].pid;
1506 insert_job(newjob, inbg);
1511 static int busy_loop(FILE * input)
1514 char *next_command = NULL;
1520 newjob.job_list = &job_list;
1521 newjob.job_context = DEFAULT_CONTEXT;
1523 /* save current owner of TTY so we can restore it on exit */
1524 parent_pgrp = tcgetpgrp(0);
1526 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1528 /* don't pay any attention to this signal; it just confuses
1529 things and isn't really meant for shells anyway */
1530 signal(SIGTTOU, SIG_IGN);
1534 /* no job is in the foreground */
1536 /* see if any background processes have exited */
1537 checkjobs(&job_list);
1539 if (!next_command) {
1540 if (get_command(input, command))
1542 next_command = command;
1545 if (!parse_command(&next_command, &newjob, &inbg) &&
1547 int pipefds[2] = {-1,-1};
1548 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1549 run_command(&newjob, inbg, pipefds);
1553 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1554 next_command = NULL;
1557 /* a job is running in the foreground; wait for it */
1559 while (!job_list.fg->progs[i].pid ||
1560 job_list.fg->progs[i].is_stopped == 1) i++;
1562 waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED);
1564 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1565 /* the child exited */
1566 job_list.fg->running_progs--;
1567 job_list.fg->progs[i].pid = 0;
1569 #ifdef BB_FEATURE_SH_ENVIRONMENT
1570 last_return_code=WEXITSTATUS(status);
1572 debug_printf("'%s' exited -- return code %d\n",
1573 job_list.fg->text, last_return_code);
1574 if (!job_list.fg->running_progs) {
1576 remove_job(&job_list, job_list.fg);
1580 /* the child was stopped */
1581 job_list.fg->stopped_progs++;
1582 job_list.fg->progs[i].is_stopped = 1;
1584 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1585 printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1586 "Stopped", job_list.fg->text);
1592 /* move the shell to the foreground */
1593 /* suppress messages when run from /linuxrc mag@sysgo.de */
1594 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1595 perror_msg("tcsetpgrp");
1601 /* return controlling TTY back to parent process group before exiting */
1602 if (tcsetpgrp(0, parent_pgrp))
1603 perror_msg("tcsetpgrp");
1605 /* return exit status if called with "-c" */
1606 if (input == NULL && WIFEXITED(status))
1607 return WEXITSTATUS(status);
1613 #ifdef BB_FEATURE_CLEAN_UP
1614 void free_memory(void)
1620 if (local_pending_command)
1621 free(local_pending_command);
1623 if (job_list.fg && !job_list.fg->running_progs) {
1624 remove_job(&job_list, job_list.fg);
1630 int shell_main(int argc_l, char **argv_l)
1632 int opt, interactive=FALSE;
1633 FILE *input = stdin;
1639 #ifdef BB_FEATURE_STANDALONE_SHELL
1640 /* These variables need re-initializing when recursing */
1641 local_pending_command = NULL;
1642 job_list.head = NULL;
1644 #ifdef BB_FEATURE_SH_ENVIRONMENT
1646 last_return_code=-1;
1651 if (argv[0] && argv[0][0] == '-') {
1653 input = fopen("/etc/profile", "r");
1655 fprintf(stdout, "Couldn't open file '/etc/profile'\n");
1657 /* Now run the file */
1663 while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1667 if (local_pending_command != 0)
1668 error_msg_and_die("multiple -c arguments\n");
1669 local_pending_command = xstrdup(argv[optind]);
1673 #ifdef BB_FEATURE_SH_ENVIRONMENT
1675 show_x_trace = TRUE;
1685 /* A shell is interactive if the `-i' flag was given, or if all of
1686 * the following conditions are met:
1688 * no arguments remaining or the -s flag given
1689 * standard input is a terminal
1690 * standard output is a terminal
1691 * Refer to Posix.2, the description of the `sh' utility. */
1692 if (argv[optind]==NULL && input==stdin &&
1693 isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1696 if (interactive==TRUE) {
1697 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1698 /* Looks like they want an interactive shell */
1699 fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1700 fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
1701 } else if (local_pending_command==NULL) {
1702 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1703 input = xfopen(argv[optind], "r");
1706 /* initialize the cwd -- this is never freed...*/
1707 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1708 getcwd(cwd, sizeof(char)*MAX_LINE);
1710 #ifdef BB_FEATURE_CLEAN_UP
1711 atexit(free_memory);
1714 return (busy_loop(input));