aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
Diffstat (limited to 'toys')
-rw-r--r--toys/pending/sh.c106
1 files changed, 55 insertions, 51 deletions
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 2f09f63b..81f91a7b 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -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 @@ config SH
-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
- Add terminal control to toysh. This is necessary for interactive use,
- so the shell isn't killed by CTRL-C.
+ 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
+ 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 @@ config SH_BUILTINS
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 @@ static char *parse_word(char *start, struct command **cmd)
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 @@ static char *parse_pipeline(char *cmdline, struct pipeline *line)
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 @@ static char *parse_pipeline(char *cmdline, struct pipeline *line)
// 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 @@ static char *parse_pipeline(char *cmdline, struct pipeline *line)
// 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 @@ static char *parse_pipeline(char *cmdline, struct pipeline *line)
start = end;
}
- if (CFG_SH_JOBCTL) line->cmdlinelen = start-cmdline;
+ if (CFG_SH_INTERACTIVE) line->cmdlinelen = start-cmdline;
return start;
}
@@ -300,7 +304,7 @@ static void run_pipeline(struct pipeline *line)
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 @@ static void run_pipeline(struct pipeline *line)
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 @@ static void handle(char *command)
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 @@ void sh_main(void)
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);