home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume20 / rc / part02 / fn.c next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  4.3 KB  |  192 lines

  1. /*
  2.    fn.c: functions for adding and deleting functions from the symbol table.
  3.    Support for signal handlers is also found here.
  4. */
  5.  
  6. #include <signal.h>
  7. #include "rc.h"
  8. #include "utils.h"
  9. #include "status.h"
  10. #include "tree.h"
  11. #include "hash.h"
  12. #include "footobar.h"
  13. #include "walk.h"
  14. #include "nalloc.h"
  15. #include "sigmsgs.h"
  16. #include "builtins.h"
  17. #include "input.h"
  18.  
  19. static void fn_handler(int);
  20.  
  21. static Node *handlers[NUMOFSIGNALS], null_function;
  22. static boolean runexit = FALSE;
  23.  
  24. /* set signals to default values for rc. this means that interactive shells ignore SIGQUIT, etc. */
  25.  
  26. void inithandler() {
  27.     if (interactive) {
  28.         signal(SIGINT, sig);
  29.         handlers[SIGINT] = &null_function;
  30.         if (!dashdee) {
  31.             signal(SIGQUIT, SIG_IGN);
  32.             handlers[SIGQUIT] = &null_function;
  33.         }
  34.     }
  35.     null_function.type = BODY;
  36.     null_function.u[0].p = null_function.u[1].p = NULL;
  37. }
  38.  
  39. /* only run this in a child process! resets signals to their default values */
  40.  
  41. void setsigdefaults(void) {
  42.     int i;
  43.  
  44.     /*
  45.        General housekeeping: (setsigdefaults happens after fork(), so it's a convenient
  46.        place to clean up)
  47.     */
  48.  
  49.     interactive = FALSE;
  50.     if (histstr != NULL)    /* Close an open history file */
  51.         close(histfd);
  52.  
  53.     /* Restore signals to SIG_DFL */
  54.  
  55.     for (i = 1; i < NUMOFSIGNALS; i++) { /* signal 0 is never used (bogus) */
  56.         if (handlers[i] != NULL) {
  57.             handlers[i] = NULL;
  58.             signal(i, SIG_DFL);
  59.         }
  60.     }
  61.     runexit = FALSE; /* No sigexit on subshells */
  62. }
  63.  
  64. /* rc's exit. if runexit is set, run the sigexit function. */
  65.  
  66. void rc_exit(int stat) {
  67.     static char *sigexit[2] = { "sigexit", NULL };
  68.  
  69.     if (runexit) {
  70.         runexit = FALSE;
  71.         funcall(sigexit);
  72.         exit(getstatus());
  73.     } else {
  74.         exit(stat);
  75.     }
  76. }
  77.  
  78. /* the signal handler for all functions. calls walk() */
  79.  
  80. static void fn_handler(int s) {
  81.     if (s < 0 || s >= NUMOFSIGNALS)
  82.         rc_error("unknown signal!?");
  83.  
  84.     signal(s, fn_handler); /* sgi seems to require re-signalling */
  85.     walk(handlers[s], TRUE);
  86. }
  87.  
  88. /*
  89.    assign a function in Node form. Check to see if the function is also a signal, and set the
  90.    signal vectors appropriately.
  91. */
  92.  
  93. void fnassign(char *name, Node *def) {
  94.     Node *newdef = treecpy(def == NULL ? &null_function : def, ealloc); /* important to do the treecopy first */
  95.     Function *new = get_fn_place(name);
  96.     int i;
  97.  
  98.     new->def = newdef;
  99.     new->extdef = NULL;
  100.  
  101.     if (strncmp(name, "sig", sizeof "sig" - 3) == 0) { /* slight optimization */
  102.         if (streq(name, "sigexit"))
  103.             runexit = TRUE;
  104.         for (i = 1; i < NUMOFSIGNALS; i++) /* zero is a bogus signal */
  105.             if (streq(signals[i][0], name)) {
  106.                 if (newdef != NULL) {
  107.                     handlers[i] = newdef;
  108.                     signal(i, fn_handler);
  109.                 } else {
  110.                     handlers[i] = &null_function;
  111.                     signal(i, SIG_IGN);
  112.                 }
  113.                 break;
  114.             }
  115.     }
  116. }
  117.  
  118. /* assign a function from the environment. store just the external representation */
  119.  
  120. void fnassign_string(char *extdef) {
  121.     char *name = get_name(extdef+3); /* +3 to skip over "fn_" */
  122.     Function *new;
  123.  
  124.     if (name == NULL)
  125.         return;
  126.  
  127.     new = get_fn_place(name);
  128.     new->def = NULL;
  129.     new->extdef = ecpy(extdef);
  130. }
  131.  
  132. /* return a function in Node form, evaluating an entry from the environment if necessary */
  133.  
  134. Node *fnlookup(char *name) {
  135.     Function *look = lookup_fn(name);
  136.     Node *ret;
  137.  
  138.     if (look == NULL)
  139.         return NULL; /* not found */
  140.     if (look->def != NULL)
  141.         return look->def;
  142.     if (look->extdef == NULL) /* function was set to null, e.g., fn foo {} */
  143.         return &null_function;
  144.  
  145.     ret = parse_fn(name, look->extdef);
  146.  
  147.     if (ret == NULL) {
  148.         efree(look->extdef);
  149.         look->extdef = NULL;
  150.         return &null_function;
  151.     } else {
  152.         return look->def = treecpy(ret, ealloc); /* Need to take it out of talloc space */
  153.     }
  154. }
  155.  
  156. /* return a function in string form (used by makeenv) */
  157.  
  158. char *fnlookup_string(char *name) {
  159.     Function *look = lookup_fn(name);
  160.  
  161.     if (look == NULL)
  162.         return NULL;
  163.     if (look->extdef != NULL)
  164.         return look->extdef;
  165.     return look->extdef = fun2str(name, look->def);
  166. }
  167.  
  168. /*
  169.    remove a function from the symbol table. If it also defines a signal handler, restore the signal handler
  170.    to its default value.
  171. */
  172.  
  173. void fnrm(char *name) {
  174.     int i;
  175.  
  176.     for (i = 1; i < NUMOFSIGNALS; i++) /* signal 0 unused */
  177.         if (streq(signals[i][0], name)) {
  178.             handlers[i] = NULL;
  179.             if (i == SIGINT)
  180.                 signal(i, sig); /* restore default signal handler for rc */
  181.             else if (i == SIGQUIT && !dashdee)
  182.                 signal(i, SIG_IGN);     /* ditto */
  183.             else
  184.                 signal(i, SIG_DFL);
  185.         }
  186.  
  187.     if (streq(name, "sigexit"))
  188.         runexit = FALSE;
  189.  
  190.     delete_fn(name);
  191. }
  192.