OpenVMS Source Code Demos
ICSIS_TO_SMTP_INTERFACE.BAS
1000 %title "ICSIS_TO_SMTP_INTERFACE_xxx.bas"
%ident "version_104.3" ! <<<---***
declare string constant k_version = "104.3" , ! &
k_program = "ICSIS_TO_SMTP_INTERFACE" !
!=========================================================================================================================
! Title : ICSIS_to_SMTP_INTERFACE_xxx.BAS !
! Author : Neil Rieck
! Purpose: send mail messages directly to an SMTP server on port 25
! 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 demo program (with hard coded test messages)
! 101 NSR 090510 1. tweaked before placing in public domain
! 102 NSR 090510 1. tweaked for Bell use
! 103 NSR 090511 1. started adding code for use with our enhanced ESPP system
! 090512 2. more work
! 090513 3. more work
! 104 NSR 090513 1. more work
! 090514 2. more work
! 3. created function wcsm_get_mime_time
!=========================================================================================================================
option type = explicit ! no kid stuff...
set no prompt !
!
! constants
!
declare word constant k_recv_size_w = 32700 !
declare word constant k_xmit_size_w = 4096 !
declare long constant k_sleep_time = 10 !
!
! 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 !
external string function wcsm_get_mime_time !
!
! local declarations
!
declare long debug% , ! &
rc% , ! return code &
i% , ! &
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 &
try% , ! &
read_miss% , ! &
read_count% , ! &
junk% , ! &
request_coldstart% , ! &
fail_safe% , ! &
error_handler% , ! when error test &
field_name% , ! count fields &
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$ , ! &
my_date$ , ! &
default_dir$ , ! default dir &
wrkg_buff$ , ! working buffer &
collapsed$ , ! collapsed buffer &
choice$ , ! pick a command &
temp_to$ , ! &
temp_from$ , ! &
temp_subj$ , ! &
temp_body$ , ! &
temp_mime$ , ! &
content_type$ , ! &
basic$QuadWord DeltaQuad ! for sys$bintim etc.
!
declare rfa rfa93 !
!
map(smtpbuf)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
!
!====================================================================================================
! init
!====================================================================================================
init: !
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 ) !
print "-i- mime time: "+ wcsm_get_mime_time !
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_SMTP_DEBUG)"
print "Debug Menu:" !
print " 0 = errors" !
print " 1 = errors + informationals" !
print " 2 = errors + informationals + data" !
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_SMTP_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 !
debug% = integer(temp$) !
use !
debug% = 0 !
end when !
print "-i- program Started with a Debug Level of "; 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) !
goto main_loop2 ! bypass first sleep
!
!========================================================================================================================
! main loop
!========================================================================================================================
main: !
when error in !
close 93 !
use !
end when !
print "-i- starting "+ str$(k_sleep_time) +" second sleep at time: "+ format_dt( wcsm_dt_stamp ) if debug% >= 1
sleep 10 ! kill some time
print "-i- running" if debug% >= 1 !
main_loop2: !
!
map (smtprequest) string d93_smtp_whole_record = 1000 , ! &
d93_smtp_align = 0 !
map (smtprequest) string d93_smtp_stamp_request = 14 , ! 14 ccyymmddhhmmss &
d93_smtp_stamp_sent = 14 , ! 28 &
d93_smtp_to = 50 , ! 78 &
d93_smtp_from = 50 , ! 128 &
d93_smtp_subject = 50 , ! 178 &
d93_smtp_urgent = 1 , ! 1 &
d93_smtp_body = 820 , ! 999 &
d93_smtp_mode = 1 , !1000 H=HTML else PLAIN &
d93_smtp_align = 0 !
when error in !
open "csmis$dat:icsis_to_smtp_interface_100.dat" as #93 &
,organization indexed &
,map smtprequest &
,primary key d93_smtp_stamp_request duplicates &
,alternate key (d93_smtp_stamp_sent,d93_smtp_stamp_request) duplicates changes &
,access modify &
,allow modify !
find #93, key#1 nxeq "88881231595959", regardless ! set key of reference
error_handler% = 0 ! cool
use !
error_handler% = err ! oops
end when !
select error_handler% !
case 0 ! we've found something
case 11,155 ! EOF, FNF
goto main !
case else !
print "-e- "+ format_dt( wcsm_dt_stamp )+" status: "+ str$(error_handler%) +" during open-find-93"
goto main !
end select !
!
! get next request (come back here after sending the current message)
!
get_next_request:
when error in !
get #93 ! get w/lock
error_handler% = 0 ! cool
use !
error_handler% = err ! oops
select error_handler% !
case 19, 138, 154 ! locked
print "-w-locked record" !
print " request: "+ d93_smtp_stamp_request !
print " sent : "+ d93_smtp_stamp_sent !
print " to : "+ edit$(d93_smtp_to ,2) !
print " from : "+ edit$(d93_smtp_from ,2) !
print " subject: "+ edit$(d93_smtp_subject ,2) !
retry ! get next record
end select !
end when !
!
select error_handler% !
case 0 !
temp_to$ = edit$(d93_smtp_to ,2) !
temp_from$ = edit$(d93_smtp_from ,2) !
temp_from$ = "custodian" if temp_from$ = "" !
if pos(temp_from$,"@",1)=0 then ! if no node was given (then we need to patch)
if pos(edit$(temp_from$,32), "ESPPATS",1) > 0 then ! if this is for esppats
if pos(edit$(src_node$,32+2),"BELLICS",1) > 0 then ! if on the intenet
temp_from$ = temp_from$ +"@"+ src_node$ ! then use this node name
else ! else must be behind the firewall
temp_from$ = temp_from$ +"@bell.ca" ! so use the public email name
end if !
else !
temp_from$ = temp_from$ +"@"+ src_node$ !
end if !
end if !
temp_subj$ = edit$(d93_smtp_subject,128+8) !
temp_subj$ = "Msg: "+ format_dt( wcsm_dt_stamp ) if temp_subj$ = ""
temp_body$ = edit$(d93_smtp_body ,128) !
select d93_smtp_mode
case "H","h"
content_type$ = "text/html"
case else
content_type$ = "text/plain"
end select
select edit$(d93_smtp_urgent ,32) !
case "Y" !
temp_mime$ = &
"Subject: "+ temp_subj$ + cr + lf + &
"From: "+ temp_from$ + cr + lf + &
"To: "+ temp_to$ + cr + lf + &
"Date: "+ wcsm_get_mime_time + cr + lf + &
"Message-ID: <"+ wcsm_dt_stamp + wcsm_dt_stamp +">" + cr + lf + &
"MIME-Version: 1.0" + cr + lf + &
"Content-Type: "+ content_type$ + cr + lf + &
"X-Priority: 1" + cr + lf + &
"X-MSMail-Priority: High" + cr + lf + &
"Importance: high" + cr + lf + cr + lf
case else !
temp_mime$ = &
"Subject: "+ temp_subj$ + cr + lf + &
"From: "+ temp_from$ + cr + lf + &
"To: "+ temp_to$ + cr + lf + &
"Date: "+ wcsm_get_mime_time + cr + lf + &
"Message-ID: <"+ wcsm_dt_stamp + wcsm_dt_stamp +">" + cr + lf + &
"MIME-Version: 1.0" + cr + lf + &
"Content-Type: "+ content_type$ + cr + lf + cr + lf
end select !
case 11, 155 ! eof, rnf
goto main !
case else !
print "-e- "+ format_dt( wcsm_dt_stamp )+" status: "+ str$(error_handler%) +" during get-93"
goto main !
end select !
!
! <<< start a connection >>>
!
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 !
!
! 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
!
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 !
!
! 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 debug% >= 1 !
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 debug% >= 1 !
src_node$ = edit$( WCSM_TrnLnm( "TCPIP_DOMAINNAME", "LNM$SYSTEM_TABLE" ),32+4+2)
dest_node$ = "127.0.0.1" !
dest_port$ = "25" !
!
if debug% >= 1 then !
print "-i- src node : ";src_node$ !
print "-i- dest node : ";dest_node$ !
print "-i- port : ";dest_port$ !
end if !
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) &
20% ! timeout in seconds &
)
gosub display_rc !
if (rc% and 1%) <> 1% then !
goto close_connection_n_exit !
end if !
!
try% = 1 ! init to stage 1
goto wait_for_response !
!
! <<< send the data (loop) >>>
!
send_data_loop: !
declare string constant k_stage4 = ">>> tel func: send data" !
stage% = 4% !
print k_stage4 if debug% >= 1 !
print "-i- time: "+ format_dt( wcsm_dt_stamp ) +" -------------->>> doing try: "+ str$(try%) if debug% >= 1
select try% !
case 1 ! place-holder (initial wait for response)
goto wait_for_response !
case 2 ! log on to the specified SMTP server
msg$ = "HELO "+ src_node$ + cr + lf !
case 3 ! send MAIL FROM
msg$ = "MAIL FROM: <"+ temp_from$ +">" + cr + lf !
case 4 ! send RCPT TO
msg$ = "RCPT TO: <"+ temp_to$ +">" + cr + lf !
case 5 ! send DATA
msg$ = "DATA" + cr + lf !
case 6 ! send data line
my_date$ = date4$(0) ! dd-Mmm-yyyy
for i% = 1 to len(my_date$) !
if mid$(my_date$,i%,1) = "-" then !
mid$(my_date$,i%,1) = " " ! dd Mmm yyyy
end if !
next i% !
!
!
msg$ = temp_mime$ + ! &
temp_body$ + ! &
cr + lf +"."+ cr + lf !
case 7 ! send QUIT
msg$ = "QUIT"+ cr + lf !
case 8 !
if debug% >= 2 then !
print "-d- ====================================" !
print "-d- the SMTP comm process was successful" !
print "-d- ====================================" !
end if !
gosub close_telnet_connection !
when error in !
d93_smtp_stamp_sent = wcsm_dt_stamp !
update #93 !
error_handler% = 0 !
use !
error_handler% = err !
end when !
if error_handler% <> 0 then !
print "-e- error: "+ str$(error_handler%) +" during update-93"
sleep 2 !
end if !
goto get_next_request !
case else ! shouldn't ever happen...
print " (???) oops!" !
goto close_connection_n_exit !
end select !
sendbuf$ = msg$ !
sendbuf_w% = len(msg$) !
print "-d- xmit data>";msg$;"<" if debug% >= 2 !
rc% = tel_send_data ( ccb%, sendbuf$, sendbuf_w% ) !
gosub display_rc !
goto close_connection_n_exit if (rc% and 1%) <> 1% !
!
!----------------------------------------------------------------------------------------------------
! data has now been sent so we'll wait for an event flag
!----------------------------------------------------------------------------------------------------
wait_for_response:
read_miss% = 0 ! init
read_count% = 0 !
wrkg_buff$ = "" !
!
wait_for_response_loop:
declare string constant k_stage5 = ">>> tel func: wait"
stage% = 5%
print k_stage5 if debug% >= 1
!
! <<< arm a timer to expire 'x' time from now >>>
!
read_count% = read_count% + 1 !
select read_count% !
case 1 ! if first time thru...
junk$ = "0 00:00:05" ! then we will only wait 5 seconds
case else ! else..,
junk$ = "0 00:00:00.10" ! we will only wait 100 mS (read buf)
end select !
!
rc% = sys$bintim(junk$, 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 ) &
if debug% >= 1
!
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_n_exit if (rc% and 1%) <> 1% !
print "-i- waking from event some flag at time: "+ format_dt( wcsm_dt_stamp ) if debug% >= 1
!
! <<< cancel all timer requests (if any) >>>
!
print "-i- Calling $CanTim" if debug% >= 1
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 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 debug% >= 1 ! here is our EOL
!
! 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
if read_count% = 1 then
print "-e- oops, no response on read #1 (really bad)"
else
print "-i- no response on read #"+ str$(read_count%) if debug% >= 1
end if
read_miss% = read_miss% + 1 ! so up the read miss count
if read_miss% <= 1 then
goto wait_for_response_loop if read_miss% < 2 ! loop if less than 2
else !
goto read_exit !
end if !
else ! we've got TCP data so fall thru
end if !
!
! <<< receive the data >>>
!
declare string constant k_stage6 = ">>> tel func: recv data"
stage% = 6%
print k_stage6 if debug% >= 1
!
! 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 !
if try% = 7 then !
print "-w- connection closed unexpectedly ("+str$(rc%)+") during try: "+ str$(try%) if debug% >= 1
else !
print "-e- connection closed unexpectedly ("+str$(rc%)+") during try: "+ str$(try%)
end if !
goto read_exit !
case else !
gosub display_rc !
goto close_connection_n_exit if (rc% and 1%) <> 1% !
end select !
!
if debug% >= 2 then !
print "-d- recv data >"+ left$(recvbuf$, recvlen_w%);"<" !
print "-d- recv count: "+ str$(recvlen_w%) !
end if !
!
print "-i- read miss : "+ str$(read_miss%) if 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 wait_for_response_loop ! loop back for more
end if !
!
if debug% >= 2 then !
print "-d- ============================================================" !
print "-d- wkg buffer len:"+str$(len(wrkg_buff$)) !
print "-d- wkg buffer>"; wrkg_buff$;"<" !
print "-d- try: "+ str$(try%) !
end if !
read_exit:
!
collapsed$ = edit$( wrkg_buff$, 128+32+16+8) ! cleanup for testing
select try% !
case 1 !
junk% = pos( collapsed$ , "220", 1) ! just opened the connection
goto fini if junk% <> 1 ! this is a demo so just exit on error
try% = try% + 1 !
goto send_data_loop !
case 2 ! HELO
junk% = pos( collapsed$ , "250", 1) ! pleased to meet you
goto fini if junk% <> 1 ! this is a demo so just exit on error
try% = try% + 1 !
goto send_data_loop !
case 3 ! MAIL FROM
junk% = pos( collapsed$ , "250", 1) ! delivered as
goto fini if junk% <> 1 ! this is a demo so just exit on error
try% = try% + 1 !
goto send_data_loop !
case 4 ! RCPT TO
junk% = pos( collapsed$ , "250", 1) ! delivered as
goto fini if junk% <> 1 ! this is a demo so just exit on error
try% = try% + 1 !
goto send_data_loop !
case 5 ! DATA
junk% = 0 !
junk% = 1 if pos( collapsed$ , "250", 1) = 1 !
junk% = 1 if pos( collapsed$ , "354", 1) = 1 !
goto fini if junk% <> 1 ! this is a demo so just exit on error
try% = try% + 1 !
goto send_data_loop !
case 6 ! data lines
junk% = pos( collapsed$ , "250", 1) ! delivered as
goto fini if junk% <> 1 ! this is a demo so just exit on error
try% = try% + 1 !
goto send_data_loop !
case 7 ! QUIT
junk% = pos( collapsed$ , "221", 1) ! delivered as
goto fini if junk% <> 1 ! this is a demo so just exit on error
try% = try% + 1 !
goto send_data_loop !
case else ! this should never happen
goto fini ! exit for now (dvlp)
end select !
!
! <<< close the connection >>>
!
close_connection_n_exit: !
gosub close_telnet_connection !
goto fini !
!
! <<< close telnet connection subroutine >>>
!
close_telnet_connection: !
declare string constant k_stage11 = ">>> tel func: close" !
stage% = 11
print k_stage11 if debug% >= 1 !
print "-i- Closing connection..." if debug% >= 1 !
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 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 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
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
sleep 1 !
else ! some kind of error....
junk% = tel_abort_connection( ccb% ) ! don't take any chances
sleep 1 !
end if !
end select !
return !
!----------------------------------------------------------------------------------------------------
!
! <<< display return code after each call to the TELNET library >>>
!
display_rc:
if (rc% and 7%) <> 1% or ! if not -s- (success) &
debug% >= 1 ! or full 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 ">>> tel func: unknown: ";
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)
!
print "-i- preparing to exit" !
gosub close_telnet_connection !
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 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 !
!
30000 end program rc% !
!
!========================================================================================================================
! external functions
!========================================================================================================================
31005 %include "[.fun]wcsm_get_mime_time.fun" !
! FUNCTION STRING wcsm_get_mime_time(string,string) !
!
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
!
Back to
Home
Neil Rieck
Waterloo, Ontario, Canada.