aboutsummaryrefslogtreecommitdiff
path: root/toys/toysh.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/toysh.c')
-rw-r--r--toys/toysh.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/toys/toysh.c b/toys/toysh.c
new file mode 100644
index 00000000..77db82db
--- /dev/null
+++ b/toys/toysh.c
@@ -0,0 +1,92 @@
+/* vi: set sw=4 ts=4:
+ *
+ * toysh - toybox shell
+ *
+ * Copyright 2006 Rob Landley <rob@landley.net>
+ *
+ * The spec for this is at:
+ * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
+ *
+ * Although things like the bash man page are good to read too.
+ */
+
+// Handle embedded NUL bytes in the command line.
+
+#include "toys.h"
+
+static int handle(char *command)
+{
+ int argc = 0, status;
+ char *argv[10], *start = command;
+ pid_t pid;
+ struct toy_list *tl;
+
+ // Parse command into argv[]
+ for (;;) {
+ char *end;
+
+ // Skip leading whitespace and detect EOL.
+ while(isspace(*start)) start++;
+ if (!*start || *start=='#') break;
+
+ // Grab next word. (Add dequote and envvar logic here)
+ end = start;
+ while (*end && !isspace(*end)) end++;
+ argv[argc++] = xstrndup(start, end-start);
+ start=end;
+ }
+ argv[argc]=0;
+
+ if (!argc) return 0;
+
+ tl = toy_find(argv[0]);
+ // This is a bit awkward, next design cycle should clean it up.
+ // Should vfork(), move to tryspawn()?
+ pid = 0;
+ if (tl && (tl->flags & TOYFLAG_NOFORK))
+ status = tl->toy_main();
+ else {
+ pid=fork();
+ if(!pid) {
+ toy_exec(argv);
+ xexec(argv);
+ } else waitpid(pid, &status, 0);
+ }
+ while(argc) free(argv[--argc]);
+
+ return 0;
+}
+
+int cd_main(void)
+{
+ char *dest = toys.argc>1 ? toys.argv[1] : getenv("HOME");
+ if (chdir(dest)) error_exit("chdir %s",dest);
+ return 0;
+}
+
+int exit_main(void)
+{
+ exit(toys.argc>1 ? atoi(toys.argv[1]) : 0);
+}
+
+int toysh_main(void)
+{
+ char *command=NULL;
+ FILE *f;
+
+ // TODO get_optflags(argv, "c:", &command);
+
+ f = toys.argv[1] ? xfopen(toys.argv[1], "r") : NULL;
+ if (command) handle(command);
+ else {
+ unsigned cmdlen=0;
+ for (;;) {
+ if (!f) putchar('$');
+ if (1 > getline(&command, &cmdlen, f ? : stdin)) break;
+ handle(command);
+ }
+ if (CFG_TOYS_FREE) free(command);
+ }
+
+ return 1;
+}