summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/OR_USING_C/09.1.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/OR_USING_C/09.1.c')
-rw-r--r--reference/C/CONTRIB/OR_USING_C/09.1.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/OR_USING_C/09.1.c b/reference/C/CONTRIB/OR_USING_C/09.1.c
new file mode 100644
index 0000000..035186d
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/09.1.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+
+main()
+{
+ char buf[1024];
+ char *args[64];
+
+ for (;;) {
+ /*
+ * Prompt for and read a command.
+ */
+ printf("Command: ");
+
+ if (gets(buf) == NULL) {
+ printf("\n");
+ exit(0);
+ }
+
+ /*
+ * Split the string into arguments.
+ */
+ parse(buf, args);
+
+ /*
+ * Execute the command.
+ */
+ execute(args);
+ }
+}
+
+/*
+ * parse--split the command in buf into
+ * individual arguments.
+ */
+parse(buf, args)
+char *buf;
+char **args;
+{
+ while (*buf != NULL) {
+ /*
+ * Strip whitespace. Use nulls, so
+ * that the previous argument is terminated
+ * automatically.
+ */
+ while ((*buf == ' ') || (*buf == '\t'))
+ *buf++ = NULL;
+
+ /*
+ * Save the argument.
+ */
+ *args++ = buf;
+
+ /*
+ * Skip over the argument.
+ */
+ while ((*buf != NULL) && (*buf != ' ') && (*buf != '\t'))
+ buf++;
+ }
+
+ *args = NULL;
+}
+
+/*
+ * execute--spawn a child process and execute
+ * the program.
+ */
+execute(args)
+char **args;
+{
+ int pid, status;
+
+ /*
+ * Get a child process.
+ */
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ exit(1);
+ }
+
+ /*
+ * The child executes the code inside the if.
+ */
+ if (pid == 0) {
+ execvp(*args, args);
+ perror(*args);
+ exit(1);
+ }
+
+ /*
+ * The parent executes the wait.
+ */
+ while (wait(&status) != pid)
+ /* empty */ ;
+}
+