home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / uucp / cntrl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  12.7 KB  |  633 lines

  1. #include "uucp.h"
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4.  
  5.  
  6. struct Proto {
  7.     char P_id;
  8.     int (*P_turnon)();
  9.     int (*P_rdmsg)();
  10.     int (*P_wrmsg)();
  11.     int (*P_rddata)();
  12.     int (*P_wrdata)();
  13.     int (*P_turnoff)();
  14. };
  15.  
  16.  
  17. extern int gturnon(), gturnoff();
  18. extern int grdmsg(), grddata();
  19. extern int gwrmsg(), gwrdata();
  20. extern int imsg();
  21. extern int omsg();
  22.  
  23. struct Proto Ptbl[]={
  24.     'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff,
  25.     '\0'
  26. };
  27.  
  28. int (*Rdmsg)()=imsg, (*Rddata)();
  29. int (*Wrmsg)()=omsg, (*Wrdata)();
  30. int (*Turnon)(), (*Turnoff)();
  31.  
  32.  
  33. #define YES "Y"
  34. #define NO "N"
  35. #define Y 'Y'
  36. #define N 'N'
  37.  
  38.  
  39. #define XUUCP 'X'    /* execute uucp (string) */
  40. #define SLTPTCL 'P'    /* select protocol  (string)  */
  41. #define USEPTCL 'U'    /* use protocol (character) */
  42. #define RCVFILE 'R'    /* receive file (string) */
  43. #define SNDFILE 'S'    /* send file (string) */
  44. #define RQSTCMPT 'C'    /* request complete (string - yes | no) */
  45. #define HUP     'H'    /* ready to hangup (string - yes | no) */
  46.  
  47.  
  48. #define W_TYPE        wrkvec[0]
  49. #define W_FILE1        wrkvec[1]
  50. #define W_FILE2        wrkvec[2]
  51. #define W_USER        wrkvec[3]
  52. #define W_OPTNS        wrkvec[4]
  53. #define W_DFILE        wrkvec[5]
  54. #define W_MODE        wrkvec[6]
  55.  
  56. #define RMESG(m, s) if (rmesg(m, s) != 0) return(FAIL);
  57. #define RAMESG(s) if (rmesg('\0', s) != 0) return(FAIL)
  58. #define WMESG(m, s) if(wmesg(m, s) != 0) return(FAIL)
  59.  
  60. char Wfile[MAXFULLNAME] = {'\0'};
  61. char Dfile[MAXFULLNAME];
  62.  
  63. /*******
  64.  *    cntrl(role, wkpre)
  65.  *    int role;
  66.  *    char *wkpre;
  67.  *
  68.  *    cntrl  -  this routine will execute the conversation
  69.  *    between the two machines after both programs are
  70.  *    running.
  71.  *
  72.  *    return codes
  73.  *        SUCCESS - ok
  74.  *        FAIL - failed
  75.  */
  76.  
  77. cntrl(role, wkpre)
  78. int role;
  79. char *wkpre;
  80. {
  81.     char msg[BUFSIZ], rqstr[BUFSIZ];
  82.     FILE *fp;
  83.     int filemode;
  84.     struct stat stbuf;
  85.     char filename[MAXFULLNAME], wrktype, *wrkvec[20];
  86.     extern (*Rdmsg)(), (*Wrmsg)();
  87.     extern char *index(), *lastpart();
  88.     int status = 1, i;
  89.     int ret;
  90.     static int pnum, tmpnum = 0;
  91.  
  92.     pnum = getpid();
  93. top:
  94.     DEBUG(4, "*** TOP ***  -  role=%d, ", role);
  95.     if (role == MASTER) {
  96.         /* get work */
  97.         if ((i = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) {
  98.             WMESG(HUP, "");
  99.             RMESG(HUP, msg);
  100.             goto process;
  101.         }
  102.         wrktype = W_TYPE[0];
  103.  
  104.         DEBUG(4, "wrktype %c, ", wrktype);
  105.         if (wrktype == XUUCP) {
  106.             int n;
  107.             msg[0] = '\0';
  108.             for (n = 1; n < i; n++) {
  109.                 strcat(msg, " ");
  110.                 strcat(msg, wrkvec[n]);
  111.             }
  112.             sprintf(rqstr, "X %s", msg);
  113.             logent(rqstr, "REQUEST");
  114.             goto sendmsg;
  115.         }
  116.  
  117.         ASSERT(i > 4, "ARG COUNT - %d\n", i);
  118.         sprintf(msg, " %s %s %s %s %s %s",
  119.             W_FILE1, W_FILE2, W_USER,
  120.             W_OPTNS, W_DFILE, W_MODE);
  121.         strcpy(User, W_USER);
  122.         ASSERT(strlen(User) <= 10, "User - %s\n", User);
  123.         sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1,
  124.           W_FILE2, W_USER);
  125.         logent(rqstr, "REQUEST");
  126.         DEBUG(4, "User - %s\n", User);
  127.         if (wrktype == SNDFILE ) {
  128.             strcpy(filename, W_FILE1);
  129.             expfile(filename);
  130.             if (chkpth(User, "", filename)) {
  131.                 /*  access denied  */
  132.                 logent("DENIED", "ACCESS");
  133.                 unlink(W_DFILE);
  134.                 unlink(Wfile);
  135.                 goto top;
  136.             }
  137.  
  138.             strcpy(Dfile, W_DFILE);
  139.             if ((fp = fopen(Dfile, "r")) == NULL
  140.               && (fp = fopen(filename, "r")) == NULL) {
  141.                 /*  can not read data file  */
  142.                 logent("CAN'T READ DATA", "FAILED");
  143.                 unlink(Wfile);
  144.                 unlink(Dfile);
  145.                 goto top;
  146.             }
  147.         }
  148.  
  149.         if (wrktype == RCVFILE) {
  150.             strcpy(filename, W_FILE2);
  151.             expfile(filename);
  152.             if (chkpth(User, "", filename)
  153.              || chkperm(filename, User, index(W_OPTNS, 'd'))) {
  154.                 /*  access denied  */
  155.                 logent("DENIED", "ACCESS");
  156.                 unlink(Wfile);
  157.                 goto top;
  158.             }
  159.             sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
  160.             if ((fp = fopen(Dfile, "w")) == NULL) {
  161.                 /*  can not create temp  */
  162.                 logent("CAN'T CREATE TM", "FAILED");
  163.                 unlink(Wfile);
  164.                 unlink(Dfile);
  165.                 goto top;
  166.             }
  167.             chmod(Dfile, 0666);
  168.         }
  169. sendmsg:
  170.         DEBUG(4, "wrktype - %c, ", wrktype);
  171.         DEBUG(4, " fileno - %d\n", fileno(fp));
  172.         WMESG(wrktype, msg);
  173.         RMESG(wrktype, msg);
  174.         goto process;
  175.     }
  176.  
  177.     /* role is slave */
  178.     RAMESG(msg);
  179.     goto process;
  180.  
  181. process:
  182.     DEBUG(4, " PROCESS: msg - %s\n", msg);
  183.     switch (msg[0]) {
  184.  
  185.     case RQSTCMPT:
  186.         DEBUG(4, "%s\n", "RQSTCMPT:");
  187.         logent((msg[1] == 'N') ? "FAILED" : "SUCCEEDED", "REQUEST");
  188.         if (role == MASTER) {
  189.             notify(W_OPTNS, W_USER, W_FILE1, Rmtname,
  190.               (msg[1] == N) ? "failed" : "succeeded");
  191.         }
  192.         goto top;
  193.  
  194.     case HUP:
  195.         DEBUG(4, "%s\n", "HUP:");
  196.         if (msg[1] == Y) {
  197.             WMESG(HUP, YES);
  198.             (*Turnoff)();
  199.             Rdmsg = imsg;
  200.             Wrmsg = omsg;
  201.             return(0);
  202.         }
  203.  
  204.         if (msg[1] == N) {
  205.             ASSERT(role == MASTER,
  206.                 "role - %d", role);
  207.             role = SLAVE;
  208.             goto top;
  209.         }
  210.  
  211.         /* get work */
  212.         if (!iswrk(Wfile, "chk", Spool, wkpre)) {
  213.             WMESG(HUP, YES);
  214.             RMESG(HUP, msg);
  215.             goto process;
  216.         }
  217.  
  218.         WMESG(HUP, NO);
  219.         role = MASTER;
  220.         goto top;
  221.  
  222.     case XUUCP:
  223.         if (role == MASTER) {
  224.             unlink(Wfile);
  225.             goto top;
  226.         }
  227.  
  228.         /*  slave part  */
  229.         i = getargs(msg, wrkvec);
  230.         strcpy(filename, W_FILE1);
  231.         if (index(filename, ';') != NULL
  232.           || index(W_FILE2, ';') != NULL
  233.           || i < 3) {
  234.             WMESG(XUUCP, NO);
  235.             goto top;
  236.         }
  237.         expfile(filename);
  238.         if (chkpth("", Rmtname, filename)) {
  239.             WMESG(XUUCP, NO);
  240.             logent("XUUCP DENIED", filename);
  241.             goto top;
  242.         }
  243.         sprintf(rqstr, "%s %s", filename, W_FILE2);
  244.         xuucp(rqstr);
  245.         WMESG(XUUCP, YES);
  246.         goto top;
  247.  
  248.     case SNDFILE:
  249.         /*  MASTER section of SNDFILE  */
  250.  
  251.         DEBUG(4, "%s\n", "SNDFILE:");
  252.         if (msg[1] == N) {
  253.             logent("DENIED", "REQUEST");
  254.             ASSERT(role == MASTER,
  255.                 "role - %d", role);
  256.             fclose(fp);
  257.             unlink(W_DFILE);
  258.             unlink(Wfile);
  259.             goto top;
  260.         }
  261.  
  262.         if (msg[1] == Y) {
  263.             /* send file */
  264.             ASSERT(role == MASTER,
  265.                 "role - %d", role);
  266.             ret = (*Wrdata)(fp, Ofn);
  267.             fclose(fp);
  268.             if (ret != 0)
  269.                 return(FAIL);
  270.             unlink(W_DFILE);
  271.             RMESG(RQSTCMPT, msg);
  272.             goto process;
  273.         }
  274.  
  275.         /*  SLAVE section of SNDFILE  */
  276.         ASSERT(role == SLAVE,
  277.             "role - %d", role);
  278.  
  279.         /* request to receive file */
  280.         /* check permissions */
  281.         i = getargs(msg, wrkvec);
  282.         ASSERT(i > 4, "ARG COUNT - %d\n", i);
  283.         sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1,
  284.           W_FILE2, W_USER);
  285.         logent(rqstr, "REQUESTED");
  286.         DEBUG(4, "msg - %s\n", msg);
  287.         DEBUG(4, "W_FILE2 - %s\n", W_FILE2);
  288.         strcpy(filename, W_FILE2);
  289.         expfile(filename);
  290.         if (chkpth("", Rmtname, filename)
  291.          || chkperm(filename, Loginuser, index(W_OPTNS, 'd'))) {
  292.             WMESG(SNDFILE, NO);
  293.             logent("DENIED", "PERMISSION");
  294.             goto top;
  295.         }
  296.         if (isdir(filename)) {
  297.             strcat(filename, "/");
  298.             strcat(filename, lastpart(W_FILE1));
  299.         }
  300.         strcpy(User, W_USER);
  301.         ASSERT(strlen(User) <= 10, "User - %s\n", User);
  302.  
  303.         DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
  304.         sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
  305.         if((fp = fopen(Dfile, "w")) == NULL) {
  306.             WMESG(SNDFILE, NO);
  307.             logent("CAN'T OPEN", "DENIED");
  308.             unlink(Dfile);
  309.             goto top;
  310.         }
  311.         chmod(Dfile, 0666);
  312.  
  313.         WMESG(SNDFILE, YES);
  314.         ret = (*Rddata)(Ifn, fp);
  315.         fclose(fp);
  316.         if (ret != 0)
  317.             return(FAIL);
  318.         /* copy to user directory */
  319.         status = xmv(Dfile, filename);
  320.         WMESG(RQSTCMPT, status ? NO : YES);
  321.         logent(status ? "FAILED" : "SUCCEEDED", "COPY");
  322.         sscanf(W_MODE, "%o", &filemode);
  323.         DEBUG(4, "mode - %o\n", filemode);
  324.         if (filemode <= 0)
  325.             filemode = 0666;
  326.         if (status == 0) {
  327.             filemode |= 0666;
  328.             chmod(filename, filemode | 0666);
  329.         }
  330.         goto top;
  331.  
  332.     case RCVFILE:
  333.         /*  MASTER section of RCVFILE  */
  334.  
  335.         DEBUG(4, "%s\n", "RCVFILE:");
  336.         if (msg[1] == N) {
  337.             logent("REQUEST", "DENIED");
  338.             ASSERT(role == MASTER,
  339.                 "role - %d", role);
  340.             unlink(Wfile);
  341.             fclose(fp);
  342.             goto top;
  343.         }
  344.  
  345.         if (msg[1] == Y) {
  346.             /* receive file */
  347.             ASSERT(role == MASTER,
  348.                 "role - %d", role);
  349.             ret = (*Rddata)(Ifn, fp);
  350.             fclose(fp);
  351.             if (ret != 0)
  352.                 return(FAIL);
  353.             /* copy to user directory */
  354.             if (isdir(filename)) {
  355.                 strcat(filename, "/");
  356.                 strcat(filename, lastpart(W_FILE1));
  357.             }
  358.             status = xmv(Dfile, filename);
  359.             WMESG(RQSTCMPT, status ? NO : YES);
  360.             logent(status ? "FAILED" : "SUCCEEDED", "COPY");
  361.             notify(W_OPTNS, W_USER, filename, Rmtname,
  362.               status ? "failed" : "succeeded");
  363.             sscanf(&msg[2], "%o", &filemode);
  364.             DEBUG(4, "mode - %o\n", filemode);
  365.             if (filemode <= 0)
  366.                 filemode = 0666;
  367.             if (status == 0) {
  368.                 unlink(Dfile);
  369.                 filemode |= 0666;
  370.                 chmod(filename, filemode | 0666);
  371.             }
  372.             goto top;
  373.         }
  374.  
  375.         /*  SLAVE section of RCVFILE  */
  376.         ASSERT(role == SLAVE,
  377.             "role - %d", role);
  378.  
  379.         /* request to send file */
  380.         strcpy(rqstr, msg);
  381.         logent(rqstr, "REQUESTED");
  382.  
  383.         /* check permissions */
  384.         i = getargs(msg, wrkvec);
  385.         ASSERT(i > 3, "ARG COUNT - %d\n", i);
  386.         DEBUG(4, "msg - %s\n", msg);
  387.         DEBUG(4, "W_FILE1 - %s\n", W_FILE1);
  388.         strcpy(filename, W_FILE1);
  389.         expfile(filename);
  390.         if (isdir(filename)) {
  391.             strcat(filename, "/");
  392.             strcat(filename, lastpart(W_FILE2));
  393.         }
  394.         strcpy(User, W_USER);
  395.         ASSERT(strlen(User) <= 10, "User - %s\n", User);
  396.         if (chkpth("", Rmtname, filename) != 0) {
  397.             WMESG(RCVFILE, NO);
  398.             logent("DENIED", "PERMISSION");
  399.             goto top;
  400.         }
  401.         DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
  402.  
  403.         if ((fp = fopen(filename, "r")) == NULL) {
  404.             WMESG(RCVFILE, NO);
  405.             logent("CAN'T OPEN", "DENIED");
  406.             goto top;
  407.         }
  408.  
  409.         /*  ok to send file */
  410.         ret = stat(filename, &stbuf);
  411.         ASSERT(ret != -1, "STAT FAILED %s", filename);
  412.         sprintf(msg, "%s %o", YES, stbuf.st_mode & 0777);
  413.         WMESG(RCVFILE, msg);
  414.         ret = (*Wrdata)(fp, Ofn);
  415.         fclose(fp);
  416.         if (ret != 0)
  417.             return(FAIL);
  418.         RMESG(RQSTCMPT, msg);
  419.         goto process;
  420.     }
  421.     return(FAIL);
  422. }
  423.  
  424.  
  425. /***
  426.  *    rmesg(c, msg)    read message 'c'
  427.  *    char *msg, c;
  428.  *
  429.  *    return code:  0  |  FAIL
  430.  */
  431.  
  432. rmesg(c, msg)
  433. char *msg, c;
  434. {
  435.     char str[50];
  436.  
  437.     DEBUG(4, "rmesg - '%c' ", c);
  438.     if ((*Rdmsg)(msg, Ifn) != 0) {
  439.         DEBUG(4, "got %s\n", "FAIL");
  440.         sprintf(str, "expected '%c' got FAIL", c);
  441.         logent(str, "BAD READ");
  442.         return(FAIL);
  443.     }
  444.     if (c != '\0' && msg[0] != c) {
  445.         DEBUG(4, "got %s\n", msg);
  446.         sprintf(str, "expected '%c' got %.25s", c, msg);
  447.         logent(str, "BAD READ");
  448.         return(FAIL);
  449.     }
  450.     DEBUG(4, "got %.25s\n", msg);
  451.     return(0);
  452. }
  453.  
  454.  
  455. /***
  456.  *    wmesg(m, s)    write a message (type m)
  457.  *    char *s, m;
  458.  *
  459.  *    return codes: 0 - ok | FAIL - ng
  460.  */
  461.  
  462. wmesg(m, s)
  463. char *s, m;
  464. {
  465.     DEBUG(4, "wmesg '%c'", m);
  466.     DEBUG(4, "%.25s\n", s);
  467.     return((*Wrmsg)(m, s, Ofn));
  468. }
  469.  
  470.  
  471. /***
  472.  *    notify(options, user, file, sys, stwork)    mail results of copy
  473.  *    char *options, *user, *file, *sys, *stword);
  474.  *
  475.  *    return codes:  none
  476.  */
  477.  
  478. notify(options, user, file, sys, stword)
  479. char *options, *user, *file, *sys, *stword;
  480. {
  481.     char str[200];
  482.     if (index(options, 'm') == NULL)
  483.         return;
  484.     sprintf(str, "file %s, system %s, copy %s\n", file, sys, stword);
  485.     mailst(user, str);
  486.     return;
  487. }
  488.  
  489.  
  490. /***
  491.  *    startup(role)
  492.  *    int role;
  493.  *
  494.  *    startup  -  this routine will converse with the remote
  495.  *    machine, agree upon a protocol (if possible) and start the
  496.  *    protocol.
  497.  *
  498.  *    return codes:
  499.  *        SUCCESS - successful protocol selection
  500.  *        FAIL - can't find common or open failed
  501.  */
  502.  
  503. startup(role)
  504. int role;
  505. {
  506.     extern (*Rdmsg)(), (*Wrmsg)();
  507.     extern imsg(), omsg();
  508.     extern char *blptcl(), fptcl();
  509.     char msg[BUFSIZ], str[BUFSIZ];
  510.  
  511.     Rdmsg = imsg;
  512.     Wrmsg = omsg;
  513.     if (role == MASTER) {
  514.         RMESG(SLTPTCL, msg);
  515.         if ((str[0] = fptcl(&msg[1])) == NULL) {
  516.             /* no protocol match */
  517.             WMESG(USEPTCL, NO);
  518.             return(FAIL);
  519.         }
  520.         str[1] = '\0';
  521.         WMESG(USEPTCL, str);
  522.         if (stptcl(str) != 0)
  523.             return(FAIL);
  524.         DEBUG(4, "protocol %s\n", str);
  525.         return(SUCCESS);
  526.     }
  527.     else {
  528.         WMESG(SLTPTCL, blptcl(str));
  529.         RMESG(USEPTCL, msg);
  530.         if (msg[1] == N) {
  531.             return(FAIL);
  532.         }
  533.  
  534.         if (stptcl(&msg[1]) != 0)
  535.             return(FAIL);
  536.         DEBUG(4, "Protocol %s\n", msg);
  537.         return(SUCCESS);
  538.     }
  539. }
  540.  
  541.  
  542. /*******
  543.  *    char
  544.  *    fptcl(str)
  545.  *    char *str;
  546.  *
  547.  *    fptcl  -  this routine will choose a protocol from
  548.  *    the input string (str) and return the found letter.
  549.  *
  550.  *    return codes:
  551.  *        '\0'  -  no acceptable protocol
  552.  *        any character  -  the chosen protocol
  553.  */
  554.  
  555. char
  556. fptcl(str)
  557. char *str;
  558. {
  559.     struct Proto *p;
  560.     extern char *index();
  561.  
  562.     for (p = Ptbl; p->P_id != '\0'; p++) {
  563.         if (index(str, p->P_id) != NULL) {
  564.             return(p->P_id);
  565.         }
  566.     }
  567.  
  568.     return('\0');
  569. }
  570.  
  571.  
  572. /***
  573.  *    char *
  574.  *    blptcl(str)
  575.  *    char *str;
  576.  *
  577.  *    blptcl  -  this will build a string of the
  578.  *    letters of the available protocols and return
  579.  *    the string (str).
  580.  *
  581.  *    return:
  582.  *        a pointer to string (str)
  583.  */
  584.  
  585. char *
  586. blptcl(str)
  587. char *str;
  588. {
  589.     struct Proto *p;
  590.     char *s;
  591.  
  592.     for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++);
  593.     return(str);
  594. }
  595.  
  596. /***
  597.  *    stptcl(c)
  598.  *    char *c;
  599.  *
  600.  *    stptcl  -  this routine will set up the six routines
  601.  *    (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the
  602.  *    desired protocol.
  603.  *
  604.  *    return codes:
  605.  *        SUCCESS - ok
  606.  *        FAIL - no find or failed to open
  607.  *
  608.  */
  609.  
  610. stptcl(c)
  611. char *c;
  612. {
  613.     struct Proto *p;
  614.  
  615.     for (p = Ptbl; p->P_id != '\0'; p++) {
  616.         if (*c == p->P_id) {
  617.             /* found protocol - set routines */
  618.             Rdmsg = p->P_rdmsg;
  619.             Wrmsg = p->P_wrmsg;
  620.             Rddata = p->P_rddata;
  621.             Wrdata = p->P_wrdata;
  622.             Turnon = p->P_turnon;
  623.             Turnoff = p->P_turnoff;
  624.             if ((*Turnon)() != 0)
  625.                 return(FAIL);
  626.             DEBUG(4, "Proto started %c\n", *c);
  627.             return(SUCCESS);
  628.         }
  629.     }
  630.     DEBUG(4, "Proto start-fail %c\n", *c);
  631.     return(FAIL);
  632. }
  633.