home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / decnet / de_wtmail.c next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  8.2 KB  |  381 lines

  1. /* de_wtmail.c: nitty gritty of decnet */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/decnet/RCS/de_wtmail.c,v 6.0 1991/12/18 20:06:35 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/decnet/RCS/de_wtmail.c,v 6.0 1991/12/18 20:06:35 jpo Rel $
  9.  *
  10.  * $Log: de_wtmail.c,v $
  11.  * Revision 6.0  1991/12/18  20:06:35  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16. /*
  17.  *      This module contains all the nitty gritty stuff which actually
  18.  *      does the decnet communications
  19.  */
  20.  
  21. #include "util.h"
  22. #include "retcode.h"
  23. #include "chan.h"
  24. #include "ap.h"
  25. #include <stdio.h>
  26. #include <fcntl.h>
  27. #include <sys/ioctl.h>
  28. #include <netdni/dni.h>
  29. #include <ctype.h>
  30.  
  31. #define DEC_OK 0x01000000
  32. #define CC     0x10
  33. #define CC_OK  0x20
  34. #define MAXDNIBYTES 128         /* Maximum bytes in a line */
  35. #define NET_TIMEOUT 120        /* Timeout for net reads/writes */
  36.  
  37. /* Externals */
  38.  
  39. extern int de_fd;
  40. extern int mrgate;
  41. extern int cc_ok;
  42. extern int map_space;
  43. extern char space_char;
  44. extern char toupper();
  45. char de_status_text[BUFSIZ];
  46.  
  47. /* Internals */
  48. char *user_addr(), *rfc_de();
  49.  
  50. /* This routine opens a logical link */
  51.  
  52. de_nopen(host, err)
  53. char *host;
  54. char *err;
  55. {
  56.     struct ses_io_type sesopts;
  57.     OpenBlock ob;
  58.     static OpenBlock template =
  59.     {
  60.         "",             /* Host name (filled in later) */
  61.         "",             /* Task name */
  62.         27,             /* Mail 11 */
  63.         "",             /* Userid */
  64.         "",             /* Account */
  65.         "",             /* Password */
  66.         {               /* Connect data */
  67.             16,     /* 16 bytes of data */
  68.             3,      /* protocol version 3 */
  69.             0,      /* ECO level 0 */
  70.             0,      /* Customer ECO level 0 */
  71.             0,      /* OS type (other) */
  72.             0,0,0,0,/* No options */
  73.             CC,     /* Send CC: line */
  74.             0,      /* Reserved */
  75.             0,      /* reserved */
  76.             0,      /* Reserved */
  77.             0,      /* RMS RFM transfer mode */
  78.             0,      /* RMS RAT type */
  79.             0,      /* Reserved */
  80.             0       /* Reserved */
  81.         }
  82.     };
  83.  
  84.     PP_NOTICE(("opening connection to [%s]", host));
  85.  
  86.     /* First open the logical link device */
  87.     PP_DBG(("attempting to open logical link device"));
  88.     if ((de_fd = open("/dev/dni", O_RDWR)) < 0)
  89.     {
  90.         strcpy(err, "failed to open logical link device");
  91.         return RP_LIO;
  92.     }
  93.  
  94.     /* Now set up I/O options. We need record mode */
  95.     sesopts.io_flags = SES_IO_RECORD_MODE;
  96.     PP_DBG(("attempting to set record mode"));
  97.     if (ioctl(de_fd, SES_IO_TYPE, &sesopts) < 0)
  98.     {
  99.         strcpy(err, "failed to set i/o options");
  100.         return RP_LIO;
  101.     }
  102.  
  103.     /* Now request link, including requesting CC: mode */
  104.     ob = template;
  105.     strcpy(ob.op_node_name, host);
  106.     if (ioctl(de_fd, SES_LINK_ACCESS, &ob) < 0)
  107.     {
  108.         switch (errno & 0xff)
  109.         {
  110.         case FAILED:    /* Connection failed */
  111.         case NODE_UNREACH: /* Node unreacheable */
  112.             sprintf(err, "failed to connect to host [%s], unreacheable", host);
  113.             return RP_NIO;
  114.         case BAD_NAME: /* Invalid host name */
  115.         case NODE_NAME:/* Unrecognised node name */
  116.             sprintf(err, "failed to connect to host [%s], bad host", host);
  117.             return RP_NO;
  118.         case BAD_OBJECT:/* Mail11 object does not exist */
  119.         case OBJ_NAME: /* Ditto */
  120.             sprintf(err, "failed to connect to host [%s], mail object not present", host);
  121.             return RP_NIO;
  122.         case BY_OBJECT: /* Mail 11 won't talk to us */
  123.             sprintf(err, "failed to connect to host [%s], mail object not communicating", host);
  124.             return RP_NIO;
  125.         default:
  126.             sprintf(err, "failed to connect to host [%s], error = %d", host, errno & 0xff);
  127.             return RP_NIO;
  128.         }
  129.     }
  130.  
  131.     /* Check if CC: is aceptable */
  132.     PP_TRACE(("connection data 0x%x(%d)", ob.op_opt_data.im_data[8], ob.op_opt_data.im_length));
  133.     if (ob.op_opt_data.im_length == 0)
  134.         cc_ok = FALSE;
  135.     else
  136.         cc_ok = (ob.op_opt_data.im_data[8] & CC_OK) == CC_OK;
  137.  
  138.     PP_NOTICE(("connection open"));
  139.     strcpy(err, "connection open");
  140.     return RP_OK;
  141. }
  142.  
  143. /* This routine closes a logical link */
  144.  
  145. de_nclose(type)
  146. int type;
  147. {
  148.     SessionData sd;
  149.  
  150.     PP_NOTICE(("closing connection"));
  151.     sd.sd_reason = 0;
  152.     sd.sd_data.im_length = 0;
  153.     if (ioctl(de_fd, SES_DISCONNECT, &sd) < 0)
  154.     {
  155.         PP_NOTICE(("failed to close connection, so aborting link"));
  156.         ioctl(de_fd, SES_ABORT, &sd);
  157.     }
  158.     close(de_fd);
  159.     PP_TRACE(("connection closed"));
  160. }
  161.  
  162. /* This routine sends a `mark', used to delimit various parts of the protocol */
  163.  
  164. de_mark()
  165. {
  166.     char mark = 0;
  167.  
  168.     PP_TRACE(("de_mark()"));
  169.     if (timeout(NET_TIMEOUT))
  170.     {
  171.         PP_NOTICE(("timed out while sending mark"));
  172.         return RP_NIO;
  173.     }
  174.     if (write(de_fd, &mark, 1) < 0)
  175.     {
  176.         timeout(0);
  177.         PP_NOTICE(("failed to transmit mark"));
  178.         return RP_NIO;
  179.     }
  180.     timeout(0);
  181.     return RP_OK;
  182. }
  183.  
  184. /* this routine sends a single address and returns a success (or otherwise)
  185.     code */
  186.  
  187. int de_wto(adr)
  188. char *adr;
  189. {
  190.  
  191.     PP_TRACE(("de_wto(%s)", adr));
  192.  
  193.     /* Extract the user part and send it */
  194.     if (de_send(user_addr(adr)) != RP_OK)
  195.         return RP_NIO;
  196.  
  197.     switch (de_status())
  198.     {
  199.     case RP_NIO:
  200.         return RP_NIO;
  201.     case RP_OK:
  202.         return RP_AOK;
  203.     case RP_NO:
  204.         return RP_USER;
  205.     default:
  206.         return RP_NO;
  207.     }
  208. }
  209.  
  210.  
  211. /* This routine sends a single, null terminated string to the decnet link */
  212.  
  213. de_send(buf)
  214. char *buf;
  215. {
  216.     int size = strlen(buf);
  217.  
  218.     PP_TRACE(("de_send(%s)", buf));
  219.     /* If size is greater than the maximum that the remote system
  220.     can handle (usually about 127 bytes) then truncate */
  221.     if (size > MAXDNIBYTES) size = MAXDNIBYTES;
  222.     if (timeout(NET_TIMEOUT))
  223.     {
  224.         PP_NOTICE(("connection timed out"));
  225.         return RP_NIO;
  226.     }
  227.     if (write(de_fd, buf, size) < 0)
  228.     {
  229.         timeout(0);
  230.         PP_NOTICE(("failed to transmit data, errno = %d", errno & 0xff));
  231.         PP_NOTICE(("data was `%s'", buf));
  232.         return RP_NIO;
  233.     }
  234.     timeout(0);
  235.     return RP_OK;
  236. }
  237.  
  238. /* This routine gets a status code from the decnet connection */
  239.  
  240. int de_status()
  241. {
  242.     char txt[LINESIZE];
  243.     long status;
  244.     int len;
  245.  
  246.     PP_TRACE(("de_status()"));
  247.  
  248.     strcpy(de_status_text, "");
  249.     if (timeout(NET_TIMEOUT))
  250.     {
  251.         PP_NOTICE(("timeout while transmitting status"));
  252.         return RP_NIO;
  253.     }
  254.     if (read(de_fd, (char *)&status, sizeof(status)) < sizeof(status))
  255.     {
  256.         timeout(0);
  257.         return (RP_NIO);
  258.     }
  259.     timeout(0);
  260.     PP_DBG(("got 0x%lx", status));
  261.  
  262.     /* If bit 0 is set then good status */
  263.     if ((status & DEC_OK) == DEC_OK)
  264.     {
  265.         return (RP_OK);
  266.     }
  267.     else
  268.     {
  269.         if (timeout(NET_TIMEOUT))
  270.         {
  271.             PP_NOTICE(("timeout while reading status"));
  272.             return RP_NIO;
  273.         }
  274.         while ((len = read(de_fd, txt, sizeof(txt))) >= 0)
  275.         {
  276.             if (len == 1 && txt[0] == 0)
  277.             {
  278.                 timeout(0);
  279.                 return RP_NO;
  280.             }
  281.             else
  282.             {
  283.                 txt[len] = '\0';
  284.                 if (sizeof(de_status_text) - strlen(de_status_text) > len)
  285.                 {
  286.                     strcat(de_status_text, txt);
  287.                     strcat(de_status_text, "\n");
  288.                 }
  289.             }
  290.         }
  291.         /* If we get here, the connection has dropped */
  292.         timeout(0);
  293.         return (RP_NIO);
  294.     }
  295. }
  296.  
  297. /* This routine takes an RFC822 message and returns the user part forced
  298.    to upper case, `_' mapped to space if necessary */
  299.  
  300. char *user_addr(addr)
  301. char *addr;
  302. {
  303.     AP_ptr  tree, group, name, local, domain, route;
  304.     char *s;
  305.     char *final;
  306.  
  307.     PP_DBG(("user_addr(%s)", addr));
  308.     if (ap_s2p(addr, &tree, &group, &name, &local, &domain, &route) == (char *)NOTOK)
  309.     {
  310.         return "Orphanage";
  311.     }
  312.     for (s = local->ap_obvalue; *s = toupper(*s); s++)
  313.     {
  314.         if (map_space && *s == space_char) *s = ' ';
  315.     }
  316.  
  317.     /* Allocate enough space for string + MRGATE:: if needed */
  318.     final = malloc(strlen(local->ap_obvalue) + 10);
  319.  
  320.     /* Tack on an MRGATE if talking to one */
  321.     strcpy(final, (mrgate) ? "MRGATE::" : "");
  322.     strcat(final, local->ap_obvalue);
  323.  
  324.     PP_DBG(("returns: %s", final));
  325.     return (final);
  326. }
  327.  
  328. /* This procedure takes an RFC822 string and converts it to DecNet format */
  329.  
  330. char *rfc_de(addr)
  331. char *addr;
  332. {
  333.     AP_ptr  tree, group, name, local, domain, route, a;
  334.     char *final;
  335.     int size = 0;
  336.  
  337.     PP_DBG(("rfc_de(%s)", addr));
  338.     if (ap_s2p(addr, &tree, &group, &name, &local, &domain, &route) == (char *)NOTOK)
  339.     {
  340.         return "Orphanage";
  341.     }
  342.  
  343.     /* OK, now troll down the tree adding up the sizes so we can alloc
  344.        a big enough string */
  345.  
  346.     for (a = tree; a ; a = a->ap_next)
  347.     {
  348.         switch(a->ap_obtype)
  349.         {
  350.         case AP_MAILBOX:
  351.             size += strlen(a->ap_obvalue) + 1;
  352.             break;
  353.         case AP_DOMAIN:
  354.             size += strlen(a->ap_obvalue) + 2;
  355.             break;
  356.         }
  357.     }
  358.  
  359.     /* Allocate the space */
  360.     final = malloc(size);
  361.  
  362.     /* Now build the decnet address */
  363.  
  364.     for (a = tree, strcpy(final, ""); a ; a = a->ap_next)
  365.     {
  366.         if (a->ap_obtype == AP_DOMAIN)
  367.         {
  368.             strcat(final, a->ap_obvalue);
  369.             strcat(final, "::");
  370.         }
  371.     }
  372.     for (a = tree; a ; a = a->ap_next)
  373.     {
  374.         if (a->ap_obtype == AP_MAILBOX)
  375.             strcat(final, a->ap_obvalue);
  376.     }
  377.  
  378.     PP_TRACE(("returns: %s", final));
  379.     return (final);
  380. }
  381.