home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / c-client / os_t20.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-14  |  10.4 KB  |  378 lines

  1. /*
  2.  * Program:    Operating-system dependent routines -- TOPS-20 version
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        6158 Lariat Loop NE
  6.  *        Bainbridge Island, WA  98110-2098
  7.  *        Internet: MRC@Panda.COM
  8.  *
  9.  * Date:    1 August 1988
  10.  * Last Edited:    14 May 1992
  11.  *
  12.  * Copyright 1992 by Mark Crispin
  13.  *
  14.  *  Permission to use, copy, modify, and distribute this software and its
  15.  * documentation for any purpose and without fee is hereby granted, provided
  16.  * that the above copyright notices appear in all copies and that both the
  17.  * above copyright notices and this permission notice appear in supporting
  18.  * documentation, and that the name of Mark Crispin not be used in advertising
  19.  * or publicity pertaining to distribution of the software without specific,
  20.  * written prior permission.  This software is made available "as is", and
  21.  * MARK CRISPIN DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
  22.  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF
  23.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL
  24.  * MARK CRISPIN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
  25.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  26.  * WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT
  27.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
  28.  * THIS SOFTWARE.
  29.  *
  30.  */
  31.  
  32.  
  33. /* Dedication:
  34.  * This file is dedicated with affection to the TOPS-20 operating system, which
  35.  * set standards for user and programmer friendliness that have still not been
  36.  * equaled by more `modern' operating systems.
  37.  * Wasureru mon ka!!!!
  38.  */
  39.  
  40. /* TCP input buffer */
  41.  
  42. #define BUFLEN 8192
  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.   int jfn;            /* jfn for connection */
  51.   char ibuf[BUFLEN];        /* input buffer */
  52. };
  53.  
  54.  
  55. #include <jsys.h>
  56. #include <time.h>
  57. #include <sys/types.h>
  58. #include <sys/time.h>
  59. #include "osdep.h"
  60. #include "mail.h"
  61. #include "misc.h"
  62.  
  63. /* Write current time in RFC 822 format
  64.  * Accepts: destination string
  65.  */
  66.  
  67. char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  68. char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  69.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  70.  
  71. void rfc822_date (char *date)
  72. {
  73.   int zone;
  74.   char *zonename;
  75.   struct tm *t;
  76.   struct timeval tv;
  77.   struct timezone tz;
  78.   gettimeofday (&tv,&tz);    /* get time and timezone poop */
  79.   t = localtime (&tv.tv_sec);    /* convert to individual items */
  80.   zone = -tz.tz_minuteswest;    /* TOPS-20 doesn't have tm_gmtoff or tm_zone */
  81.   zonename = timezone (tz.tz_minuteswest,t->tm_isdst);
  82.                 /* and output it */
  83.   sprintf (date,"%s, %d %s %d %02d:%02d:%02d %+03d%02d (%s)",
  84.        days[t->tm_wday],t->tm_mday,months[t->tm_mon],t->tm_year+1900,
  85.        t->tm_hour,t->tm_min,t->tm_sec,
  86.        (t->tm_isdst ? 1 : 0) + zone/60,abs (zone) % 60,zonename);
  87. }
  88.  
  89. /* Get a block of free storage
  90.  * Accepts: size of desired block
  91.  * Returns: free storage block
  92.  */
  93.  
  94. void *fs_get (size_t size)
  95. {
  96.   void *block = malloc (size);
  97.   if (!block) fatal ("Out of free storage");
  98.   return (block);
  99. }
  100.  
  101.  
  102. /* Resize a block of free storage
  103.  * Accepts: ** pointer to current block
  104.  *        new size
  105.  */
  106.  
  107. void fs_resize (void **block,size_t size)
  108. {
  109.   if (!(*block = realloc (*block,size))) fatal ("Can't resize free storage");
  110. }
  111.  
  112.  
  113. /* Return a block of free storage
  114.  * Accepts: ** pointer to free storage block
  115.  */
  116.  
  117. void fs_give (void **block)
  118. {
  119.   free (*block);
  120.   *block = NIL;
  121. }
  122.  
  123.  
  124. /* Report a fatal error
  125.  * Accepts: string to output
  126.  */
  127.  
  128. void fatal (char *string)
  129. {
  130.   mm_fatal (string);        /* pass up the string */
  131.   abort ();            /* die horribly */
  132. }
  133.  
  134. /* Copy string with CRLF newlines
  135.  * Accepts: destination string
  136.  *        pointer to size of destination string
  137.  *        source string
  138.  *        length of source string
  139.  */
  140.  
  141. char *strcrlfcpy (char **dst,unsigned long *dstl,char *src,unsigned long srcl)
  142. {
  143.   if (srcl > *dstl) {        /* make sure enough space for text */
  144.     fs_give ((void **) dst);    /* fs_resize does an unnecessary copy */
  145.     *dst = (char *) fs_get ((*dstl = srcl) + 1);
  146.   }
  147.                 /* copy strings */
  148.   if (srcl) memcpy (*dst,src,srcl);
  149.   *(*dst + srcl) = '\0';    /* tie off destination */
  150.   return *dst;            /* return destination */
  151. }
  152.  
  153.  
  154. /* Length of string after strcrlflen applied
  155.  * Accepts: source string
  156.  *        length of source string
  157.  */
  158.  
  159. unsigned long strcrlflen (char *src,unsigned long srcl)
  160. {
  161.   return srcl;            /* this is easy on TOPS-20 */
  162. }
  163.  
  164. /* Server log in
  165.  * Accepts: user name string
  166.  *        password string
  167.  *        optional place to return home directory
  168.  * Returns: T if password validated, NIL otherwise
  169.  */
  170.  
  171. long server_login (char *user,char *pass,char **home)
  172. {
  173.   int uid;
  174.   int argblk[5];
  175.   char tmp[MAILTMPLEN];
  176.   argblk[1] = RC_EMO;        /* require exact match */
  177.   argblk[2] = (int) (user-1);    /* user name */
  178.   argblk[3] = 0;        /* no stepping */
  179.   if (!jsys (RCUSR,argblk)) return NIL;
  180.   uid = argblk[1] = argblk[3];    /* user number */
  181.   argblk[2] = (int) (pass-1);    /* password */
  182.   argblk[3] = 0;        /* no special account */
  183.   if (!jsys (LOGIN,argblk)) return NIL;
  184.   if (home) {            /* wants home directory? */
  185.     argblk[1] = 0;        /* no special flags */
  186.     argblk[2] = uid;        /* user number */
  187.     argblk[3] = 0;        /* no stepping */
  188.     jsys (RCDIR,argblk);    /* get directory number */
  189.     argblk[1] = (int) (tmp-1);    /* destination */
  190.     argblk[2] = argblk[3];    /* directory number */
  191.     jsys (DIRST,argblk);    /* get home directory string */
  192.     *home = cpystr (tmp);    /* copy home directory */
  193.   }
  194.   return T;
  195. }
  196.  
  197. /* TCP/IP open
  198.  * Accepts: host name
  199.  *        contact port number
  200.  * Returns: TCP stream if success else NIL
  201.  */
  202.  
  203. TCPSTREAM *tcp_open (char *host,int port)
  204. {
  205.   char tmp[MAILTMPLEN];
  206.   TCPSTREAM *stream = NIL;
  207.   int argblk[5];
  208.   int jfn;
  209.   char file[MAILTMPLEN];
  210.   argblk[1] = monsym (".GTDPN");/* get IP address and primary name */
  211.   argblk[2] = (int) (host-1);    /* pointer to host */
  212.   argblk[4] = (int) (tmp-1);
  213.   if (!jsys (GTDOM,argblk)) {    /* do it the domain way */
  214.     argblk[1] = _GTHSN;        /* failed, convert string to number */
  215.     if (!jsys (GTHST,argblk)) {    /* and do it by host table */
  216.       sprintf (tmp,"No such host as %s",host);
  217.       mm_log (tmp,ERROR);
  218.       return NIL;
  219.     }
  220.     argblk[1] = _GTHNS;        /* convert number to string */
  221.     argblk[2] = (int) (tmp-1);
  222.                 /* get the official name */
  223.     if (!jsys (GTHST,argblk)) strcpy (tmp,host);
  224.   }
  225.   sprintf (file,"TCP:.%o-%d;PERSIST:30;CONNECTION:ACTIVE",argblk[3],port);
  226.   argblk[1] = GJ_SHT;        /* short form GTJFN% */
  227.   argblk[2] = (int) (file-1);    /* pointer to file name */
  228.                 /* get JFN for TCP: file */
  229.   if (!jsys (GTJFN,argblk)) fatal ("Unable to create TCP JFN");
  230.   jfn = argblk[1];        /* note JFN for later */
  231.                 /* want 8-bit bidirectional I/O */
  232.   argblk[2] = OF_RD|OF_WR|(FLD (8,monsym("OF%BSZ")));
  233.   if (!jsys (OPENF,argblk)) {
  234.     sprintf (file,"Can't connect to %s,%d server",tmp,port);
  235.     mm_log (file,ERROR);
  236.     return NIL;
  237.   }
  238.                 /* create TCP/IP stream */
  239.   stream = (TCPSTREAM *) fs_get (sizeof (TCPSTREAM));
  240.                 /* copy official host name */
  241.   stream->host = cpystr (tmp);
  242.   argblk[1] = _GTHNS;        /* convert number to string */
  243.   argblk[2] = (int) (tmp-1);
  244.   argblk[3] = -1;        /* want local host */
  245.   if ((!jsys (GTDOM,argblk)) && !jsys (GTHST,argblk)) strcpy (tmp,"LOCAL");
  246.   stream->localhost = cpystr (tmp);
  247.   stream->jfn = jfn;        /* init JFN */
  248.   return stream;
  249. }
  250.  
  251. /* TCP/IP authenticated open
  252.  * Accepts: host name
  253.  *        service name
  254.  * Returns: TCP/IP stream if success else NIL
  255.  */
  256.  
  257. TCPSTREAM *tcp_aopen (char *host,char *service)
  258. {
  259.   return NIL;
  260. }
  261.  
  262. /* TCP/IP receive line
  263.  * Accepts: TCP/IP stream
  264.  * Returns: text line string or NIL if failure
  265.  */
  266.  
  267. char *tcp_getline (TCPSTREAM *stream)
  268. {
  269.   int argblk[5];
  270.   int size;
  271.   int s2;
  272.   char *line;
  273.   char *p1;
  274.   char *p2;
  275.   argblk[1] = stream->jfn;    /* read from TCP */
  276.                 /* pointer to buffer */
  277.   argblk[2] = (int) (stream->ibuf-1);
  278.   argblk[3] = BUFLEN;        /* max number of bytes to read */
  279.   argblk[4] = '\015';        /* terminate on CR */
  280.   if (!jsys (SIN,argblk)) return NIL;
  281.   size = BUFLEN-argblk[3];    /* number of bytes read */
  282.                 /* if didn't get a complete line */
  283.   if (stream->ibuf[size-1] != '\015') {
  284.     p1 = (char *) fs_get (size);/* copy this buffer's worth */
  285.     memcpy (p1,stream->ibuf,size);
  286.                 /* recurse to get remainder */
  287.     if (p2 = tcp_getline (stream)) {
  288.                 /* built total string */
  289.       line = (char *) fs_get (size+1+(s2 = strlen (p2)));
  290.       memcpy (line,p1,size);    /* copy first part */
  291.       memcpy (line+size,p2,s2);    /* and second part */
  292.       line[size+s2] = '\0';    /* tie off string with null */
  293.       fs_give ((void **) &p2);    /* flush partial string */
  294.       fs_give ((void **) &p1);    /* flush initial fragment */
  295.     }
  296.     else line = p1;        /* return the fragment */
  297.   }
  298.   else {
  299.                 /* copy string less CR to free storage */
  300.     line = (char *) fs_get (size);
  301.     memcpy (line,stream->ibuf,--size);
  302.     line[size] = '\0';        /* tie off string with null */
  303.     jsys (BIN,argblk);        /* eat the line feed */
  304.   }
  305.   return line;
  306. }
  307.  
  308. /* TCP/IP receive buffer
  309.  * Accepts: TCP/IP stream
  310.  *        size in bytes
  311.  *        buffer to read into
  312.  * Returns: T if success, NIL otherwise
  313.  */
  314.  
  315. long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer)
  316. {
  317.   int argblk[5];
  318.   argblk[1] = stream->jfn;    /* read from TCP */
  319.   argblk[2] = (int) (buffer-1);    /* pointer to buffer */
  320.   argblk[3] = -size;        /* number of bytes to read */
  321.   if (!jsys (SIN,argblk)) return NIL;
  322.   buffer[size] = '\0';        /* tie off text */
  323.   return T;
  324. }
  325.  
  326.  
  327. /* TCP/IP send string as record
  328.  * Accepts: TCP/IP stream
  329.  * Returns: T if success else NIL
  330.  */
  331.  
  332. long tcp_soutr (TCPSTREAM *stream,char *string)
  333. {
  334.   int argblk[5];
  335.   argblk[1] = stream->jfn;    /* write to TCP */
  336.   argblk[2] = (int) (string-1);    /* pointer to buffer */
  337.   argblk[3] = 0;        /* write until NUL */
  338.   if (!jsys (SOUTR,argblk)) return NIL;
  339.   return T;
  340. }
  341.  
  342.  
  343. /* TCP/IP close
  344.  * Accepts: TCP/IP stream
  345.  */
  346.  
  347. void tcp_close (TCPSTREAM *stream)
  348. {
  349.   int argblk[5];
  350.   argblk[1] = stream->jfn;    /* close TCP */
  351.   jsys (CLOSF,argblk);
  352.                 /* flush host names */
  353.   fs_give ((void **) &stream->host);
  354.   fs_give ((void **) &stream->localhost);
  355.   fs_give ((void **) &stream);    /* flush the stream */
  356. }
  357.  
  358. /* TCP/IP return host for this stream
  359.  * Accepts: TCP/IP stream
  360.  * Returns: host name for this stream
  361.  */
  362.  
  363. char *tcp_host (TCPSTREAM *stream)
  364. {
  365.   return stream->host;        /* return host name */
  366. }
  367.  
  368.  
  369. /* TCP/IP return local host for this stream
  370.  * Accepts: TCP/IP stream
  371.  * Returns: local host name for this stream
  372.  */
  373.  
  374. char *tcp_localhost (TCPSTREAM *stream)
  375. {
  376.   return stream->localhost;    /* return local host name */
  377. }
  378.