diff options
Diffstat (limited to 'builtins.c')
| -rw-r--r-- | builtins.c | 255 |
1 files changed, 162 insertions, 93 deletions
@@ -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) { |