home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / imap-3.0 / ANSI / c-client / os_dwa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  11.5 KB  |  448 lines

  1. /*
  2.  * Program:    Operating-system dependent routines -- DOS (Waterloo) version
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    11 April 1989
  13.  * Last Edited:    15 June 1993
  14.  *
  15.  * Copyright 1993 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35.  
  36. #include <tcp.h>        /* must be before TCPSTREAM definition */
  37.  
  38.  
  39. /* TCP input buffer -- must be large enough to prevent overflow */
  40.  
  41. #define BUFLEN 8192
  42.  
  43.  
  44. /* TCP I/O stream (must be before osdep.h is included) */
  45.  
  46. #define TCPSTREAM struct tcp_stream
  47. TCPSTREAM {
  48.   char *host;            /* host name */
  49.   char *localhost;        /* local host name */
  50.   tcp_Socket *tcps;        /* tcp socket */
  51.   long ictr;            /* input counter */
  52.   char *iptr;            /* input pointer */
  53.   char ibuf[BUFLEN];        /* input buffer */
  54. };
  55.  
  56.  
  57.  
  58. /* Private function prototypes */
  59.  
  60. #include "mail.h"
  61. #include "osdep.h"
  62. #include <time.h>
  63. #include <sys\timeb.h>
  64. #include "misc.h"
  65.  
  66. /* Undo compatibility definition */
  67.  
  68. #undef tcp_open
  69.  
  70.  
  71. /* Global data */
  72.  
  73. short sock_initted = 0;        /* global so others using net can see it */
  74. unsigned long rndm = 0xfeed;    /* initial `random' number */
  75.  
  76. /* Write current time in RFC 822 format
  77.  * Accepts: destination string
  78.  */
  79.  
  80. char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  81.  
  82. void rfc822_date (char *date)
  83. {
  84.   time_t ti = time (0);
  85.   struct tm *t;
  86.   tzset ();            /* initialize timezone stuff */
  87.   t = localtime (&ti);        /* output local time */
  88.   sprintf (date,"%s, %d %s %d %02d:%02d:%02d %s",
  89.        days[t->tm_wday],t->tm_mday,months[t->tm_mon],t->tm_year+1900,
  90.        t->tm_hour,t->tm_min,t->tm_sec,tzname[t->tm_isdst]);
  91. }
  92.  
  93. /* Get a block of free storage
  94.  * Accepts: size of desired block
  95.  * Returns: free storage block
  96.  */
  97.  
  98. void *fs_get (size_t size)
  99. {
  100.   void *block = malloc (size);
  101.   if (!block) fatal ("Out of free storage");
  102.   return (block);
  103. }
  104.  
  105.  
  106. /* Resize a block of free storage
  107.  * Accepts: ** pointer to current block
  108.  *        new size
  109.  */
  110.  
  111. void fs_resize (void **block,size_t size)
  112. {
  113.   if (!(*block = realloc (*block,size))) fatal ("Can't resize free storage");
  114. }
  115.  
  116.  
  117. /* Return a block of free storage
  118.  * Accepts: ** pointer to free storage block
  119.  */
  120.  
  121. void fs_give (void **block)
  122. {
  123.   free (*block);
  124.   *block = NIL;
  125. }
  126.  
  127.  
  128. /* Report a fatal error
  129.  * Accepts: string to output
  130.  */
  131.  
  132. void fatal (char *string)
  133. {
  134.   mm_fatal (string);        /* pass the string */
  135.   abort ();            /* die horribly */
  136. }
  137.  
  138. /* Copy string with CRLF newlines
  139.  * Accepts: destination string
  140.  *        pointer to size of destination string
  141.  *        source string
  142.  *        length of source string
  143.  */
  144.  
  145. char *strcrlfcpy (char **dst,unsigned long *dstl,char *src,unsigned long srcl)
  146. {
  147.   if (srcl > *dstl) {        /* resize if not enough space */
  148.     fs_give ((void **) dst);    /* fs_resize does an unnecessary copy */
  149.     *dst = (char *) fs_get ((size_t) (*dstl = srcl) + 1);
  150.   }
  151.                 /* copy strings */
  152.   if (srcl) memcpy (*dst,src,(size_t) srcl);
  153.   *(*dst + srcl) = '\0';    /* tie off destination */
  154.   return *dst;            /* return destination */
  155. }
  156.  
  157.  
  158. /* Length of string after strcrlfcpy applied
  159.  * Accepts: source string
  160.  *        length of source string
  161.  */
  162.  
  163. unsigned long strcrlflen (STRING *s)
  164. {
  165.   return SIZE (s);        /* no-brainer on DOS! */
  166. }
  167.  
  168.  
  169. /* Return my home directory name
  170.  * Returns: my home directory name
  171.  */
  172.  
  173. char *hdname = NIL;
  174.  
  175. char *myhomedir ()
  176. {
  177.   int i;
  178.   char *s;
  179.   if (!hdname) {        /* get home directory name if not yet known */
  180.     hdname = cpystr ((s = getenv ("HOME")) ? s : "");
  181.     if ((i = strlen (hdname)) && ((hdname[i-1] == '\\') || (hdname[i-1]=='/')))
  182.       hdname[i-1] = '\0';    /* tie off trailing directory delimiter */
  183.   }
  184.   return hdname;
  185. }
  186.  
  187. /* TCP/IP open
  188.  * Accepts: host name
  189.  *        contact port number
  190.  * Returns: TCP/IP stream if success else NIL
  191.  */
  192.  
  193. TCPSTREAM *TCP_open (char *host,long port)
  194. {
  195.   TCPSTREAM *stream = NIL;
  196.   tcp_Socket *sock;
  197.   long adr,i,j,k,l;
  198.   char *s;
  199.   char tmp[MAILTMPLEN];
  200.   char hostname[MAILTMPLEN];
  201.                 /* initialize if first time here */
  202.   if (!sock_initted++) sock_init();
  203.                 /* set default gets routine */
  204.   if (!mailgets) mailgets = mm_gets;
  205.   /* The domain literal form is used (rather than simply the dotted decimal
  206.      as with other Unix programs) because it has to be a valid "host name"
  207.      in mailsystem terminology. */
  208.                 /* look like domain literal? */
  209.   if (host[0] == '[' && host[strlen (host)-1] == ']') {
  210.     if (((i = strtol (s = host+1,&s,10)) <= 255) && *s++ == '.' &&
  211.     ((j = strtol (s,&s,10)) <= 255) && *s++ == '.' &&
  212.     ((k = strtol (s,&s,10)) <= 255) && *s++ == '.' &&
  213.     ((l = strtol (s,&s,10)) <= 255) && *s++ == ']' && !*s) {
  214.       adr = (i << 24) + (j << 16) + (k << 8) + l;
  215.       sprintf (hostname,"[%ld.%ld.%ld.%ld]",i,j,k,l);
  216.     }
  217.     else {
  218.       sprintf (tmp,"Bad format domain-literal: %.80s",host);
  219.       mm_log (tmp,ERROR);
  220.       return NIL;
  221.     }
  222.   }
  223.   else {            /* lookup host name */
  224.     if (!(adr = resolve (host))) {
  225.       sprintf (tmp,"Host not found: %s",host);
  226.       mm_log (tmp,ERROR);
  227.       return NIL;
  228.     }
  229.     else strcpy (hostname, host);/* need way to do canonical host name */
  230.   }
  231.  
  232.                 /* OK to instantiate socket now */
  233.   sock = (tcp_Socket *) fs_get (sizeof (tcp_Socket));
  234.                 /* open connection */
  235.   if (!tcp_open (sock,(word)0,adr,(word)port,NULL)) {
  236.     sprintf (tmp,"Can't connect to %.80s,%ld",hostname,port);
  237.     mm_log (tmp,ERROR);
  238.     fs_give ((void **) &sock);
  239.     return NIL;
  240.   }
  241.                 /* create TCP/IP stream */
  242.   stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM));
  243.                 /* official host name */
  244.   stream->host = cpystr (hostname);
  245.   adr = gethostid ();        /* get local IP address */
  246.   i = adr >> 24; j = (adr >> 16) & 0xff; k = (adr >> 8) & 0xff; l = adr & 0xff;
  247.   sprintf (tmp,"[%ld.%ld.%ld.%ld]",i,j,k,l);
  248.   stream->localhost = cpystr (tmp);
  249.   stream->tcps = sock;        /* init socket */
  250.   stream->ictr = 0;        /* init input counter */
  251.   return stream;        /* return success */
  252. }
  253.   
  254. /* TCP/IP authenticated open
  255.  * Accepts: host name
  256.  *        service name
  257.  * Returns: TCP/IP stream if success else NIL
  258.  */
  259.  
  260. TCPSTREAM *tcp_aopen (char *host,char *service)
  261. {
  262.   return NIL;            /* always NIL on DOS */
  263. }
  264.  
  265. /* TCP/IP receive line
  266.  * Accepts: TCP/IP stream
  267.  * Returns: text line string or NIL if failure
  268.  */
  269.  
  270. char *tcp_getline (TCPSTREAM *stream)
  271. {
  272.   int n,m;
  273.   char *st,*ret,*stp;
  274.   char c = '\0';
  275.   char d;
  276.                 /* make sure have data */
  277.   if (!tcp_getdata (stream)) return NIL;
  278.   st = stream->iptr;        /* save start of string */
  279.   n = 0;            /* init string count */
  280.   while (stream->ictr--) {    /* look for end of line */
  281.     d = *stream->iptr++;    /* slurp another character */
  282.     if ((c == '\015') && (d == '\012')) {
  283.       ret = (char *) fs_get (n--);
  284.       memcpy (ret,st,n);    /* copy into a free storage string */
  285.       ret[n] = '\0';        /* tie off string with null */
  286.       return ret;
  287.     }
  288.     n++;            /* count another character searched */
  289.     c = d;            /* remember previous character */
  290.   }
  291.                 /* copy partial string from buffer */
  292.   memcpy ((ret = stp = (char *) fs_get (n)),st,n);
  293.                 /* get more data from the net */
  294.   if (!tcp_getdata (stream)) return NIL;
  295.                 /* special case of newline broken by buffer */
  296.   if ((c == '\015') && (*stream->iptr == '\012')) {
  297.     stream->iptr++;        /* eat the line feed */
  298.     stream->ictr--;
  299.     ret[n - 1] = '\0';        /* tie off string with null */
  300.   }
  301.                 /* else recurse to get remainder */
  302.   else if (st = tcp_getline (stream)) {
  303.     ret = (char *) fs_get (n + 1 + (m = strlen (st)));
  304.     memcpy (ret,stp,n);        /* copy first part */
  305.     memcpy (ret + n,st,m);    /* and second part */
  306.     fs_give ((void **) &stp);    /* flush first part */
  307.     fs_give ((void **) &st);    /* flush second part */
  308.     ret[n + m] = '\0';        /* tie off string with null */
  309.   }
  310.   return ret;
  311. }
  312.  
  313. /* TCP/IP receive buffer
  314.  * Accepts: TCP/IP stream
  315.  *        size in bytes
  316.  *        buffer to read into
  317.  * Returns: T if success, NIL otherwise
  318.  */
  319.  
  320. long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer)
  321. {
  322.   unsigned long n;
  323.   char *bufptr = buffer;
  324.   while (size > 0) {        /* until request satisfied */
  325.     if (!tcp_getdata (stream)) return NIL;
  326.     n = min (size,stream->ictr);/* number of bytes to transfer */
  327.                 /* do the copy */
  328.     memcpy (bufptr,stream->iptr,(size_t) n);
  329.     bufptr += n;        /* update pointer */
  330.     stream->iptr +=n;
  331.     size -= n;            /* update # of bytes to do */
  332.     stream->ictr -=n;
  333.   }
  334.   bufptr[0] = '\0';        /* tie off string */
  335.   return T;
  336. }
  337.  
  338.  
  339. /* TCP/IP receive data
  340.  * Accepts: TCP/IP stream
  341.  * Returns: T if success, NIL otherwise
  342.  */
  343.  
  344. long tcp_getdata (TCPSTREAM *stream)
  345. {
  346.   int status;
  347.   if (!stream->tcps) return NIL;/* no-no nuked socket */
  348.   while (stream->ictr < 1) {    /* if buffer empty, block for input and read */
  349.     if (!_ip_delay1 (stream->tcps,600,NULL,&status))
  350.       stream->ictr = sock_fastread (stream->tcps,
  351.                     stream->iptr = stream->ibuf,BUFLEN);
  352.     else if (status == 1) {    /* nuke the socket if closed */
  353.       sock_close (stream->tcps);
  354.       fs_give ((void **) &stream->tcps);
  355.       return NIL;
  356.     }
  357.   }
  358.   return T;
  359. }
  360.  
  361. /* TCP/IP send string as record
  362.  * Accepts: TCP/IP stream
  363.  * Returns: T if success else NIL
  364.  */
  365.  
  366. long tcp_soutr (TCPSTREAM *stream,char *string)
  367. {
  368.                 /* output the cruft */
  369.   sock_puts (stream->tcps,string);
  370.   return T;            /* all done */
  371. }
  372.  
  373.  
  374. /* TCP/IP send string
  375.  * Accepts: TCP/IP stream
  376.  *        string pointer
  377.  *        byte count
  378.  * Returns: T if success else NIL
  379.  */
  380.  
  381. long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size)
  382. {
  383.   sock_write (stream->tcps,string,(int) size);
  384.   return T;
  385. }
  386.  
  387.  
  388. /* TCP/IP close
  389.  * Accepts: TCP/IP stream
  390.  */
  391.  
  392. void tcp_close (TCPSTREAM *stream)
  393. {
  394.   if (stream->tcps){         /* nuke the socket */
  395.     sock_close (stream->tcps);
  396.     _ip_delay2 (stream->tcps,0,NULL,NULL);
  397.   }
  398.   fs_give ((void **) &stream->tcps);
  399.                 /* flush host names */
  400.   fs_give ((void **) &stream->host);
  401.   fs_give ((void **) &stream->localhost);
  402.   fs_give ((void **) &stream);    /* flush the stream */
  403. }
  404.  
  405. /* TCP/IP get host name
  406.  * Accepts: TCP/IP stream
  407.  * Returns: host name for this stream
  408.  */
  409.  
  410. char *tcp_host (TCPSTREAM *stream)
  411. {
  412.   return stream->host;        /* return host name */
  413. }
  414.  
  415.  
  416. /* TCP/IP get local host name
  417.  * Accepts: TCP/IP stream
  418.  * Returns: local host name
  419.  */
  420.  
  421. char *tcp_localhost (TCPSTREAM *stream)
  422. {
  423.   return stream->localhost;    /* return local host name */
  424. }
  425.  
  426. /* These functions are only used by rfc822.c for calculating cookies.  So this
  427.  * is good enough.  If anything better is needed fancier functions will be
  428.  * needed.
  429.  */
  430.  
  431.  
  432. /* Return random number
  433.  */
  434.  
  435. long random ()
  436. {
  437.   return rndm *= 0xdae0;
  438. }
  439.  
  440.  
  441. /* Return `process ID'
  442.  */
  443.  
  444. long getpid ()
  445. {
  446.   return 1;
  447. }
  448.