summaryrefslogtreecommitdiff
path: root/builtins.c
diff options
context:
space:
mode:
authorToby Goodwin <toby@paccrat.org>2018-03-17 18:36:15 +0000
committerToby Goodwin <toby@paccrat.org>2018-03-17 18:36:15 +0000
commit2dd0aa249c9bac4e5c616d1f386dc4271fdbab46 (patch)
tree973fff29c8728ec9a1bf7f53a8b613a214c5c809 /builtins.c
parent1128baa58acaff32e4538d5878b916fba091c574 (diff)
parent54ccf74c675696318b697182573a86668fe36f50 (diff)
Merge branch 'master' into ifnot
Diffstat (limited to 'builtins.c')
-rw-r--r--builtins.c259
1 files changed, 164 insertions, 95 deletions
diff --git a/builtins.c b/builtins.c
index 477ff71..5aa90bc 100644
--- a/builtins.c
+++ b/builtins.c
@@ -20,8 +20,8 @@
#include "rlimit.h"
#include "sigmsgs.h"
-static void b_break(char **), b_cd(char **), b_continue(char **), b_eval(char **), b_exit(char **),
- b_newpgrp(char **), b_return(char **), b_shift(char **), b_umask(char **),
+static void b_break(char **), b_cd(char **), b_continue(char **), b_eval(char **), b_flag(char **),
+ b_exit(char **), b_newpgrp(char **), b_return(char **), b_shift(char **), b_umask(char **),
b_wait(char **), b_whatis(char **);
#if HAVE_SETRLIMIT
@@ -46,27 +46,28 @@ static struct {
{ b_eval, "eval" },
{ b_exec, "exec" },
{ b_exit, "exit" },
+ { b_flag, "flag" },
#if HAVE_SETRLIMIT
- { b_limit, "limit" },
+ { b_limit, "limit" },
#endif
- { b_newpgrp, "newpgrp" },
- { b_return, "return" },
- { b_shift, "shift" },
- { b_umask, "umask" },
- { b_wait, "wait" },
- { b_whatis, "whatis" },
- { b_dot, "." },
+ { b_newpgrp, "newpgrp" },
+ { b_return, "return" },
+ { b_shift, "shift" },
+ { b_umask, "umask" },
+ { b_wait, "wait" },
+ { b_whatis, "whatis" },
+ { b_dot, "." },
#ifdef ADDONS
- ADDONS
+ ADDONS
#endif
};
extern builtin_t *isbuiltin(char *s) {
- int i;
- for (i = 0; i < arraysize(builtins); i++)
- if (streq(builtins[i].name, s))
- return builtins[i].p;
- return NULL;
+ int i;
+ for (i = 0; i < arraysize(builtins); i++)
+ if (streq(builtins[i].name, s))
+ return builtins[i].p;
+ return NULL;
}
/* funcall() is the wrapper used to invoke shell functions. pushes $*, and "return" returns here. */
@@ -89,13 +90,13 @@ extern void funcall(char **av) {
}
static void arg_count(char *name) {
- fprint(2, RC "too many arguments to %s\n", name);
- set(FALSE);
+ fprint(2, RC "too many arguments to %s\n", name);
+ set(FALSE);
}
static void badnum(char *num) {
- fprint(2, RC "`%s' is a bad number\n", num);
- set(FALSE);
+ fprint(2, RC "`%s' is a bad number\n", num);
+ set(FALSE);
}
/* a dummy command. (exec() performs "exec" simply by not forking) */
@@ -107,90 +108,90 @@ extern void b_exec(char **ignore) {
/* echo -n omits a newline. echo -- -n echos '-n' */
static void b_echo(char **av) {
- char *format = "%A\n";
- if (*++av != NULL) {
- if (streq(*av, "-n"))
- format = "%A", av++;
- else if (streq(*av, "--"))
- av++;
- }
- fprint(1, format, av);
- set(TRUE);
+ char *format = "%A\n";
+ if (*++av != NULL) {
+ if (streq(*av, "-n"))
+ format = "%A", av++;
+ else if (streq(*av, "--"))
+ av++;
+ }
+ fprint(1, format, av);
+ set(TRUE);
}
#endif
/* cd. traverse $cdpath if the directory given is not an absolute pathname */
static void b_cd(char **av) {
- List *s, nil;
- char *path = NULL;
- size_t t, pathlen = 0;
- if (*++av == NULL) {
- s = varlookup("home");
- *av = (s == NULL) ? "/" : s->w;
- } else if (av[1] != NULL) {
- arg_count("cd");
- return;
- }
- if (isabsolute(*av) || streq(*av, ".") || streq(*av, "..")) { /* absolute pathname? */
- if (chdir(*av) < 0) {
- set(FALSE);
- uerror(*av);
- } else
- set(TRUE);
- } else {
- s = varlookup("cdpath");
- if (s == NULL) {
- s = &nil;
- nil.w = "";
- nil.n = NULL;
- }
- do {
- if (s != &nil && *s->w != '\0') {
- t = strlen(*av) + strlen(s->w) + 2;
- if (t > pathlen)
- path = nalloc(pathlen = t);
- strcpy(path, s->w);
- if (!streq(s->w, "/")) /* "//" is special to POSIX */
- strcat(path, "/");
- strcat(path, *av);
- } else {
- pathlen = 0;
- path = *av;
- }
- if (chdir(path) >= 0) {
- set(TRUE);
- if (interactive && *s->w != '\0' && !streq(s->w, "."))
- fprint(1, "%s\n", path);
- return;
- }
- s = s->n;
- } while (s != NULL);
- fprint(2, "couldn't cd to %s\n", *av);
- set(FALSE);
- }
+ List *s, nil;
+ char *path = NULL;
+ size_t t, pathlen = 0;
+ if (*++av == NULL) {
+ s = varlookup("home");
+ *av = (s == NULL) ? "/" : s->w;
+ } else if (av[1] != NULL) {
+ arg_count("cd");
+ return;
+ }
+ if (isabsolute(*av) || streq(*av, ".") || streq(*av, "..")) { /* absolute pathname? */
+ if (chdir(*av) < 0) {
+ set(FALSE);
+ uerror(*av);
+ } else
+ set(TRUE);
+ } else {
+ s = varlookup("cdpath");
+ if (s == NULL) {
+ s = &nil;
+ nil.w = "";
+ nil.n = NULL;
+ }
+ do {
+ if (s != &nil && *s->w != '\0') {
+ t = strlen(*av) + strlen(s->w) + 2;
+ if (t > pathlen)
+ path = nalloc(pathlen = t);
+ strcpy(path, s->w);
+ if (!streq(s->w, "/")) /* "//" is special to POSIX */
+ strcat(path, "/");
+ strcat(path, *av);
+ } else {
+ pathlen = 0;
+ path = *av;
+ }
+ if (chdir(path) >= 0) {
+ set(TRUE);
+ if (interactive && *s->w != '\0' && !streq(s->w, "."))
+ fprint(1, "%s\n", path);
+ return;
+ }
+ s = s->n;
+ } while (s != NULL);
+ fprint(2, "couldn't cd to %s\n", *av);
+ set(FALSE);
+ }
}
static void b_umask(char **av) {
- int i;
- if (*++av == NULL) {
- set(TRUE);
- i = umask(0);
- umask(i);
- fprint(1, "0%o\n", i);
- } else if (av[1] == NULL) {
- i = o2u(*av);
- if ((unsigned int) i > 0777) {
- fprint(2, "bad umask\n");
- set(FALSE);
- } else {
- umask(i);
- set(TRUE);
- }
- } else {
- arg_count("umask");
- return;
- }
+ int i;
+ if (*++av == NULL) {
+ set(TRUE);
+ i = umask(0);
+ umask(i);
+ fprint(1, "0%o\n", i);
+ } else if (av[1] == NULL) {
+ i = o2u(*av);
+ if ((unsigned int) i > 0777) {
+ fprint(2, "bad umask\n");
+ set(FALSE);
+ } else {
+ umask(i);
+ set(TRUE);
+ }
+ } else {
+ arg_count("umask");
+ return;
+ }
}
static void b_exit(char **av) {
@@ -199,6 +200,74 @@ static void b_exit(char **av) {
rc_exit(getstatus());
}
+static void b_flag(char **av) {
+ bool *flagp = NULL;
+ char f;
+ int mode = 3; /* 0 = reset (-), 1 = set (+), 2 = test */
+ const char *usage = "usage: flag f [ + | - ]\n";
+
+ if (*++av == NULL) {
+ fprint(2, RC "not enough arguments to flag\n");
+ set(FALSE);
+ return;
+ }
+ f = av[0][0];
+ if (f == '\0' || av[0][1] != '\0') goto flag_usage;
+ if (*++av == NULL) {
+ mode = 2;
+ } else if (av[0][0] == '+' && av[0][1] == '\0') {
+ mode = 1;
+ } else if (av[0][0] == '-' && av[0][1] == '\0') {
+ mode = 0;
+ }
+ if (mode == 3) goto flag_usage;
+ switch (f) {
+ case 'c':
+ if (mode != 2) goto flag_immutable;
+ set(dashsee[0] != NULL);
+ return;
+ case 'd':
+ if (mode != 2) goto flag_immutable;
+ flagp = &dashdee; break;
+ case 'e': flagp = &dashee; break;
+ case 'i': flagp = &interactive; break;
+ case 'l':
+ if (mode != 2) goto flag_immutable;
+ flagp = &dashell; break;
+ case 'n': flagp = &dashen; break;
+ case 'o':
+ if (mode != 2) goto flag_immutable;
+ flagp = &dashoh; break;
+ case 'p':
+ if (mode != 2) goto flag_immutable;
+ flagp = &dashpee; break;
+ case 's':
+ if (mode != 2) goto flag_immutable;
+ flagp = &dashess; break;
+ case 'v': flagp = &dashvee; break;
+ case 'x': flagp = &dashex; break;
+ }
+ if (flagp != NULL) {
+ if (mode == 2)
+ set(*flagp);
+ else {
+ *flagp = mode;
+ set(TRUE);
+ }
+ } else {
+ fprint(2, RC "unknown flag");
+ set(FALSE);
+ }
+ return;
+flag_immutable:
+ fprint(2, RC "flag immutable\n");
+ set(FALSE);
+ return;
+flag_usage:
+ fprint(2, usage);
+ set(FALSE);
+}
+
/* raise a "return" exception, i.e., return from a function. if an integer argument is present, set $status to it */
static void b_return(char **av) {