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