home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / yapp / part04 / driver.c next >
C/C++ Source or Header  |  1994-05-29  |  25KB  |  766 lines

  1. /* DRIVER.C */
  2. static    char sccsid[] = "@(#)driver.c 1.2 94/01/20 (c)1993 thalerd";
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <ctype.h>
  7. #ifndef NeXT
  8. #include <unistd.h>
  9. #endif
  10. #include <sys/types.h>
  11. #include <sys/file.h>
  12. #include <sys/stat.h>
  13. #include <signal.h>
  14. #include <pwd.h>
  15. #include "config.h"
  16. #include "struct.h"
  17. #include "driver.h"
  18. #include "xalloc.h"
  19. #include "lib.h"
  20. #include "macro.h"
  21. #include "joq.h"
  22. #include "rfp.h"
  23. #include "change.h"
  24. #include "item.h" /* needed by sep.h */
  25. #include "sep.h"
  26. #include "help.h"
  27. #include "conf.h"
  28. #include "system.h"
  29. #include "files.h"
  30. #include "sum.h"   /* for refresh_list */
  31. #include "edbuf.h" /* for text_cmd_dispatch */
  32. #include "misc.h"  /* for misc_cmd_dispatch */
  33.  
  34. /* GLOBAL VARS */
  35.  
  36. /* Status info */
  37. flag_t         flags =0;            /* user settable parameter flags */
  38. unsigned char  mode  =M_OK;         /* input mode (which prompt)     */
  39. flag_t         status=0;            /* system status flags           */
  40.  
  41. /* Conference info */
  42. short   current = -1;              /* current index to cflist       */
  43. short   confidx = -1;              /* current index to conflist     */
  44. short   defidx  = -1;
  45. short   joinidx = -1;              /* current index to conflist     */
  46. char    confname[MAX_LINE_LENGTH]; /* name of current conference    */
  47. char  **cflist = (char **)0;       /* User's conflist               */
  48. char  **fw;                        /* List of FW's for current conf */
  49. partentry_t part[MAX_ITEMS];       /* User participation info       */
  50.  
  51. /* System info */
  52. char    bbsdir[MAX_LINE_LENGTH];   /* Directory for bbs files       */
  53. char    helpdir[MAX_LINE_LENGTH];  /* Directory for help files      */
  54. assoc_t conflist[MAX_LIST_LENGTH]; /* System table of conferences   */
  55. short   maxconf=0;                 /* maximum index to conflist     */
  56. char    hostname[MAX_LINE_LENGTH]; /* System host name */
  57.  
  58. /* Info on the user */
  59. uid_t   uid;                       /* User's UID                    */
  60. char    login[L_cuserid];          /* User's login                  */
  61. char    home[MAX_LINE_LENGTH];     /* User's home directory         */
  62. char    work[MAX_LINE_LENGTH];     /* User's work directory         */
  63.  
  64. /* Item statistics */
  65. status_t   st_glob;                /* statistics on current conference */
  66. status_t   st_new;                 /* statistics on new conference to join */
  67. sumentry_t sum[MAX_ITEMS];         /* items in current conference      */
  68. response_t re[MAX_RESPONSES];      /* responses to current item        */
  69.  
  70. /* Variables global to this module only */
  71. static char cmdbuf[MAX_LINE_LENGTH];
  72.        char pipebuf[MAX_LINE_LENGTH];
  73.        char evalbuf[MAX_LINE_LENGTH];
  74. static char *options="dulosnj:";    /* Command-line options          */
  75. option_t option[]={                /* User-definable flags          */
  76. /*  name,       mask,        default, */
  77.    "debug",     O_DEBUG,     DEFAULT_OFF,
  78.    "buffer",    O_BUFFER,    DEFAULT_ON,
  79.    "default",   O_DEFAULT,   DEFAULT_ON,
  80.    "observe",   O_OBSERVE,   DEFAULT_OFF,
  81.    "st_rip",    O_STRIP,     DEFAULT_OFF,
  82.    "so_urce",   O_SOURCE,    DEFAULT_ON,
  83.    "f_orget",   O_FORGET,    DEFAULT_ON,
  84.    "sta_y",     O_STAY,      DEFAULT_OFF,
  85.    "dot",       O_DOT,       DEFAULT_ON,
  86.    "ed_always", O_EDALWAYS,  DEFAULT_OFF,
  87.    "me_too",    O_METOO,     DEFAULT_ON,
  88.    "nu_mbered", O_NUMBERED,  DEFAULT_OFF,
  89.    "d_ate",     O_DATE,      DEFAULT_OFF,
  90.    "u_id",      O_UID,       DEFAULT_OFF,
  91.    "ma_iltext", O_MAILTEXT,  DEFAULT_OFF,
  92.    "autosave",  O_AUTOSAVE,  DEFAULT_OFF,
  93.    "verbose",   O_VERBOSE,   DEFAULT_OFF,
  94.    "scr_ibbler",O_SCRIBBLER, DEFAULT_OFF,
  95.    "sig_niture",O_SIGNITURE, DEFAULT_OFF,
  96.    "readonly",  O_READONLY,  DEFAULT_OFF
  97. };
  98.  
  99. void
  100. open_pipe()
  101. {
  102.    char *pager,*p;
  103.  
  104.    /* Need to check if pager exists */
  105.    if (!(status & S_REDIRECT)) {
  106.       if (!pipebuf[0]) strcpy(pipebuf,expand("pager",DM_VAR));
  107.  
  108.       /* Compress it a bit */
  109.       pager=pipebuf;
  110.       while (*pager && *pager==' ') pager++; /* skip leading/trailing spaces */
  111.       for (p=pager+strlen(pager)-1; *p==' ' && p>=pager; p--) *p='\0'; 
  112.       if (*pager=='"') {
  113.          pager++;
  114.          if (p>=pager && *p=='"') { *p='\0'; p--; }
  115.       }
  116.       if (*pager=='\'') {
  117.          pager++;
  118.          if (p>=pager && *p=='\'') { *p='\0'; p--; }
  119.       }
  120.  
  121.       if (!(flags & O_BUFFER) 
  122.        || (pager[0] && (st_glob.outp =spopen(pager))==NULL))
  123.          pager[0]='\0';
  124.       if (!pager[0]) 
  125.          st_glob.outp =stdout;
  126.    }
  127. }
  128.  
  129. /******************************************************************************/
  130. /* PRINT PROMPT FOR AN INPUT MODE                                             */
  131. /******************************************************************************/
  132. void               /* RETURNS: (nothing) */
  133. print_prompt(mod)  /* ARGUMENTS:         */
  134. unsigned char mod; /*    Input mode      */
  135.    char *str;
  136.  
  137.    switch(mod & M_MASK) {
  138.    case M_OK :  /* In a conference or not? */
  139.                 str = (confidx<0) ? "noconfp" : "prompt";
  140.                 break;
  141.    case M_RFP:  str = (st_glob.c_status & (CS_OBSERVER|CS_NORESPONSE))?
  142.                  "obvprompt":"rfpprompt";
  143.                 break;
  144.    case M_TEXT: str="text";      break;
  145.    case M_JOQ:  str="joqprompt"; break;
  146.    case M_EDB:  str="edbprompt"; break;
  147.    }
  148.    if (flags & O_DEBUG) printf("!%s!\n",str);
  149.    confsep(str,confidx,&st_glob,part,1); /* expand seps & print */
  150. }
  151.  
  152. /******************************************************************************/
  153. /* COMMAND LOOP: PRINT PROMPT & GET RESPONSE                                  */
  154. /******************************************************************************/
  155. char             /* RETURNS: 0 on eof, 1 else   */
  156. get_command(def) /* ARGUMENTS:                  */
  157. char *def;       /*    Default command (if any) */
  158. {
  159.    char ok=1,inbuff[MAX_LINE_LENGTH],*inb;
  160.  
  161.    if (status & S_INT) status &= ~S_INT; /* Clear interrupt */
  162.    if (status & S_REDIRECT) spclose(st_glob.outp );
  163.    if (cmdbuf[0]) strcpy(inbuff,cmdbuf);
  164.    else {
  165.       print_prompt(mode);
  166.       if (mode==M_OK) status &= ~S_STOP;
  167.    }
  168.    if (cmdbuf[0] || (ok = (ngets(inbuff,st_glob.inp)!=NULL))) {
  169.  
  170.       /* Strip leading & trailing spaces */
  171.       for (inb=inbuff+strlen(inbuff)-1; inb>=inbuff && *inb==' '; inb--) *inb=0;
  172.       for (inb=inbuff; *inb==' '; inb++);
  173.  
  174.       if (!*inb) ok = command(def,0);
  175.       else       ok = command(inb,0);
  176.    }
  177.    return ok;
  178. }
  179.  
  180. /******************************************************************************/
  181. /* CLEAN UP MEMORY AND EXIT                                                   */
  182. /******************************************************************************/
  183. void        /* RETURNS: (nothing) */
  184. endbbs(ret) /* ARGUMENTS:         */
  185. int ret;    /*    Exit status     */
  186. {
  187.    int i;
  188.  
  189.    if (flags & O_DEBUG) printf("endbbs:\n");
  190.    if (confidx>=0) leave(0,(char**)0); /* leave current conference */
  191.  
  192.    /* Free up space, etc */
  193.    for (i=0; i<maxconf; i++) {
  194.       xfree(conflist[i].name);
  195.       xfree(conflist[i].location);
  196.    }
  197.    for (i=0; i<MAX_RESPONSES; i++) {
  198.       if (re[i].login)    { xfree(re[i].login);    re[i].login   =0; }
  199.       if (re[i].fullname) { xfree(re[i].fullname); re[i].fullname=0; }
  200. #ifdef NEWS
  201.       if (re[i].mid)      { xfree(re[i].mid);      re[i].mid     =0; }
  202. #endif
  203.    }
  204.     clear_cache();   /* throw out stat cache */
  205.    undefine(~0);    /* undefine all macros */
  206.    xfree(cflist);
  207.    mcheck();        /* verify that files are closed */
  208.    xcheck();        /* verify that memory is clean */
  209.    (void)exit(ret);
  210. }
  211.  
  212. void
  213. open_cluster(bdir,hdir)
  214. char *bdir, /*   BBSDIR  */
  215.      *hdir; /*   HELPDIR */
  216. {
  217.    short i;
  218.  
  219.    /* Free up space, etc */
  220.    for (i=0; i<maxconf; i++) {
  221.       xfree(conflist[i].name);
  222.       xfree(conflist[i].location);
  223.    }
  224.  
  225.    /* Read in /usr/bbs/conflist */
  226.    strcpy(bbsdir,bdir);
  227.    strcpy(helpdir,hdir);
  228.    if (!grab_list(bbsdir,"conflist",conflist,&maxconf)) 
  229.       endbbs(2);
  230.    for (i=1; i<maxconf; i++)
  231.       if (!strcmp(conflist[0].location,conflist[i].location)
  232.        ||   match(conflist[0].location,conflist[i].name)) defidx=i;
  233.    if (defidx<0) printf("Warning: bad default conference\n");
  234.  
  235.    /* Source system rc file */
  236.    mode = M_SUPERSANE;
  237.    source(bbsdir,"rc");
  238.    mode = M_OK;
  239. }
  240.  
  241. /******************************************************************************/
  242. /* PROCESS COMMAND LINE ARGUMENTS                                             */
  243. /******************************************************************************
  244. Function:    init
  245. Called by:   main
  246. Arguments:   
  247. Returns:    
  248. Calls:       source for .cfonce and system rc
  249.              grab_file to get .cflist and conflist
  250. Description: Sets up global variables, i.e. uid, login, envars,
  251.              workdir, processes rc file for system and for user
  252. ******************************************************************************/
  253. void            /* RETURNS: (nothing)                  */
  254. init(argc,argv) /* ARGUMENTS:                          */
  255. int    argc;    /*    Number of command-line arguments */
  256. char **argv;    /*    Command-line argument list       */
  257. {
  258.    short c,o,i;
  259.    struct passwd *pwd;
  260.    extern char *optarg;
  261.    extern int optind,opterr;
  262.    char **namestr,buff[MAX_LINE_LENGTH];
  263.    char mbox[MAX_LINE_LENGTH],*mail;
  264.    struct sigvec vec;
  265.  
  266.    /* Print identification */
  267.  
  268.    /* Start up interrupt handling *
  269.    for (c=1; c<=32; c++)
  270.       signal(c, handle_other);
  271.     * */
  272.    signal(SIGINT,  handle_int);
  273.    signal(SIGPIPE, handle_pipe);
  274.    /* *
  275.    signal(SIGINT,  handle_other);
  276.    signal(SIGPIPE, handle_other);
  277.     * */
  278.    sigvec(SIGINT,  NULL, &vec);
  279.    vec.sv_flags &= ~SV_INTERRUPT;
  280.    sigvec(SIGINT,  &vec, NULL);
  281.  
  282.    /* Initialize options */
  283.    for (o=0; o<sizeof(option)/sizeof(option_t); o++)
  284.       flags |= option[o].deflt * option[o].mask;
  285.  
  286.    /* Set up user variables */
  287.    cmdbuf[0] = pipebuf[0] = evalbuf[0] = '\0';
  288.    st_glob.c_status = 0;
  289. #ifdef NEWS
  290.     st_glob.c_article = 0;
  291. #endif
  292.    st_glob.inp = stdin;
  293.    uid = getuid();
  294.    if (!(pwd = getpwuid(uid))) {
  295.       error("reading ","user entry");
  296.       endbbs(2);
  297.    }
  298.    strcpy(login,   pwd->pw_name);
  299.    strcpy(st_glob.fullname,pwd->pw_gecos);
  300.    strcpy(home,    pwd->pw_dir);
  301.    if (access(home,X_OK)) {
  302.       error("accessing ",home);
  303.       endbbs(2);
  304.    }
  305.    sprintf(work,"%s/.cfdir",home);
  306.    if (access(work,X_OK)) strcpy(work,home);
  307.    strcpy(buff,work);
  308.    if (gethostname(hostname,MAX_LINE_LENGTH))
  309.       error("getting host name",NULL);
  310.  
  311.    /* Process command line options here */
  312.    if (!uid || uid==geteuid()) {
  313.       printf("login %s -- invoking bbs -%s\n",login,(uid)?"n":"no");
  314.       flags &= ~(O_SOURCE); /* for security */
  315.       if (!uid) 
  316.             flags |= O_OBSERVE|O_READONLY; 
  317.    }
  318.    confname[0]=0;
  319.    while ((c = getopt(argc, argv, options)) != -1) {
  320.       o = strchr(options,c)-options;
  321.       if (o>=0 && o<6) flags ^= (1<<o);
  322.       else if (c=='j') strcpy(confname,optarg);
  323.         if (c=='o')
  324.             flags ^= O_READONLY;  /* -o does observer AND readonly */
  325.    }
  326.    if (optind < argc) strcpy(confname,argv[argc-1]);
  327.  
  328.    /* Read in WORK/.cflist */
  329.    st_glob.listtime = 0;
  330.    refresh_list();
  331.    
  332.    for (i=0; i<MAX_RESPONSES; i++) {
  333.       re[i].fullname = re[i].login = NULL;
  334. #ifdef NEWS
  335.         re[i].mid = NULL;
  336.       re[i].article = 0;
  337. #endif
  338.    }
  339.  
  340.    /* Set up user customizations */
  341.    def_macro("today",DM_PARAM,"+0");
  342.    mail = getenv("MAIL");
  343.    if (!mail) {
  344.       sprintf(mbox,"%s/%s",MAILDIR,login);
  345.       mail = mbox;
  346.    }
  347.    def_macro("mailbox",DM_VAR,mail);
  348.    mail = getenv("SHELL");
  349.    if (mail) def_macro("shell",DM_VAR|DM_ENVAR,mail);
  350.    mail = getenv("EDITOR");
  351.    if (mail) def_macro("editor",DM_VAR|DM_ENVAR,mail);
  352.    mail = getenv("MESG");
  353.    if (mail) def_macro("mesg",DM_VAR|DM_ENVAR,mail);
  354.  
  355.    /* Read in /usr/bbs/conflist */
  356.    for (i=0; i<MAX_LIST_LENGTH; i++)
  357.       conflist[i].name = conflist[i].location = 0;
  358.    open_cluster(BBSDIR,HELPDIR);
  359.  
  360.    if (strcmp(work,buff)) { /* for cfdir command */
  361.       strcpy(buff,work);
  362.       refresh_list();
  363.    }
  364.  
  365.    /* Execute user's cfonce file */
  366.    source(work,".cfonce");
  367.    if (strcmp(work,buff))
  368.       source(work,".cfonce");
  369.  
  370.    /* Reset name */
  371.    namestr=explode(pwd->pw_gecos,expand("gecos",DM_VAR));
  372.    strcpy(st_glob.fullname,(xsizeof(namestr)>0)? namestr[0] : "Unknown");
  373.    xfree(namestr);
  374.  
  375.    /* Join initial conference */
  376.    if (flags & O_DEBUG)
  377.       printf("Default: %hd %s\n",defidx,conflist[defidx].name);
  378.    if (!(flags & O_DEFAULT) || defidx<0) {
  379.       current = -1;
  380.       st_glob.i_current = 0; /* No current item */
  381.    } else if (confname[0])
  382.       join(confname, 0);
  383.    else if (cflist && xsizeof(cflist))
  384.       join(cflist[current=0], 2); /* force join */
  385.    else {
  386.       join(compress(conflist[defidx].name), 2); /* force join */
  387.    }
  388. }
  389.  
  390. /******************************************************************************/
  391. /* PROCESS COMMAND LINE ARGUMENTS                                             */
  392. /******************************************************************************
  393. Function:    char source(char *dir, char *filename)
  394. Called by:   init
  395. Arguments:   File to source
  396. Returns:     
  397. Calls:       command for each statement
  398. Description: Executes commands in a file, does NOT grab_file since it
  399.              only needs 1-time sequential access.
  400. *******************************************************************************/
  401. char                 /* RETURNS: 0 on error, 1 else         */
  402. source(dir,filename) /* ARGUMENTS:                          */
  403. char *dir;           /*    Directory containing file        */
  404. char *filename;      /*    Filename of commands to execute  */
  405. {
  406.    FILE *fp;
  407.    char buff[MAX_LINE_LENGTH];
  408.  
  409.    if (filename)
  410.       sprintf(buff,"%s/%s",dir,filename);
  411.    else
  412.       strcpy(buff,dir);
  413.    if (flags & O_DEBUG) printf("source: %s\n",buff);
  414.    if ((fp=mopen(buff,O_R|O_SILENT))==NULL) return 0;
  415.    if (st_glob.inp != stdin) 
  416.       mclose(st_glob.inp);
  417.    st_glob.inp = stdin;
  418.    while (ngets(buff, fp)) {
  419.       if ((flags & O_VERBOSE) && mode==M_SANE)
  420.          printf("command: %s\n",buff);
  421.       st_glob.inp = fp;
  422.       command(buff,0);
  423.       st_glob.inp = stdin;
  424.    }
  425.    mclose(fp);
  426.    return 1;
  427. }
  428.             
  429. /******************************************************************************/
  430. /* PROCESS COMMAND LINE ARGUMENTS                                             */
  431. /******************************************************************************
  432. Function:    char command(char *command)
  433. Called by:   main
  434. Arguments:   command to process
  435. Returns:     0 if done, 1 else
  436. Calls:       join() for "join", "next" commands
  437.              leave() for "next", "quit" commands
  438. Description: For all command modes, this processes a user command.
  439.              Interrupts go back to here, without changing command mode.
  440. *******************************************************************************/
  441. char              /* RETURNS: Done flag                  */
  442. command(str,lvl)  /* ARGUMENTS:                          */
  443. char *str;        /*    Command to execute               */
  444. int   lvl;        /*    Recursion depth                  */
  445. {
  446.    int argc=0;    /*    Number of arguments */
  447.    unsigned short i;
  448.    char *argv[MAX_ARGS],cmddel,bufdel;
  449.    char *Sptr,*Eptr,state=1,ok;
  450.    char cmd[MAX_LINE_LENGTH],*cmd2;
  451.  
  452.    if (!str || !*str) return 1;
  453.    if (flags & O_DEBUG) printf("command: %s\n",str);
  454.    if (lvl > CMD_DEPTH) {
  455.       printf("UNK Too many expansions.\n");
  456.       return 0;
  457.    }
  458.  
  459.    /* Process shell escape */
  460.    if (str[0]=='!') {
  461. /* Undone at request of sno and jep
  462.       if (mode==M_SANE)
  463.          printf("Conference rc cannot exec: %s\n",str);
  464.       else {
  465. */
  466.          unix_cmd(str+1);
  467.          printf("!\n");
  468. /*    } */
  469.       return 1;
  470.  
  471.    /* And comments */
  472.    } else if (str[0]=='#') return 1;
  473.  
  474.    cmddel = expand("cmddel",DM_VAR)[0];
  475.    bufdel = expand("bufdel",DM_VAR)[0];
  476.  
  477.    /* Get arguments using a state machine for lexical analysis */
  478.    Sptr=str;
  479.    pipebuf[0]=cmdbuf[0]='\0';
  480.    while (state && argc<MAX_ARGS) {
  481.       switch(state) {
  482.       case 1: /* between words */
  483.               while (isspace(*Sptr)) Sptr++;
  484.               if      (*Sptr==cmddel)  { Sptr++;    state=0; }
  485.               else if (*Sptr==bufdel)  { Eptr= ++Sptr; state=6; }
  486.               else if (*Sptr=='|')  { Eptr= ++Sptr; state=7; }
  487.               else if (*Sptr=='>')  { Eptr=Sptr; state=9; }
  488.               else if (*Sptr=='\'') { Eptr= ++Sptr; state=4; }
  489.               else if (*Sptr=='`')  { Eptr= ++Sptr; state=8; }
  490. /*            else if (*Sptr=='\"') { Eptr= ++Sptr; state=3; } */
  491.               else if (*Sptr=='\"') { Eptr=Sptr; state=3; }
  492.               else if (*Sptr=='\\') { Eptr=Sptr; state=5; }
  493.               else if (*Sptr)       { Eptr=Sptr; state=2; }
  494.               else       state=0;
  495.               break;
  496.  
  497.       case 2: /* normal word */
  498.               while (*Eptr && !isspace(*Eptr)
  499.                && *Eptr!=cmddel && *Eptr!=bufdel 
  500.                && !strchr("|`'>\\\"",*Eptr)
  501.                && !(Eptr>Sptr && *(Eptr-1)=='=') /* '=' terminates word */
  502.                && (argc || *Sptr=='-' || isdigit(*Sptr) || !isdigit(*Eptr)))
  503.                  Eptr++;
  504.  
  505.               argv[argc]=(char*)xalloc(0,Eptr-Sptr+1);
  506.               strncpy(argv[argc],Sptr,Eptr-Sptr);
  507.               argv[argc++][Eptr-Sptr]=0;
  508.               Sptr = Eptr;
  509.  
  510.               if (argc==1) {
  511.                  cmd2=(char *)expand(argv[0],((mode & M_MASK)==M_RFP)? DM_RFP : DM_OK);
  512.                  if (cmd2) {
  513.                     sprintf(cmd,"%s%s",cmd2,Eptr);
  514.                     xfree(argv[argc=0]);
  515.                     Sptr = cmd;
  516.                  }
  517.               }
  518.  
  519.               state=1;
  520.               break;
  521.  
  522.       case 3: /* "stuff" */
  523.               do { 
  524.                  Eptr++; 
  525.               } while (*Eptr && (*Eptr!='\"' || *(Eptr-1)=='\\'));
  526. /*            argv[argc]=xalloc(0,Eptr-Sptr+1); */
  527.               argv[argc]=(char*)xalloc(0,Eptr-Sptr+2);
  528. /*            strncpy(argv[argc],Sptr,Eptr-Sptr); */
  529.               strncpy(argv[argc],Sptr,Eptr-Sptr+1);
  530. /*            argv[argc++][Eptr-Sptr]=0; */
  531.               argv[argc++][Eptr-Sptr+1]=0;
  532.  
  533.               if (*Eptr) Eptr++;
  534.               Sptr = Eptr;
  535.               state=1;
  536.               break;
  537.  
  538.       case 4: /* 'stuff' */
  539.               do { Eptr++; } while (*Eptr && *Eptr!='\'');
  540.               argv[argc]=(char*)xalloc(0,Eptr-Sptr+1);
  541.               strncpy(argv[argc],Sptr,Eptr-Sptr);
  542.               argv[argc++][Eptr-Sptr]=0;
  543.  
  544.               if (*Eptr) Eptr++;
  545.               Sptr = Eptr;
  546.               state=1;
  547.               break;
  548.  
  549.       case 5: /* \\ */
  550.               argv[argc]=(char*)xalloc(0,2);
  551.               strcpy(argv[argc++],"\\");
  552.               Sptr = Eptr+1;
  553.               state=1;
  554.               break;
  555.  
  556.       case 6: /* ,stuff */
  557.               do { Eptr++; } while (*Eptr && *Eptr!=cmddel);
  558.               strncpy(cmdbuf,Sptr,Eptr-Sptr);
  559.               cmdbuf[Eptr-Sptr]=0;
  560.               Sptr = Eptr;
  561.               state=1;
  562.               break;
  563.  
  564.       case 7: /* | stuff */
  565.               do { Eptr++; } while (*Eptr && *Eptr!=cmddel && *Eptr!=bufdel);
  566.               strncpy(pipebuf,Sptr,Eptr-Sptr);
  567.               pipebuf[Eptr-Sptr]=0;
  568.               Sptr = Eptr;
  569.               state=1;
  570.               break;
  571.  
  572.       case 8: /* `command` */
  573.               do { Eptr++; } while (*Eptr && *Eptr!='`');
  574.               strncpy(cmd,Sptr,Eptr-Sptr);
  575.               cmd[Eptr-Sptr]=0;
  576.  
  577.               status |=  S_EXECUTE;
  578.               evalbuf[0] = '\0';
  579.               command(cmd,lvl+1);
  580.               status &= ~S_EXECUTE;
  581.               argv[argc]=(char*)xalloc(0,strlen(evalbuf)+1);
  582.               strcpy(argv[argc++],evalbuf);
  583.  
  584.               if (*Eptr) Eptr++;
  585.               Sptr = Eptr;
  586.               state=1;
  587.               break;
  588.  
  589.       case 9: /* > file */
  590.               do { Eptr++; } while (*Eptr=='>');
  591.               do { Eptr++; } while (isspace(*Eptr));
  592.               do { 
  593.                  Eptr++; 
  594.               } while (*Eptr && *Eptr!=cmddel && *Eptr!=bufdel && *Eptr!=' ');
  595.               strcpy(pipebuf,"cat ");
  596.               strncat(pipebuf,Sptr,Eptr-Sptr);
  597.               pipebuf[4+Eptr-Sptr]=0;
  598.               Sptr = Eptr;
  599.               state=1;
  600.               break;
  601.       }
  602.    }
  603. /*
  604.    if (*Sptr) strcpy(cmdbuf,Sptr);
  605.    else       cmdbuf[0]='\0';
  606. */
  607.    if (argc) {
  608.    
  609.       /* Expand macros */
  610. #if 0
  611. /*
  612.       cmd2=(char *)expand(argv[0],((mode & M_MASK)==M_RFP)? DM_RFP : DM_OK);
  613. */
  614.       cmd2=0;
  615.       if (cmd2) {
  616.          xfree(argv[0]);
  617.          strcpy(cmd,cmd2);
  618. /* implode(cmd+strlen(cmd),argv," ",1); argv isn't malloc'ed */
  619.          for (i=1; i<argc; i++) {
  620.             strcat(cmd," ");
  621.             strcat(cmd,argv[i]);
  622.             xfree(argv[i]);
  623.          }
  624.          ok = command(cmd,lvl+1);
  625.       } else 
  626. #endif
  627.       {
  628.       
  629.          /* Execute command */
  630.          switch(mode & M_MASK) {
  631.          case M_OK:   ok=  ok_cmd_dispatch(argc,argv); break;
  632.          case M_JOQ:  ok= joq_cmd_dispatch(argc,argv); break;
  633.          case M_TEXT: ok=text_cmd_dispatch(argc,argv); break;
  634.          case M_RFP:  ok= rfp_cmd_dispatch(argc,argv); break;
  635.          case M_EDB:  ok= edb_cmd_dispatch(argc,argv); break;
  636.          default: printf("Unknown mode %d\n",mode); break;
  637.          }
  638.    
  639.          /* Free args */
  640.          for (i=0; i<argc; i++) xfree(argv[i]);
  641.       }
  642.    } else
  643.       ok=1; /* don't abort on null command */
  644.  
  645.    /* Do next ; cmd unless EOF or command says to halt (ok==2) */
  646.    if (ok==1 && *Sptr && !(status & S_STOP)) {
  647.       ok=command(Sptr,lvl+1); 
  648.    } 
  649. /* else if (*Sptr) status &= ~S_STOP; */
  650.    return ok;
  651. }
  652.  
  653. /* Commands available at the Ok: prompt only */
  654. static dispatch_t ok_cmd[]={
  655.    "i_tem",     do_read,
  656.    "r_ead",     do_read,
  657.    "pr_int",    do_read,
  658.    "e_nter",    enter,
  659.    "s_can",     do_read,
  660.    "b_rowse",   do_read,
  661.    /* j_oin */
  662.    "le_ave",    leave,
  663.    "n_ext",     do_next,
  664.    "che_ck",    check,
  665.    "rem_ember", remember,
  666.    "forget",    forget,
  667.    "unfor_get", remember,
  668.    "k_ill",     do_kill,
  669.    "freeze",    freeze,
  670.    "thaw",      freeze,
  671.    /* sync_hronous */
  672.    /* async_hronous */
  673.    "retire",    freeze,
  674.    "unretire",  freeze,
  675.    "f_ind",     do_find,
  676.    "l_ocate",   do_find,
  677.    "seen",      fixseen,
  678.    "fix_seen",  fixseen,
  679.    "re_spond",  respond,
  680.    /* lpr_int */
  681.    "li_nkfrom", linkfrom,
  682.    "abort",     leave,
  683. /* ex_it q_uit st_op good_bye log_off log_out h_elp exp_lain sy_stem unix al_ias
  684.  * def_ine una_lias und_efine ec_ho echoe echon echoen echone so_urce m_ail 
  685.  * t_ransmit sen_dmail chat write d_isplay que_ry */
  686.    "p_articipants", participants,
  687. /* w_hoison am_superuser */
  688.    "resign",    resign,
  689. /* chd_ir uma_sk sh_ell f_iles dir_ectory ty_pe e_dit cdate da_te t_est 
  690.  * clu_ster 
  691.  */
  692.    "ps_eudonym",respond,
  693.    "list",      check,
  694.    0, 0
  695. };
  696.  
  697. /******************************************************************************/
  698. /* DISPATCH CONTROL TO APPROPRIATE MISC. COMMAND FUNCTION                     */
  699. /******************************************************************************/
  700. char                       /* RETURNS: 0 to quit, 1 else */
  701. ok_cmd_dispatch(argc,argv) /* ARGUMENTS:                 */
  702. int    argc;               /*    Number of arguments     */
  703. char **argv;               /*    Argument list           */
  704. {
  705.    int i;
  706.  
  707.    for (i=0; ok_cmd[i].name; i++)
  708.       if (match(argv[0],ok_cmd[i].name))
  709.          return ok_cmd[i].func(argc,argv);
  710.  
  711.    /* Command dispatch */
  712.    if (match(argv[0],"j_oin"))    {
  713.       if (argc==2) join(argv[1],0); 
  714.       else if (confidx>=0) {
  715.          confsep("joinmsg",confidx,&st_glob,part,0); 
  716.       } else 
  717.          printf("Not in a conference!\n");
  718.    } else return misc_cmd_dispatch(argc,argv);
  719.    return 1;
  720. }
  721.  
  722. /******************************************************************************/
  723. /* PROCESS A GENERIC SIGNAL (if enabled)                                      */
  724. /******************************************************************************/
  725. void 
  726. handle_other(sig, code, scp, addr)
  727. int sig, code;
  728. /* struct sigcontext */ void *scp;
  729. char *addr;
  730. {
  731.    if (status & S_PIPE) printf("%d Pipe interrupt %d!\n",getpid(),sig);
  732.    else printf("%d Interrupt %d!\n",getpid(),sig);
  733.    status |= S_INT;
  734. }
  735.  
  736. /******************************************************************************/
  737. /* PROCESS A USER INTERRUPT SIGNAL                                            */
  738. /******************************************************************************/
  739. void         /* RETURNS: (nothing) */
  740. handle_int() /* ARGUMENTS: (none)  */
  741. {
  742.    struct sigvec vec;
  743.  
  744.    if (!(status & S_PIPE)) {
  745.       printf("Interrupt!\n");
  746.       status |= S_INT;
  747.    }
  748.    signal(SIGINT,  handle_int);
  749.    sigvec(SIGINT,  NULL, &vec);
  750.    vec.sv_flags |= SV_INTERRUPT;
  751.    sigvec(SIGINT,  &vec, NULL);
  752. }
  753.  
  754. /******************************************************************************/
  755. /* PROCESS AN INTERRUPT CAUSED BY A PIPE ABORTING                             */
  756. /******************************************************************************/
  757. void          /* RETURNS: (nothing) */
  758. handle_pipe() /* ARGUMENTS: (none)  */
  759. {
  760.    printf("Pipe interrupt?\n");
  761.    /* spclose(st_glob.outp );*/
  762.    signal(SIGPIPE, handle_pipe);
  763.    status |= S_INT;
  764. }
  765.