]> Chaos Git - misc/ysh.git/commitdiff
misc: implement builtin cd, begin docs, fixups
authorJon Feldman <chaos.kagami@gmail.com>
Wed, 26 Jul 2017 13:45:25 +0000 (09:45 -0400)
committerJon Feldman <chaos.kagami@gmail.com>
Wed, 26 Jul 2017 13:45:25 +0000 (09:45 -0400)
DOC/DEFICIENCES.md [new file with mode: 0644]
DOC/EXAMPLES.md [new file with mode: 0644]
DOC/PATH_RESOLUTION.md [new file with mode: 0644]
DOC/PITFALLS.md [new file with mode: 0644]
builtin/cd.c
builtin/math.c [new file with mode: 0644]
gsh_main.c

diff --git a/DOC/DEFICIENCES.md b/DOC/DEFICIENCES.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/DOC/EXAMPLES.md b/DOC/EXAMPLES.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/DOC/PATH_RESOLUTION.md b/DOC/PATH_RESOLUTION.md
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/DOC/PITFALLS.md b/DOC/PITFALLS.md
new file mode 100644 (file)
index 0000000..f619edf
--- /dev/null
@@ -0,0 +1,51 @@
+Pitfalls and things not to assume
+-----------------------------------
+
+Posix
+------
+
+This is not POSIX compliant. It is not intended to be, since this
+contorts the shell into working in a certain manner, and in practice,
+/bin/sh usually means /bin/bash.
+
+Subcommands
+------------
+
+Subcommands may very well look like the subshell "$()" / "`" operator
+in bash. They are not.
+
+Commands are resolved in dependency order until no more replacements are
+needed. This is contrary to how bash, zsh, etc work; they literally
+spawn another shell to handle anything within. To explain with graphs:
+
+bash: echo $(echo hello $(echo world) ho)
+
+echo $
+    echo hello $ ho
+        echo world
+
+xsh:  echo {echo hello {echo world} ho}
+
+echo {echo hello $ ho}
+    echo world
+echo $
+    echo hello world ho
+
+This behavior has a few importan6 things to note about it.
+ 1) Subcommands inherit the environment of the shell, not
+    a "parent" subcommand.
+ 2) Subcommands do not spawn another shell.
+
+Variables
+----------
+
+Variables (starting with the $ character) are resolved after subcommands
+and double-quoted strings.
+Consider the following:
+
+= NAME 42
+echo "${echo NAME}"
+
+So first, echo NAME is evaluated. The contents of the double-quoted string
+are then evaluated, leaving a string named "$NAME". This is then interpreted to
+be a variable, resulting in the output 42.
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..da58cb4b2f2e8cc414b88f4a76e6d6d946f6d1a4 100644 (file)
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int builtin_chdir(char* nam, char** argv, char** stdout) {
+    assert(nam);
+    assert(argv[0]);
+
+    int ret = 0;
+
+    if (argv[1] == NULL) {
+        // No path was provided in cd, so just go $HOME
+    } else if (argv[1]) {
+        ret = chdir(argv[1]);
+    }
+
+    if (ret == -1)
+        perror("cd");
+
+    return ret;
+}
diff --git a/builtin/math.c b/builtin/math.c
new file mode 100644 (file)
index 0000000..e69de29
index 0e77e3bfe34c20933b80314135167738008fa9ab..58e0fe6a130e317f7443791e44717900b358ec9a 100644 (file)
@@ -348,6 +348,29 @@ pid_t fork_and_execvp(const char *file, char *const argv[], char** stdout) {
     return pid;
 }
 
+typedef int (*builtin_fn_t)(char*, char**, char**);
+
+int builtin_chdir(char* nam, char** argv, char** stdout);
+
+typedef struct {
+    char name[64];
+    builtin_fn_t func;
+} builtin_info_t;
+
+builtin_info_t builtin_info[] = {
+    { "cd", builtin_chdir },
+    { "",   NULL },
+};
+
+int check_builtin(char* name) {
+    for (int i = 0; builtin_info[i].func != NULL; i++) {
+        if (!strcmp(name, builtin_info[i].name)) {
+            return i;
+        }
+    }
+    return -1;
+}
+
 void execute(ast_t* tree, char** stdout) {
     // Important note; this function is only for fully resolved trees of commands.
     // If any unresolved subshells or groups exist, this function is undefined.
@@ -369,9 +392,14 @@ void execute(ast_t* tree, char** stdout) {
     argv[tree->size] = NULL;
     prog = argv[0];
 
-    pid_t pid = fork_and_execvp(prog, argv, stdout);
-    int wstatus;
-    pid = waitpid(pid, &wstatus, 0);
+    int builtin_chk = check_builtin(prog);
+    if (builtin_chk != -1) {
+        builtin_info[builtin_chk].func(prog, argv, stdout);
+    } else {
+        pid_t pid = fork_and_execvp(prog, argv, stdout);
+        int wstatus;
+        pid = waitpid(pid, &wstatus, 0);
+    }
 }
 
 void ast_resolve_subs(ast_t* ast, int master) {