#!/usr/local/bin/kermit +
;
; File APAGE.KSC
; Version 5.0
;
; TAP/IXO alphanumeric paging script for Kermit 95 and C-Kermit.
; Authors: F. da Cruz and C. Gianone, Columbia University, September 1996.
;
; For use with C-Kermit 7.0 / K95 1.1.19 or later.
; For a detailed explanation, consult "Using C-Kermit", 2nd Ed., pp.454-456.

if LLT \v(version) 700196 stop 1 C-Kermit 7.0 or K95 1.1.19 or later required.

; Version 2.0: July 1997:
;  1. To make TAPMSG fit into 1K for small C-Kermit versions.
;  2. Change END to STOP within SWITCH to work around bug.
; Version 3.0: September 1997:
;  1. Change STOP back to END because bug is fixed.
;  2. Added robustness.
; Version 4.0: August 1998:
;  1. Additional robustness - requires 2K command buffer.
;  2. Diagnostics.
; Version 5.0: February 2000:
;  1. Improved portability and parameterization
;
; WARNING: Automatic redialing is restricted or illegal in some
; countries.  Modify the lines marked "IF LEGAL!" if below this applies
; in your location.
;
; TAPMSG, defined below, is an alphanumeric pager dialing script that
; implements the Telocator Alphanumeric Protocol (TAP), also known as IXO,
; for sending one-line alphanumeric pages.  TAPMSG assumes the connection
; to the paging service is already made.
;
; The APAGE macro makes a connection to the paging service and then uses
; TAPMSG to send the page.  The following is a SAMPLE; you will need to adjust
; it to work with your paging service.  Hint: Some paging services are very
; picky about modem configurations.  For example, experience has shown that to
; dial a certain service successfully with a USR V.34 modem, just about all of
; the modem's features must be turned off prior to dialing.
;
; GENERAL INSTRUCTIONS
;
; Edit the APSETUP macro below to contain the device name for dialing plus any
; special communications parameters (lines marked "(*)" below).  Then whenever
; you want to send an alpha page, tell Kermit to "take" the file (which
; installs the APAGE and TAPMSG definitions) and then to send a page, just
; type:
;
;   apage pagerid { this is a message }
;
; at the K-95> prompt, for example:
;
;   apage 99997654321 { Please call the office }
;
; If you always want the APAGE macro available, add a TAKE command for this
; file to your K95CUSTOM.INI file.
;
; Note: the pager ID number should not contain any spaces or else you must
; enclose it in braces:
;
;   apage { 999 76 543 21 } { This is a message }
;
; Ditto for the message.
;
; DEBUGGING: If you want to see diagnostic and progress messages, type
; "define testing 1" at the Kermit prompt before trying to send a page.
;
; The alpha paging service phone number is taken from the Kermit variable
; APAGEPHONE.  If the Kermit variable is not defined, it is taken from the
; environment variable APAGEPHONE.  If none of these is defined, a prompt
; is given so you can enter it by hand.
;
; UNIX INSTRUCTIONS
; 
; Change the top line to indicate the full pathname of the C-Kermit 7.0
; executable, if it is not /usr/local/bin/kermit.  Edit the APSETUP macro
; below as required, then store this file in your path with a name like
; alphapage, give it execute permission, and then you can run it by name:
;
;   alphapage pagerid message
;
if not defined APAGEPHONE assign APAGEPHONE \$(APAGEPHONE)
while not def APAGEPHONE {
    ask APAGEPHONE { Alpha paging service phone number? } 
}

local \%n                      ; (for error messages)
assign \%n \fbasename(\%0)

if not def TESTING def TESTING 0 ; Set to 1 for testing / debugging
if \m(TESTING) {		 ; So we can watch what happens
    set dial display on
    set input echo on
    set terminal echo local    ; So output goes in session log
    log session                ; Creates session.log in current directory
    log transact               ; Creates transact.log in current directory
}

; EDIT the APSETUP macro for your modem, dialout device, and
; the communication setup required by your paging service.

define APSETUP {               ; Set up the calling parameters.
    if eq \v(system) WIN32 {   ; (*) In Windows use the default TAPI device.
        set tapi line          
        if fail end 1
    } else {                   ; Elsewhere...
        set modem type usr     ; (*) Specify the modem type.
        set line /dev/ttyS1    ; (*) Specify dialout port.
	if fail end 1
    }
    set speed 1200             ; (*) Speed required by paging service
    set parity even            ; (*) Parity required by paging service
    set flow none              ; (*) No flow control
    set modem flow none        ; (*) ...
    set dial retries 20        ; (*) Allow 20 redials (IF LEGAL!)
    set dial interval 1        ; (*) 1 sec between redial attempts (IF LEGAL!)
}

define APAGE {                 ; Call the paging service and send a page.
    local rc                   ; rc = Return code for this macro
    if < \v(argc) 2 end 1 Pager ID required
    do apsetup
    if fail end 1
    set modem error-correction off
    set modem data-compression off
    set modem speed-matching off
    set output pacing 200      ; Talk s-l-o-w-l-y to the paging service
    dial \m(APAGEPHONE)        ; Call the pager service
    asg rc \v(status)	       ; Save DIAL status
    if = \m(rc) 0 {            ; If the call is answered
        tapmsg \%1 {\%2}       ; Send the page
        asg rc \v(status)      ; Save the result
    } else {                   ; Otherwise
        echo Page failed.      ; Fail.
    }
    hangup                     ; Hang up the phone
    ;
    ; For shared in-out ports you might need to reset the port's original
    ; speed here and maybe also send it some kind of reset command like ATZ0.
    ;
    set modem type \v(modem)   ; Restore default modem settings
    end \m(rc)                 ; Return
}

; TAPMSG Telocator Alphanumeric Protocol execution.  Call with:
;   \%1 = Pager ID (PIN)
;   \%2 = Message (single line)
;  Assumes connection is made.  Uses TAP to send PIN and 1-line message.
;
def TAPMSG {
    local \%i \%m \%s blk		; Local variables
    asg \%m \2\%1\13\%2\13\3		; <STX>ID<CR>msg<CR><ETX>
    asg \%s \fchecksum(\%m)		; Get checksum and make block
    asg blk \%m\fchar(\fmod(\%s/256,16)+48)-
\fchar(\fmod(\%s/16,16)+48)-
\fchar(\fmod(\%s,16)+48)\13		; Checksummed TAP block
    if \m(TESTING) xecho WAITING FOR ID= PROMPT...
    for \%i 1 6 1 {			; Try six times to get prompt
	out \13				; Send <CR>
	in 3 ID=			; Wait for "ID="
	if succ break
        if \m(TESTING) xecho NO ID= PROMPT - TRYING AGAIN
    }
    if > \%i 6 end 1 FAILED: No "ID=" prompt after 6 tries
    for \%i 1 8 1 {			; Send <ESC>PG1, get <ACK>
	msleep 500
	output \{27}PG1\13
        if \m(TESTING) echo SENT <ESC>PG1(\%i)...
	minput 3 {\6\13} {\21\13} {ID=} {\27\4\13}
        if \m(TESTING) echo RESULT=\v(minput)
	switch \v(minput) {
	  :0, continue			; Timeout
	  :1, break			; <ACK>
	  :2, continue			; <NAK>
	  :3, out \{27}PG1\13, continue
	  :4, end 1 Forced disconnect	; Forced disconnect - fatal
	}
	break
    }
    if > \%i 8 end 1 Timeout during TAP
    in 10 \27[p\13			; Wait for go-ahead
    if fail end 1 No go-ahead		; Didn't get it
    for \%i 1 8 1 {			; Try eight times
	msleep 500
	output \m(blk)			; Send block
        if \m(TESTING) echo SENT BLOCK (\%i)...
	minput 8 {\6\13} {\21\13} {\13\27\4\13} {\30\13}
        if \m(TESTING) echo RESULT=\v(minput)
	switch \v(minput) {             ; Get response
	  :0, continue                  ; Timeout
	  :1, break                     ; <ACK> - success
	  :2, continue                  ; <NAK>
	  :3, end 1 Forced Disconnect
	  :4, echo ERROR - RETRYING, continue
	}
	out \4\13                       ; Sign off with <EOT>
	in 8 \27\4\13                   ; Get <ESC><EOT> back
	break                           ; But ignore timeout
    }
    if > \%i 8 end 1 Too many retries
}

; If invoked as a "kerbang" script execute it now.

if equal "\%0" "\v(cmdfil)" {
    if ( != \v(argc) 3 ) exit 1 {usage: \%n <pagerid> <message>}
    apage {\%1} {\%2}
    exit \v(status)
}

; (End)
