Author | Jakob Wakeling <[email protected]> |
Date | 2023-12-28 01:17:38 |
Commit | 59a2eecffbf9c4899c9539de4938ffe8f3932b49 |
Parent | 1e336bf413a12ed3c021cd24e982c973ff68a00e |
Add basic builtin functionality
Diffstat
A | src/bltn.c | | | 30 | ++++++++++++++++++++++++++++++ |
A | src/bltn.h | | | 11 | +++++++++++ |
A | src/builtin/cd.c | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/exec.c | | | 8 | +++++++- |
M | src/main.c | | | 15 | ++++++++------- |
5 files changed, 111 insertions, 8 deletions
diff --git a/src/bltn.c b/src/bltn.c new file mode 100644 index 0000000..e8def8d --- /dev/null +++ b/src/bltn.c @@ -0,0 +1,30 @@ +// Copyright (C) 2023, Jakob Wakeling +// All rights reserved. + +#include "bltn.h" +#include "util/util.h" + +#include <stdio.h> + +extern const char *const version; /* main.c */ +extern bool _loop; /* main.c */ +extern s32 _ret; /* exec.c */ + +static int bltn_exit(int, char *[]) { _loop = false; return 0; } +static int bltn_false(int, char *[]) { return 1; } +static int bltn_help(int, char *[]) { fputs(version, stdout); return 0; } +static int bltn_true(int, char *[]) { return 0; } + +extern int bltn_cd(int, char *[]); + +static int getret(int, char *[]) { printf("%d\n", _ret); return 0; } + +bltn bltns[] = { + { "cd", &bltn_cd }, + { "exit", &bltn_exit }, + { "false", &bltn_false }, + { "help", &bltn_help }, + { "true", &bltn_true }, + { "ret", &getret }, + { NULL, NULL } +}; diff --git a/src/bltn.h b/src/bltn.h new file mode 100644 index 0000000..5e8c3b3 --- /dev/null +++ b/src/bltn.h @@ -0,0 +1,11 @@ +// Copyright (C) 2023, Jakob Wakeling +// All rights reserved. + +#ifndef ESH_BUILTIN_H_2C7ANH8K +#define ESH_BUILTIN_H_2C7ANH8K + +typedef struct { const char *name; int (*fn)(int, char *[]); } bltn; + +extern bltn bltns[]; + +#endif // ESH_BUILTIN_H_2C7ANH8K diff --git a/src/builtin/cd.c b/src/builtin/cd.c new file mode 100644 index 0000000..32fda42 --- /dev/null +++ b/src/builtin/cd.c @@ -0,0 +1,55 @@ +// Copyright (C) 2023, Jakob Wakeling +// All rights reserved. + +#include "../util/optget.h" +#include "../util/util.h" + +#include <unistd.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static const char *const help; +extern const char *const version; /* main.c */ + +int bltn_cd(int, char *av[]) { + struct opt opt = OPTGET_INIT; opt.str = "LP"; opt.lops = (struct lop[]){ + { "help", ARG_NUL, 256 }, + { "version", ARG_NUL, 257 }, + { NULL, 0, 0 }, + }; + + struct { s32 mode; } args = {}; + + for (int c; (c = optget(&opt, av, 1)) != -1;) { + switch (c) { + case 'L': { args.mode = 0; } break; + case 'P': { args.mode = 1; } break; + case 256: { fputs(help, stdout); } return 0; + case 257: { fputs(version, stdout); } return 0; + default: {} return -1; + } + } + + char *path = av[opt.ind] ? av[opt.ind] : getenv("HOME"); + if (chdir(path)) { + fprintf(stderr, "%s: %s: %s\n", av[0], path, strerror(errno)); + errno = 0; return -1; + } + + path = getcwd(NULL, 0); setenv("PWD", path, 1); + + free(path); return 0; +} + +static const char *const help = + "cd - change directory\n" + "Usage:\n" + " cd [-L|-P] [directory]\n" + "Options:\n" + " -L Handle the operand dot-dot logically\n" + " -P Handle the operand dot-dot physically\n" + " --help Display help information\n" +; diff --git a/src/exec.c b/src/exec.c index a6e144c..50ff146 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,6 +1,7 @@ // Copyright (C) 2023, Jakob Wakeling // All rights reserved. +#include "bltn.h" #include "exec.h" #include "parse.h" #include "util/log.h" @@ -34,7 +35,12 @@ static s32 execute_comm(ast *a, int fdi, int fd[2]) { /* If the command is null, then do nothing */ if (!a->s) { return _ret; } - /* TODO handle builtins */ + /* Handle builtins */ + for (bltn *b = bltns; b->name; b += 1) { + if (strcmp(a->s, b->name) == 0) { + return b->fn(a->c.al - 1, a->c.a); + } + } pid_t pid; int status, rin = -1, rout = -1, rerr = -1; diff --git a/src/main.c b/src/main.c index b0a9221..93ac722 100644 --- a/src/main.c +++ b/src/main.c @@ -17,10 +17,11 @@ static void reset(int); static const char *const help; -static const char *const version; +const char *const version; static jmp_buf jmp; static sig_atomic_t jmpflag = false; +bool _loop = true; int main(int, char *av[]) { struct opt opt = OPTGET_INIT; opt.str = "Ep"; opt.lops = (struct lop[]){ @@ -39,7 +40,7 @@ int main(int, char *av[]) { case 258: { __debug = true; } break; case 256: { fputs(help, stdout); } return 0; case 257: { fputs(version, stdout); } return 0; - default: { return -1; } + default: {} return -1; } } @@ -53,7 +54,7 @@ int main(int, char *av[]) { if (!line) { if (errno) { log_warn("lineread: %s", strerror(errno)); } break; } eval(line, strlen(line)); free(line); - } while (true); + } while (_loop); return __warned; } @@ -67,14 +68,14 @@ static const char *const help = "Usage:\n" " esh [--debug]\n" "Options:\n" - " --help Display help information\n" - " --version Display version information\n" - " --debug Enable debug logging\n" " -E Output lexer tokens\n" " -p Output parser AST \n" + " --debug Enable debug logging\n" + " --help Display help information\n" + " --version Display version information\n" ; -static const char *const version = +const char *const version = "ESH, version " PROJECT_VERSION "\n" "Copyright (C) 2023, Jakob Wakeling\n" "All rights reserved.\n"