#module NNTP_FEED "V5.5"

/*
**++
**  FACILITY:
**
**      NNTP_FEED
**
**  ABSTRACT:
**
**      Use the NNTP IHAVE command to manage NEWS distribution
**
**  AUTHOR:
**
**      Geoff Huston
**
**  COPYRIGHT:
**
**      Copyright © 1988
**
**  MODIFICATION HISTORY:
**
**      V5.3    14-Jun-1988     GIH
**                              Applied various BUG FIXES - Mats Sundvall
**
**      V5.4    16-Aug-1988     MS (Mats Sundvall)
**                              Logging code added
**
**      V5.5     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 "newsinclude.h"
#include "newsdefine.h"
#include iodef
#include lnmdef
#include time
#include psldef

#define LOG_TABLE   "LNM$SYSTEM"

#define CMUTCP     1

#ifdef TWG
#define  WINTCP     2
#include <types.h>
#include <socket.h>
#include <netdb.h>
#include <in.h>
#include <inetiodef.h>

#define NNTP_PORT       (119)

struct host_ent dest_host;
struct sockaddr_in data_socket = {0};
#endif

#define CLIENT_TIMER 120
#define RESP_TIMER 30
#define MAX_NOISE  10
#define X_BUF_SIZE 1024
#define OUT_BUF_TERM "\n"

static char net_open_chan[20] = {""},
            ibuf[X_BUF_SIZE],
            obuf[512],
            xbuf[X_BUF_SIZE + 1];

static char *rptr;

static unsigned short net_chan,
             trm;
static int net_read_status = 0,
           hiber_state = 0,
           cmd_code,
           net_proto = 0,
           status;

static struct iosb {
    unsigned short iostatus;
    unsigned short iosize;
    int netinfo;
    } read_iosb,
      write_iosb;

struct FAB grpfab,              /* newsgroup file fab */
           itmfab;              /* newsitem file fab */


struct RAB grprab,              /* newsgroup file rab */
           itmrab;              /* newsitem file rab */

ITM newsitm;                    /* newsitem i/o buffer */


GRP newsgrp;                    /* newsgroup i/o buffer */

static int *c$_tmphead = 0;         /* head of side list */

int     failed = 0,
        expired = 0,
        accepted = 0,
        rejected = 0,
        offered = 0;

char    lhost[32],
        node[32],
        datum[32],
        logfile[256],
        dbgfile[256],
        idfile[256];

dat()
{
    struct tm *stm;
    int cur_time;
    char *p;
    static char *node_name = 0;
    static int seq = 0;

    time(&cur_time);
    p = ctime(&cur_time);
    p += 4;
    stm = localtime(&cur_time);
    sprintf(datum,"%d %.3s %d %02d:%02d:%02d ",
        stm->tm_mday,p,stm->tm_year,stm->tm_hour,stm->tm_min,stm->tm_sec);
}

/*
 *  c$alloc_tmp
 *
 *  Allocate temporary storage for use with c$ calls
 */

static int *c$alloc_tmp(size)
    int size;
{
    int *tmp;

    tmp = malloc(size + 4);
    *tmp = c$_tmphead;
    c$_tmphead = tmp;
    return(c$_tmphead + 1);
}

/*
 *  c$dsc
 *
 * Allocate a string descriptor in the temp arg area
 */

c$dsc(str)
    char *str;
{
    struct dsc$descriptor *tmpdsc;

    tmpdsc = c$alloc_tmp(8);
    tmpdsc->dsc$w_length = strlen(str);
    tmpdsc->dsc$b_dtype = DSC$K_DTYPE_T;
    tmpdsc->dsc$b_class = DSC$K_CLASS_S;
    tmpdsc->dsc$a_pointer = str;
    return(tmpdsc);
}


/*
 *  c$cks
 *
 *  Check return status, signal errors, and free the temp argument area
 */

c$cks(status)
    int status;
{
    int *tmp;

    if (!(status & 1)) lib$signal(status);
    while (c$_tmphead) {
        tmp = *c$_tmphead;
        free(c$_tmphead);
        c$_tmphead = tmp;
        }
    return(status);
}


/*
 *  nosysprv
 *
 *  Turn off installed sysprv - BUT if user already had sysprv from AUTHORIZE
 *  then leave it on (as there is no change in user functionality)
 */

nosysprv()
{
    unsigned int authprivs[2], msysprv[2] ;
    int item = JPI$_AUTHPRIV;

    msysprv[0] = (1 << PRV$V_SYSPRV);
    msysprv[1] = 0;
    c$cks(lib$getjpi(&item,0,0,&authprivs,0,0));
    if (!(authprivs[0] & (1 << PRV$V_SYSPRV))) c$cks(sys$setprv(0,msysprv,0,0));

}


/*
 *  sysprv
 *
 *  Turn sysprv on as a temp priv - assumes image was installed with SYSPRV
 */

sysprv()
{
    unsigned int msysprv[2];

    msysprv[0] = (1 << PRV$V_SYSPRV);
    msysprv[1] = 0;
    c$cks(sys$setprv(1,msysprv,0,0));
}


/*----------------------------------------------------------------------
 *  n e t _ w r i t e
 *
 *  Write a string to the net channel
 *----------------------------------------------------------------------
 */

net_write(b)
    char *b;
{
    int status;

    strcpy(obuf,b);
    strcat(obuf,OUT_BUF_TERM);
    status = sys$qiow(0,net_chan,IO$_WRITEVBLK,&write_iosb,0,0,
        obuf,strlen(obuf),0,(net_proto == CMUTCP),0,0);
    if ((!status & 1) || (!((status = write_iosb.iostatus) & 1))) {
        close_net();
        printf("Lost connection to NEWS SERVER ([%c] %s)",
                (net_proto ? 'T' : 'D'),net_open_chan);
        *net_open_chan = 0;
        net_read_status = 0;
        return(0);
    }
    return(1);
}


/*----------------------------------------------------------------------
 *  n e t _ r e a d
 *
 *  AST routine from net read:
 *  If error from read then cancel link and set read status to 2
 *  Otherwise filter out return chars and then scan for newline char
 *----------------------------------------------------------------------
 */

net_read()
{
    char *cp;

    if (!(read_iosb.iostatus & 1)) {
        if (*net_open_chan) {
            close_net();
            printf("Lost connection to NEWS SERVER ([%c] %s)",
                (net_proto ? 'T' : 'D'),net_open_chan);
            *net_open_chan = 0;
            }
        net_read_status = 2;
        if (hiber_state) {
            sys$canwak(0,0);
            sys$wake(0,0);
            }
        }
    else {
        rptr[read_iosb.iosize] = '\0';
        cp = rptr;
        while (*rptr) {
            if (*rptr != '\r') *cp++ = *rptr;
            rptr++;
            }
        *cp = '\0';
        line_read();
        }
}

/*
 *  line_read
 *
 *  Extract a line form the comms buffer - If there is no line break
 *  character in the buffer then issue an async qio to read in more
 *  characters into the buffer.
 */

line_read()
{
    char *cp,
         *xptr = xbuf,
         sav_char;

    if (cp = strchr(xbuf,'\n')) {
        ++cp;
        sav_char = *cp;
        *cp = '\0';
        strcpy(ibuf,xbuf);
        *cp = sav_char;
        do *xptr++ = *cp; while (*cp++);
        net_read_status = 1;
        if (hiber_state) {
            sys$canwak(0,0);
            sys$wake(0,0);
            }
        return(1);
        }
    rptr = xbuf + strlen(xbuf);
    return(sys$qio(0,net_chan,IO$_READVBLK,&read_iosb,net_read,0,
                   rptr,X_BUF_SIZE - strlen(xbuf),0,0,0,0));
}

/*
 *  wait_net_response
 *
 *  Wait for a response from remote system - cmd indicates that all text
 *  should be skipped until NNTP command response is obtained
 */

wait_net_response(secs,cmd)
    int secs,
        cmd;
{
    int mins,
        sec,
        waittime[2];
    char bintime[30];

    mins = secs / 60;
    sec = secs & 60;

    sprintf(bintime,"0 0:%d:%d.00",mins,sec);
    sys$bintim(c$dsc(bintime),waittime);
    net_read_status = 0;
    while (!net_read_status) {
        sys$schdwk(0,0,waittime,0);
        hiber_state = 1;
        if (!(line_read() & 1)) {
            close_net();
            printf("Cannot read from NEWS SERVER ([%c] %s)",
                (net_proto ? 'T' : 'D'),net_open_chan);
            hiber_state = net_read_status = 0;
            *net_open_chan = 0;
            return(0);
        }

        sys$hiber();
        hiber_state = 0;

        if (!net_read_status) {
            close_net();
            printf("Read timed out from NEWS SERVER ([%c] %s)",
                (net_proto ? 'T' : 'D'),net_open_chan);
            net_read_status = 0;
            *net_open_chan = 0;
            return(0);
            }
        if (net_read_status == 2) return(0);
        net_read_status = 0;
        if (!cmd) return(1);
        if (sscanf(ibuf,"%d",&cmd_code) == 1) {
            if ((cmd_code == 400) || (cmd_code == 205)) {
                sys$dassgn(net_chan);
                printf("NEWS SERVER has exited ([%c] %s)",
                        (net_proto ? 'T' : 'D'),net_open_chan);
                *net_open_chan = 0;
                return(0);
                }
            else return(cmd_code);
            }
        }
}

/*
 *  open_net
 *
 *  Open network link
 */

open_net(node,proto)
    char *node;
    int proto;
{
    char netobj[32];

    strcpy(netobj,node);
    if (proto == CMUTCP) {
        if (sys$assign(c$dsc("IP:"),&net_chan,0,0) & 1) {
            if ((sys$qiow(0,net_chan,IO$_CREATE,&read_iosb,0,0,
                          netobj,119,0,1,0,300) & 1)
               && (read_iosb.iostatus & 1)) return(1);
            sys$dassgn(net_chan);
            }
        return(0);
        }
#ifdef TWG
    else if (proto == WINTCP) {
        if (sys$assign(c$dsc("INET:"),&net_chan,0,0) & 1) {
            if ((sys$qiow(0,net_chan,IO$_SOCKET,&read_iosb,0,0,
                    AF_INET,SOCK_STREAM,0,0,0,0) & 1) &&
               (read_iosb.iostatus & 1)) {

                dest_host = *gethostbyname(inpline);
                data_socket.sin_addr.s_addr = *((u_long *)dest_host.h_addr);
                data_socket.sin_family = AF_INET;
                data_socket.sin_port = htons(NNTP_PORT);
                if ((sys$qiow(0,net_chan,IO$_CONNECT,&read_iosb,0,
                        &data_socket,sizeof(data_socket),0,0,0,0) & 1) &&
                   (read_iosb.iostatus & 1)) return(1);
                }
            }
            sys$dassgn(net_chan);
            return(0);
        }
#endif
    else {
        sprintf(netobj,"%s::\"NEWS=\"",node);
        return(sys$assign(c$dsc(netobj),&net_chan,0,0) & 1);
        }
}

/*
 *  close_net
 *
 *  Close network link
 */

close_net()
{
    if (net_proto) {
        sys$cancel(net_chan);
        sys$qiow(0,net_chan,IO$_DELETE,0,0,0,0,0,0,0,0,0);
        }
    sys$dassgn(net_chan);
}

/*
 *  toggle_link
 *
 *  Write a non-command to the net chan and wait for the command-not-recognised
 *  response from the server.
 */

toggle_link()
{
    if (!net_write("YCMND") || (!(wait_net_response(RESP_TIMER,1)))) {
        if (*net_open_chan) {
            close_net();
            printf("Lost connection to NEWS SERVER ([%c] %s)",
                    (net_proto ? 'T' : 'D'),net_open_chan);
            *net_open_chan = 0;
            }
        return(0);
        }
    return(1);
}

/*
 *  s_to_lower
 *
 *  convert a string to lower case
 */

char *s_to_lower(s)
    char *s;
{
    char *save = s;
    while (*s) {
        *s = tolower(*s);
        s++;
        }
    return(save);
}

/*
 *  open_rem_chan
 *
 *  Open channel to remote NNTP server on host name node, using protocol
 *  proto (2 == WINTCP, 1 == CMUTCP, 0 = DECNET)
 */

open_rem_chan(node,proto)
    char *node;
    int proto;
{
    int reply;

    s_to_lower(node);
    if (*net_open_chan) {
        if ((proto != net_proto) || (strcmp(node,net_open_chan))) {
            close_net();
            net_read_status = 0;
            *net_open_chan = 0;
            }
        else toggle_link();
        }

    if (!*net_open_chan) {
        strcpy(net_open_chan,node);
        if (!open_net(net_open_chan,proto)) {
            net_read_status = 0;
            *net_open_chan = 0;
            return(0);
            }
        else net_proto = proto;
        if (!(reply = wait_net_response(CLIENT_TIMER,1))) {
            close_net();
            net_read_status = 0;
            *net_open_chan = 0;
            return(0);
            }
        if (reply!=200) {
            printf("Postings not allowed to NEWS SERVER ([%c] %s)",
                (net_proto ? 'T' : 'D'),net_open_chan);
            if (reply==201) {
                printf(",only transfer allowed.");
                return(1);
                }
            return(0);
            }
        }
    return(1);
}


emergency_break(fpr,fpi,fpw,fpd,logging,debugging,lines_written)
    FILE *fpr, *fpi, *fpw, *fpd;
    int debugging, lines_written,logging;
{
    char inpstr[132];
    FILE *fpl;

    fclose(fpr);
    fclose(fpi);
    if (logging){
        dat();
        fpl = fopen(logfile,"a+");
        fprintf(fpl,"%s %s: nntpxmit: %s %d offered %d accepted %d rejected %d failed %d expired\n",
                datum, lhost, node, offered, accepted, rejected, failed, expired);
        fprintf(fpl,"%s %s: nntpxmit: %s Connection lost. Transfer aborted.\n",
                datum, lhost, node);
         fclose(fpl);
         }
    if (lines_written && (failed || rejected || accepted)) {
        while (fgets(inpstr,132,fpr)) fprintf(fpw,"%s\n",inpstr);
        fclose(fpw);
        lib$rename_file(c$dsc("nntpfeed.tmp"),c$dsc(idfile),
                        0,0,0,0,0,0,0,0,0,0);
        }
    else {
        fclose(fpw);
        delete("nntpfeed.tmp;");
        }
    if (debugging) fclose(fpd);
    exit();
}

/*
 *  util_dir
 *
 *  Convert a newsgroup name to a VMS directory string
 */

char dir_result[SUBJLEN + SUBJLEN];

util_dir(input)
    char *input;
{
    char *p = dir_result,
         *in = input;

    while (*in) {
        if (isalnum(*in) || (*in == '-') || (*in == '.')) *p++ = *in++;
        else {
            *p++ = '_';
            if (*in == '_') *p++ = '_';
            else if (*in < '0') *p++ = (*in - '!') + 'A';
            else if (*in < 'A') *p++ = (*in - ':') + '0';
            else if (*in < 'a') *p++ = (*in - '[') + 'P';
            else *p++ = (*in - '{') + 'V';
            in++;
            }
        }
    *p = '\0';
    return(dir_result);
}

/*
 *  open_server_files
 *
 *  Open the item and newsgroup files for sharing
 */

open_server_files()
{
    itmfab = cc$rms_fab;
    itmfab.fab$b_bks = 4;
    itmfab.fab$b_fac = FAB$M_GET;
    itmfab.fab$l_fna = Item_file;
    itmfab.fab$b_fns = strlen(itmfab.fab$l_fna);
    itmfab.fab$w_mrs = sizeof newsitm;
    itmfab.fab$b_shr = FAB$M_SHRDEL | FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD;

    itmrab = cc$rms_rab;
    itmrab.rab$l_fab = &itmfab;
    itmrab.rab$b_krf = 0;
    itmrab.rab$b_ksz = 4;
    itmrab.rab$l_ubf = &newsitm;
    itmrab.rab$w_usz = sizeof newsitm;
    itmrab.rab$l_rbf = &newsitm;
    itmrab.rab$w_rsz = sizeof newsitm;

    grpfab = cc$rms_fab;
    grpfab.fab$b_fac = FAB$M_GET ;
    grpfab.fab$l_fna = Group_file;
    grpfab.fab$b_fns = strlen(grpfab.fab$l_fna);
    grpfab.fab$b_shr = FAB$M_SHRDEL | FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD;

    grprab = cc$rms_rab;
    grprab.rab$l_fab = &grpfab;
    grprab.rab$l_ubf = &newsgrp;
    grprab.rab$w_usz = sizeof newsgrp;
    grprab.rab$l_rbf = &newsgrp;
    grprab.rab$w_rsz = sizeof newsgrp;

    if (!((status = sys$open(&itmfab)) & 1)) return(0);
    if (!((status = sys$connect(&itmrab)) & 1)) return(0);
    if (!((status = sys$open(&grpfab)) & 1)) return(0);
    if (!((status = sys$connect(&grprab)) & 1)) return(0);
    return(1);
}

/*
 *  main
 */

main(argc,argv)
    int argc;
    char *argv[];
{
    char proto[32],
         l_id[IDLEN + 2],
         inpline[132],
         inpline0[256],
         itm_fname[256],
         cmd[132],
         *cp;
    int  proto_num = 0,
         last_ok = 1,
         lines_written = 0,
         have_open_channel_OK = 0,
         noise = 0,
         logging = 0,
         debugging = 0,
         reply,
         i;
    char exec_mode = PSL$C_EXEC,
         translate_value[256];
    unsigned int trnlist[4];
    unsigned short len;
    FILE *fpr,
         *fpi,
         *fpl,
         *fpw,
         *fpd;

    if ((argc < 4) || (argc > 6)) {
        printf("Usage: NNTPFEED node proto file [log] [dbgfile]\n");
        exit(1);
        }
    if (argc==6) {
        strcpy(logfile,argv[4]);
        strcpy(dbgfile,argv[5]);
        debugging = 1;
        logging = 1;
        }
    if (argc==5) {
        strcpy(logfile,argv[4]);
        logging = 1;
        }
    if (!open_server_files()) {
        printf("FileError: Cannot open NEWS datafiles\n");
        exit(1);
        }

   /*    Set up item list for exec mode logical names */

    trnlist[0] = (LNM$_STRING << 16) + LNM$C_NAMLENGTH;
    trnlist[1] = translate_value;
    trnlist[2] = &len;
    trnlist[3] = 0;

    if (!(sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_ADDRESS"),&exec_mode,&trnlist) & 1)) {
        printf("NEWS_ADDRESS not defined - exiting\n");
        exit(1);
        }
    else {
        translate_value[len] = '\0';
        s_to_lower(strcpy(lhost,translate_value));
        }

    strcpy(node,argv[1]);
    strcpy(proto,argv[2]);
    strcpy(idfile,argv[3]);

#ifdef TWG
    if (tolower(*proto) == 't') proto_num = WINTCP;
    if (tolower(*proto) == 'w') proto_num = WINTCP;
#else
    if (tolower(*proto) == 't') proto_num = CMUTCP;
    if (tolower(*proto) == 'c') proto_num = CMUTCP;
#endif
    sysprv();
    if (!(fpr=fopen(idfile,"r"))) {
        nosysprv();
        printf("FileError: Cannot open file: %s\n",idfile);
        exit(1);
        }
    if (cp = strchr(idfile,';')) *cp = '\0';
    fpw = fopen("nntpfeed.tmp","w");
    if(debugging) fpd = fopen(dbgfile,"w");

    printf("\tConnecting to NEWS SERVER on node %s:: ...\n",node);
    while (fgets(inpline,132,fpr)) {
        if (cp = strchr(inpline,'\n')) *cp = '\0';
        for (i = 0; i < (IDLEN + 2); ++i) l_id[i] = '\0';
        strncpy(l_id,inpline,IDLEN);
        s_to_lower(l_id);

        itmrab.rab$l_kbf = l_id;
        itmrab.rab$b_ksz = IDLEN + 2;
        itmrab.rab$b_krf = 1;
        itmrab.rab$l_rop = RAB$M_KGE | RAB$M_RRL | RAB$M_NLK;
        itmrab.rab$b_rac = RAB$C_KEY;

        grprab.rab$l_kbf = &(newsitm.itm_grp);
        grprab.rab$b_ksz = 2;
        grprab.rab$b_krf = 1;
        grprab.rab$l_rop = RAB$M_RRL | RAB$M_NLK;
        grprab.rab$b_rac = RAB$C_KEY;

        if ((!(sys$get(&itmrab) & 1)) || (strcmp(l_id,newsitm.itm_id)) || (!(sys$get(&grprab) & 1))) {
            if (debugging) fprintf(fpd,"ItemAccess: Cannot locate item %s\n",inpline);
            continue;
            expired++;
            }
        sprintf(itm_fname,Itm_template,util_dir(newsgrp.grp_name),newsitm.itm_num);
        if (!(fpi = fopen(itm_fname,"r"))) {
            if (debugging) fprintf(fpd,"FileAccess: Cannot open item file %s\n",itm_fname);
            if (debugging) fprintf(fpd, "Retry: %s\n",inpline);
            fprintf(fpw,"%s\n",inpline);
            ++lines_written;
            continue;
            }

        if (debugging && !have_open_channel_OK) fprintf(fpd,"X> Try open channel to remote node\n");
        if (!open_rem_chan(node,proto_num)) {
            if (debugging) fprintf(fpd,"Cannot connect to node, retry: %s\n",inpline);
            fprintf(fpw,"%s\n",inpline);
            ++lines_written;
            if (!last_ok) {
                if (++noise == MAX_NOISE) {
                    if (debugging) fprintf(fpd, "AccessError: To many retries on NEWS SERVER link to node %s::\n",node);
                    emergency_break(fpr,fpi,fpw,fpd,logging,debugging,lines_written);
                    }
                }
            else if (debugging) fprintf(fpd, "AccessError: No connection on NEWS SERVER link to node %s::\n",node);
            last_ok = 0;
            fclose(fpi);
            continue;
            }

        sprintf(cmd,"IHAVE %s",inpline);
        have_open_channel_OK = 1;

        if (debugging) fprintf(fpd,"X> %s< ",cmd);
        offered++;
        if ((!net_write(cmd)) || (!(reply = wait_net_response(CLIENT_TIMER,1)))) {
            fprintf(fpw,"%s\n",inpline);
            ++lines_written;
            fprintf(fpd, "No reply recieved, retry: %s\n",inpline);
            if (!last_ok) {
                if (++noise == MAX_NOISE) {
                    if (debugging) fprintf(fpd, "AccessError: To many retries on NEWS SERVER link to node %s::\n",node);
                    emergency_break(fpr,fpi,fpw,fpd,logging,debugging,lines_written);
                    }
                }
            else if (debugging) fprintf(fpd, "AccessError: Lost connection to NEWS SERVER on node %s::\n",node);
            last_ok = 0;
            fclose(fpi);
            continue;
            }
        if (debugging) fprintf(fpd,"%d>", reply);
        last_ok = 1;
        noise = 0;
        if ((reply == 435) || (reply == 437)) {
            rejected++;
            fclose(fpi);
            if (debugging) fprintf(fpd,"\n");
            continue;
            }
        if (reply != 335) {
            failed++;
            fclose(fpi);
            fprintf(fpw,"%s\n",inpline);
            ++lines_written;
            if (debugging) fprintf(fpd,"\n");
            continue;
            }
        while (fgets(inpline0,256,fpi)) {
            char *t;
            if (!strcmp(inpline0,".\n")) strcpy(inpline0,"..\n");
            if (t = strchr(inpline0,'\n')) *t = '\0';
            net_write(inpline0);
            }
        fclose(fpi);
        strcpy(inpline0,".");
        net_write(inpline0);
        if (!(reply = wait_net_response(CLIENT_TIMER,1))) {
            fprintf(fpw,"%s\n",inpline);
            ++lines_written;
            if (!last_ok) {
                if (++noise == MAX_NOISE) {
                    fprintf(fpd, "AccessError: To many retries on NEWS SERVER link to node %s::\n",node);
                    emergency_break(fpr,fpi,fpw,fpd,logging,debugging,lines_written);
                    }
                }
            else if (debugging) fprintf(fpd,"AccessError: Broken connection on NEWS SERVER link to node %s::\n",node);
            last_ok = 0;
            fclose(fpi);
            continue;
        }
        if (debugging) fprintf(fpd," %d\n",reply);
        if (reply == 435  || reply == 437) {
            rejected++;
            continue;
            }
        if (reply == 235) {
            accepted++;
            continue;
            }
        if (reply == 436 || reply == 441) {
            failed++;
            }
        fprintf(fpw,"%s\n",inpline);
        ++lines_written;
        }
    fclose(fpr);
    fclose(fpw);            /* close nntpfeed.tmp */
    if (lines_written) lib$rename_file(c$dsc("nntpfeed.tmp"),c$dsc(idfile),0,0,0,0,0,0,0,0,0,0);
    else delete("nntpfeed.tmp;");
    if (logging){
        dat();
        fpl = fopen(logfile,"a+");
        fprintf(fpl,"%s %s: nntpxmit: %s %d offered %d accepted %d rejected %d failed %d expired\n",
                datum, lhost, node, offered, accepted, rejected, failed, expired);
         fclose(fpl);
         }

    if (debugging) fclose(fpd);
    if (lines_written) strcat(idfile,";-1");
    while (!delete(idfile));
}
