Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!uunet!haven.umd.edu!cville-srv.wam.umd.edu!ni.umd.edu!sayshell.umd.edu!louie
From: louie@sayshell.umd.edu (Louis A. Mamakos)
Newsgroups: comp.unix.bsd
Subject: Re: BSDI and IXO
Date: 3 Jul 1993 15:21:53 GMT
Organization: University of Maryland, College Park
Lines: 290
Message-ID: <21486h$f5q@ni.umd.edu>
References: <20sp7v$9hr@cyberspace.com>
NNTP-Posting-Host: sayshell.umd.edu
In article <20sp7v$9hr@cyberspace.com> brc@cyberspace.com (Brian Cartmell) writes:
>Does anyone have a program that works on BSD that will connect to a device
>dial a number and transfer Alpha Pager Message via the IXO for alpha pagers?
I have an expect script (actually, two files) that does this. It can
use tip(1) to actually talk to the modem. We also have a different
module that telnets to an terminal server with dial-out modems too,
that just uses a different "hardware" file.
This pretty ugly and disgusting, but the implementation of the IXO
protocol in TCL, I thought, was rather interesting.
It's usually invoked as
beep pagerid "It's broken! Help!" pagerid2 "Help! It's down!"
there's also a way to pass it a file containing pagerids and messages for
"bulk" beeping.
Louis Mamakos
------------ beep.expect
#!/local/bin/expect
#
# Call a beeper. By default, uses tip(1c) to establish the modem connection
# which requires an entry in /etc/remote that looks like this:
#
# dialer:dv=/dev/cufa:br#38400:pa=even:
#
log_user 0
#debug 1
# definition of paging service's phone number
set service "474-4657"
# hardware to use
set hardware beep.tip
# definitions of various ascii control characters used by the paging
# protocol
set STX \002
set ETX \003
set ACK \006
set NAK \025
set RS \036
set ESC \033
set EOT \004
# ===
proc error { msg } {
puts stderr "Error: $msg"
exit
}
# ===
#
# compute the checksum over the paging transaction packet. Return the
# checksum string
#
proc checksum { s } {
set sum 0
foreach ch [split $s {}] {
scan $ch "%c" v
incr sum $v
}
return [format "%c%c%c" [expr "48 + (($sum >> 8) & 15)"] \
[expr "48 + (($sum >> 4) & 15)"] \
[expr "48 + ($sum & 15)"]];
}
# ===
proc get_response {} {
global ACK NAK RS ESC EOT
expect "*$ACK\r" {puts stderr "resp: OK"; return "OK"} \
"*$NAK\r" {puts stderr "resp: NAK"; return "NAK"} \
"*$RS\r" {puts stderr "resp: ABANDON"; return "ABANDON"} \
"*$ESC$EOT\r" {puts stderr "resp: DISC"; return "DISC"} \
timeout {puts stderr "resp: TIMEOUT"; return "TIMEOUT"}
}
# ===
#
# Generate a page to "pin" carrying the message "message"
#
proc page { pin message } {
global STX ETX
set attempts 0
regsub "\t+" $message " " message
set message [string range $message 0 238]
set pgstr "${STX}${pin}\r${message}\r${ETX}"
set block "$pgstr[checksum $pgstr]\r"
send $block
puts stderr "Sending page to $pin"
set resp [get_response]
#
# Examine the response. Only "NAK" responses are retried
#
while {! [string compare "NAK" $resp] && $attempts < 5} {
puts stderr "Resending block due to NAK"
exec sleep 1
send $block
set resp [get_response]
incr attempts
}
return $resp
}
# ===
#
# condition the paging system to accept the Paging Entry Terminal protocol,
# rather than thinking we're a dumb terminal out here.
#
proc dologin {} {
global ESC
foreach i {once} {
set timeout 5
expect {*ID=} break timeout {}
set timeout 2
send "\r"
expect {*ID=} break timeout {}
send "\r"
expect {*ID=} break timeout {}
send "\r"
expect "*ID=" break timeout {}
send "\r"
expect "*ID=" break timeout {
send_user "Error: waiting for id= prompt\r"
return -1
}
}
set timeout 10
# this is the magic bit..
send "${ESC}PG1000000\r"
case [set resp [get_response]] in {
OK {puts stderr "Logged into paging service"}
NAK {error "to send of PG1"}
TIMEOUT {error "timeout of response to PG1"}
* {error "Unexpected response '$resp' during login"}
}
return 0
}
# ===
proc logout {} {
global EOT
send "$EOT\r"
case [get_response] in {
DISC {puts stderr "Normal disconnect"}
RS {puts stderr "Some pages may have failed"}
}
}
# ============= start of main program =============
set argc [llength $argv]
set dofile 0
set arg 1
if {$argc>2 && ([string compare FILES [lindex $argv 1]] == 0)} {
set dofile 1
set arg 2
} else {
if {$argc < 3} {
puts stderr \
"usage: [lindex $argv 0] pagerid message \[pagerid message ...\]"
exit
}
}
source $hardware
set success 0
for {set tries 5} {$tries} {set tries [expr $tries-1]} {
# invoke communication facility specific function to establish
# a connection with the paging service
connect $service
# attempt to initiate session protocol
if {[dologin] == 0} {
set success 1
break
}
}
if { $success == 0 } {
error "Gave up looking for a working modem at the other end"
}
while {!$dofile && ($arg < $argc)} {
set who [lindex $argv $arg]
set msg [string range [lindex $argv [expr $arg+1]] 0 238]
set arg [expr $arg+2]
puts stderr "Paging $who with $msg"
page $who "$msg"
}
if {$dofile} {
while {$arg < $argc} {
set dofile [open [set filename [lindex $argv $arg]] r]
incr arg
if {[gets $dofile who] < 0} {
puts stderr "EOF reading recpient from $filename"
exec rm -f $filename
continue
}
if {[gets $dofile msg] < 0} {
puts stderr "EOF reading message from $filename"
exec rm -f $filename
continue
}
if {[regsub "^ID=" $who "" who] == 0} {
puts stderr "$filename: Missing ID= on pager line"
exec rm -f $filename
continue
}
if {[regsub "^MSG=" $msg "" msg] == 0} {
puts stderr "$filename: Missing ID= on pager line"
exec rm -f $filename
continue
}
close $dofile
puts stderr "Paging $who with $msg"
if {[page $who "$msg"] == "OK"} {
exec rm -f $filename
}
}
}
# end session protocol
logout
#
# invoke communication facility specific function to disconnect from
# paging service
#
disconnect "Mission sucessful\n"
exit 0
----------- beep.tip
proc connect { pagerservice } {
global spawn_id pid
uplevel 1 set pid [spawn tip dialer]
expect "connected*"
send "AT\r"
expect "*OK*" {}
send "ATE0\r"
expect "*OK*" {}
send "ATM0&N15&K0DT${pagerservice}\r"
set timeout 20
expect "*CONNECT*\r" {} timeout {error "modem didn't return CONNECT"}
expect_after eof {error "Got EOF (default)"} \
{\rNO\ CARRIER\r} {error "Lost connection"}
}
proc disconnect { msg } {
send "\r~.\r"
send_user $msg
}