diff toys/toysh.c @ 2:67b517913e56

Infrastructure, first drop of toy shell, and a bit of work on df.
author landley@driftwood
date Thu, 05 Oct 2006 16:18:03 -0400
parents
children 266a462ed18c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/toysh.c	Thu Oct 05 16:18:03 2006 -0400
@@ -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;
+}