Acknowledge contributions of Pavel Roskin, and fix doc building
[oweals/busybox.git] / lash.c
diff --git a/lash.c b/lash.c
index 44ffe968f2c6a4096da7abd101c6b296a3fde313..8ea5e305befcbca4b28f9bc2f0ab9144b40e28cc 100644 (file)
--- a/lash.c
+++ b/lash.c
@@ -113,15 +113,18 @@ static int busy_loop(FILE * input);
 static struct builtInCommand bltins[] = {
        {"bg", "Resume a job in the background", "bg [%%job]", shell_fg_bg},
        {"cd", "Change working directory", "cd [dir]", shell_cd},
-       //{"echo", "Echo arguments on stdout", "echo arg1 [...]", shell_echo},
-       {"env", "Print all environment variables", "env", shell_env},
        {"exit", "Exit from shell()", "exit", shell_exit},
        {"fg", "Bring job into the foreground", "fg [%%job]", shell_fg_bg},
        {"jobs", "Lists the active jobs", "jobs", shell_jobs},
-       {"pwd", "Print current directory", "pwd", shell_pwd},
        {"export", "Set environment variable", "export [VAR=value]", shell_export},
        {"unset", "Unset environment variable", "unset VAR", shell_unset},
-       
+       {NULL, NULL, NULL, NULL}
+};
+
+/* Table of built-in functions */
+static struct builtInCommand bltins_forking[] = {
+       {"env", "Print all environment variables", "env", shell_env},
+       {"pwd", "Print current directory", "pwd", shell_pwd},
        {".", "Source-in and run commands in a file", ". filename", shell_source},
        {"help", "List shell built-in commands", "help", shell_help},
        {NULL, NULL, NULL, NULL}
@@ -129,8 +132,11 @@ static struct builtInCommand bltins[] = {
 
 static const char shell_usage[] =
 
-       "sh [FILE]...\n\n" "The BusyBox command interpreter (shell).\n\n";
-
+       "sh [FILE]...\n" 
+#ifndef BB_FEATURE_TRIVIAL_HELP
+       "\nlash: The BusyBox command interpreter (shell).\n\n"
+#endif
+       ;
 
 static char cwd[1024];
 static char *prompt = "# ";
@@ -246,6 +252,9 @@ static int shell_help(struct job *cmd, struct jobSet *junk)
        for (x = bltins; x->cmd; x++) {
                fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
        }
+       for (x = bltins_forking; x->cmd; x++) {
+               fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
+       }
        fprintf(stdout, "\n\n");
        return TRUE;
 }
@@ -720,6 +729,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg)
        return 0;
 }
 
+
 static int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
 {
        struct job *job;
@@ -727,14 +737,10 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
        int nextin, nextout;
        int pipefds[2];                         /* pipefd[0] is for reading */
        struct builtInCommand *x;
+#ifdef BB_FEATURE_STANDALONE_SHELL
+       const struct BB_applet *a = applets;
+#endif
 
-       /* handle built-ins here -- we don't fork() so we can't background
-          these very easily */
-       for (x = bltins; x->cmd; x++) {
-               if (!strcmp(newJob.progs[0].argv[0], x->cmd)) {
-                       return (x->function(&newJob, jobList));
-               }
-       }
 
        nextin = 0, nextout = 1;
        for (i = 0; i < newJob.numProgs; i++) {
@@ -745,6 +751,13 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
                        nextout = 1;
                }
 
+               /* Match any built-ins here */
+               for (x = bltins; x->cmd; x++) {
+                       if (!strcmp(newJob.progs[i].argv[0], x->cmd)) {
+                               return (x->function(&newJob, jobList));
+                       }
+               }
+
                if (!(newJob.progs[i].pid = fork())) {
                        signal(SIGTTOU, SIG_DFL);
 
@@ -761,6 +774,25 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
                        /* explicit redirections override pipes */
                        setupRedirections(newJob.progs + i);
 
+                       /* Match any built-ins here */
+                       for (x = bltins_forking; x->cmd; x++) {
+                               if (!strcmp(newJob.progs[i].argv[0], x->cmd)) {
+                                       exit (x->function(&newJob, jobList));
+                               }
+                       }
+#ifdef BB_FEATURE_STANDALONE_SHELL
+                       /* Handle busybox internals here */
+                       while (a->name != 0) {
+                               if (strcmp(newJob.progs[i].argv[0], a->name) == 0) {
+                                       int argc;
+                                       char** argv=newJob.progs[i].argv;
+                                       for(argc=0;*argv!=NULL; argv++, argc++);
+                                       exit((*(a->main)) (argc, newJob.progs[i].argv));
+                               }
+                               a++;
+                       }
+#endif
+
                        execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
                        fatalError("sh: %s: %s\n", newJob.progs[i].argv[0],
                                           strerror(errno));
@@ -949,6 +981,7 @@ int shell_main(int argc, char **argv)
        getcwd(cwd, sizeof(cwd));
 
 #ifdef BB_FEATURE_SH_COMMAND_EDITING
+       cmdedit_init();
        signal(SIGWINCH, win_changed);
        win_changed(0);
 #endif
@@ -961,9 +994,12 @@ int shell_main(int argc, char **argv)
                fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
                fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
        } else {
+               if (*argv[1]=='-') {
+                       usage("sh\n\nlash -- the BusyBox LAme SHell (command interpreter)\n");
+               }
                input = fopen(argv[1], "r");
                if (!input) {
-                       fatalError("A: Couldn't open file '%s': %s\n", argv[1],
+                       fatalError("sh: Couldn't open file '%s': %s\n", argv[1],
                                           strerror(errno));
                }
        }