home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / smphone / ph_io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-03-28  |  11.4 KB  |  408 lines

  1. #include "util.h"
  2. #include "mmdf.h"
  3. #include "d_returns.h"
  4. #include "ph.h"
  5. /*
  6.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  7.  *     
  8.  *
  9.  *     Copyright (C) 1979,1980,1981  University of Delaware
  10.  *     
  11.  *     Department of Electrical Engineering
  12.  *     University of Delaware
  13.  *     Newark, Delaware  19711
  14.  *
  15.  *     Phone:  (302) 738-1163
  16.  *     
  17.  *     
  18.  *     This program module was developed as part of the University
  19.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  20.  *     
  21.  *     Acquisition, use, and distribution of this module and its listings
  22.  *     are subject restricted to the terms of a license agreement.
  23.  *     Documents describing systems using this module must cite its source.
  24.  *
  25.  *     The above statements must be retained with all copies of this
  26.  *     program and may not be removed without the consent of the
  27.  *     University of Delaware.
  28.  *     
  29.  *
  30.  *     version  -1    David H. Crocker    March   1979
  31.  *     version   0    David H. Crocker    April   1980
  32.  *     version  v7    David H. Crocker    May     1981
  33.  *     version   1    David H. Crocker    October 1981
  34.  *
  35.  */
  36. /*#define RUNALON   */
  37.  
  38. /*                  Handle telephone-based i/o                          */
  39.  
  40. extern struct ll_struct   *logptr;
  41. extern int    d_errno;              /* dial package error                 */
  42. extern char *blt ();
  43. extern struct ps_rstruct ps_rp;
  44.  
  45. /*  NOTE:  load initialization routines from ph_iouser or ph_ioslave    */
  46.  
  47. /*   ************  (ph_)  PHONE MAIL I/O SUB-MODULE  ****************** */
  48.  
  49. ps_cmd (cmd)          /* Send a command */
  50. char    *cmd;
  51. {
  52.     short     retval;
  53.  
  54. #ifdef DEBUG
  55.     ll_log (logptr, LLOGPTR, "ps_cmd (%s)", cmd);
  56. #endif
  57.  
  58.     if ( rp_isbad(retval = ph_wrec(cmd, strlen(cmd))) )
  59.         return(retval);
  60.  
  61.     if (rp_isbad (retval = ps_irdrply ())) {
  62.     return( ps_rp.sm_rval = retval );
  63.     }
  64.     return (RP_OK);
  65.  
  66. }
  67. /* */
  68.  
  69. ps_irdrply ()             /* get net reply & stuff into ps_rp   */
  70. {
  71.     static char sep[] = "; ";     /* for sticking multi-lines together  */
  72.     static char sm_rnotext[] = "No reply text given";
  73.     short     len,
  74.         tmpreply,
  75.             retval;
  76.     char    linebuf[LINESIZE];
  77.     char    tmpmore;
  78.     register char  *linestrt;     /* to bypass bad initial chars in buf */
  79.     register short    i;
  80.     register char   more;      /* are there continuation lines?      */
  81.  
  82. #ifdef DEBUG
  83.     ll_log (logptr, LLOGBTR, "ps_irdrply ()");
  84. #endif
  85.  
  86. newrply: 
  87.     for (more = FALSE, ps_rp.sm_rgot = FALSE, ps_rp.sm_rlen = 0;
  88.         rp_isgood (retval = ph_rrec (linebuf, &len));)
  89.     {                  /* 1st col in linebuf gets reply code */
  90.     for (linestrt = linebuf;  /* skip leading baddies, probably     */
  91.         len > 0 &&        /*  from a lousy Multics              */
  92.             (!isascii ((char) *linestrt) ||
  93.             !isdigit ((char) *linestrt));
  94.         linestrt++, len--);
  95.  
  96.     tmpmore = FALSE;          /* start fresh                        */
  97.     tmpreply = atoi (linestrt);
  98.     blt (linestrt, ps_rp.sm_rstr, 3);    /* Grab reply code    */
  99.     if ((len -= 3) > 0)
  100.     {
  101.         linestrt += 3;
  102. #ifdef SPACED_CONTINUE
  103.         for ( ; len > 0 && isspace (*linestrt); linestrt++, len--);    
  104.                        /* Skip white space in case dash is offset      */
  105. #endif SPACED_CONTINUE
  106.         if (len > 0 && *linestrt == '-')
  107.         {
  108.         tmpmore = TRUE;
  109.         linestrt++;
  110.         if (--len > 0)
  111.             for (; len > 0 && isspace (*linestrt); linestrt++, len--);
  112.         }
  113.     }
  114.  
  115.     if (more)          /* save reply value from 1st line     */
  116.         {                  /* we at end of continued reply?      */
  117.         if (tmpreply != ps_rp.sm_rval || tmpmore)
  118.         continue;
  119.         more = FALSE;      /* end of continuation                */
  120.     }
  121.     else              /* not in continuation state          */
  122.     {
  123.         ps_rp.sm_rval = tmpreply;
  124.         more = tmpmore;   /* more lines to follow?              */
  125.  
  126.         if (len <= 0)
  127.         {              /* fake it, if no text given          */
  128.         blt (sm_rnotext, linestrt = linebuf,
  129.                (sizeof sm_rnotext) - 1);
  130.         len = (sizeof sm_rnotext) - 1;
  131.         }
  132.     }
  133.  
  134.     if ((i = min (len, (LINESIZE - 1) - ps_rp.sm_rlen)) > 0)
  135.     {              /* if room left, save the human text  */
  136.         blt (linestrt, &ps_rp.sm_rstr[ps_rp.sm_rlen], i);
  137.         ps_rp.sm_rlen += i;
  138.         if (more && ps_rp.sm_rlen < (LINESIZE - 4))
  139.         {              /* put a separator between lines      */
  140.         blt (sep, &(ps_rp.sm_rstr[ps_rp.sm_rlen]), (sizeof sep) - 1);
  141.         ps_rp.sm_rlen += (sizeof sep) - 1;
  142.         }
  143.     }
  144. #ifdef DEBUG
  145.     else
  146.         ll_log (logptr, LLOGFTR, "skipping");
  147. #endif
  148.  
  149.     if (!more)
  150.     {
  151. #ifdef DEBUG
  152.         ll_log (logptr, LLOGBTR, "(%u)%.*s", ps_rp.sm_rval,
  153.             ps_rp.sm_rlen, ps_rp.sm_rstr);
  154. #endif
  155.         if (ps_rp.sm_rval < 100)
  156.         goto newrply;     /* skip info messages                 */
  157.  
  158.         ps_rp.sm_rstr[ps_rp.sm_rlen] = '\0';  
  159.                   /* keep things null-terminated */
  160.  
  161.         ps_rp.sm_rgot = TRUE;
  162.         return (RP_OK);
  163.     }
  164.     }
  165.     return (retval);          /* error return                       */
  166. }
  167.  
  168. /*                 READ FROM REMOTE MAIL PROCESS                    */
  169.  
  170. ph_rrec (linebuf, len)           /* read one "record"                    */
  171. char   *linebuf;          /* where to stuff the text              */
  172. int      *len;                      /* where to stuff the length count      */
  173. {
  174.     short     retval;
  175.     int       goteot;               /* completed packet                   */
  176.  
  177. #ifdef DEBUG
  178.     ll_log (logptr, LLOGBTR, "ph_rrec ()");
  179. #endif
  180.  
  181. #ifdef RUNALON
  182.     *len = read (0, linebuf, LINESIZE - 1);
  183.     *len -= 1;
  184. #else
  185.     linebuf[0] = '\0';
  186.  
  187.     if ((*len = d_rcvdata (linebuf, LINESIZE - 1, &goteot)) < 0)
  188.     {
  189.     retval = ph_d2rpval (*len);
  190.     printx("problem reading from remote host (%s)\n", rp_valstr (retval));
  191.     ll_log (logptr, LLOGTMP,
  192.         "ph_rrec:  d_rcvdata err (%s)", rp_valstr (retval));
  193.     return (retval);
  194.     }
  195. #endif
  196.  
  197.     if (*len == 0)
  198.     {
  199. #ifdef DEBUG
  200.     ll_log (logptr, LLOGFTR, "zero len read");
  201. #endif
  202.     return (RP_DONE);
  203.     }
  204.     linebuf[*len] = '\0';      /* keep things null-terminated        */
  205.  
  206. #ifdef DEBUG
  207.     if (!goteot)          /* packet is too long                 */
  208.     ll_log (logptr, LLOGFTR, "*** oversized packet");
  209. #endif
  210.                   /* let is slip, for now               */
  211. #ifdef DEBUG
  212.     ll_log (logptr, LLOGFTR, "(%d)'%s'", *len, linebuf);
  213. #endif
  214.  
  215.     printx ("<-(%s)\n", linebuf);
  216.     fflush (stdout);
  217.  
  218.     return (RP_OK);
  219. }
  220. /* */
  221.  
  222. ph_rstm (buffer, len)            /* read buffered block of text        */
  223. char   *buffer;              /* where to stuff the text            */
  224. int      *len;                      /* where to stuff count               */
  225. {
  226.     static int    goteos;           /* save end-of-stream across calls    */
  227.  
  228. #ifdef DEBUG
  229.     ll_log (logptr, LLOGBTR, "ph_rstm ()");
  230. #endif
  231.  
  232.     if (goteos)              /* was set automatically by dial      */
  233.     {
  234. #ifdef DEBUG
  235.     ll_log (logptr, LLOGFTR, "returning DONE");
  236. #endif
  237.     goteos = FALSE;
  238.     *buffer = '\0';
  239.     *len = 0;
  240.     return (RP_DONE);
  241.     }
  242.  
  243. #ifdef RUNALON
  244.     printx ("dm_rstm: ");
  245.  
  246.     *len = read (0, buffer, *len - 1);
  247.     if (*len == 0)
  248.     goteos = TRUE;
  249. #else
  250.     *len = d_rcvdata (buffer, *len - 1, &goteos);
  251. #endif
  252.  
  253.     if (*len < 0)
  254.     {
  255.     ll_log (logptr, LLOGGEN, "rdstm: error rcvdata");
  256.     return (ph_d2rpval (*len));
  257.     }
  258.     buffer[*len] = '\0';
  259.  
  260. #ifdef DEBUG
  261.     ll_log (logptr, LLOGFTR, "(%d)'%s'", *len, buffer);
  262. #endif
  263.     return (RP_OK);
  264. }
  265. /*                 WRITE TO REMOTE MAIL PROCESS                        */
  266.  
  267. ph_wrec (linebuf, len)           /* write a record/packet              */
  268. char    linebuf[];          /* chars to write                     */
  269. int       len;                      /* number of chars to write           */
  270. {
  271.     short     retval;
  272.  
  273. #ifdef DEBUG
  274.     ll_log (logptr, LLOGBTR, "ph_wrec ()");
  275.     ll_log (logptr, LLOGFTR, "(%d)'%s'", len, linebuf);
  276. #endif
  277.  
  278. #ifdef RUNALON
  279.     if (linebuf == 0 && len == 0)
  280.     {
  281.     printf ("p_wrec (eof)\n");
  282.     fflush (stdout);
  283.     return (RP_OK);
  284.     }
  285.     if (write (1, linebuf, len) != len)
  286.     return (RP_DHST);
  287.     write (1, "\n", 1);          /* make it pretty */
  288.     return (RP_OK);
  289. #endif
  290.  
  291.     if ((retval = d_snstream (linebuf, len)) < D_OK ||
  292.         (retval = d_sneot ()) < D_OK)
  293.     return (ph_d2rpval (retval));
  294.  
  295.     printx("->(%s)\n",linebuf);
  296.     fflush(stdout);    
  297.  
  298.     return (RP_OK);
  299. }
  300. /* */
  301.  
  302. ph_wstm (buffer, len)            /* write next part of char stream     */
  303. char    buffer[];          /* chars to write                     */
  304. int       len;                      /* number of chars to write           */
  305. {
  306.     short     retval;
  307.  
  308. #ifdef DEBUG
  309.     ll_log (logptr, LLOGBTR, "ph_wstm () (%d)'%s'", len, buffer ? buffer : "");
  310. #endif
  311.  
  312. #ifdef RUNALON
  313.     retval = write (1, buffer, len);
  314.     if (retval == len)
  315.     return (RP_OK);
  316.     else
  317.     return (RP_NO);
  318. #endif
  319.  
  320.     if (buffer == 0 && len == 0)
  321.     retval = d_sneot ();     /* flush the buffer                   */
  322.     else
  323.     retval = d_snstream (buffer, len);
  324.  
  325.     if (retval < D_OK)
  326.     return (ph_d2rpval (retval));
  327.     return (RP_OK);
  328. }
  329. /* */
  330.  
  331. ph_d2rpval (retval)               /* map d_errno into rp.h value        */
  332. int       retval;
  333. {
  334. #ifdef DEBUG
  335.     ll_log (logptr, LLOGBTR, "(%d) => dial err (%d)", retval, d_errno);
  336. #endif
  337.  
  338.     switch (d_errno)
  339.     {
  340.     case D_LOGERR:           /* probably locked                    */
  341.         ll_err (logptr, LLOGTMP, "phone log");
  342.         return (RP_AGN);      /* maybe  transient problem           */
  343.  
  344.     case D_NOPORT:            /* no port or line available          */
  345.     case D_BUSY: 
  346.     case D_ABAN: 
  347.         return (RP_AGN);      /* highly transient problem           */
  348.  
  349.     case D_TIMEOUT:           /* alarm during port read/write call  */
  350.         return (RP_TIME);     /* same type of code                  */
  351.  
  352.     case D_RCVQUIT:           /* a QUIT packet has been received    */
  353.         return (RP_DONE);
  354.  
  355.     case D_PORTEOF:           /* eof on port                        */
  356.         return (RP_EOF);
  357.  
  358.     case D_NOPWR:             /* the dialer has no power            */
  359.     case D_PORTOPEN:          /* error trying to open port          */
  360.         return (RP_NET);
  361.  
  362.     case D_PORTRD:            /* error on port read                 */
  363.     case D_PORTWRT:           /* error on port write                */
  364.         return (RP_NIO);
  365.  
  366.     case D_NORESP:            /* no response to transmitted packet  */
  367.         return (RP_DHST);     /* assume the host is messed up       */
  368.  
  369.     case D_PATHERR:           /* error in path packet               */
  370.     case D_PACKERR:           /* error in packet format             */
  371.         return (RP_BHST);
  372.  
  373.     case D_TSOPEN:            /* error opening transcript file      */
  374.     case D_LOCKERR:           /* error opening/creating lock file   */
  375.         return (RP_LOCK);
  376.  
  377.     case D_CALLLOG:           /* error opening call log file        */
  378.         return (RP_FOPN);
  379.  
  380.     case D_TSWRITE:           /* error writing on transcript file   */
  381.         return (RP_FIO);
  382.  
  383.     case D_SYSERR:            /* undistinguished system error       */
  384.     case D_FORKERR:           /* couldn't fork after several tries  */
  385.     case D_PRTSGTTY:          /* error doing stty or gtty on port   */
  386.         return (RP_LIO);
  387.  
  388.     case D_SCRERR:            /* error in script file               */
  389.     case D_ACCERR:            /* error in access file               */
  390.     case D_NONUMBS:           /* no numbers given to dialer         */
  391.     case D_NOESC:             /* no esacpe character could be found */
  392.     case D_BADSPD:            /* bad speed designation              */
  393.         return (RP_PARM);
  394.  
  395.     case D_INTERR:            /* internal package error             */
  396.     case D_INITERR:           /* trouble initializing               */
  397.     case D_BADDIG:            /* bad digit passed to dialer         */
  398.         return (RP_NO);
  399.  
  400.     default:           /* punt                               */
  401.         ll_err (logptr, LLOGTMP,
  402.             "unclassified category (%d) phone error (%d)",
  403.                 retval, d_errno);
  404.         return (RP_NO);
  405.     }
  406. }
  407.  
  408.