home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / mush.rstevens.tar.gz / mush.tar / init.c < prev    next >
C/C++ Source or Header  |  1992-10-30  |  14KB  |  484 lines

  1. /* init.c    (c) copyright 1986 (Dan Heller) */
  2.  
  3. /* init.c -- functions and whatnot that initialize everything */
  4. #include "mush.h"
  5. #include <pwd.h>
  6.  
  7. #if defined(BSD) || defined(HPUX) || defined(IRIX4)
  8. #include <netdb.h>
  9. #endif /* BSD || HPUX || IRIX4 */
  10.  
  11. #if defined(SYSV) && !defined(HPUX) && !defined(IRIX4)
  12. #include <sys/utsname.h>
  13. #endif /* SYSV && !HPUX && !IRIX4 */
  14.  
  15. void
  16. init()
  17. {
  18.     char         *home, *realname, *argv[4];
  19.     extern char        *getlogin();
  20.     char        buf[MAXPATHLEN];
  21. #if defined(SYSV) && !defined(HPUX) && !defined(IRIX4)
  22.     extern struct passwd *getpwuid();  /* sys-v forgot this in pwd.h! */
  23.     struct utsname ourhost;
  24. #else
  25.     char ourhost[128];
  26. #endif /* SYSV && !HPUX && !IRIX4 */
  27.     register char     *p;
  28.     struct passwd     *entry;
  29.     int            cnt;
  30. #if defined(BSD) || defined(HPUX) || defined(IRIX4)
  31.     struct hostent     *hp;
  32. #endif /* BSD || HPUX || IRIX4 */
  33.  
  34.     home = getenv("HOME");
  35.     if (realname = getenv("NAME")) {
  36.     (void) strcpy(buf, realname);
  37.     }
  38.     argv[1] = "=";
  39.     argv[3] = NULL;
  40.  
  41.     if (!(entry = getpwuid(getuid())))
  42.     if (p = getlogin())
  43.         strdup(login, p);
  44.     else {
  45.         strdup(login, "unknown");
  46.         print("I don't know you, but that's ok.\n");
  47.     }
  48.     else {
  49.     strdup(login, entry->pw_name);
  50.     if (!home || !*home)
  51.         home = entry->pw_dir;
  52.     if (!realname && (realname = entry->pw_gecos)) {
  53.         if (p = index(realname, ','))
  54.         *p = 0;
  55.         for (p = buf; *realname; realname++)
  56.         if (*realname == '&')
  57.             *p++ = upper(*login), p += Strcpy(p, login+1);
  58.         else
  59.             *p++ = *realname;
  60.         *p = 0;
  61.     }
  62.     endpwent();
  63.     }
  64.     if (!home || !*home || Access(home, W_OK)) {
  65.     if (home && *home)
  66.         error(home);
  67.     else
  68.         print("No home!? ");
  69.     print_more("Using \"%s\" as home.\n", home = ALTERNATE_HOME);
  70.     } else {
  71.     argv[0] = "home";
  72.     argv[2] = home;
  73.     (void) add_option(&set_options, argv);
  74.     }
  75.  
  76.     if (realname && *buf) {
  77.     /* realname has already been copied to buf */
  78.     argv[0] = "realname";
  79.     argv[2] = buf;
  80.     (void) add_option(&set_options, argv);
  81.     }
  82.  
  83. #ifdef HOMEMAIL
  84.     strdup(spoolfile, sprintf(buf, "%s/%s", home, MAILFILE));
  85. #else /* HOMEMAIL */
  86. #ifdef ENV_MAIL
  87.     if ((p = getenv("MAIL")) && *p)
  88.     strdup(spoolfile, p);
  89.     else
  90. #endif /* ENV_MAIL */
  91.     strdup(spoolfile, sprintf(buf, "%s/%s", MAILDIR, login));
  92. #endif /* HOMEMAIL */
  93.     mailfile = "";
  94.  
  95.     crt = 24;
  96.     screen = 18;
  97.     wrapcolumn = 0; /* Default is no wrap */
  98.     escape = DEF_ESCAPE;
  99.     prompt = DEF_PROMPT;
  100.  
  101. #if defined(BSD) || defined(HPUX) || defined(IRIX4)
  102.     (void) gethostname(ourhost, sizeof ourhost);
  103.     if (!(hp = gethostbyname(ourhost))) {
  104.     if (ourname = (char **)calloc((unsigned)2, sizeof (char *)))
  105.         strdup(ourname[0], ourhost);
  106.     } else {
  107.     int n = -1;
  108.     cnt = 2; /* 1 for ourhost and 1 for NULL terminator */
  109.  
  110.         for (p = hp->h_name; p && *p; p = hp->h_aliases[++n])
  111.             if (strcmp(ourhost, p)) /* if host name is different */
  112.                 cnt++;
  113.  
  114.         if (ourname = (char **)malloc((unsigned)cnt * sizeof (char *))) {
  115.             n = -1;
  116.             cnt = 0;
  117.             ourname[cnt++] = savestr(ourhost);
  118.             for (p = hp->h_name; p && *p; p = hp->h_aliases[++n])
  119.                 if (strcmp(ourhost, p)) /* if host name is different */
  120.                     ourname[cnt++] = savestr(p);
  121.             ourname[cnt++] = NULL;
  122.         }
  123.     }
  124. #else
  125. #ifdef SYSV
  126.     if (ourname = (char **)calloc((unsigned)2, sizeof (char *))) {
  127.     if ((uname (&ourhost) >= 0) && (*ourhost.nodename))
  128.         ourname[0] = savestr(ourhost.nodename);
  129.     else {
  130.         /* Try to use uuname -l to get host's name if uname didn't work */
  131.         char buff[50];
  132.         char *p;
  133.         FILE *F;
  134.  
  135.         if (F = popen("exec uuname -l", "r")) {
  136.         if ((fgets(buff, sizeof buff, F) == buff) &&
  137.             (p = strchr(buff, '\n'))) {
  138.             *p = '\0';        /* eliminate newline */
  139.             ourname[0] = savestr (buff);
  140.         }
  141.         (void)pclose(F);
  142.         }
  143.     }
  144.     }
  145. #endif /* SYSV */
  146. #endif /* BSD || HPUX || IRIX4 */
  147.     if (ourname && ourname[0]) {
  148.     for (p = buf, cnt = 0; ourname[cnt]; cnt++) {
  149.         if (cnt)
  150.         *p++ = ' ';
  151.         p += Strcpy(p, ourname[cnt]);
  152.     }
  153.     argv[0] = "hostname";
  154.     argv[2] = buf;
  155.     (void) add_option(&set_options, argv);
  156.     }
  157.  
  158.     init_bindings();
  159. }
  160.  
  161. /*
  162.  * Source a file, or just the default file.  Since sourcing files
  163.  * means reading possible aliases, don't expand the ! as history
  164.  * by setting the IGN_BANG flag.  Since a command in the sourced file
  165.  * may call source on another file, this routine may be called from
  166.  * within itself.  Continue to ignore ! chars by setting save_bang (local).
  167.  *
  168.  * Try opening the file passed to us.  If not given, check for the correct
  169.  * .rc file which is found in the user's home dir.
  170.  *
  171.  * return -1 for filesystem errors, -2 for attempting to read a directory.
  172.  */
  173. source(argc, argv)
  174. char **argv;
  175. {
  176.     register char *p;
  177.     FILE      *fp;
  178.     char       file[MAXPATHLEN];
  179.     u_long      save_bang = ison(glob_flags, IGN_BANG);
  180.     int          line_no = 0;
  181.  
  182.     if (argc && *++argv && !strcmp(*argv, "-?"))
  183.     return help(0, "source", cmd_help);
  184.     if (argc && *argv)
  185.     (void) strcpy(file, *argv);
  186.     else if ((p = getenv("MUSHRC")) && *p || (p = getenv("MAILRC")) && *p)
  187.     (void) strcpy(file, p);
  188.     else {
  189.     char *home = do_set(set_options, "home");
  190.     if (!home || !*home)
  191.         home = ALTERNATE_HOME;
  192.     if (Access(sprintf(file, "%s/%s", home, MAILRC), R_OK)
  193.         && Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), R_OK))
  194.         if (argc || argv)
  195.         (void) strcpy(file, DEFAULT_RC);
  196.         else
  197.         return -1;
  198.     }
  199.  
  200.     argc = 0; /* don't ignore ENOENT */
  201.     p = getpath(file, &argc);
  202.     /* Try the ALT_DEF_RC if DEFAULT_RC fails */
  203.     if (argc && !strcmp(file, DEFAULT_RC)) {
  204.     argc = 0; /* don't ignore ENOENT */
  205.     (void) strcpy(file, ALT_DEF_RC);
  206.     p = getpath(file, &argc);
  207.     }
  208.     if (argc) {
  209.     /* Don't print error messages for missing default files */
  210.     if (strcmp(file, ALT_DEF_RC))
  211.         if (argc == -1) {
  212.         print("%s: %s\n", file, p);
  213.         return -1;
  214.         } else {
  215.         print("%s is a directory.\n", file);
  216.         return -2;
  217.         }
  218.     return -1;
  219.     }
  220.     if (!(fp = fopen(p, "r"))) {
  221.     if (errno != ENOENT)
  222.         error("Can't open %s", p);
  223.     return -1;
  224.     }
  225.     turnon(glob_flags, IGN_BANG); /* ignore ! when reading record files */
  226.     (void) strcpy(file, p);
  227.     (void) src_parse(file, fp, 0, 0, &line_no);
  228.     /* if we entered the routine ignoring !, leave it that way. */
  229.     if (!save_bang)
  230.     turnoff(glob_flags, IGN_BANG);
  231.     /* Sourcing might change things, so abort pipes/macros */
  232.     return 0 - (in_pipe() || in_macro());
  233. }
  234.  
  235. /*
  236.  * Do the actual file parsing for source().  The first argument should
  237.  * be the name of the file referenced by the second argument.  The third
  238.  * argument is used for handling nested if_else_endif expressions.  The
  239.  * fourth argument is used to keep track of the recursion depth, and the
  240.  * last argument keeps track of the line number in the current file.
  241.  *
  242.  * This function calls itself recursively.  It also calls do_command(),
  243.  * which may in turn call source() recursively.
  244.  *
  245.  * If-then-else nesting algorithm:
  246.  *  On any "if" (whether parsing or not), increment if_else
  247.  *  On true "if" when parsing, evaluate by recursion
  248.  *  On false "if" when parsing, set find_else equal to if_else
  249.  *  On any "if" when not parsing, set find_endif equal to if_else
  250.  *  On "else", invert parsing only when find_else equals if_else
  251.  *  When "if" was false and there is nesting, recur for "else"
  252.  *  Skip nested "if...endif" when find_else or find_endif true
  253.  *  On "endif" or when recursion returns, decrement if_else
  254.  *  On "endif", test both find_endif and find_else against if_else:
  255.  *   when either matches, reset that one;
  256.  *   when the lesser (less nested) matches, resume parsing
  257.  *  On "endif", when if_else hits 0, continue (depth 0) or return
  258.  */
  259. src_parse(file, fp, if_else, depth, line_no)
  260. char    *file;
  261. FILE    *fp;
  262. int      if_else, depth, *line_no;
  263. {
  264.     register char *p, *p2, **newargv;
  265.     static int    exited;
  266.     int       parsing = 1, cont_line = 0;
  267.     int          find_else = 0, find_endif = 0;
  268.     char       line[BUFSIZ];
  269.     int          argc;
  270.  
  271.     exited = 0;
  272.  
  273.     while (p = fgets(&line[cont_line], BUFSIZ - cont_line - 1, fp)) {
  274.     (*line_no)++;
  275.     if (p2 = index(p, '\n'))
  276.         while (p2 > p && *p2 == '\n' || isspace(*p2))
  277.         *p2-- = 0;  /* get rid of newline and trailing spaces */
  278.     else {
  279.         print("%s: line %d:%s line too long, truncated at %d characters.\n",
  280.         file, *line_no, cont_line? " continued" : "", BUFSIZ);
  281.         p2 = no_newln(p);
  282.     }
  283.     if (*p2 == '\\') {
  284.         *p2++ = ' ';
  285.         cont_line = p2 - line;
  286.         continue;
  287.     } else
  288.         cont_line = 0;
  289.     /* don't consider comments (#) in lines. check if # is within quotes */
  290.     if (p = any(line, "\"'#\\")) {
  291.         register int balanced = 1;
  292.         do {
  293.         if (*p == '\\' && p[1])
  294.             p = any(p+2, "\"'#\\");
  295.         else if (*p != '#') {
  296.             /* first find matching quote */
  297.             register char *quote = index(p+1, *p);
  298.             if (!quote) {
  299.             print("%s: line %d: unbalanced %c.\n",
  300.                 file, *line_no, *p);
  301.             balanced = 0;
  302.             } else
  303.             p = any(quote+1, "\"'#\\");
  304.         }
  305.         } while (p && *p != '#' && balanced);
  306.         if (!balanced)
  307.         continue;
  308.         if (p && *p == '#')
  309.         *p = 0; /* found a Comment: null terminate line at comment */
  310.     }
  311.     if (!*line || !parsing && !(newargv = mk_argv(line, &argc, 0))
  312.     || parsing && !(newargv = make_command(line, TRPL_NULL, &argc))) {
  313.         if (!strncmp(line, "if", 2))
  314.         find_else = ++if_else, parsing = FALSE;
  315.         continue;
  316.     }
  317.     if (!strcmp(newargv[0], "endif")) {
  318.         if (!if_else)
  319.         print("%s: line %d: endif with no \"if\".\n", file, *line_no);
  320.         else {
  321.         /* If looking for an else or endif, reset parsing */
  322.         if (find_endif && find_endif == if_else) {
  323.             if (find_endif <= find_else || !find_else)
  324.             parsing = 1, find_else = 0;
  325.             find_endif = 0;
  326.         }
  327.         /* Note: find_else never < find_endif */
  328.         if (find_else && find_else == if_else)
  329.             parsing = !parsing, find_else = 0;
  330.         /* Decrement if_else and check depth */
  331.         if (--if_else == 0)
  332.             /* Resume parsing if at the top */
  333.             if (depth == 0)
  334.             parsing = 1;
  335.             /* Return if not at the top */
  336.             else
  337.             return 1;
  338.         }
  339.         goto bad;
  340.     } else if (!strcmp(newargv[0], "else")) {
  341.         if (!if_else)
  342.         print("%s: line %d: if-less \"else\".\n", file, *line_no);
  343.         /* If inside an else, ignore nested else;
  344.          *  otherwise, recur when if_else > 1 */
  345.         else if (!find_else && !find_endif && !parsing) {
  346.         parsing = src_parse(file, fp, 1, depth + 1, line_no);
  347.         --if_else;
  348.         } else if (find_else == if_else || if_else == 1) {
  349.         find_else = 0;
  350.         parsing = !parsing;
  351.         if (!parsing)
  352.             find_endif = if_else;
  353.         }
  354.         goto bad;
  355.     } else if (!strcmp(newargv[0], "if")) {
  356.         /* if statements are of the form:
  357.          *     if expr
  358.          *     if !expr  or  if ! expr
  359.          *     if expr == expr   or   if expr != expr
  360.          */
  361.         int equals = TRUE, pattern = FALSE;
  362.         register char *lhs = newargv[1], *rhs = NULL;
  363.  
  364.         if_else++;
  365.         /* If parsing, set parsing to 0 until
  366.          *  evaluating the "if" proves otherwise.
  367.          * If not parsing, skip to the "endif".
  368.          */
  369.         if (parsing)
  370.         parsing = 0;
  371.         else {
  372.         if (!find_endif)
  373.             find_endif = if_else;
  374.         goto bad;
  375.         }
  376.         if (!lhs || !*lhs) {
  377.         print("%s: line %d: if what?\n", file, *line_no);
  378.         goto bad;
  379.         }
  380.         /* "lhs" is the left hand side of the equation
  381.          * In this instance, we're doing case 2 above (check for negation).
  382.          */
  383.         if (*lhs == '!') {
  384.         if (!*++lhs && !(lhs = newargv[2])) {
  385.             print("%s: line %d: syntax error: \"if ! <what?>\"\n",
  386.             file, *line_no);
  387.             goto bad;
  388.         }
  389.         equals = FALSE;
  390.         }
  391.         if (*lhs == '-' && (lhs[1] == 'e' || lhs[1] == 'z') && !lhs[2]) {
  392.         char *path;
  393.         int n = 1; /* ignore ENOENT, I'll handle it here */
  394.         struct stat statb;
  395.  
  396.         /* check for existence or zero-length folders/files */
  397.         if (argc > 3 + (!equals)) {
  398.             print("%s: line %d: if %s \"filename\"\n",
  399.             file, *line_no, lhs);
  400.             goto bad;
  401.         }
  402.         path = getpath(newargv[argc-1], &n);
  403.         parsing = !equals ^ (n == -1 || n == 1 && lhs[1] == 'e' ||
  404.             !stat(path, &statb) && (lhs[1] == 'e' || !statb.st_size));
  405.         } else {
  406.         if (equals && argc > 2) {
  407.             if (argc != 4) {
  408.             print("%s: %d: argument count error: %d args.\n",
  409.                 file, *line_no, argc);
  410.             goto bad;
  411.             }
  412.             /* now check newargv[2] for == or != or =~ or !~ */
  413.             if (!strcmp(newargv[2], "!=") ||
  414.                 (pattern = !strcmp(newargv[2], "!~")))
  415.             equals = !equals;
  416.             else if (!strcmp(newargv[2], "=~"))
  417.             pattern = TRUE;
  418.             else if (strcmp(newargv[2], "==")) {
  419.             print("%s: %d: use `==' or `!=' only.\n",
  420.                 file, *line_no);
  421.             goto bad;
  422.             }
  423.             rhs = newargv[3];
  424.         }
  425.         if (rhs) {
  426.             /* Some fun tricks with booleans here.
  427.              * Extra ! ops make sure all == are on 0 or 1;
  428.              * aside from that, we want (glob == equals)
  429.              * or (!strcmp == equals).  Make sense?  
  430.              */
  431.             if (pattern && !glob(lhs,rhs) == !equals)
  432.             parsing = 1;
  433.             else if (!pattern && !strcmp(lhs, rhs) == !!equals)
  434.             parsing = 1;
  435.         } else if (isdigit(*lhs))
  436.             parsing = !!(atoi(lhs) ? equals : !equals);
  437.         else if (!strcmp(lhs, "redirect") && (!isatty(0) != !equals)
  438.               /* (ison(glob_flags, REDIRECT) && equals ||
  439.                isoff(glob_flags, REDIRECT) && !equals) */
  440.             || !strcmp(lhs, "is_shell") && (!is_shell == !equals)
  441.             || !strcmp(lhs, "is_sending") &&
  442.               (ison(glob_flags, IS_SENDING) && equals ||
  443.                isoff(glob_flags, IS_SENDING) && !equals)
  444.             || !strcmp(lhs, "hdrs_only") &&
  445.               (hdrs_only && equals || !hdrs_only && !equals)
  446.             || !strcmp(lhs, "istool") &&
  447.               (istool && equals || !istool && !equals)
  448.             || !strcmp(lhs, "iscurses") &&
  449.               ((iscurses || ison(glob_flags, PRE_CURSES)) && equals
  450.               || (isoff(glob_flags, PRE_CURSES) &&
  451.                   !iscurses && !equals)))
  452.             parsing = 1;
  453.         }
  454.         if (parsing) {
  455.         parsing = src_parse(file, fp, 1, depth + 1, line_no);
  456.         --if_else;
  457.         }
  458.         else
  459.         find_else = if_else; /* Look for a matching else */
  460. bad:
  461.         free_vec(newargv);
  462.         continue;
  463.     }
  464.     if (parsing && argc > 0)
  465.         if (!strcmp(newargv[0], "exit")) {
  466.         if_else = find_else = find_endif = 0;
  467.         exited = 1;
  468.         break;
  469.         } else {
  470.         (void) do_command(argc, newargv, msg_list);
  471.         exited = 0;
  472.         }
  473.     else
  474.         free_vec(newargv);
  475.     }
  476.     if (if_else && !exited)
  477.     print("%s: missing endif\n", file);
  478.     if (depth == 0)
  479.     (void) fclose(fp);
  480.     else
  481.     (void) fseek(fp, 0L, 2); /* Skip ahead to the end */
  482.     return 0;
  483. }
  484.