changeset 1319:1fa185766188 draft

Brush the dust off toysh. Simplify the config micromanagement tangle to just a single "interactive" option. Fix an unused variable and wrong variable type.
author Rob Landley <rob@landley.net>
date Mon, 26 May 2014 20:39:20 -0500
parents 955169e818d0
children b2cc738d3cfc
files toys/pending/sh.c
diffstat 1 files changed, 55 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/toys/pending/sh.c	Mon May 26 12:25:47 2014 -0500
+++ b/toys/pending/sh.c	Mon May 26 20:39:20 2014 -0500
@@ -24,8 +24,8 @@
 USE_SH(NEWTOY(cd, NULL, TOYFLAG_NOFORK))
 USE_SH(NEWTOY(exit, NULL, TOYFLAG_NOFORK))
 
-USE_SH(NEWTOY(sh, "c:i", TOYFLAG_BIN))
-USE_SH(OLDTOY(toysh, sh, "c:i", TOYFLAG_BIN))
+USE_SH(NEWTOY(sh, "c:"USE_SH_INTERACTIVE("i"), TOYFLAG_BIN))
+USE_SH(OLDTOY(toysh, sh, OPTSTR_sh, TOYFLAG_BIN))
 
 config SH
   bool "sh (toysh)"
@@ -38,13 +38,46 @@
 
     -c	command line to execute
 
-config SH_TTY
-  bool "Interactive shell (terminal control)"
+config SH_INTERACTIVE
+  bool "Interactive shell"
+  default n
+  depends on SH
+  help
+    This shell supports terminal control (so the shell isn't killed by CTRL-C),
+    job control (fg, bg, jobs), and reads /etc/profile and ~/.profile when
+    running interactively.
+
+    -i	interactive mode (default when STDIN is a tty)
+
+config EXIT
+  bool
   default n
   depends on SH
   help
-    Add terminal control to toysh.  This is necessary for interactive use,
-    so the shell isn't killed by CTRL-C.
+    usage: exit [status]
+
+    Exit shell.  If no return value supplied on command line, use value
+    of most recent command, or 0 if none.
+
+config CD
+  bool
+  default n
+  depends on SH
+  help
+    usage: cd [-PL] [path]
+
+    Change current directory.  With no arguments, go $HOME.
+
+    -P	Physical path: resolve symlinks in path.
+    -L	Local path: .. trims directories off $PWD (default).
+*/
+
+/*
+This level of micromanagement is silly, it adds more complexity than it's
+worth. (Not just to the code, but decision fatigue configuring it.)
+
+That said, the following list is kept for the moment as a todo list of
+features I need to implement.
 
 config SH_PROFILE
   bool "Profile support"
@@ -143,35 +176,6 @@
   help
     Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set,
     unset, read, alias.
-
-config EXIT
-  bool
-  default n
-  depends on SH
-  help
-    usage: exit [status]
-
-    Exit shell.  If no return value supplied on command line, use value
-    of most recent command, or 0 if none.
-
-config CD
-  bool
-  default n
-  depends on SH
-  help
-    usage: cd [path]
-
-    Change current directory.  With no arguments, go to $HOME.
-
-config CD_P
-  bool # "-P support for cd"
-  default n
-  depends on SH
-  help
-    usage: cd [-PL]
-
-    -P    Physical path: resolve symlinks in path.
-    -L    Cancel previous -P and restore default behavior.
 */
 
 #define FOR_sh
@@ -218,7 +222,7 @@
   char *end;
 
   // Detect end of line (and truncate line at comment)
-  if (CFG_SH_PIPES && strchr("><&|(;", *start)) return 0;
+  if (strchr("><&|(;", *start)) return 0;
 
   // Grab next word.  (Add dequote and envvar logic here)
   end = start;
@@ -244,7 +248,7 @@
 
   if (!cmdline) return 0;
 
-  if (CFG_SH_JOBCTL) line->cmdline = cmdline;
+  if (CFG_SH_INTERACTIVE) line->cmdline = cmdline;
 
   // Parse command into argv[]
   for (;;) {
@@ -253,7 +257,7 @@
     // Skip leading whitespace and detect end of line.
     while (isspace(*start)) start++;
     if (!*start || *start=='#') {
-      if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline;
+      if (CFG_SH_INTERACTIVE) line->cmdlinelen = start-cmdline;
       return 0;
     }
 
@@ -265,7 +269,7 @@
 
     // If we hit the end of this command, how did it end?
     if (!end) {
-      if (CFG_SH_PIPES && *start) {
+      if (*start) {
         if (*start==';') {
           start++;
           break;
@@ -277,7 +281,7 @@
     start = end;
   }
 
-  if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline;
+  if (CFG_SH_INTERACTIVE) line->cmdlinelen = start-cmdline;
 
   return start;
 }
@@ -300,7 +304,7 @@
     memset(&toys, 0, sizeof(struct toy_context));
 
     if (!setjmp(rebound)) {
-      toys.rebound = rebound;
+      toys.rebound = &rebound;
       toy_init(tl, cmd->argv);
       tl->toy_main();
     }
@@ -315,10 +319,8 @@
     if (!cmd->pid) xexec(cmd->argv);
     else waitpid(cmd->pid, &status, 0);
 
-    if (CFG_SH_FLOWCTL || CFG_SH_PIPES) {
-      if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status);
-      if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status);
-    }
+    if (WIFEXITED(status)) cmd->pid = WEXITSTATUS(status);
+    if (WIFSIGNALED(status)) cmd->pid = WTERMSIG(status);
   }
 
   return;
@@ -359,7 +361,8 @@
 void cd_main(void)
 {
   char *dest = *toys.optargs ? *toys.optargs : getenv("HOME");
-  xchdir(dest);
+
+  xchdir(dest ? dest : "/");
 }
 
 void exit_main(void)
@@ -372,16 +375,17 @@
   FILE *f;
 
   // Set up signal handlers and grab control of this tty.
-  if (CFG_SH_TTY) {
-    if (isatty(0)) toys.optflags |= 1;
-  }
+  if (CFG_SH_INTERACTIVE && isatty(0)) toys.optflags |= FLAG_i;
+
   f = *toys.optargs ? xfopen(*toys.optargs, "r") : NULL;
   if (TT.command) handle(TT.command);
   else {
     size_t cmdlen = 0;
     for (;;) {
-      char *command = 0;
-      if (!f) xputc('$');
+      char *prompt = getenv("PS1"), *command = 0;
+
+      // TODO: parse escapes in prompt
+      if (!f) printf("%s", prompt ? prompt : "$ ");
       if (1 > getline(&command, &cmdlen, f ? f : stdin)) break;
       handle(command);
       free(command);