home *** CD-ROM | disk | FTP | other *** search
- /*
- fn.c: functions for adding and deleting functions from the symbol table.
- Support for signal handlers is also found here.
- */
-
- #include <signal.h>
- #include "rc.h"
- #include "utils.h"
- #include "status.h"
- #include "tree.h"
- #include "hash.h"
- #include "footobar.h"
- #include "walk.h"
- #include "nalloc.h"
- #include "sigmsgs.h"
- #include "builtins.h"
- #include "input.h"
-
- static void fn_handler(int);
-
- static Node *handlers[NUMOFSIGNALS], null_function;
- static boolean runexit = FALSE;
-
- /* set signals to default values for rc. this means that interactive shells ignore SIGQUIT, etc. */
-
- void inithandler() {
- if (interactive) {
- signal(SIGINT, sig);
- handlers[SIGINT] = &null_function;
- if (!dashdee) {
- signal(SIGQUIT, SIG_IGN);
- handlers[SIGQUIT] = &null_function;
- }
- }
- null_function.type = BODY;
- null_function.u[0].p = null_function.u[1].p = NULL;
- }
-
- /* only run this in a child process! resets signals to their default values */
-
- void setsigdefaults(void) {
- int i;
-
- /*
- General housekeeping: (setsigdefaults happens after fork(), so it's a convenient
- place to clean up)
- */
-
- interactive = FALSE;
- if (histstr != NULL) /* Close an open history file */
- close(histfd);
-
- /* Restore signals to SIG_DFL */
-
- for (i = 1; i < NUMOFSIGNALS; i++) { /* signal 0 is never used (bogus) */
- if (handlers[i] != NULL) {
- handlers[i] = NULL;
- signal(i, SIG_DFL);
- }
- }
- runexit = FALSE; /* No sigexit on subshells */
- }
-
- /* rc's exit. if runexit is set, run the sigexit function. */
-
- void rc_exit(int stat) {
- static char *sigexit[2] = { "sigexit", NULL };
-
- if (runexit) {
- runexit = FALSE;
- funcall(sigexit);
- exit(getstatus());
- } else {
- exit(stat);
- }
- }
-
- /* the signal handler for all functions. calls walk() */
-
- static void fn_handler(int s) {
- if (s < 0 || s >= NUMOFSIGNALS)
- rc_error("unknown signal!?");
-
- signal(s, fn_handler); /* sgi seems to require re-signalling */
- walk(handlers[s], TRUE);
- }
-
- /*
- assign a function in Node form. Check to see if the function is also a signal, and set the
- signal vectors appropriately.
- */
-
- void fnassign(char *name, Node *def) {
- Node *newdef = treecpy(def == NULL ? &null_function : def, ealloc); /* important to do the treecopy first */
- Function *new = get_fn_place(name);
- int i;
-
- new->def = newdef;
- new->extdef = NULL;
-
- if (strncmp(name, "sig", sizeof "sig" - 3) == 0) { /* slight optimization */
- if (streq(name, "sigexit"))
- runexit = TRUE;
- for (i = 1; i < NUMOFSIGNALS; i++) /* zero is a bogus signal */
- if (streq(signals[i][0], name)) {
- if (newdef != NULL) {
- handlers[i] = newdef;
- signal(i, fn_handler);
- } else {
- handlers[i] = &null_function;
- signal(i, SIG_IGN);
- }
- break;
- }
- }
- }
-
- /* assign a function from the environment. store just the external representation */
-
- void fnassign_string(char *extdef) {
- char *name = get_name(extdef+3); /* +3 to skip over "fn_" */
- Function *new;
-
- if (name == NULL)
- return;
-
- new = get_fn_place(name);
- new->def = NULL;
- new->extdef = ecpy(extdef);
- }
-
- /* return a function in Node form, evaluating an entry from the environment if necessary */
-
- Node *fnlookup(char *name) {
- Function *look = lookup_fn(name);
- Node *ret;
-
- if (look == NULL)
- return NULL; /* not found */
- if (look->def != NULL)
- return look->def;
- if (look->extdef == NULL) /* function was set to null, e.g., fn foo {} */
- return &null_function;
-
- ret = parse_fn(name, look->extdef);
-
- if (ret == NULL) {
- efree(look->extdef);
- look->extdef = NULL;
- return &null_function;
- } else {
- return look->def = treecpy(ret, ealloc); /* Need to take it out of talloc space */
- }
- }
-
- /* return a function in string form (used by makeenv) */
-
- char *fnlookup_string(char *name) {
- Function *look = lookup_fn(name);
-
- if (look == NULL)
- return NULL;
- if (look->extdef != NULL)
- return look->extdef;
- return look->extdef = fun2str(name, look->def);
- }
-
- /*
- remove a function from the symbol table. If it also defines a signal handler, restore the signal handler
- to its default value.
- */
-
- void fnrm(char *name) {
- int i;
-
- for (i = 1; i < NUMOFSIGNALS; i++) /* signal 0 unused */
- if (streq(signals[i][0], name)) {
- handlers[i] = NULL;
- if (i == SIGINT)
- signal(i, sig); /* restore default signal handler for rc */
- else if (i == SIGQUIT && !dashdee)
- signal(i, SIG_IGN); /* ditto */
- else
- signal(i, SIG_DFL);
- }
-
- if (streq(name, "sigexit"))
- runexit = FALSE;
-
- delete_fn(name);
- }
-