diff options
author | Jakob Kaivo <jkk@ung.org> | 2019-03-13 21:47:51 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2019-03-13 21:47:51 -0400 |
commit | a088e851fb45fe38e6a228770fa5d0c04cddb7f5 (patch) | |
tree | ccec5f171001fde3ad8d18b8241a8c1f441a77fc /builtins.c |
migrate to gitlab
Diffstat (limited to 'builtins.c')
-rw-r--r-- | builtins.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/builtins.c b/builtins.c new file mode 100644 index 0000000..886ebaf --- /dev/null +++ b/builtins.c @@ -0,0 +1,167 @@ +/* + * UNG's Not GNU + * + * Copyright (c) 2011-2017, Jakob Kaivo <jkk@ung.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "sh.h" +#include <stddef.h> +#include <string.h> +#include <libgen.h> +#include <unistd.h> + +struct builtin { + const char *name; + int (*main)(int argc, char *argv[]); +}; + +/* Special built-ins */ +/* break */ +/* : */ +/* continue */ +int dot_main(int argc, char *argv[]); +int eval_main(int argc, char *argv[]); +int exec_main(int argc, char *argv[]); +int exit_main(int argc, char *argv[]); +int export_main(int argc, char *argv[]); +int readonly_main(int argc, char *argv[]); +/* return */ +int set_main(int argc, char *argv[]); +int shift_main(int argc, char *argv[]); +int times_main(int argc, char *argv[]); +int trap_main(int argc, char *argv[]); +int unset_main(int argc, char *argv[]); + +static struct builtin special_builtins[] = { + { "break", NULL }, + { ":", NULL }, + { "continue", NULL }, + { ".", dot_main }, + { "eval", eval_main }, + { "exec", exec_main }, + { "exit", exit_main }, + { "export", export_main }, + { "readonly", readonly_main }, + { "return", NULL }, + { "set", set_main }, + { "shift", shift_main }, + { "times", times_main }, + { "trap", trap_main }, + { "unset", unset_main }, + { 0, 0 }, +}; + +/* Regular built-ins */ +int alias_main(int argc, char *argv[]); +int bg_main(int argc, char *argv[]); +int cd_main(int argc, char *argv[]); +int command_main(int argc, char *argv[]); +int false_main(int argc, char *argv[]); +int fc_main(int argc, char *argv[]); +int fg_main(int argc, char *argv[]); +int getopts_main(int argc, char *argv[]); +int jobs_main(int argc, char *argv[]); +int kill_main(int argc, char *argv[]); +int newgrp_main(int argc, char *argv[]); +int pwd_main(int argc, char *argv[]); +int read_main(int argc, char *argv[]); +int true_main(int argc, char *argv[]); +int ulimit_main(int argc, char *argv[]); +int umask_main(int argc, char *argv[]); +int unalias_main(int argc, char *argv[]); +int wait_main(int argc, char *argv[]); + +static struct builtin regular_builtins[] = { + { "alias", alias_main }, + { "bg", bg_main }, + { "cd", cd_main }, + { "command", command_main }, + { "false", false_main }, + { "fc", fc_main }, + { "fg", fg_main }, + { "getopts", getopts_main }, + { "jobs", jobs_main }, + { "kill", kill_main }, + { "newgrp", newgrp_main }, + { "pwd", pwd_main }, + { "read", read_main }, + { "true", true_main }, + { "ulimit", ulimit_main }, + { "umask", umask_main }, + { "unalias", unalias_main }, + { "wait", wait_main }, + { 0, 0 }, +}; + +static int (*sh_getbuiltin(const char *util, struct builtin *bi))(int argc, char *argv[]) +{ + for (int i = 0; bi[i].name; i++) { + if (!strcmp(bi[i].name, util)) { + return bi[i].main; + } + } + + return NULL; +} + +int sh_builtin(int argc, char *argv[]) +{ + char *util = basename(argv[0]); + if (!strcmp(util, "break")) { + return BREAK; + } else if (!strcmp(util, ":")) { + return 0; + } else if (!strcmp(util, "continue")) { + return CONTINUE; + } else if (!strcmp(util, "return")) { + return RETURN; + } + + int (*m)(int, char *[]) = sh_getbuiltin(util, special_builtins); + if (m == NULL) { + m = sh_getbuiltin(util, regular_builtins); + if (m == NULL) { + return 1; + } + } + + optind = 1; + opterr = 1; + optarg = NULL; + + return m(argc, argv); +} + +static int is_builtin(const char *util, struct builtin *bi) +{ + for (int i = 0; bi[i].name; i++) { + if (!strcmp(bi[i].name, util)) { + return 1; + } + } + + return 0; +} + +int sh_is_special_builtin(const char *util) +{ + return is_builtin(util, special_builtins); +} + +int sh_is_regular_builtin(const char *util) +{ + return is_builtin(util, regular_builtins); +} |