#module NEWSREMCLIENT "V5.6"

/*
**++
**  FACILITY:
**
**      NEWSREMCLIENT
**
**  ABSTRACT:
**
**      Interface between local NEWS reader and a remote NNTP implementation.
**      This module contains all necessary calls to access the remote site
**      using NNTP.
**
**  AUTHOR:
**
**      Geoff Huston
**
**  COPYRIGHT:
**
**      Copyright © 1988
**
**  MODIFICATION HISTORY:
**
**      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.
**
**          Changed DECnet object name to "NNTP".
**
**          Allow task definition by the logical name NEWS_node_TASK
**          i.e. DEFINE NEWS_CSC_TASK "NEWS="
**
**      V5.6    11-Nov-1988     GIH
**          Add get_server_header to get the remote item header only
**
**--
**/

#include "newsinclude.h"
#include "newsdefine.h"
#include "newsextern.h"
#include iodef

#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 TMP_FILE_NAME "SYS$SCRATCH:NEWS_REMOTE.ITEM"
#define X_BUF_SIZE 1024

char client_msg[132];
char get_server_title[132];
int  get_server_size;

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;

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

static struct nol {
        char *nodename;
        char *taskname;
        struct nol *next;
        } *nh = 0;


/*
 *  net_write
 *
 *  Write a string to the net channel
 */

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

    strcpy(obuf,b);
    strcat(obuf,"\r\n");
    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))) {
        char proto_type;

        if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
        else if (net_proto == WINTCP) proto_type = 'W';
#endif
        else proto_type = 'D';
        close_net();
        sprintf(client_msg,"Lost connection to NEWS SERVER ([%c] %s)",proto_type,net_open_chan);
        *net_open_chan = 0;
        net_read_status = 0;
        return(0);
    }
    return(1);
}

/*
 *  net_read
 *
 *  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) {
            char proto_type;

            if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
            else if (net_proto == WINTCP) proto_type = 'W';
#endif
            else proto_type = 'D';
            close_net();
            sprintf(client_msg,"Lost connection to NEWS SERVER ([%c] %s)",proto_type,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)) {
            char proto_type;

            if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
            else if (net_proto == WINTCP) proto_type = 'W';
#endif
            else proto_type = 'D';
            close_net();
            sprintf(client_msg,"Cannot read from NEWS SERVER ([%c] %s)",proto_type,net_open_chan);
            hiber_state = net_read_status = 0;
            *net_open_chan = 0;
            return(0);
        }

        sys$hiber();
        hiber_state = 0;

        if (!net_read_status) {
            char proto_type;

            if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
            else if (net_proto == WINTCP) proto_type = 'W';
#endif
            else proto_type = 'D';
            close_net();
            sprintf(client_msg,"Read timed out from NEWS SERVER ([%c] %s)",proto_type,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)) {
                char proto_type;

                if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
                else if (net_proto == WINTCP) proto_type = 'W';
#endif
                else proto_type = 'D';
                sys$dassgn(net_chan);
                sprintf(client_msg,"NEWS SERVER has exited ([%c] %s)",proto_type,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 {
        struct nol *tmp;

        s_to_upper(node);
        tmp = nh;
        while (tmp) {
            if (!strcmp(node,tmp->nodename)) break;
            tmp = tmp->next;
            }
        if (!tmp) {
            char logname[64],
                 *gotenv;

            sprintf(logname,"NEWS_%s_TASK",node);
            if (gotenv = getenv(logname)) strcpy(logname,gotenv);
            else sprintf(logname,"TASK=NNTP");

            tmp = malloc(sizeof *tmp);
            strcpy((tmp->nodename = malloc(strlen(node) + 1)),node);
            strcpy((tmp->taskname = malloc(strlen(logname) + 1)),logname);
            tmp->next = nh;
            nh = tmp;
            }
        sprintf(netobj,"%s::\"%s\"",node,tmp->taskname);
        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) {
           char proto_type;

            if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
            else if (net_proto == WINTCP) proto_type = 'W';
#endif
            else proto_type = 'D';
            close_net();
            sprintf(client_msg,"Lost connection to NEWS SERVER ([%c] %s)",proto_type,net_open_chan);
            *net_open_chan = 0;
            }
        return(0);
        }
    return(1);
}

/*
 *  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;
{
    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)) {
            char proto_type;

            if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
            else if (net_proto == WINTCP) proto_type = 'W';
#endif
            else proto_type = 'D';
            sprintf(client_msg,"Cannot connect to NEWS SERVER ([%c] %s)",proto_type,net_open_chan);
            net_read_status = 0;
            *net_open_chan = 0;
            return(0);
            }
        else net_proto = proto;
        if (!(wait_net_response(CLIENT_TIMER,1))) {
            char proto_type;

            if (net_proto == CMUTCP) proto_type = 'T';
#ifdef TWG
            else if (net_proto == WINTCP) proto_type = 'W';
#endif
            else proto_type = 'D';
            close_net();
            net_read_status = 0;
            *net_open_chan = 0;
            sprintf(client_msg,"Cannot connect to NEWS SERVER ([%c] %s)",proto_type,net_open_chan);
            return(0);
            }
        }
    return(1);
}

/*
 *  get_server_file
 *
 *  Get a newsitem text from remote system
 */

FILE *get_server_file(id,node,tmp_name,put_file,proto)
    char *id,
         *node,
         *tmp_name,
         *put_file;
    int proto;
{
    FILE *fpw;
    char cmd[132];
    int data = 0,
        ofile,
        ifile;

    sprintf(err_oline,"\tConnecting to NEWS SERVER on node %s:: ...\n",node);
    err_line(err_oline);
    if (screen_active) {
        smg$end_pasteboard_update(&pid);
        smg$begin_pasteboard_update(&pid);
        }
    if (!tmp_name) tmp_name = cmd;
    *tmp_name = '\0';
    if (!open_rem_chan(node,proto)) {
        sprintf(err_oline,"\tERROR - Cannot connect to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    sprintf(cmd,"ARTICLE %s",id);
    if (!net_write(cmd) || (wait_net_response(CLIENT_TIMER,1) != 220)) {
        sprintf(err_oline,"\tERROR - Lost link to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    fpw = fopen(TMP_FILE_NAME,"w");
    get_server_size = 0;
    *get_server_title = '\0';
    while (wait_net_response(RESP_TIMER,0) == 1) {
        if (!strcmp(ibuf,".\n")) break;
        else if (!strcmp(ibuf,"..\n")) strcpy(ibuf,".\n");
        ++data;
        fputs(ibuf,fpw);
        if (!get_server_size && !strncmp(ibuf,"Lines:",6)) {
            if (!sscanf(ibuf,"Lines: %d",&get_server_size)) get_server_size = 0;
            }
        else if ((!*get_server_title) && !strncmp(ibuf,"Subject:",8)) {
            char *cp;
            strcpy(get_server_title,ibuf + 9);
            if (cp = strchr(get_server_title,'\n')) *cp = '\0';
            }
        }
    fclose(fpw);
    if ((!data) || (strcmp(ibuf,".\n"))) {
        while (!(delete(TMP_FILE_NAME)));
        sprintf(err_oline,"\tERROR - Lost link to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    if (put_file)
    {
        sysprv();
        if (!(ifile = rms_open(TMP_FILE_NAME))) {
            nosysprv();
            if (fpw = fopen(TMP_FILE_NAME,"r")) strcpy(tmp_name,TMP_FILE_NAME);
            else while (!(delete(TMP_FILE_NAME)));
            clear_err_line();
            return(fpw);
            }
        if (!(ofile = rms_create(put_file,0xa000))) {
            nosysprv();
            if (fpw = fopen(TMP_FILE_NAME,"r")) strcpy(tmp_name,TMP_FILE_NAME);
            else while (!(delete(TMP_FILE_NAME)));
            clear_err_line();
            return(fpw);
            }
        while (rms_get(ibuf,511,ifile)) rms_put(ibuf,ofile);
        rms_close(ifile);
        rms_close(ofile);
        nosysprv();
        while (!(delete(TMP_FILE_NAME)));
        if (fpw = fopen(put_file,"r")) *tmp_name = 1;
        clear_err_line();
        return(fpw);
        }
    if (fpw = fopen(TMP_FILE_NAME,"r")) strcpy(tmp_name,TMP_FILE_NAME);
    else while (!(delete(TMP_FILE_NAME)));
    clear_err_line();
    return(fpw);
}

/*
 *  get_server_header
 *
 *  Get a newsitem header from remote system
 */

FILE *get_server_header(id,node,tmp_name,proto)
    char *id,
         *node,
         *tmp_name;
    int proto;
{
    FILE *fpw;
    char cmd[132];
    int data = 0,
        ofile,
        ifile;

    sprintf(err_oline,"\tConnecting to NEWS SERVER on node %s:: ...\n",node);
    err_line(err_oline);
    if (screen_active) {
        smg$end_pasteboard_update(&pid);
        smg$begin_pasteboard_update(&pid);
        }
    if (!tmp_name) tmp_name = cmd;
    *tmp_name = '\0';
    if (!open_rem_chan(node,proto)) {
        sprintf(err_oline,"\tERROR - Cannot connect to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    sprintf(cmd,"HEAD %s",id);
    if (!net_write(cmd) || (wait_net_response(CLIENT_TIMER,1) != 220)) {
        sprintf(err_oline,"\tERROR - Lost link to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    fpw = fopen(TMP_FILE_NAME,"w");
    get_server_size = 0;
    *get_server_title = '\0';
    while (wait_net_response(RESP_TIMER,0) == 1) {
        if (!strcmp(ibuf,".\n")) break;
        else if (!strcmp(ibuf,"..\n")) strcpy(ibuf,".\n");
        ++data;
        fputs(ibuf,fpw);
        if (!get_server_size && !strncmp(ibuf,"Lines:",6)) {
            if (!sscanf(ibuf,"Lines: %d",&get_server_size)) get_server_size = 0;
            }
        else if ((!*get_server_title) && !strncmp(ibuf,"Subject:",8)) {
            char *cp;
            strcpy(get_server_title,ibuf + 9);
            if (cp = strchr(get_server_title,'\n')) *cp = '\0';
            }
        }
    fclose(fpw);
    if ((!data) || (strcmp(ibuf,".\n"))) {
        while (!(delete(TMP_FILE_NAME)));
        sprintf(err_oline,"\tERROR - Lost link to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    if (fpw = fopen(TMP_FILE_NAME,"r")) strcpy(tmp_name,TMP_FILE_NAME);
    else while (!(delete(TMP_FILE_NAME)));
    clear_err_line();
    return(fpw);
}

/*
 *  server_check_ids
 *
 *  Obtain a directory from the remote system for a newsgroup
 */

server_check_ids(check_id_head)
    struct grps *check_id_head;
{
    struct grps *reply = check_id_head;
    struct itms *tmp;
    char cmd[132];
    struct tm *stm;

    while (reply) {
        printf("\tWorking on %s (Served on %s::)\n",reply->grpname,reply->grpnode);
        if (open_rem_chan(reply->grpnode,reply->nproto)) {
            stm = localtime(&(reply->grptime));
            sprintf(cmd,"XUPDGROUP %s %02d%02d%02d %02d%02d%02d",reply->grpname,stm->tm_year,stm->tm_mon + 1,stm->tm_mday,stm->tm_hour,stm->tm_min,stm->tm_sec);
            if (net_write(cmd)) {
                if (wait_net_response(CLIENT_TIMER,1) == 380) {
                    tmp = reply->ids;
                    while (tmp) {
                        sprintf(cmd,"%s",tmp->itmid);
                        if (!net_write(cmd)) {
                            printf("\t\tLost link to NEWS Server on %s\n",reply->grpnode);
                            reply = reply->grpsnext;
                            continue;
                            }
                        tmp = tmp->itmsnext;
                        }
                    if (!net_write(".")) {
                        printf("\t\tLost link to NEWS Server on %s\n",reply->grpnode);
                        reply = reply->grpsnext;
                        continue;
                        }
                    if (!(wait_net_response(CLIENT_TIMER,1) == 280)) {
                        printf("\t\tLost link to NEWS Server on %s\n",reply->grpnode);
                        reply = reply->grpsnext;
                        continue;
                        }
                    while (wait_net_response(RESP_TIMER,0) == 1) {
                        if (!strcmp(ibuf,".\n")) break;
                        tmp = malloc(sizeof *tmp);
                        if (*ibuf == 'D') {
                            ibuf[strlen(ibuf) - 1] = '\0';
                            strcpy(tmp->itmid,&ibuf[2]);
                            tmp->itmdate = 0;
                            tmp->itmsnext = reply->idr;
                            reply->idr = tmp;
                            }
                        else if (sscanf(ibuf,"%s %d %d %[^\n]",tmp->itmid,&(tmp->itmdate),&(tmp->itmsize),tmp->itmtitle) == 4) {
                            tmp->itmsnext = reply->idr;
                            reply->idr = tmp;
                            }
                        else free(tmp);
                        }
                    }
                else {
                    sprintf(cmd,"NEWNEWS %s %02d%02d%02d %02d%02d%02d",reply->grpname,stm->tm_year,stm->tm_mon + 1,stm->tm_mday,stm->tm_hour,stm->tm_min,stm->tm_sec);
                    if (net_write(cmd) && (wait_net_response(CLIENT_TIMER,1) == 230)) {
                        while (wait_net_response(RESP_TIMER,0) == 1) {
                            if (!strcmp(ibuf,".\n")) break;
                            tmp = malloc(sizeof *tmp);
                            tmp->itmsnext = reply->idr;
                            reply->idr = tmp;
                            sscanf(ibuf,"%s",tmp->itmid);
                            time(&tmp->itmdate);
                            tmp->itmsize = 0;
                            }
                        }
                    else printf("\t\tLost link to NEWS Server on %s\n",reply->grpnode);
                    }
                }
            else printf("\t\tLost link to NEWS Server on %s\n",reply->grpnode);
            }
        else printf("\t\tNo link to NEWS Server on %s\n",reply->grpnode);
        reply = reply->grpsnext;
        }
}

server_get_titles(reply,irecheck)
    struct grps *reply;
    struct itms *irecheck;
{
    char cmd[132];

    printf("\tTitle search on %s (Served on %s::)\n",reply->grpname,reply->grpnode);
    while (irecheck) {
        *(irecheck->itmtitle) = '\0';
        if (open_rem_chan(reply->grpnode,reply->nproto)) {
            sprintf(cmd,"HEAD %s",irecheck->itmid);
            if ((net_write(cmd)) && (wait_net_response(CLIENT_TIMER,1) == 221)) {
                char *cp;

                while (wait_net_response(RESP_TIMER,0) == 1) {
                    if (!strcmp(ibuf,".\n")) break;
                    else if (!strcmp(ibuf,"..\n")) strcpy(ibuf,".\n");
                    if (cp = strchr(ibuf,'\n')) *cp = '\0';
                    if ((!*(irecheck->itmtitle)) && !strncmp(ibuf,"Subject:",8)) {
                        strncpy(irecheck->itmtitle,ibuf + 9,SUBJLEN);
                        irecheck->itmtitle[SUBJLEN - 1] = '\0';
                        }
                    }
                }
            }
        if (!*(irecheck->itmtitle)) *(irecheck->itmid) = '\0';
        irecheck = irecheck->itmsnext;
        }
}

char *server_get_newsgroups(node,proto,sincetime)
    char *node;
    int proto,
        sincetime;
{
    char cmd[132];
    int malloc_size = 0,
        resp_size = 0;
    char *return_buf = 0;
    struct tm *stm;

    sprintf(err_oline,"\tConnecting to NEWS SERVER on node %s:: ...\n",node);
    err_line(err_oline);
    if (screen_active) {
        smg$end_pasteboard_update(&pid);
        smg$begin_pasteboard_update(&pid);
        }
    if (!open_rem_chan(node,proto)) {
        sprintf(err_oline,"\tERROR - Cannot connect to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    if (sincetime) {
        stm = localtime(&sincetime);
        sprintf(cmd,"NEWGROUPS %02d%02d%02d %02d%02d%02d",stm->tm_year,stm->tm_mon + 1,stm->tm_mday,stm->tm_hour,stm->tm_min,stm->tm_sec);
        }
    else sprintf(cmd,"LIST");
    if (!net_write(cmd) || (wait_net_response(CLIENT_TIMER,1) != 215)) {
        sprintf(err_oline,"\tERROR - Lost link to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        return(0);
        }
    return_buf = malloc(malloc_size = 512);
    *return_buf = '\0';
    while (wait_net_response(RESP_TIMER,0) == 1) {
        if (!strcmp(ibuf,".\n")) break;
        resp_size += strlen(ibuf);
        if (malloc_size < resp_size + 10) return_buf = realloc(return_buf,(malloc_size += (resp_size + 512)));
        strcat(return_buf,ibuf);
        }
    if (strcmp(ibuf,".\n")) {
        sprintf(err_oline,"\tERROR - Lost link to NEWS SERVER on node %s::\n",node);
        err_line(err_oline);
        if (screen_active) {
            smg$end_pasteboard_update(&pid);
            smg$begin_pasteboard_update(&pid);
            }
        }
    return(return_buf);
}
/*
 *  s_to_upper
 *
 *  convert a string to lower case
 */

s_to_upper(s)
    char *s;
{
    char *save = s;
    while (*s) {
        *s = toupper(*s);
        s++;
        }
    return(save);
}
