#!/usr/local/bin/kermit8 ; -------------------------------------------------------------------- ; ; cook2.ksc ; ; ; Author ; ------ ; R. M. Almeria, Anteon Corp., 2003 ; ; ; Purpose ; ------- ; This kermit script is designed to take 1 to N times two arguments ; (a pager-id and a message) and to connect to Arch's paging service ; via a modem using their special service number. ; ; So you can basically connect to the service and issue several pages ; or just one. You could send a message to someone's pager like so: ; ; cook2.ksc 4441111 "hello world" ; ; or you could send multiple messages to multiple pagers like so: ; ; cook2.ksc 4441111 "test1" 4442222 "test2" 4443333 "test3" ; ; ; Special Remarks ; --------------- ; This program implements the TAP (Telocator Alphanumeric Protocol) ; for pagers. ; ; ; Language ; -------- ; This program is written in Kermit script. Please read the book ; "Using C-KERMIT" by Frank da Cruz et al., for more details. ; ; ; Revision History ; ---------------- ; v1.1 -- February 5, 2003 @ 3:48 PM ; Added copious debug statements that are toggled (0/1) via ; the DEBUG constant (it is defined in the initialization section). ; ; v1.0 -- January 28, 2003 @ 5:55 PM ; Initial revision. ; ; -------------------------------------------------------------------- ; -------------------------------------------------------------------- ; Check the number of command line arguments and exit if insufficient. ; -------------------------------------------------------------------- xif < \v(args) 4 { echo \10This kermit8 paging script accepts unlimited alphanumeric- pager-id/message pairs.\10 echo {SYNTAX:\10\9cook2.ksc pagerid1 message1 pagerid2 message2- pagerid3 message3 . . . \10} echo { EX:\10\9./cook2.ksc 9992322 "Hello World!"\10} exit } ; -------------------------------------------------------------------- ; Define the SendBlock function which sends a message (block) to the ; paging service. This function is also called initially to send the ; first message. ; -------------------------------------------------------------------- def SENDBLOCK { local \%b \%c \%s blk ; Create a string composed of the pager-id and message with ; appropriate control chars. assign \%b \2\&p[\%m]\13\&m[\%m]\13\3 ; Calculate the checksum required for TAP and add to the final ; message string that will be sent to the paging service. assign \%c \fchecksum(\%b) assign blk \%b\fchar(\fmod(\%c/256,16)+48)\fchar(\fmod(\%c/16,16)+48)\fchar(\fmod(\%c,16)+48)\13 assign \%s \flength(blk) ; Make sure that the size of the block is less than MaxBlockSize. xif < \%s \%y { if \m(DEBUG) echo {DEBUG: {SENDBLOCK} Sending '\&m[\%m]' to '\&p[\%m]'} output \m(blk) return 1 } else { return 0 } } ; -------------------------------------------------------------------- ; Define the SendNextBlock function which sends the second thru last ; messages (blocks) to the paging service (one block sent per ; function call). This function calls SendBlock to send its messages. ; -------------------------------------------------------------------- def SENDNEXTBLOCK { xif < \%m+1 \%n { ; There are still messages to send so send them. assign \%q 0 ; Reset the retries counter. assign \%m \feval(\%m + 1) sendblock return \v(return) } else { ; We are done with the paging service so disconnect. output \4\13 ; Send if \m(DEBUG) echo {DEBUG: {SENDNEXTBLOCK} Sending .} input 3 {\27\4\13} ; Look for assign \%f 1 ; Set Finished to true. return 0 } } ; -------------------------------------------------------------------- ; Define the TAP (Telocator Alphanumeric Protocol) function. ; -------------------------------------------------------------------- def SENDTAPMSG { assign \%o \6\13 ; OK = assign \%t \21\13 ; TRY AGAIN = assign \%a \30\13 ; ABANDON = assign \%d \27\4\13 ; DISCONNECT = assign \%x 0 ; Initialize the loop variable. assign \%f 0 ; Initialize Finished flag to false. assign \%w 5 ; Initialize MaxIDAttempts. :dowhile ; Look for 'ID=' string for at least MaxIDAttempts before exiting. xif = \%f 0 { xif < \%x \%w { output \13 input 3 {ID=} xif success { assign \%f 1 } else { assign \%x \feval(\%x + 1) } goto dowhile } } ; Exit if we didn't get the 'ID=' string. xif = \%f 0 { assign \%e 0 end } assign \%q 0 ; Initialize protocol Retries and NOT dialing retries. assign \%u 1 ; Initialize First to true. assign \%f 0 ; Reset Finished to false. assign \%v 0 ; Initialize SentBlock to false. assign \%y 233 ; Define MaxBlockSize. Typically 256 according to the ; protocol but Cook limits this to 233. assign \%z 3 ; Define MaxRetries. while = \%f 0 { xif = \%u 1 { xif < \%q \%z { if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} Sending PG1.} ; Tell the paging service that we want to send an ; alphanumeric page. output {\27PG1\13} ; Sending PG1 ; Wait for a response from the paging service... ; either OK, TRY AGAIN, DISCONNECT, 'ID=' or ; TIMEOUT. minput 3 {\%o} {\%t} {\%d} {ID=} switch \v(minput) { :0, break ; TIMEOUT :1, ; OK = if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} Received OK.} if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} Waiting for [p.} ; Wait for the go-ahead from the paging service. input 3 {\27[p\13} xif success { msleep 500 xif < \%m \%n { if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} Calling SENDBLOCK.} sendblock ; Send first block. assign \%v \v(return) assign \%u 0 } else { assign \%f 1 ; Set Finished to true. } } else { assign \%f 1 ; Set Finished to true. } break :2, ; TRY AGAIN = if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} Received TRY AGAIN.} break :3, ; DISCONNECT = if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} Received DISCONNECT.} assign \%f 1 ; Set Finished to true. break :4, break ; Received 'ID=' send PG1 again } ; Increment the Retries counter. assign \%q \feval(\%q + 1) } else { assign \%f 1 ; Set Finished to true. } } else { ; Look for the response to the first and succeeding blocks that ; were sent to the paging service. We are waiting for an OK, ; ABANDON, TRY AGAIN, DISCONNECT or TIMEOUT response. minput 3 {\%o} {\%a} {\%t} {\%d} switch \v(minput) { :0, break ; TIMEOUT :1, ; OK = if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} - Received OK.} msleep 500 if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} - Calling SENDNEXTBLOCK.} sendnextblock assign \%v \v(return) break :2, ; ABANDON = if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} - Received ABANDON.} msleep 500 if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} - Calling SENDNEXTBLOCK.} sendnextblock assign \%v \v(return) break :3, ; TRY AGAIN = if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} - Received TRY AGAIN.} msleep 500 xif = \%v 1 { xif < \%q \%z { sendblock assign \%v \v(return) ; Increment the retries counter. assign \%q \feval(\%q + 1) } else { sendnextblock assign \%v \v(return) } } else { sendnextblock assign \%v \v(return) } break :4, ; DISCONNECT = if \m(DEBUG) echo {DEBUG: {SENDTAPMSG} - Received DISCONNECT.} assign \%f 1 ; Set Finished to true. break } } } xif < \%m+1 \%n { assign \%e 0 ; Return false (Didn't send all messages due to errors). } else { assign \%e 1 ; Return true (We sent all of the messages). } } ; -------------------------------------------------------------------- ; Initialization. ; -------------------------------------------------------------------- assign DEBUG 1 ; Calculate the number of messages to send. assign \%n \feval( (\v(args) - 2)/2) declare \&p[\%n] ; Declare the pager-id array. declare \&m[\%n] ; Declare the message array. ; Populate the pager-id and message arrays with the args. for \%x 0 \%n-1 1 { assign \%i \feval(2 + (\%x * 2)) ; Compute the pager-id index. assign \%j \feval(3 + (\%x * 2)) ; Compute the message index. assign \&p[\%x] \&@[\%i] ; Add pager-id to pager-id array. assign \&m[\%x] \&@[\%j] ; Add message to message array. } assign \%m 0 ; Initialize message index (MIndex). assign \%r 0 ; Initialize the Reconnects counter. assign \%s 3 ; Define MaxReconnects. assign COOKPDX 9,5031234567 ; Set to local paging service phone number. assign \%e 0 ; Initialize TAP Error Flag to false. ; -------------------------------------------------------------------- ; Try to connect to the paging service. ; -------------------------------------------------------------------- :restart if \m(DEBUG) echo {\10DEBUG: RESTART NO. \%r} set modem hangup-method modem-command if \m(DEBUG) echo {DEBUG: Issuing initial HANGUP.} hangup if \m(DEBUG) echo {DEBUG: Setting modem type} set modem type att-dataport if \m(DEBUG) echo {DEBUG: Setting the port to '/dev/cua/4'} set port /dev/cua/4 xif failure { echo {ERROR: I could not connect to /dev/cua/4} goto terminate } if \m(DEBUG) echo {DEBUG: Setting up the terminal.} set speed 2400 set parity even set stop-bits 1 set flow-control xon/xoff set modem flow none set modem error-correction off set modem data-compression off set modem speed-matching off ;set carrier-watch off set output pacing 200 set dial retries 5 set dial interval 1 if \m(DEBUG) echo {DEBUG: DIALING....} dial \m(COOKPDX) xif success { if \m(DEBUG) echo {DEBUG: Calling SENDTAPMSG.} sendtapmsg xif = \%e 0 { xif < \%r \%s { xif < \%m \%n { assign \%r \feval(\%r + 1) goto restart } } } } :terminate if \m(DEBUG) echo {DEBUG: Hanging up.} hangup if \m(DEBUG) echo {DEBUG: Exiting.} exit