gih900@CSC.ANU.OZ.AU (Geoff Huston) (01/18/90)
$! ................... Cut between dotted lines and save. ...................
$!...........................................................................
$! VAX/VMS archive file created by VMS_SHARE V06.10 7-FEB-1989.
$!
$! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from
$! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au).
$!
$! To unpack, simply save, concatinate all parts into one file and
$! execute (@) that file.
$!
$! This archive was created by user GIH900
$! on 17-JAN-1990 13:22:29.00.
$!
$! ATTENTION: To keep each article below 31 blocks (15872 bytes), this
$! program has been transmitted in 2 parts. You should
$! concatenate ALL parts to ONE file and execute (@) that file.
$!
$! It contains the following 1 file:
$! NNTP_XFER.C
$!
$!============================================================================
$ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL )
$ VERSION = F$GETSYI( "VERSION" )
$ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK
$ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", -
"VMS_SHARE V06.10 7-FEB-1989 requires VMS V4.4 or higher."
$ EXIT 44 ! SS$_ABORT
$VERSION_OK:
$ GOTO START
$!
$UNPACK_FILE:
$ WRITE SYS$OUTPUT "Creating ''FILE_IS'"
$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION -
VMS_SHARE_DUMMY.DUMMY
b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) )
; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE
, b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors
:= 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN
& "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION
( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail
& LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP
; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK
( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 )
; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip
<> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF
; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT )
; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip
:= MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip
<> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET )
; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part )
); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF
; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE
; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1
; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line
<> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF
; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors
:= i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT
( "The following line could not be unpacked properly:" ); SPLIT_LINE
; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL
( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH
( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1
); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP
; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION
( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO
( "The following !UL errors were detected while unpacking !AS", i_errors
, s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" )
; ENDIF; EXIT;
$ DELETE VMS_SHARE_DUMMY.DUMMY;*
$ CHECKSUM 'FILE_IS
$ WRITE SYS$OUTPUT " CHECKSUM ", -
F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." )
$ RETURN
$!
$START:
$ FILE_IS = "NNTP_XFER.C"
$ CHECKSUM_IS = 197966869
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/*
X**++
X** FACILITY:
X** NNTP_XFER
X**
X** ABSTRACT:
X** Use the NNTP NEWNEWS commands to implement a feed initiated by the
X** receiver rather than the IHAVE/SENDME protocol which is sender
X** initiated.
X**
X** AUTHOR:
X** Geoff Huston
X**
X** COPYRIGHT:
X** Copyright `169 1989
X**
X** MODIFICATION HISTORY:
X** V5.9.1`00925-Sep-1989`009GIH
X**`009 Initial version, based on NNTP_FEED
X**--
X**/
X`012
X#module NNTP_XFER "V5.9"
X
X#include "newsinclude.h"
X#include "newsdefine.h"
X
X#include iodef
X#include time
X#include signal
X
X
X#define CMUTCP 1
X#define WINTCP 2
X#define MULTINETTCP 3
X
X#ifdef TWG
X#define TWG 1
X#else
X#ifdef MULTINET
X#define MULTINET 1
X#endif
X#endif
X
X#if TWG `124`124 MULTINET
X#include <types.h>
X#include <socket.h>
X#include <netdb.h>
X#include <in.h>
X#include <inetiodef.h>
X
X#define NNTP_PORT (119)
X
Xstruct hostent *dest_host;
Xstruct sockaddr_in data_socket = `1230`125;
X#endif
X
X#define CLIENT_TIMER 250
X#define RESP_TIMER 30
X#define X_BUF_SIZE 1024
X#define MAX_BATCH_SIZE 250000
X#define MAX_RESTART_ATTEMPT`00920
X
Xchar net_open_chan[128] = `123""`125,
X ibuf[X_BUF_SIZE],
X fnode[256],
X scratch_area[256];
X
Xshort net_chan;
X
Xint cmd_code,
X offered = 0,
X accepted = 0,
X proto_num = 0,
X net_proto = 0,
X debugging = 0,
X logging = 0,
X days = 1;
X
Xstruct iosb_block `123
X unsigned short iostatus;
X unsigned short iosize;
X int netinfo;
X `125 iosb,
X write_iosb;
X
Xint *c$_tmphead = 0; /* head of side list */
X
Xchar node[128],
X logfile[256];
X
Xchar *s_to_upper();
X`012
X`012
X/*
X * c$alloc_tmp
X *
X * Allocate temporary storage for use with c$ calls
X */
X
Xint *c$alloc_tmp(size)
X int size;
X`123
X int *tmp;
X
X tmp = malloc(size + 4);
X *tmp = c$_tmphead;
X c$_tmphead = tmp;
X return(c$_tmphead + 1);
X`125
X
X/*
X * c$dsc
X *
X * Allocate a string descriptor in the temp arg area
X */
X
Xc$dsc(str)
X char *str;
X`123
X struct dsc$descriptor *tmpdsc;
X
X tmpdsc = c$alloc_tmp(8);
X tmpdsc->dsc$w_length = strlen(str);
X tmpdsc->dsc$b_dtype = DSC$K_DTYPE_T;
X tmpdsc->dsc$b_class = DSC$K_CLASS_S;
X tmpdsc->dsc$a_pointer = str;
X return(tmpdsc);
X`125
X
X/*
X * c$cks
X *
X * Check return status, signal errors, and free the temp argument area
X */
X
Xc$cks(status)
X int status;
X`123
X int *tmp;
X
X if (!(status & 1)) lib$signal(status);
X while (c$_tmphead) `123
X tmp = *c$_tmphead;
X free(c$_tmphead);
X c$_tmphead = tmp;
X `125
X return(status);
X`125
X
X/*
X * nosysprv
X *
X * Turn off installed sysprv - BUT if user already had sysprv from AUTHORIZE
X * then leave it on (as there is no change in user functionality)
X */
X
Xnosysprv()
X`123
X unsigned int authprivs[2], msysprv[2] ;
X int item = JPI$_AUTHPRIV;
X
X msysprv[0] = PRV$M_SYSPRV;
X msysprv[1] = 0;
X c$cks(lib$getjpi(&item,0,0,&authprivs,0,0));
X if (!(authprivs[0] & PRV$M_SYSPRV)) c$cks(sys$setprv(0,msysprv,0,0));
X`125
X
X/*
X * sysprv
X *
X * Turn sysprv on as a temp priv - assumes image was installed with SYSPRV
X */
X
Xsysprv()
X`123
X unsigned int msysprv[2];
X
X msysprv[0] = PRV$M_SYSPRV;
X msysprv[1] = 0;
X c$cks(sys$setprv(1,msysprv,0,0));
X`125
X`012
X/*
X * nntp_write
X *
X * Synchronous write of a string to the net channel
X */
X
Xnntp_write(b)
X char *b;
X`123
X static char obuf[512];
X int sts;
X
X strcpy(obuf,b);
X strcat(obuf,"\r\n");
X if (debugging) printf("nntp_write: %s",obuf);
X sts = sys$qiow(0,net_chan,IO$_WRITEVBLK,&write_iosb,0,0,
X obuf,strlen(obuf),0,(net_proto == CMUTCP),0,0);
X if (!(sts & 1) `124`124 !(write_iosb.iostatus & 1)) `123
X close_net();
X if (debugging) printf("nntp_write: Lost connection to Server\n");
X return(0);
X `125
X return(1);
X`125
X`012
X/*
X * nntp_read
X *
X * Timed read of the net channel for a full line
X */
X
Xjmp_buf nntp_env;
X
Xcancel_nntp_read()
X`123
X close_net();
X if (debugging) printf("nntp_read: ReadTimeout - Lost connection\n");
X longjmp(nntp_env,1);
X`125
X
Xnntp_read(b,timer)
X char *b;
X int timer;
X`123
X static char ibuf[X_BUF_SIZE + 1];
X struct iosb_block r_iosb;
X char *cp, *rp;
X int sts;
X
X *b = '\0';
X if (setjmp(nntp_env)) return(0);
X signal(SIGALRM,cancel_nntp_read);
X alarm(timer);
V sts = sys$qiow(0,net_chan,IO$_READVBLK,&r_iosb,0,0,ibuf,X_BUF_SIZE,0,0,0,0)
X;
X alarm(0);
X if (!(sts & 1) `124`124 (!(r_iosb.iostatus & 1))) `123
X close_net();
V if (debugging) printf("nntp_read: Error status return - connection lost\n
X");
X return(0);
X `125
X ibuf[r_iosb.iosize] = '\0';
X rp = ibuf;
X do `123
X if (cp = strchr(rp,'\r')) *cp++ = '\0';
X strcat(b,rp);
X rp = cp;
X `125 while(rp);
X return(1);
X`125
X`012
Xchar lbuf[X_BUF_SIZE + 1] = `123""`125;
X
Xnntp_read_line(b,timer)
X char *b;
X int timer;
X`123
X char *cp, *pp;
X
X *b = '\0';
X while (strlen(b) < 1024) `123
X if (cp = strchr(lbuf,'\n')) `123
X *cp = '\0';
X strcat(b,lbuf);
X strcat(b,"\n");
X ++cp;
X pp = lbuf;
X while (*pp++ = *cp++);
X return(1);
X `125
X strcat(b,lbuf);
X if (!nntp_read(lbuf,timer)) return(0);
X `125
X`125
X`012
X/*
X * wait_net_response
X *
X * Wait for a response from remote system - cmd indicates that all text
X * should be skipped until NNTP command response is obtained
X */
X
Xwait_net_response(secs,cmd)
X int secs,
X cmd;
X`123
X if (nntp_read_line(ibuf,secs)) `123
X if (debugging) printf("nntp_read: %s",ibuf);
X if (!cmd) return(1);
X if (sscanf(ibuf,"%d",&cmd_code) == 1) `123
X if ((cmd_code == 400) `124`124 (cmd_code == 205)) `123
X close_net();
X if (debugging) printf("nntp_read: connection shutdown response\n");
X return(0);
X `125
X else return(cmd_code);
X `125
X `125
X else `123
X if (debugging) printf("nntp_read: connection lost\n");
X return(0);
X `125
X`125
X`012
X/*
X * open_net
X *
X * Open network link
X */
X
Xopen_net(node,proto)
X char *node;
X int proto;
X`123
X char netobj[128];
X
X strcpy(netobj,node);
X if (proto == CMUTCP) `123
X if (!(sys$assign(c$dsc("IP:"),&net_chan,0,0) & 1)) return(0);
V if ( (sys$qiow(0,net_chan,IO$_CREATE,&iosb,0,0,netobj,119,0,1,0,300) &
X 1)
X && (iosb.iostatus & 1)) return(1);
X sys$dassgn(net_chan);
X return(0);
X `125
X#if TWG
X else if (proto == WINTCP) `123
X if (sys$assign(c$dsc("INET:"),&net_chan,0,0) & 1) `123
X#elif MULTINET
X else if (proto == MULTINETTCP) `123
X if (sys$assign(c$dsc("INET0:"),&net_chan,0,0) & 1) `123
X#endif
X#if TWG `124`124 MULTINET
V if ( (sys$qiow(0,net_chan,IO$_SOCKET,&iosb,0,0,AF_INET,SOCK_STREAM,0,
X0,0,0) & 1)
X && (iosb.iostatus & 1)) `123
X if (!(dest_host = gethostbyname(netobj))) `123
X if (debugging) printf("open_net: gethostbyname returned null\n");
X`009 sys$dassgn(net_chan);
X`009 return(0);
X`009 `125
X data_socket.sin_addr.s_addr = *((u_long *)dest_host->h_addr);
X data_socket.sin_family = AF_INET;
X data_socket.sin_port = htons(NNTP_PORT);
V if ( (sys$qiow(0,net_chan,IO$_CONNECT,&iosb,0,0,&data_socket,sizeof
X(data_socket),0,0,0,0) & 1)
X && (iosb.iostatus & 1))
X return(1);
X `125
X `125
X if (debugging) printf("open_net: io$_connect or io$_Socket error\n");
X if (debugging) printf("open_net: iosb.iostatus=%X\n",iosb.iostatus);
X sys$dassgn(net_chan);
X return(0);
X `125
X#endif
X else `123
X char logname[132],
X *gotenv;
X
X sprintf(logname,"NEWS_%s_TASK",node);
X s_to_upper(logname);
X if (gotenv = getenv(logname)) strcpy(logname,gotenv);
X else sprintf(logname,"TASK=NNTP");
X s_to_upper(logname);
X sprintf(netobj,"%s::\"%s\"",node,logname);
X return(sys$assign(c$dsc(netobj),&net_chan,0,0) & 1);
X `125
X`125
X`012
X/*
X * close_net
X *
X * Close network link
X */
X
Xclose_net()
X`123
X if (net_proto) `123
X sys$cancel(net_chan);
X sys$qiow(0,net_chan,IO$_DELETE,0,0,0,0,0,0,0,0,0);
X `125
X sys$dassgn(net_chan);
X`125
X`012
X/*
X * toggle_link
X *
V * Write a non-command to the net chan and wait for the command-not-recognis
Xed
X * response from the server.
X */
X
Xtoggle_link()
X`123
X if (!nntp_write("STAT") `124`124 (!(wait_net_response(RESP_TIMER,1)))) `123
X if (*net_open_chan) `123
X close_net();
V printf("Lost connection to NEWS SERVER ([%c] %s)",(net_proto?'T':'D'),n
Xet_open_chan);
X *net_open_chan = 0;
X `125
X return(0);
X `125
X return(1);
X`125
X`012
X/*
X * s_to_lower, s_to_upper
X *
X */
X
Xchar *s_to_lower(s)
X char *s;
X`123
X char *save = s;
X
X while (*s) `123
X *s = tolower(*s);
X s++;
X `125
X return(save);
X`125
X
Xchar *s_to_upper(s)
X char *s;
X`123
X char *save = s;
X
X while (*s) `123
X *s = toupper(*s);
X s++;
X `125
X return(save);
X`125
X`012
X/*
X * open_rem_chan
X *
X * Open channel to remote NNTP server on host name node, using protocol
X * proto_num (3 == MULTINETTCP, 2 == WINTCP, 1 == CMUTCP, 0 = DECNET)
X */
X
Xchar restart_node[256];
Xint restart_proto_num,
X restarts = 0;
X
Xrestart_nntp()
X`123
X if (++restarts > MAX_RESTART_ATTEMPT) return(0);
X printf("(Lost NNTP connection - restart attempted)\n");
X return(open_rem_chan(restart_node,restart_proto_num));
X`125
X
Xopen_rem_chan(node,proto_num)
X char *node;
X int proto_num;
X`123
X int reply;
X
X strcpy(restart_node,node);
X restart_proto_num = proto_num;
X s_to_lower(node);
X if (*net_open_chan) `123
X if ((proto_num != net_proto) `124`124 (strcmp(node,net_open_chan))) `123
X close_net();
X *net_open_chan = 0;
X `125
X else toggle_link();
X `125
X if (!*net_open_chan) `123
X strcpy(net_open_chan,node);
X if (!open_net(net_open_chan,proto_num)) `123
X *net_open_chan = 0;
X if (debugging) printf("open_chan: Could not open network channel\n");
X return(0);
X `125
X else net_proto = proto_num;
X if (!(reply = wait_net_response(CLIENT_TIMER,1))) `123
X close_net();
X *net_open_chan = 0;
V if (debugging) printf("open_chan: No reply recieved in %d secs\n",CLIEN
XT_TIMER);
X return(0);
X `125
X if ((reply!=200) && (reply!=201)) `123
V printf("Connection refused to NEWS SERVER ([%c] %s)",(net_proto ? 'T' :
X 'D'),net_open_chan);
X return(0);
X `125
X `125
X return(1);
X`125
X`012
X/*
X * ITM routines
X *
X */
Xstruct FAB itmfab; /* newsitem file fab */
X
Xstruct RAB itmrab; /* newsitem file rab */
X
XITM newsitm; /* newsitem i/o buffer */
X
Xopen_itm_file()
-+-+-+-+-+ End of part 1 +-+-+-+-+-