#module NNTP_TCPWIN "V5.5"

/*
**++
**  FACILITY:
**
**      NNTP_TCPWIN
**
**  ABSTRACT:
**
**      This module contains the QIO interface to the WIN implementation
**      of TCP/IP, V3.0.  The module provices a single-threaded interface to
**      the NEWSSERVER module.
**
**  AUTHOR:
**
**      Geoff Huston
**
**  COPYRIGHT:
**
**      Copyright © 1988
**
**  MODIFICATION HISTORY:
**
**      V6.0     7-Oct-1988     GIH
**          Included modifications for WIN TCP/IP V3.0 support by Jim Patterson
**          (jimp@cognos.uucp)
**          NOTE: I have NOT tested the WIN support modifications.
**--
**/

#include descrip
#include iodef
#include signal
#include stdio

                                /* Include WIN internet definitions */
#include <types.h>
#include <socket.h>
#include <netdb.h>

#define TIMEOUT     600         /* read wait timeout  - 10 minutes */
#define X_BUF_SIZE  2048        /* size of line assembly read buffer */

                                /* check status bits */
#define cks(s)      if (!((c$status = (s)) & 1)) lib$signal(c$status)

static unsigned short f;               /* tcp i/o channel */

static int c$status;                   /* return status */

static unsigned short iosb[4];    /* i/o status blocks */
static unsigned short *i_o_sts = iosb;
static char nntp_buffer[X_BUF_SIZE];
static char *nntp_ptr = nntp_buffer;
static int nntp_size = 0;

int (*next_function)();

main()
{
    if (!server_init(1)) exit(1);
    if (!open_net()) exit(1);
    server_init_unit(1);
    while (next_function) (*next_function)(1);
    server_shut();
    close_net();
}

/*
 *  cancel_net
 *
 *  If the read timer expires then cancel this server task (by exiting)
 */

cancel_net()
{
#ifdef DEBUG
    fprintf(stderr,"Cancel_net\n");
#endif
    sys$cancel(f);
    write_net("400 service discontinued - read timeout\r\n");
    cks(sys$qiow(0,f,IO$_DELETE,iosb,0,0,0,0,0,0,0,0));
    cks(*i_o_sts);
    sys$dassgn(f);
    exit(1);
}

static int nntp_fillbuf()
{
    signal(SIGALRM,cancel_net);
    alarm(TIMEOUT);
    cks(sys$qiow(0,f,IO$_READVBLK,iosb,0,0,nntp_buffer, sizeof(nntp_buffer),0,0,0,0));
    alarm(0);
    if (!iosb[1]) return(-1);
    nntp_ptr = nntp_buffer;
    nntp_size = iosb[1]-1;
    return(*nntp_ptr++);
}

static int nntp_getchar()
{
    if (!nntp_size) return(nntp_fillbuf());
    nntp_size--;
    return(*nntp_ptr++);
}

/*
 *  read_net
 *
 *  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"
 */

read_net(string, size,unit)
    char *string;
    int size;
    int unit;
{
    char *cp;
    int c = 0;

    for (cp = string; size; size--) {
        c = nntp_getchar();
        if (c == '\r') c = nntp_getchar(); /* skip CR */
        *cp++ = c;
        if (c == '\n') break;
        }
    *cp = '\0';
#ifdef DEBUG
    fprintf(stderr,"Read_net:%s\n",string);
#endif
    return(0);
}

/*
 *  write_net
 *
 *  write to the client process - catch i/o errors and abort
 */

write_net(s,unit)
    char *s;
    int unit;
{
#ifdef DEBUG
    fprintf(stderr,"Write_net:%s\n",s);
#endif
    cks(sys$qiow(0,f,IO$_WRITEVBLK,iosb,0,0,s,strlen(s),0,1,0,0));
    cks(*i_o_sts);
}

next_call(unit,func,type)
    int unit;
    int (*func)();
    int type;
{
    next_function = func;
}

/*
 *  open_net
 *
 *  Open TCP channel
 */

open_net()
{
                                        /* WIN TCP modifications: */
    $DESCRIPTOR(ipdsc,"INET:");
    struct hostent dest_host;

#ifdef DEBUG
    fprintf(stderr,"Open_net\n");
#endif
    cks(sys$assign(&ipdsc,&f,0,0));
    cks(sys$qiow(0,f,IO$_ACCESS,iosb,0,0,AF_INET,SOCK_STREAM,119,0,0,0));
    cks(*i_o_sts);
    return(1);
}

/*
 *  close_net
 *
 *  Close the TCP link
 */

close_net()
{
#ifdef DEBUG
    fprintf(stderr,"Close_net\n");
#endif
    sys$cancel(f);
    cks(sys$qiow(0,f,IO$_DELETE,iosb,0,0,0,0,0,0,0,0));
    cks(*i_o_sts);
    sys$dassgn(f);
}
