OpenVMS Source Code Demos

ICSIS_TO_POP3_INTERFACE.BAS

1000	%title "ICSIS_TO_POP3_INTERFACE_100"
 	%ident			    "version_102.1"				! <<<---***
	declare string constant k_version = "102.1"			,	!						&
				k_program = "ICSIS_TO_POP3_INTERFACE"		!
	!=========================================================================================================================
	! Title  : ICSIS_to_POP3_INTERFACE_xxx.BAS				!
	! Author : Neil Rieck
	! Purpose: reading mail messages stored in an POP3 server on port 110
	! Notes  : 1.	by declaring the passing mechanisms in the external statements, it seems that we don't need to use
	!		VAX-BASIC's LOC() statement to substitute for an ampersand (address ref) in DEC-C and VAX-C
	!	   2.	this program must be built (from DCL) as follows:
	!			$ basic  file.bas
	!			$ link   file,	sys$input/options
	!					tcpware:tellib/lib
	!					sys$share:tcpware_socklib_shr/share
	!=========================================================================================================================
	! History:
	! ver who when   what
	! --- --- ------ ---------------------------------------------------------------------------------------------------------
	! 100 NSR 090426 1. original program (with hard coded test messages)
	!	  090427 2. added support for more POP3 verbs
	!		 3. added more code for data extraction
	! 101 NSR 090510 1. tweaked before placing in public domain
	! 102 NSR 090510 1. tweaked for Bell use
	!=========================================================================================================================
	option type = explicit							! no kid stuff...
	set no prompt								!
	!
	!	constants
	!
	declare word constant k_recv_size_w	= 4096				!
	declare word constant k_xmit_size_w	= 1024				!
	declare long constant k_list_size	= 100				!
	!
	!	system declarations
	!
	%include "starlet"	%from %library "sys$library:basic$starlet"	! system services
	%include "$ssdef"	%from %library "sys$library:basic$starlet"	! ss$
	%include "lib$routines"	%from %library "sys$library:basic$starlet"	! lib$
	%include "$secdef"	%from %library "sys$library:basic$starlet"	! sec$
	%include "$libdtdef"	%from %library "sys$library:basic$starlet"	! eg. LIB$K_DELTA_SECONDS_F
	%include "$libdef"	%from %library "sys$library:basic$starlet"	! eg. lib$_normal
	%include "$jpidef"	%from %library "sys$library:basic$starlet"	! jpi$
	%include "[.inc]VMS_Structures.inc"					! IOSB recs etc.
	!
	!	home brewed functions
	!
	external string function wcsm_trnlnm (string, string)			!
	external string function wcsm_dt_stamp 					!
	external long   function get_timer_bit_vector(long)			! required for used with SYS$WFLOR
	external string function format_dt					!
	!
	map (neil) long icsis_debug%						! this map also appears in the sub proc
	declare	long	rc%							,! return code				&
			i%							,! 					&
			list%							,!					&
			ptr%							,!					&
			x%							,!					&
			stage%							,! for flow tracing			&
			ccb%							,! connection control block		&
			sleep_counter%						,! time stamp period			&
			timer_event_flag%					,! timer event flag			&
			timer_ef_state%						,! timer event flag state		&
			tcp_event_flag%						,! tcp event flag			&
			tcp_ef_state%						,! tcp event flag state			&
			mask%							,! required for sys$wflor		&
			dead_air_test%						,!					&
			try%							,!					&
			read_miss%						,!					&
			junk%							,!					&
			junk2%							,!					&
			channel_open%						,!					&
			cr%							,!					&
			lf%							,!					&
			start%							,!					&
			end1%							,!					&
			end2%							,!					&
			request_coldstart%					,!					&
			fail_safe%						,!					&
			error_handler%						,! when error test			&
			buff_len%						,! total len of buff			&
			read_only%						,! open read only			&
			buff_start% 						,! start of mlr				&
			buff_end%   						,! end of mlr				&
			buff_next_start% 					,! start of mlr				&
			buff_next_end%   					,! end of mlr				&
			field_name%						,! count fields				&
			file108_open%						,!					&
			connected_once%						,!					&
		word	recvlen_w%						,!					&
			sendbuf_w%						,!					&
			my_port_w%						,!					&
			received_bytes_waiting_w%				,!					&
		string	default_node$						,!					&
			msg$							,!					&
			msg_previous$						,!					&
			src_node$						,!					&
			dest_node$						,!					&
			dest_port$						,!					&
			user_name$						,!					&
			pass_word$						,!					&
			target_id$						,! logical				&
			temp$							,!					&
			junk$							,!					&
			msg_num$						,!					&
			my_date$						,!					&
			default_dir$						,! default dir				&
			wrkg_buff$						,! working buffer			&
			collapsed$						,! collapsed buffer			&
			choice$ 						,! pick a command			&
			list$(k_list_size)					,!					&
	basic$QuadWord	DeltaQuad						 ! for sys$bintim etc.
	!
	declare rfa rfa96							!
	!
	map(POP3)string								!	&
		sendbuf$	= k_xmit_size_w			,		!	&
		recvbuf$	= k_recv_size_w					!
	!
	declare string constant	dq	= '34'C					! double quote (ascii 34)
	!
	!	<<< TCPware definitions >>>
	!
	%include "[.inc]tcpware_ccb_definitions.inc"				! ccb definitions
	!
	external long function tel_allocate_ccb(	long by ref	,	! ccb-ptr		&
							word by ref	,	! rcv-buf-size		&
							word by ref	)	! snd-buf-size
	!
	external long function tel_get_ccb(		long by ref	,	! ccb-ptr		&
							word by ref	,	! field-code		&
							any  by ref	)	! value
	!
	external long function tel_deallocate_ccb(	long by ref	)	! ccb-ptr
	!
	external long function tel_close_connection(	long by ref	)	! ccb-ptr
	!
	external long function tel_abort_connection(	long by ref	)	! ccb-ptr
	!
	external long function tel_open_connection(	long by ref	,	! ccb-ptr		&
							long by ref	,	! ia			&
							string by desc	,	! host			&
					!~~~		long by ref	,	x cmd-rtn		&
							long by value	,	! cmd-rtn		&
							long by ref	,	! efn			&
							long by ref	,	! ast-addr		&
							word by ref	,	! port			&
							long by ref	)	! timeout
        !
	external long function tel_receive_data(	long by ref	,	! ccb-ptr		&
							word by ref	,	! buffer-size		&
							string by ref	,	! buffer		&
							word by ref	)	! byte-count
	!
	external long function tel_send_data(		long by ref	,	! ccb-ptr		&
							string by ref	,	! buffer		&
							word by ref	)	! byte-count
	!
	external long function tel_send_command(	long by ref	,	! ccb-ptr		&
							string by ref	,	! buffer		&
							word by ref	)	! byte-count
	!
	!==========================================================================================
	!
	!	/// Jpi Setup	///
	!
	record JpiRec								! structure of Jpi Record
	   ItemRec ItemVar(0)							! 0 -> 0 items
	   long    list_term							! mark end-of-list
	end record JpiRec							!
	!
	declare	JpiRec	JpiBuf							! Now declare a variable using it
	!
	!    Storage for info returned by GETJpi
	!
	MAP(Jpi)string	ProcName = 15	,					! process name					&
		long	ProcName_L						! returned length of PROC NAME
	!
	!========================================
	!	Make JpiBuf Entries
	!========================================
	!
	JpiBuf::ItemVar(0%)::BuffLen	= 15					! 4 bytes (1 long)
	JpiBuf::ItemVar(0%)::ItemCode	= Jpi$_Prcnam				! Process Name
	JpiBuf::ItemVar(0%)::BuffAddr	= LOC( ProcName)			!
	JpiBuf::ItemVar(0%)::RtnLenAdr	= LOC( ProcName_L)			!
	!
	JpiBuf::LIST_TERM		= Jpi$C_ListEnd				! end of list
	!
	!====================================================================================================
	!	main
	!====================================================================================================
	main:
	margin #0, 132								! width for the log file
	print k_program +"_"+ k_version						!
	print string$(len(k_program +"_"+ k_version), asc("="))			! underline previous line (how will this optimize?)
	print "-i-time: "+ format_dt( wcsm_dt_stamp )				!
	icsis_debug%		= 0						!  init
	connected_once%		= 0						!
	request_coldstart%	= 0						!
	!
	when error in								!
	    print "=================================================="		!
	    print "You have 5 seconds to answer the next question"		!
	    print "(on timeout, this program will use logical ICSIS_TO_POP3_DEBUG)"
	    print "Debug Menu:"							!
	    print " 0 = only errors"						!
	    print " 1 = errors + informationals"				!
	    print " 2 = full"							!
	    wait 5%								!
	    input "Enter Debug Level? (0-2, defaults to 0) "; temp$		!
	    error_handler% = 0							!
	use									!
	    print "-i- timer expired"						!
            temp$ = edit$( WCSM_TrnLnm( "ICSIS_TO_POP3_DEBUG", "LNM$SYSTEM_TABLE" ),32+4+2)
	end when								!
	!
	!	note: some debug logicals use YES/NO so we'll support this as well as numbers
	!
	select left$(temp$,1)							! YES -> Y
	    case "Y"								!
		temp$ = "2"							!
	    case "N"								!
		temp$ = "0"							!
	end select								!
	when error in								!
	    icsis_debug% = integer(temp$)					!
	use									!
	    icsis_debug% = 0							!
	end when								!
	print "-i- program Started with a Debug Level of "; icsis_debug%	!
	!
	rc% = sys$GetJpiW(,0%,,JpiBuf,,,)					! get our process name
	print "-e- GetJpiW rc: "+ str$(rc%)		if ((rc% and 7%) <> 1)	!
	print "-i- ProcName: "+ left$(ProcName,ProcName_L)			!
	!
	!====================================================================================================
	!
	!	<<< restart connection >>>
	!
	restart_connection:							!
	dead_air_test%		= 0						!
	sendbuf$		= ""						!
	recvbuf$		= ""						!
	!
	!	<<< get some event flags for later >>>
	!
	if tcp_event_flag% = 0 then						! if not yet allocated
	    rc% = lib$get_EF( tcp_event_flag% )					! get an event flag
	    if ((rc% and 7%) <> 1) then						!
		print "lib$get_EF-1 rc: ";str$(rc%)				!
		goto rc_exit							!
	    end if								!
	end if									!
	!
	! Implementation notes for lexical %hardened
	!
	! 0: original code
	!    only one event flag (tcp_event_flag%) is used to detect when data has arrived from the other end
	! 1: hardened code
	!    two event flags are used:
	!	1. one event flag (tcp_event_flag%) is used to detect when data has arrived from the other end
	!	2. a second event flag (timer_event_flag%) is used to determine when a no activity timer has expired
	!
    %let %hardened=1%								! 0=original code, 1=hardened code
    %if  %hardened=1% %then							! hardened code -----------------------------------
	if timer_event_flag% = 0 then						! if not yet allocated
	    rc% = lib$get_EF( timer_event_flag% )				! get another event flag
	    if ((rc% and 7%) <> 1) then						!
		print "lib$get_EF-2 rc: ";str$(rc%)				!
		goto rc_exit							!
	    end if								!
	end if									!
    %end %if									! -------------------------------------------------
	!
	!	have the system allocate a connection control block and save the address in ccb%
	!
	if ccb% = 0 then							! if not yet allocated
	    declare string constant k_stage1 = ">>> tel func: allocate"		!
	    stage% = 1								!
	    print k_stage1				if icsis_debug% >= 2	!
	    rc% = tel_allocate_ccb( ccb%, k_recv_size_w, k_xmit_size_w )	! allocate a ccb and then address in ccb%
	    gosub display_rc							!
	    goto rc_exit if (rc% and 1%) <> 1%					! this may be too drastic ???
	end if									!
	!
	!	<<< open a connection >>>
	!
	declare string constant k_stage3 = ">>> tel func: open"			!
	stage% = 3%								!
	print k_stage3				if icsis_debug% >= 2		!
	src_node$  = edit$( WCSM_TrnLnm( "TCPIP_DOMAINNAME", "LNM$SYSTEM_TABLE" ),32+4+2)
	dest_node$ =	"127.0.0.1"						!
	dest_port$ =	"110"							!
        !
	print "-i- src  node : ";src_node$					!
	print "-i- dest node : ";dest_node$					!
	print "-i- port      : ";dest_port$					!
	my_port_w% = integer(dest_port$)					! prep for open
	!
	!	note: this isn't stated in the manual, but you'll get an error if timeout isn't >=20 or 0
	!
	rc% = tel_open_connection(												&
		ccb%								,! ccb-ptr					&
										,! ia		(use IA or HOST, not both)	&
		dest_node$							,! host		(use IA or HOST, not both)	&
										,! cmd-rtn	must leave blank for NONE	&
		tcp_event_flag%							,! efn						&
										,! ast-addr	must leave blank for NONE	&
		my_port_w%							,! port (7=echo, 23=telnet , 25=smtp, 110=pop3)	&
		20%								 ! timeout in seconds				&
	)
	gosub display_rc							!
	if (rc% and 1%) <> 1% then						!
	    goto close_connection						!
	end if									!
	channel_open% = 1							!
	!
	try% = 1								! init to stage 1 (nothing to send...
	goto wait_for_response							! ...so just wait for the open message)
	!
	!	<<< send the data (loop) >>>
	!
	send_data_loop:								!
	declare string constant k_stage4 = ">>> tel func: send data"		!
	stage% = 4%								!
	print k_stage4				if icsis_debug% >= 2		!
	print "-i- time: "+ format_dt( wcsm_dt_stamp ) +" -------------->>> doing try: "+ str$(try%)
	select try%								!
	   case 1								! place-holder (initial wait for response)
		goto wait_for_response						!
	   case 2								! send user
		msg$	= "USER esppats" + cr + lf				!
	   case 3								! send password
		msg$	= "PASS whatever" + cr + lf				!
	   case 4								! send STAT
		msg$	= "STAT" + cr + lf					! this command isn't very useful
		try%	= try% + 1						! prep for next step
		goto send_data_loop						!
	   case 5								! send LIST
		msg$	= "LIST" + cr + lf					!
	   case 6								! RETR
		ptr% = ptr% + 1							!
		if ptr% > list% then						! if done
		    try% = 99							! then prep for QUIT
		    goto send_data_loop						!
		else								!
		    !   <<< Example data >>>
		    !	+OK 6 messages (5334 octets)
		    !	1 889
		    !	2 889
		    !	3 889
		    !	4 889
		    !	5 889
		    !	6 889
		    junk% = pos(list$(ptr%)," ",0)				! look for first <sp>
		    if junk% <= 1 then						! this should never happen
			print "-e- logic error 123 so exiting"			!
		    else							!
			msg_num$ = left$(list$(ptr%), junk%-1)			! extract message number
		    end if							!
		    msg$ = "RETR "+ msg_num$ +				cr + lf	!
		end if								!
	   case 7								! delete messages
		try% = 6							!
		goto send_data_loop						! <<<< do not delete just now
		msg$ = "DELE "+ junk$ +					cr + lf	!
	   case 8								! delete messages
		try% = 99							!
		goto send_data_loop						!
	   case 99								! delete messages
		msg$ = "QUIT"+						cr + lf	!
	   case 100								!
		print "==================================="			!
		print "the POP3 comm process was successul"			!
		print "==================================="			!
		goto close_connection						!
	   case else								! shouldn't ever happen...
		print " (???) oops!"						!
		goto close_connection						!
	end select								!
	sendbuf$	= msg$							!
	sendbuf_w%	= len(msg$)						!
	print "-i- xmit data>";msg$;"<"	if icsis_debug% >= 1			!
	rc% = tel_send_data ( ccb%, sendbuf$, sendbuf_w% )			!
	gosub display_rc							!
	goto close_connection if (rc% and 1%) <> 1%				!
	!
	!----------------------------------------------------------------------------------------------------
	!	data has now been sent so we'll wait for an event flag
	!----------------------------------------------------------------------------------------------------
	wait_for_response:
	declare string constant k_stage5 = ">>> tel func: wait"
	stage% = 5%
	print k_stage5				if icsis_debug% >= 2
    %if  %hardened=0% %then								! original code ---------------------------
	!
	!	<<< wait for the TCP event flag to change state >>>
	!
	if icsis_debug% >= 1 then							!
	    print "-i- waiting for flag ";tcp_event_flag%;" at time: "+ format_dt( wcsm_dt_stamp )
	end if										!
	rc% = sys$waitfr( tcp_event_flag% )						! wait for a response from a single flag
	gosub display_rc								!
	goto close_connection if (rc% and 1%) <> 1%					!
	if icsis_debug% >= 1 then							!
	    print "-i- waking from event flag "+ str$(tcp_event_flag%) +" at time: "+ format_dt( wcsm_dt_stamp )
	end if										!
    %else										! hardened code ---------------------------
	!
	!	<<< arm a timer to expire 'x' time from now >>>
	!
	declare string constant	k_delay010 = "0 00:00:10"				! set delay time 10 seconds from now
	rc% = sys$bintim(k_delay010, DeltaQuad )					! init delta time ('x' time from now)
	print "-e- sys$bintim rc: "+ str$(rc%) if ((rc% and 1%) <> 1%)			!
	rc% = sys$setimr(timer_event_flag%,DeltaQuad by ref,,,)				! now use it to schedule a wake up
	print "-e- sys$setimr rc: "+ str$(rc%) if ((rc% and 1%) <> 1%)			!
	!
	! note: for the SYS$WFLOR call to work, both event flags must be in the same event flag cluster.
	!	The first parameter is only used to determine which event flag cluster to test.
	!	The second parameter (mask) contains bits representing event flags within that cluster
	!
	mask% =			get_timer_bit_vector(  tcp_event_flag%)			! insert vector 1 into mask
	mask% = mask% or	get_timer_bit_vector(timer_event_flag%)			! insert vector 2 into mask
	!
	!	<<< wait for either the 'TCP event flag' or the 'TIMER event flag' to change state >>>
	!
	print "-i- waiting for flag ";tcp_event_flag%; " or flag "; timer_event_flag%; " time: "+ format_dt( wcsm_dt_stamp )
	!
	rc% = sys$wflor( tcp_event_flag%, mask%)					! wait for a response from one of two flags
	print "-e- sys$waitfr rc: "+ str$(rc%) if ((rc% and 1%) <> 1%)			!
	gosub display_rc								!
	goto close_connection if (rc% and 1%) <> 1%					!
	if icsis_debug% >= 1 then							!
	    print "-i- waking from event some flag at time: "+ format_dt( wcsm_dt_stamp )
	end if										!
	!
	!	<<< cancel all timer requests (if any) >>>
	!
	print "-i- Calling $CanTim"							!
	rc% = sys$cantim(,)								! cancel all timer requests
	print "-e- sys$cantim rc: "+ str$(rc%) if ((rc% and 1%) <> 1%)			!
	!
	!	which event flag is set? TCP or TIMER?
	!
	rc% = sys$readEF(tcp_event_flag%, junk%)					! test TCP event flag
	select rc%									!
	    case SS$_WASCLR								!
		tcp_ef_state% = 0							!
	    case SS$_WASSET								!
		tcp_ef_state% = 1							!
	    case else									!
		print "-e- sys$readef-tcp rc: "+ str$(rc%)				!
	end select									!
	print "-i- TCP EF State: ";str$(tcp_ef_state%);" ";	if icsis_debug% >= 1	! no BASIC EOL required here
	!
	rc% = sys$readEF(timer_event_flag%, junk%)					! test TIMER event flag
	select rc%
	    case SS$_WASCLR
		timer_ef_state% = 0
	    case SS$_WASSET
		timer_ef_state% = 1
	    case else
		print "-e- sys$readef-timer rc: "+ str$(rc%)
	end select
	print "-i- Timer EF State: ";str$(timer_ef_state%) if icsis_debug% >= 1		!
	!
	!	at this point either the TCP-EF or the TIMER-EF could be set
	!
	if (timer_ef_state% = 1)	and						! if the TIMER-EF is set		&
	   (  tcp_ef_state% = 0)							! and the TCP-EF is clear
	then										! then something timed out
	    select dead_air_test%							!
		case 0									! if not doing a dead air test
		    print "-i- starting dead-air test"					!
		    dead_air_test% = dead_air_test% + 1					! ...then arm the test
		    goto send_data_loop							! ...now send a key stroke to View-1
		case else
		    print "-e- ALERT: the dead-air test has failed. Starting a new connection cycle"
		    goto close_connection						! but need to disconnect first
	    end select
	else										! we've got TCP data so fall thru
	end if
    %end %if										! hardened code ---------------------------
	!
	!	<<< receive the data >>>
	!
	declare string constant k_stage6 = ">>> tel func: recv data"
	stage% = 6%
	print k_stage6					if icsis_debug% >= 2
	!
	read_miss% = 0%									! init
	wrkg_buff$ = ""									!
	buff_len% = 0%									!
	!
	!	<<< read loop >>>
	!
	read_loop:
    %let %method=3%									! we want method 3		bf_120.9
    %if %method<1% %then
	lexical %method value too low							! abort compile if too low
    %end %if
    %if %method>3% %then
	lexical %method value too high							! abort compile if too high
    %end %if
    %if  %method=1% %then								! using polling method (original code)
	junk% = 1									! start a read
    %end %if										!
    %if  %method=2% %then								! avoid polling via TEL_GET_CCB	   bf_120.7
	!
	!	peek into the interface to see if any data is waiting in the receive buffer
	!
	!	Note: this technique may not be reliable since we've recently seen conditions where the event flag remains set
	!	even though 'bytes waiting' is set to zero. (Could this happen when an EOL character is stuck in the interface?)
	!
	rc% = tel_get_ccb( ccb%, CCB_RCVBCNT, received_bytes_waiting_w% )		!				   bf_120.7
	gosub display_rc								!
	print "-i- ccbRcvbcnt: "+str$(received_bytes_waiting_w%) if icsis_debug% >= 1	!
	junk% = received_bytes_waiting_w% 						!
   %end %if
   %if  %method=3% %then								! avoid polling via SYS$ReadEF
	!
	!	Note: since the event flag will be set when ever data is available, this is probably the best technique to
	!	use other than polling via the call to TEL_READ_DATA
	!
	rc% = sys$readEF(tcp_event_flag%, junk%)					! test TCP event flag		bf_120.9
	select rc%
	    case SS$_WASCLR
		tcp_ef_state% = 0							! data not available
	    case SS$_WASSET
		tcp_ef_state% = 1							! data is available
	    case else
		print "-e- sys$readef-tcp rc: "+ str$(rc%)
	end select
	junk% = tcp_ef_state%								!
    %end %if
	select junk%									! any data available?
	    case 0									! no...
		recvlen_w%	= 0							! indicate that no data was received
	    case else									! yes...
		!
		!  read data from the TCP buffer
		!
		!	Note: we get here via a test of TEL_GET_CCB to avoid polling with TEL_RECEIVE_DATA.
		!	See page 9-16 of the TCPware programmer's manual for details
		!
	        rc% = tel_receive_data( ccb%, k_recv_size_w, recvbuf$, recvlen_w%)	! receive data <<<------***
		select rc%								!
		    case SS$_VCCLOSED, SS$_TIMEOUT, SS$_THIRDPARTY			!				bf_123.1
			print "-w- connection closed unexpectedly ("+str$(rc%)+")"	!
			goto close_connection						! cleanup etc.
		    case else								!
			gosub display_rc						!
			goto close_connection if (rc% and 1%) <> 1%			!
		end select								!
		!
		if icsis_debug% >= 2 then						!
		    print "-i- recv data >"+ left$(recvbuf$, recvlen_w%);"<"		!
		    print "-i- recv count: "+ str$(recvlen_w%)				!
		end if									!
	end select									!
	!
	print "-i- read miss : "+ str$(read_miss%) if icsis_debug% >= 1			!
	if recvlen_w% > 0% then								! we've got some data...
		read_miss% = 0%								! ...so prep to continue (not a miss)
		wrkg_buff$ = wrkg_buff$ + left$(recvbuf$, recvlen_w%)			! concat recv data into holding buffer
		goto read_loop								! loop back for more
	else										! we didn't get any data...
		read_miss% = read_miss% + 1%						! so up the read miss count
		sleep 1									! kill some time
		goto read_loop if read_miss% <= 1					! loop if less than 2 seconds
	end if										!
	!
	if icsis_debug% >= 1 then							!
	    print "-i- ============================================================"	!
	    print "-i- wkg buffer len:"+str$(len(wrkg_buff$))				!
	    print "-i- wkg buffer>"; wrkg_buff$;"<"					!
	    print "-i- try: "+ str$(try%)						!
	    print "-i- ============================================================"	!
	end if										!
	!
	collapsed$ = edit$( wrkg_buff$, 128+32+16+8)				! cleanup for testing
	junk% = pos( collapsed$ , "-ERR", 1)					!
	goto fini	if junk% = 1						! this is a demo so just exit on error
	!
	select try%								!
	    case 1								!
		goto fini	if len(collapsed$) = 0				! this is a demo so just exit on error
		try% = try% + 1							!
		goto send_data_loop						!
	    case 2								! USER
		junk% = pos( collapsed$ , "+OK", 1)				!
		goto fini	if junk% <> 1					! this is a demo so just exit on error
		try% = try% + 1							!
		goto send_data_loop						!
	    case 3								! PASS
		junk% = pos( collapsed$ , "+OK", 1)				!
		goto fini	if junk% <> 1					! this is a demo so just exit on error
		try% = try% + 1							!
		goto send_data_loop						!
	    case 4								! STAT
		junk% = pos( collapsed$ , "+OK", 1)				!
		goto fini	if junk% <> 1					! this is a demo so just exit on error
		try% = try% + 1							!
		goto send_data_loop						!
	    case 5								! LIST
		junk% = pos( collapsed$ , "+OK", 1)				!
		goto fini	if junk% <> 1					! this is a demo so just exit on error
		!
		list%	= 0							! init line counter
		start%	= 0							! init starting position
		scan_more5:							!
		cr%	= pos(wrkg_buff$, cr, start%+1)				! find position of <cr> (usually is first)
		lf%	= pos(wrkg_buff$, lf, start%+1)				! find position of <lf> (usually is second)
		if cr% > 0 and lf% > 0 then					! if we've got a pair
		    end1% = min(cr%,lf%)					!
		    end2% = max(cr%,lf%)					!
		else								!
		    end1% = 0							! init
		    end1% = cr%	if cr% > 0					!
		    end1% = lf%	if lf% > 0					!
		    end2% = end1%						!
		end if								!
		if end1% > 0 then						!
		    goto no_more_room	if list% >= k_list_size			!
		    junk$	= seg$(wrkg_buff$, start%+1, end1%-1)		!
		    if junk$ <> "." then					! if not end-of-list indicator
			list% = list% + 1					! prep for insert
		 	list$(list%) = seg$(wrkg_buff$, start%+1, end1%-1)	!
		    end if							!
		    start% = end2%						!
		    goto scan_more5						!
		end if								!
		no_more_room:							!
		print "-i- dumping contents of message list"			!
		for ptr% = 1 to list%						!
		    print "-i-debug Line: "+ str$(ptr%) + " len: "+ str$(len(list$(ptr%))) +" msg: "+ list$(ptr%)
		next ptr%							!
		select list%							!
		    case <= 1							! line #1 = "+OK x messages (xxx octects)"
			try% = 99						! prep for QUIT
		    case else							!
			ptr% = 1						!
			try% = try% + 1						! prep for RETR
		end select							!
		goto send_data_loop						!
	    case 6								! RETR
		junk% = pos( collapsed$ , "+OK", 1)				!
		goto fini	if junk% <> 1					! this is a demo so just exit on error
		print "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
		print "1>"+ wrkg_buff$			+"<2"			!
		!
		!	prep to discard the first line
		!
		cr%	= pos(wrkg_buff$, cr, start%+1)				! find position of <cr> (usually is first)
		lf%	= pos(wrkg_buff$, lf, start%+1)				! find position of <lf> (usually is second)
		if cr% > 0 and lf% > 0 then					! if we've got a pair
		    end1% = min(cr%,lf%)					!
		    end2% = max(cr%,lf%)					!
		else								!
		    end1% = 0							! init
		    end1% = cr%	if cr% > 0					!
		    end1% = lf%	if lf% > 0					!
		    end2% = end1%						!
		end if								!
		print "3>"+ right$(wrkg_buff$,end2%+1)	+"<4"			!
		print "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
		try% = try% + 1							!
		goto send_data_loop						!
	    case 7								! DELE
		junk% = pos( collapsed$ , "+OK", 1)				!
		goto fini	if junk% <> 1					! this is a demo so just exit on error
		try% = try% + 1							!
		goto send_data_loop						!
	    case 99								! QUIT
		junk% = pos( collapsed$ , "+OK", 1)				!
		goto fini	if junk% <> 1					! this is a demo so just exit on error
		try% = try% + 1							!
		goto send_data_loop						!
	    case else								!
		goto fini							! exit for now (dvlp)
	end select								!
	!
	!	<<< close the connection >>>
	!
	close_connection:							!
	gosub close_telnet_connection						!
	goto fini								!
	!
	!	<<< close telnet connection subroutine >>>
	!
	close_telnet_connection:						!
	return if channel_open% = 0						!
	declare string constant k_stage11 = ">>> tel func: close"		!
	stage% = 11%								!
	print k_stage11			if icsis_debug% >= 2			!
	print "Closing connection..."						!
	rc% = tel_close_connection( ccb% )					! this only closes my xmit...
	gosub display_rc							!
	fail_safe% = 0								! init fail safe counter
	!
	buffer_purge:								!
	print "-i- purging receive buffer <<<---***"	if icsis_debug% >= 1	!
	fail_safe% = fail_safe% + 1						!
	junk% = tel_receive_data( ccb%, k_recv_size_w, recvbuf$, recvlen_w%)	! clean out receive buffer
	print "-i- receive buffer purge. Bytes: "+ str$(recvlen_w%) +" rc: ";str$(junk%)	if icsis_debug% >= 1
	select junk%								!
	    case SS$_VCCLOSED, SS$_TIMEOUT, SS$_THIRDPARTY			! now totally closed so fall thru
	    case else
		if (junk% and 7%) = 1 then					! if no errors				bf_125.4
		    junk% = sys$bintim("0 00:00:00.10", DeltaQuad )		! then init delta time to 100 mS
		    junk% = sys$schdwk(,,DeltaQuad by ref,)			! schedule a wakeup ? seconds from now
		    junk% = sys$hiber						! go to sleep
		    goto buffer_purge if fail_safe% <= 50			! loop back (5 second worse case limit)
		    junk% = tel_abort_connection( ccb% )			! don't take any chances		bf_122.8
		    sleep 5							!					bf_122.8
		else								! some kind of error....
		    junk% = tel_abort_connection( ccb% )			! don't take any chances
		    sleep 1							!
		end if								!
	end select								!
	channel_open% = 0							!
	return									!
	!----------------------------------------------------------------------------------------------------
	!
	!	<<< display return code after each call to the TELNET library >>>
	!
	display_rc:
	if (rc% and 7%) <> 1%	or						! if not -s- (success)		&
	   icsis_debug% >= 1%							! or debugging is enabled
	then
		select stage%
		    case 1%
			print k_stage1;
		    case 3%
			print k_stage3;
		    case 4%
			print k_stage4;
		    case 5%
			print k_stage5;
		    case 6%
			print k_stage6;
		    case 11%
			print k_stage11;
		    case else
			print "Oops: ";
		end select
		!
		print " >>> ";
		select (rc% and 7%)
		    case 0%
			print "-w-";
		    case 1
			print "-s-";
		    case 2
			print "-e-";
		    case 3
			print "-i-";
		    case 4
			print "-f-";
		    case else
			print "-?-";
		end select
		print " rc: ";str$(rc%)
	end if
	return

	!====================================================================================================
	!	<<< adios... >>>
	!====================================================================================================
	fini:
	rc% = 1									! vms -s-
 	!
	!	rc% must be set up b4 this point (and must not be changed)
	!
	rc_exit:
	!
	!	pre-exit clenaup (optional stuff but let's do it anyway)
	!
	gosub close_telnet_connection						!					bf_122.5
	if ccb% <> 0% then							!
	    junk% = tel_deallocate_ccb( ccb% )					!
	    print "-e- tel_deallocate_ccb rc: "+str$(junk%) if ((junk% and 7%) <> 1)
	end if									!
	if tcp_event_flag% <> 0 then						!
	    junk% = lib$free_EF( tcp_event_flag% )				! free the event flag
	    print "-e- lib$free_EF-tcp rc: "+str$(junk%) if ((junk% and 7%) <> 1)
	end if									!
    %if  %hardened=1% %then							! hardened code ---------------------------
	if timer_event_flag% <> 0 then						!
	    junk% = lib$free_EF( timer_event_flag% )				! free the event flag
	    print "-e- lib$free_EF-timer rc: "+str$(junk%) if ((junk% and 7%) <> 1)
	end if									!
    %end %if									! -----------------------------------------
	!
30000	end program rc%
	!
        !========================================================================================================================
	!	external functions
	!========================================================================================================================
31010   %include "[.fun]wcsm_trnlnm.fun"
        ! FUNCTION STRING WCSM_TRNLNM(LOGICAL_NAME, TABLE_NAME$)
	!
31020   %include "[.fun]wcsm_dt_stamp.fun"
        ! FUNCTION STRING wcsm_dt_stamp
	!
31030	function string format_dt(string inbound$)				!
	option type=explicit							!
	    select len(inbound$)						!
		case 12	to 14							! eg. CCYYMMDDhhmm or CCYYMMDDhhmmss
		    format_dt = left$(inbound$,8) +"."+ right$(inbound$,9)	!
		case 15								! eg. CCYYMMDDhhmmsst
		    format_dt = left$(inbound$,8) +"."+ mid$(inbound$,9,6) +	!						&
			left$(inbound$,15)					!
		case else							!
		    format_dt = inbound$					!
	    end select								!
	end function								!
	!
	!======================================================================
	!	get timer bit vector
	!	(see OpenVMS system systevices documentation for "sys$wflor")
	!
	!	notes:	cluster	event flags
	!		0	00- 31
	!		1	32- 63
	!		2	64- 95
	!		3	96-127
	!======================================================================
31040	function long get_timer_bit_vector(long event_flag)
	option type = explicit
	declare long temp
	!
	select event_flag
	    case <= 31
		temp = event_flag
	    case <= 63
		temp = event_flag - 32
	    case <= 95
		temp = event_flag - 64
	    case else
		temp = event_flag -96
	end select
	!
	select temp								! this code will avoid an integer overflow
	    case 31								! need to set bit #31
!					 33222222222211111111110000000000
!					 10987654321098765432109876543210
		get_timer_bit_vector = B"10000000000000000000000000000000"L	! so return this
	    case else								!
		get_timer_bit_vector = (2% ^ temp)				! else return this
	end select
	!
	end function								! get_timer_bit_vector
	!
	!####################################################################################################
	!
	!	KAWC09::Neil> telnet 127.0.0.1 110
	!	%TCPWARE_TELNET-I-TRYING, trying localhost,pop3 (127.0.0.1,110) ...
	!	%TCPWARE_TELNET-I-ESCCHR, escape (attention) character is "^\"
	!	USER esppats
	!	+OK Password required for "esppats"
	!	PASS whatever
	!	+OK Username/password combination ok
	!	STAT
	!	+OK 2 478
	!	LIST
	!	+OK 2 messages (478 octets)
	!	1 239
	!	2 239
	!	.
	!	RETR 1
	!	+OK 239 octets
	!	Date: 27-APR-2009 13:22:14.89
	!	From: <neil@kawc09>
	!	Subject: this is a test
	!	Cc:
	!	To: ESPPATS
	!	X-VMS-From: KAWC09::NEIL
	!	X-POP3-Server: kawc09.on.bell.ca TCPware(R) POP3 V5.8-2
	!	X-POP3-ID: 2009-04-27.13:27:57.0
	!
	!	this is test 1
	!
	!	.
	!	DELE 1
	!	+OK Message 1 has been deleted.
	!	STAT
	!	+OK 1 239
	!	LIST
	!	+OK 1 messages (239 octets)
	!	2 239
	!	.
	!	DELE 2
	!	+OK Message 2 has been deleted.
	!	STAT
	!	+OK 0 0
	!	LIST
	!	+OK 0 messages (0 octets)
	!	.
	!
	!----------------------------------------------------------------------------------------------------
	!	KAWC09::Neil> telnet 127.0.0.1 110
	!	%TCPWARE_TELNET-I-TRYING, trying localhost,pop3 (127.0.0.1,110) ...
	!	%TCPWARE_TELNET-I-ESCCHR, escape (attention) character is "^\"
	!	+OK TCPware(R) POP3 server V5.8-2 at kawc09.on.bell.ca, up since 2009-04-27 12:22:43
	!	USER esppats
	!	+OK Password required for "esppats"
	!	PASS whatever
	!	+OK Username/password combination ok
	!	LIST
	!	+OK 2 messages (466 octets)
	!	1 233
	!	2 233
	!	.
	!

Back to Home
Neil Rieck
Waterloo, Ontario, Canada.