From:	CSBVAX::MRGATE!cmf%unix.CIS.PITTSBURGH.EDU@VB.CC.CMU.EDU@SMTP 13-MAR-1988 20:34
To:	ARISIA::EVERHART
Subj:	Re: nntp for CMU-TEK


Received: from VB.CC.CMU.EDU by C.CS.CMU.EDU with TCP; Sun 13 Mar 88 18:55:23-EST
Received: from VMS.CIS.PITTSBURGH.EDU by VB.CC.CMU.EDU; Sun, 13 Mar 88 18:55 EST
Received: from TCP-DAEMON by vms.cis.pittsburgh.edu; Sun, 13 Mar 88 18:48 EDT
Received: by unix.cis.pittsburgh.edu (5.54/6.29)	id AA27103; Sun, 13 Mar 88
 18:47:38 EST
Date: Sun, 13 Mar 88 18:47:36 EDT
From: "Carl M. Fongheiser" <cmf%unix.CIS.PITTSBURGH.EDU@VB.CC.CMU.EDU>
Subject: Re: nntp for CMU-TEK
To: cmu-tek-tcp@C.CS.CMU.EDU
Message-Id: <8803132347.AA27103@unix.cis.pittsburgh.edu>
X-Mailer: Elm [version 1.5b]

I have a clientlib.c file which uses CMU-TEK TCP.  It is currently in use
in my near-completion rn for VMS.  Anyway, since it's not too long, I'm
enclosing it.

				Carl Fongheiser
				University of Pittsburgh
				cmf%vms.cis.pittsburgh.edu@vb.cc.cmu.edu
				cmf@pittvms.BITNET
				...!pitt!cisunx!cmf

---------------------------- Cut here ---------------------------------
/* DEC/CMS REPLACEMENT HISTORY, Element CLIENTLIB.C*/
/* *1    19-NOV-1987 16:18:31 CMF "NNTP Client access routines via CMU/TEK TCP"*/
/* DEC/CMS REPLACEMENT HISTORY, Element CLIENTLIB.C*/
/*
 * NNTP client routines
 *
 * Carl Fongheiser, University of Pittsburgh
 *
 * Dependencies:
 *
 *  CMU/TEK TCP (known to be compatible with 6.0 and 6.2)
 *  NNTP server (known to communicate with version 1.3 on Unix)
 */

#include <stdio.h>
#include <iodef.h>
#include <ssdef.h>
#include <descrip.h>
#include "response_codes.h"

unsigned short ser_unit;	/* Unit to communicate with server */

/*
 * server_init()  Get a connection to the remote news server
 *
 *    Parameters:       "machine" is the machine to connect to
 *
 *    Returns:          -1 on error, 0 otherwise.
 *
 *    Side Effects:      connects to server.
 */

server_init(machine)
char *machine;
{
  char line[256];

  if (getsocket(machine) < 0)	/* Get a socket to the server, */
    return(-1);			/* return if an error occurred */

  /* Now get the server's signon message */

  (void) get_server(line, sizeof(line));
  if (line[0] != CHAR_OK) {
    (void) sys$dassgn(ser_unit);
    return(-1);
  }
  return(0);
}

/*
 * getsocket -- get us a TCP channel connected to the news server.
 *
 *    Parameters:   "machine" is the machine the server is running on.
 *
 *    Returns:      0 on success, -1 on error.
 *
 *    Side effects: Connects to server, deposits channel number in ser_unit.
 *
 *    Errors:       Signalled.
 */

getsocket(machine)
char *machine;
{
  $DESCRIPTOR(ipdsc,"IP:");
  unsigned short status;
  unsigned short iosb[4];

  status = sys$assign(&ipdsc, &ser_unit, 0, 0);
  if ((status & 1) == 0) {
    lib$signal(status);
    return(-1);
  }
  status = sys$qiow(0, ser_unit, IO$_CREATE, iosb, 0, 0,
		    machine, 119, 0, 1, 0, 300);
  if ((status & 1) == 0) {
    lib$signal(status);
    return(-1);
  }
  if ((iosb[0] & 1) == 0) {
    if (iosb[0] == SS$_ABORT)
      lib$signal(*(int *) &iosb[2]);
    else
      lib$signal(iosb[0]);
    return(-1);
  }
  return(0);
}

/*
 * put_server() -- send a line of text to the server, terminating it
 * with CR and LF, as per ARPA standard.
 *
 *   Parameters:       "string" is the string to be sent to the server.
 *
 *   Returns:          Nothing.
 *
 *   Side effects:     Talks to the server.
 *
 *   Note:             This routine sets the push bit each time it is
 *                     called.  For large transmissions (i.e., posting
 *                     news) don't use it.  Instead, do the QIOW's
 *                     yourself and set the push bit when you're done.
 */

void
put_server(string)
char *string;
{
#ifdef DEBUG
  fprintf(stderr,">>> %s\n", string);
#endif
  sys$qiow(0, ser_unit, IO$_WRITEVBLK, 0, 0, 0,
	   string, strlen(string), 0, 0, 0, 0);
  sys$qiow(0, ser_unit, IO$_WRITEVBLK, 0, 0, 0,
	   "\r\n", 2, 0, 1, 0, 0);
}

static char nntp_buffer[1024];
static int  nntp_ptr;
static int  nntp_size = 0;

/*
 * get_server -- get a line of text from the server.  Strips
 * CR's and LF's.
 *
 *    Parameters:        "string" has the buffer space for the line
 *                       received.  "size" is the size of the buffer.
 *
 *    Returns:           -1 on error, 0 otherwise.
 *
 *    Side effects:      Talks to server, changes contents of "string"
 */

get_server(string, size)
char *string;
int size;
{
  register char *cp;
  register int c = 0;

  for (cp = string; size; cp++,size--) {
    c = nntp_getchar();
    if (c < 0)
      return(-1);
    if (c == '\n') {
      *cp = '\0';
      break;
    } else
      *cp = (char) c;
  }
  cp = strchr(string, '\r');
  if (cp)
    *cp = '\0';
#ifdef DEBUG
  fprintf(stderr,"<<< %s\n",string);
#endif

  return(0);
}

static int nntp_getchar()
{
  if (nntp_size == 0)
    return (nntp_fillbuf());
  nntp_size--;
  return(nntp_buffer[nntp_ptr++]);
}

static int nntp_fillbuf()
{
  int status;
  unsigned short iosb[4];

  status = sys$qiow(0, ser_unit, IO$_READVBLK, iosb, 0, 0,
		    nntp_buffer, sizeof(nntp_buffer), 0, 0, 0, 0);
  if ((status & 1) == 0)
    return(-1);
  if ((iosb[0] & 1) == 0)
    return(-1);
  if (iosb[1] == 0)
    return(-1);
  nntp_ptr = 0;
  nntp_size = iosb[1]-1;
  return(nntp_buffer[nntp_ptr++]);
}

/*
 * close_server -- close the connection to the server, after sending the
 *                 "QUIT" command.
 *
 *    Parameters:        None.
 *
 *    Returns:           Nothing.
 *
 *    Side effects:      Closes the connection with the server.
 *                       You can't use "put_server" or "get_server"
 *                       after this routine is called.
 */

void
close_server()
{
  char ser_line[256];

  put_server("QUIT");
  (void) get_server(ser_line, sizeof(ser_line));
  (void) sys$dassgn(ser_unit);
}
