home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / telecom / uucp_442 / src / dmail / execom.c < prev    next >
C/C++ Source or Header  |  1990-12-27  |  13KB  |  539 lines

  1.  
  2. /*
  3.  *  EXECOM.C
  4.  *
  5.  *  $Header: Beta:src/uucp/src/dmail/RCS/execom.c,v 1.1 90/02/02 12:03:41 dillon Exp Locker: dillon $
  6.  *
  7.  *  (C) Copyright 1985-1990 by Matthew Dillon,  All Rights Reserved.
  8.  *
  9.  *  Routines to parse and execute command lines.
  10.  *
  11.  *  Global Routines:    DO_COMMAND()
  12.  *            EXEC_COMMAND()
  13.  *            FIX()
  14.  *
  15.  *  Static Routines:    E_COMMAND()
  16.  *            BREAKOUT()
  17.  *            FIND_COMMAND()
  18.  */
  19.  
  20.  
  21. #include <pwd.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include "dmail.h"
  25. #include "execom.h"
  26.  
  27. #define F_EXACT     0
  28. #define F_ABBR        1
  29. #define SCRBUF        1024
  30.  
  31. extern char *breakout();
  32.  
  33. extern int do_quit(), do_exit(), do_help(), do_list(), do_setlist();
  34. extern int do_select(), do_type(), do_header(), do_next(), do_mark();
  35. extern int do_unmark(), do_reply(), do_delnext(), do_rlist();
  36. extern int do_write(), do_shell(), do_set_var(), do_unset_var();
  37. extern int do_number(), do_cd(), do_source(), do_defer(), do_echo();
  38. extern int do_go(), do_break();
  39.  
  40. extern int do_if(), do_else(), do_endif();
  41. extern int do_ver(), do_delprev();
  42.  
  43. struct COMMAND Command[] = {
  44.     do_number   , 0,    0,            "",
  45.     do_mark     , 0,    ST_DELETED,        "delete",
  46.     do_unmark   , 0,    ST_DELETED,        "undelete",
  47.     do_header   , 0,    0,            "header",
  48.     do_type     , 0,    0,            "type",
  49.     do_echo     , 0,    0,            "echo",
  50.     do_go        , 0,    0,            "go",
  51.     do_reply    , 0,    R_REPLY,        "reply",
  52.     do_reply    , 0,    R_INCLUDE,        "Reply",
  53.     do_reply    , 0,    R_MAIL,         "mail",
  54.     do_reply    , 0,    R_FORWARD,        "forward",
  55.     do_reply    , 0,    R_FWDINCL,        "Forward",
  56.     do_select   , 0,    0,            "select",
  57.     do_select   , 0,    1,            "reselect",
  58.     do_defer    , 0,    1,            "defer",
  59.     do_list     , 0,    0,            "list",
  60.     do_rlist    , 0,    0,            "rlist",
  61.     do_next     , 0,    1,            "next",
  62.     do_next     , 0,    -1,            "back",
  63.     do_next     , 0,    2,            "_next",
  64.     do_next     , 0,    -2,            "_back",
  65.     do_delnext  , 0,    0,            "dt",
  66.     do_delprev  , 0,    0,            "db",
  67.     do_set_var  , 0,    0,            "set",
  68.     do_unset_var, 0,    0,            "unset",
  69.     do_set_var  , 0,    1,            "alias",
  70.     do_unset_var, 0,    1,            "unalias",
  71.     do_set_var  , C_NO,    2,            "malias",
  72.     do_unset_var, C_NO,    2,            "munalias",
  73.     do_setlist  , 0,    0,            "setlist",
  74.     do_cd        , 0,    0,            "cd",
  75.     do_source   , 0,    0,            "source",
  76.     do_unmark   , 0,    ST_READ | ST_STORED,"preserve",
  77.     do_mark     , 0,    ST_READ,        "mark",
  78.     do_mark     , 0,    ST_TAG,         "tag",
  79.     do_unmark   , 0,    ST_TAG,         "untag",
  80.     do_unmark   , 0,    ST_STORED,        "unwrite",
  81.     do_write    , 0,    0,            "write",
  82.     do_shell    , 0,    0,            "!",
  83.     do_exit     , 0,    0,            "x",
  84.     do_quit     , 0,    0,            "quit",
  85.     do_exit     , 0,    1,            "xswitch",
  86.     do_quit     , 0,    1,            "qswitch",
  87.     do_help     , 0,    0,            "help",
  88.     do_help     , 0,    0,            "?",
  89.     do_break    , 0,    0,            "nobreak",
  90.     do_break    , 0,    1,            "breakok",
  91.     do_if        , C_COND,    0,            "if",
  92.     do_else     , C_COND,    0,            "else",
  93.     do_endif    , C_COND,    0,            "endif",
  94.     do_ver        , 0,    0,            "version",
  95.     NULL        , 0,    0,            NULL };
  96.  
  97. char *Desc[] = {
  98.     "",
  99.     "<list>                   mark messages for deletion",
  100.     "<list>                   UNDELETE & UNMARK messages",
  101.     "[msg]                    Display header of a message",
  102.     "[msg]                    type a message",
  103.     "args....                 Echo to the screen",
  104.     "#                        Go to a message, don't print out",
  105.     "                         reply to mail",
  106.     "                         reply to mail, include recv'd text",
  107.     "user user ...            send mail to users",
  108.     "user user ...            forward mail to users",
  109.     "Field [!]match [match][ , Field match.]  SELECT from entire message list",
  110.     "Field [!]match [match][ , Field match.]  SELECT from current message list",
  111.     "                         De-select any read messages",
  112.     "<list>                   list mail as specified by SETLIST",
  113.     "[+/-][N]                 list relative to current position",
  114.     "[msg]                    type/header next or message #",
  115.     "[msg]                    type/header previous or message #",
  116.     "[msg]                    go to next or message #",
  117.     "[msg]                    go to previous or message #",
  118.     "                         delete current, type next",
  119.     "                         delete current, type prev",
  120.     "[var [string]]           set a variable",
  121.     "var var var ...          unset a variable",
  122.     "[var [string]]           set an alias",
  123.     "var var var ...          unset an alias",
  124.     "[var [string]]           set a mail alias",
  125.     "var var var ...          unset a mail alias",
  126.     "[-s] [cols] Field [cols] Field...    SET LIST format for LIST",
  127.     "path                     CD to a directory",
  128.     "file                     Source a file",
  129.     "<list>                   UNREAD & UNMARK messages",
  130.     "<list>                   mark messages as 'read'",
  131.     "<list>                   tag messages for whatever",
  132.     "<list>                   untag messages",
  133.     "<list>                   unwrite messages",
  134.     "file <list>              append messages to a file, delete on quit",
  135.     "[command]                execute a shell [command]",
  136.     "                         EXIT, do not save changes",
  137.     "                         QUIT, update files",
  138.     "from to                  Exit and switch to a new from/to file",
  139.     "from to                  Quit and switch to a new from/to file",
  140.     "[topic]                  help on a topic",
  141.     "[topic]                  alternate form of HELP",
  142.     "                         Disable INTR (stackable)",
  143.     "                         Enable  INTR (stackable)",
  144.     "[!]variable              conditionals (stackable)",
  145.     "",
  146.     "",
  147.     "                         Print the version number",
  148.     NULL };
  149.  
  150.  
  151. do_command()
  152. {
  153.     static char comline[1024];
  154.  
  155.     if (Current >= 0 && Current < Entries)
  156.     printf("%3d:", Entry[Current].no);
  157.     else
  158.     printf("nul:");
  159.     fflush (stdout);
  160.     if (gets (comline) == NULL)
  161.     done (1);
  162.     exec_command(comline);
  163.     return (1);
  164. }
  165.  
  166.  
  167.  
  168. /*
  169.  * EXEC_COMMAND()
  170.  *
  171.  *
  172.  */
  173.  
  174.  
  175. struct MLIST {
  176.     struct MLIST *next;
  177. };
  178.  
  179. static struct MLIST *Mlist;
  180.  
  181. char *
  182. mpush(amount)
  183. int amount;
  184. {
  185.     struct MLIST *ml;
  186.  
  187.     push_break();
  188.     ml = (struct MLIST *)malloc (amount + sizeof(*Mlist));
  189.     ml->next = Mlist;
  190.     Mlist = ml;
  191.     pop_break();
  192.     return ((char *)Mlist + sizeof(*Mlist));
  193. }
  194.  
  195.  
  196. char *
  197. mpop()
  198. {
  199.     char *old = NULL;
  200.  
  201.     push_break();
  202.     if (Mlist == NULL) {
  203.     puts ("MLIST INTERNAL ERROR");
  204.     } else {
  205.     old = (char *)Mlist + sizeof(*Mlist);
  206.     xfree (Mlist);
  207.     Mlist = Mlist->next;
  208.     }
  209.     pop_break();
  210.     return (old);
  211. }
  212.  
  213. void
  214. mrm()
  215. {
  216.     push_break();
  217.     while (Mlist) {
  218.     xfree (Mlist);
  219.     Mlist = Mlist->next;
  220.     }
  221.     pop_break();
  222. }
  223.  
  224.  
  225. exec_command(base)
  226. char *base;
  227. {
  228.     char *str;
  229.     int i;
  230.  
  231.     if (push_base()) {
  232.     push_break();
  233.     pop_base();
  234.     mrm();
  235.     pop_break();
  236.     return (-1);
  237.     }
  238.     strcpy (str = mpush(strlen(base) + 1), base);
  239.     i = e_command(str);
  240.     if (mpop() != str)
  241.     puts ("POP ERROR");
  242.     pop_base();
  243.     return (i);
  244. }
  245.  
  246.  
  247. static
  248. e_command(base)
  249. char *base;
  250. {
  251.     char *com, *start, *avline, *alias;
  252.     int flag = 0;
  253.     int i, pcount, len, ccno;
  254.  
  255. loop:
  256.     com = breakout (&base, &flag);
  257.     if (*com == '\0') {
  258.     if (flag > 1)
  259.         return (1);
  260.     goto loop;
  261.     }
  262.     if ((ccno = find_command(com, F_EXACT)) < 0) {
  263.     if (*com == '$')
  264.         alias = get_var (LEVEL_SET, com + 1);
  265.     else
  266.         alias = get_var (LEVEL_ALIAS, com);
  267.     if (alias == NULL) {
  268.         if ((ccno = find_command (com, F_ABBR)) < 0) {
  269.         if (!XDisable)
  270.             printf ("%s Command Not found\n", com);
  271.         return (XDisable ? 1 : -1);
  272.         } else {
  273.         goto good_command;
  274.         }
  275.     }
  276.  
  277.     /* At this point, base points to arguments */
  278.  
  279.     start = (flag == 0) ? base : "";
  280.     while (flag == 0) {             /* find ';' or end of string        */
  281.         flag = -1;            /* disable breakout's "" terminator */
  282.         breakout (&base, &flag);
  283.     }
  284.  
  285.     /*
  286.      * At this point, start points to all arguments, base set up for next
  287.      * string
  288.      */
  289.  
  290.     if (*alias == '%') {
  291.         int xx = 0;
  292.         char *select;
  293.  
  294.         alias = strcpy (mpush (strlen(alias) + 1), alias);
  295.         select = breakout (&alias, &xx);
  296.         set_var (LEVEL_SET, select + 1, start);
  297.         i = e_command (alias);
  298.         unset_var (LEVEL_SET, select + 1);
  299.         mpop();
  300.     } else {
  301.         com = mpush (strlen(alias) + strlen(start) + 2);
  302.         strcpy (com, alias);
  303.         strcat (com, (flag == 1) ? ";" : " ");
  304.         strcat (com, start);
  305.         i = e_command (com);
  306.         if (mpop() != com)
  307.         puts ("ME BAE ERROR");
  308.     }
  309.     if (i < 0)
  310.         return (-1);
  311.     if (flag > 1)
  312.         return (1);
  313.     goto loop;
  314.     }
  315. good_command:
  316.     if (XDisable && (Command[ccno].stat & C_COND) == 0) {
  317.     while (flag < 1)
  318.         breakout (&base, &flag);
  319.     if (flag > 1)
  320.         return (1);
  321.     goto loop;
  322.     }
  323.     if (Command[ccno].stat & C_NO  &&  XDebug == 0) {
  324.     printf ("%s  Is currently being developed\n", Command[ccno].name);
  325.     return (-1);
  326.     }
  327.     if (XDebug)
  328.     printf ("Good command, Raw: %s\n", com);
  329.     i = pcount = 0;
  330.     av[i] = mpush (strlen(com) + 1);
  331.     ++pcount;
  332.     strcpy (av[i++], com);
  333.     while (flag < 1) {
  334.     com = breakout (&base, &flag);
  335.     if (XDebug)
  336.         printf ("BREAKOUT %d %s\n", strlen(com), com);
  337.     if (*com == '\0')
  338.         continue;
  339.     switch (*com) {
  340.     case '~':
  341.         if (com[1] == '/'  ||  com[1] == '\0') {
  342.         av[i] = mpush (strlen(home_dir) + strlen(com + 1) + 1);
  343.         ++pcount;
  344.         strcpy (av[i], home_dir);
  345.         strcat (av[i], com + 1);
  346.         } else {
  347.         struct passwd *passwd;
  348.         char *user = com;
  349.  
  350.         while (*com) {
  351.             if (*com == '/') {
  352.             *com = '\0';
  353.             ++com;
  354.             break;
  355.             }
  356.             ++com;
  357.         }
  358.         if ((passwd = getpwnam(user)) == NULL) {
  359.             printf ("USER %s Not found\n", user);
  360.             while (pcount--)
  361.             mpop();
  362.             return (-1);
  363.         }
  364.         av[i] = mpush (strlen(passwd->pw_dir) + strlen(com) + 2);
  365.         ++pcount;
  366.         strcpy (av[i], passwd->pw_dir);
  367.         if (*com) {
  368.             strcat (av[i], "/");
  369.             strcat (av[i], com);
  370.         }
  371.         }
  372.         break;
  373.     case '\"':
  374.         av[i] = com + 1;
  375.         while (*++com && *com != '\"');
  376.         *com = '\0';
  377.         break;
  378.     case '$':
  379.         if (*(com + 1) == '$') {
  380.         av[i] = getenv(com + 2);
  381.         if (av[i] == NULL) {
  382.             printf ("Env. Var %s not found\n", com + 2);
  383.             av[i] = com;
  384.         }
  385. #ifdef AMIGA
  386.         av[i] = strcpy (mpush(strlen(av[i]) + 1), av[i]);
  387.         ++pcount;
  388. #endif
  389.         }  else {
  390.         av[i] = get_var (LEVEL_SET, com + 1);
  391.         if (av[i] == NULL)
  392.             av[i] = com;
  393.         av[i] = strcpy (mpush(strlen(av[i]) + 1), av[i]);
  394.         ++pcount;
  395.         }
  396.         break;
  397.     default:
  398.         av[i] = com;
  399.         break;
  400.     }
  401.     ++i;
  402.     }
  403.     av[i] = NULL;
  404.     ac = i;
  405.     for (len = 0, i = 0; i < ac; ++i)
  406.     len += strlen (av[i]) + 1;
  407.     avline = mpush (len + 1);
  408.     *avline = '\0';
  409.     for (i = 0; i < ac; ++i) {
  410.     strcat (avline, av[i]);
  411.     if (i + 1 < ac)
  412.         strcat (avline, " ");
  413.     }
  414.     if (XDebug)
  415.     printf ("DEST: %s\n", avline);
  416.     i = (*Command[ccno].func)(avline, Command[ccno].val);
  417.     if (mpop() != avline)
  418.     puts ("AVLINE ERROR");
  419.     while (pcount--)
  420.     mpop();
  421.     fix();
  422.     if (i < 0)
  423.     return (i);
  424.     if (flag < 2)
  425.     goto loop;
  426.     return (1);
  427. }
  428.  
  429.  
  430. /*
  431.  * BREAKOUT
  432.  *
  433.  * Breakout next argument.  If FLAG is set to 1 on return, the argument
  434.  * returned is the last in the command.  If FLAG is set to 2 on return, the
  435.  * argument returned is the last, period.
  436.  *
  437.  */
  438.  
  439. static char *
  440. breakout(base, flag)
  441. int *flag;
  442. char **base;
  443. {
  444.     register char *str, *scr;
  445.  
  446. loop:
  447.     str = *base;            /* next start        */
  448.     while (*str == ' ' || *str == 9)    /* skip spaces and such */
  449.     ++str;
  450.     switch (*str) {
  451.     case '\0':                          /* no more arguments    */
  452.     *flag = 2;
  453.     *base = str;
  454.     return (str);
  455.     case ';':                           /* no more args in this command */
  456.     *flag = 1;
  457.     *str = '\0';
  458.     *base = str + 1;
  459.     return (str);
  460.     }
  461.     scr = str;
  462.     for (;;) {                          /* valid argument of somesort   */
  463.     switch (*scr) {
  464.     case ' ':
  465.     case 9:
  466.         if (*flag >= 0)
  467.         *scr = '\0';
  468.         *base = scr + 1;
  469.         *flag = 0;
  470.         return (str);
  471.     case '\"':
  472.         ++scr;
  473.         while (*scr && (*scr++ != '\"'));   /* place to end of quote */
  474.         break;
  475.     case '\0':
  476.         *flag = 2;
  477.         *base = scr;
  478.         return (str);
  479.     case ';':
  480.         *flag = 1;
  481.         *base = scr + 1;
  482.         *scr = '\0';
  483.         return (str);
  484.     default:
  485.         ++scr;
  486.     }
  487.     }
  488. }
  489.  
  490.  
  491.  
  492. fix()
  493. {
  494.     register int i;
  495.  
  496.     for (i = (Current < 0) ? 0 : Current; i < Entries; ++i) {
  497.     if (Entry[i].no  &&  !(Entry[i].status & ST_DELETED)) {
  498.         Current = i;
  499.         return (1);
  500.     }
  501.     }
  502.     if (Current >= Entries) {
  503.     Current = Entries - 1;
  504.     /* Can become -1 if no entries  */
  505.     }
  506.     for (i = Current; i >= 0; --i) {
  507.     if (Entry[i].no  &&  !(Entry[i].status & ST_DELETED)) {
  508.         Current = i;
  509.         return (-1);
  510.     }
  511.     }
  512.     Current = -1;
  513.     return (-1);
  514. }
  515.  
  516.  
  517. static
  518. find_command(str, arg)
  519. char *str;
  520. int arg;
  521. {
  522.     int i;
  523.     int len = strlen (str);
  524.  
  525.     if (*str >= '0'  &&  *str <= '9')
  526.     return (0);
  527.     for (i = 0; Command[i].func; ++i) {
  528.     if (strncmp (str, Command[i].name, len) == 0) {
  529.         if (arg == F_ABBR)
  530.         return (i);
  531.         if (strcmp (str, Command[i].name) == 0)
  532.         return (i);
  533.         return (-1);
  534.     }
  535.     }
  536.     return (-1);
  537. }
  538.  
  539.