/*
* TCP/IP String IOT routines - TOPS-20 version
*
* Mark Crispin, SUMEX Computer Project, 4 August 1988
*
* Copyright (c) 1988 Stanford University
*
*/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jsys.h>
#include "tcpsio.h"
#include "misc.h"

/* src:<kccdist.kcc-6.lib.gen>memstr.c */
extern void bcopy(char *,char *,int);


#define BUFLEN 8192

typedef struct tcp_stream {
 char *host;                   /* host name */
 char *localhost;              /* local host name */
 int jfn;                      /* jfn for connection */
 char ibuf[BUFLEN];            /* input buffer */
} TCPSTREAM;

extern void usrlog();


/* TCP/IP open
* Accepts: host name
*          contact port number
* Returns: TCP stream if success else NIL
*/

TCPSTREAM *tcp_open (host,port)
   char *host;
   int port;
{
 char tmp[1024];
 TCPSTREAM *stream = NIL;
 int argblk[5];
 int jfn;
 char hostname[128];
 char file[128];
 argblk[1] = monsym (".GTDPN");/* get IP address and primary name */
 argblk[2] = (int) (host-1);   /* pointer to host */
 argblk[4] = (int) (hostname-1);
 if (!jsys (GTDOM,argblk)) {   /* do it the domain way */
   argblk[1] = _GTHSN;         /* failed, convert string to number */
   if (!jsys (GTHST,argblk)) { /* and do it by host table */
     sprintf (tmp,"No such host as %s",host);
     usrlog (tmp);
     return (NIL);
   }
   argblk[1] = _GTHNS;         /* convert number to string */
   argblk[2] = (int) (hostname-1);
                               /* get the official name */
   if (!jsys (GTHST,argblk)) strcpy (hostname,host);
 }
 sprintf (file,"TCP:.%o-%d;PERSIST:30;CONNECTION:ACTIVE",argblk[3],port);
 argblk[1] = GJ_SHT;           /* short form GTJFN% */
 argblk[2] = (int) (file-1);   /* pointer to file name */
 if (!jsys (GTJFN,argblk)) {   /* get JFN for TCP: file */
   usrlog ("Unable to create TCP JFN");
   return (NIL);
 }
 jfn = argblk[1];              /* note JFN for later */
                               /* want 8-bit bidirectional I/O */
 argblk[2] = OF_RD|OF_WR|(FLD (8,monsym("OF%BSZ")));
 if (!jsys (OPENF,argblk)) {
   sprintf (tmp,"Can't connect to %s,%d server",hostname,port);
   usrlog (tmp);
   return (NIL);
 }
                               /* create TCP/IP stream */
 stream = (TCPSTREAM *) malloc (sizeof (TCPSTREAM));
                               /* copy official host name */
 stream->host = malloc (1+strlen (hostname));
 strcpy (stream->host,hostname);
 argblk[1] = _GTHNS;           /* convert number to string */
 argblk[2] = (int) (hostname-1);
 argblk[3] = -1;               /* want local host */
 if (!jsys (GTDOM,argblk))     /* copy local host name */
  if (!jsys (GTHST,argblk)) strcpy (hostname,"LOCAL");
 stream->localhost = malloc (1+strlen (hostname));
 strcpy (stream->localhost,hostname);
 stream->jfn = jfn;            /* init JFN */
 return (stream);
}

/* TCP/IP receive line
* Accepts: TCP/IP stream
* Returns: text line string or NIL if failure
*/

char *tcp_getline (stream)
   TCPSTREAM *stream;
{
 int argblk[5];
 int size;
 char *line;
 argblk[1] = stream->jfn;      /* read from TCP */
                               /* pointer to buffer */
 argblk[2] = (int) (stream->ibuf-1);
 argblk[3] = BUFLEN;           /* max number of bytes to read */
 argblk[4] = '\015';           /* terminate on CR */
 if (!jsys (SIN,argblk)) return (NIL);
 size = BUFLEN-argblk[3]-1;    /* number of bytes read (not including CR) */
 line = malloc (size+1);       /* copy string to free storage */
 bcopy (stream->ibuf,line,size);
 line[size] = '\0';            /* tie off string with null */
 jsys (BIN,argblk);            /* eat the line feed */
 return (line);
}

/* TCP/IP receive buffer
* Accepts: TCP/IP stream
*          size in bytes
*          buffer to read into
* Returns: T if success, NIL otherwise
*/

tcp_getbuffer (stream,size,buffer)
   TCPSTREAM *stream;
   int size;
   char *buffer;
{
 int argblk[5];
 argblk[1] = stream->jfn;      /* read from TCP */
 argblk[2] = (int) (buffer-1); /* pointer to buffer */
 argblk[3] = -size;            /* number of bytes to read */
 if (!jsys (SIN,argblk)) return (NIL);
 buffer[size] = '\0';          /* tie off text */
 return (T);
}

/* TCP/IP send string as record
* Accepts: TCP/IP stream
* Returns: T if success else NIL
*/

tcp_soutr (stream,string)
   TCPSTREAM *stream;
   char *string;
{
 int argblk[5];
 argblk[1] = stream->jfn;      /* write to TCP */
 argblk[2] = (int) (string-1); /* pointer to buffer */
 argblk[3] = 0;                /* write until NUL */
 if (!jsys (SOUTR,argblk)) return (NIL);
 return (T);
}


/* TCP/IP close
* Accepts: TCP/IP stream
*/

void tcp_close (stream)
   TCPSTREAM *stream;
{
 int argblk[5];
 argblk[1] = stream->jfn;      /* close TCP */
 jsys (CLOSF,argblk);
 free (stream->host);          /* flush host names */
 free (stream->localhost);
 free ((char *) stream);       /* flush the stream */
}

/* TCP/IP return host for this stream
* Accepts: TCP/IP stream
* Returns: host name for this stream
*/

char *tcp_host (stream)
   TCPSTREAM *stream;
{
 return (stream->host);        /* return host name */
}


/* TCP/IP return local host for this stream
* Accepts: TCP/IP stream
* Returns: local host name for this stream
*/

char *tcp_localhost (stream)
   TCPSTREAM *stream;
{
 return (stream->localhost);   /* return local host name */
}