#!/bin/sh - # # expect-shell functions # # Simple script to call a telnet server # # NOTE: these functions expect that the executables "pty" and "waitfor" are # available. # # "pty" allows programs needing a tty (like telnet) to accept standard input # and output when program does not allow piping. It also ensures the data # remains line buffered, rather than waiting for a full 'block' of text. # # "waitfor" reads standard input until it sees the given character string # or a timeout is reached, (a shell "expect" statment). It does NOT read # standard input any further than the last character of this string. # # WARNING: some versions of telnet flushes its input after it has connected, # As such you need to delay any automatic imput by about 5 seconds, or have # the script wait until it sees the connection message before senting input. # It may be better to use "netcat", "nc", "mconnect" or some other network # connection program that does not have the 'buffering' and 'input flushing' # problems of "telnet". # # File Descriptors used # >&4 Send to the telnet server # <&5 Recieve from the telnet server # >&6 terminal output (for debugging) # ><&8 The file opened for upload and download # PROGNAME=`basename $0` # base name of program ORIGDIR=`pwd` # original directory BINDIR=`dirname $0` # directory of script cd $BINDIR # cd to script directory BINDIR=`pwd` # set correctly, full path to script DEBUG= # turn debugging output on/off Server="localhost" # the server to call Port=echo # on this port (echo port) Prompt='telnet>' # telnet prompt to look for tmpfiles="" # the temporary file to remove on trap abort # ---------------------------------------------------------- # NOTE: these routines use $I as an input buffer. Read() { # just read a line (read telnet info) exec <&5; read I [ "$DEBUG" ] && echo "--> $I" >&6 } ReadIgnore() { # don't even log the read exec <&5; read I } CheckRead() { # Read and check that we read the given argument exec <&5; read I [ "$DEBUG" ] && echo "--> $I" >&6 case "$I" in $1) return 0 ;; *) echo >&6 "$name : \`\`$I''"; return 1 ;; esac } ReadFile() { # Download to the given filename # NOTE: EOF is a `.' on a line by itself exec <&5 8>"$1"; : > "$1" while :; do exec <&5; read I [ "$DEBUG" ] && echo "==> $I" >&6 [ "$I" = '.' ] && break echo >8 "$I" done exec 8>&- } Send() { # Send a string to the server [ "$DEBUG" ] && echo "<-" "$@" >&6 echo >&4 "$@" } SendRead() { # Send and ignore the return echo send "$@"; ReadIgnore } SendFile() { # Upload the given filename to the server # NOTE: EOF is a `.' on a line by itself exec 8<"$1" while exec <&8; read I; do [ "$DEBUG" ] && echo "<=" "$I" >&6 echo >&4 "$I" ReadIgnore done [ "$DEBUG" ] && echo "<= ." >&6 echo >&4 "." ReadIgnore exec 8<&- } WaitFor() { # wait for the given string to be received if [ "$DEBUG" ]; then waitfor "$1" <&5 2>&1 | sed 's/^/ <- /' >&6 else waitfor "$1" <&5 2>/dev/null fi } QuitServer() { # Close the telnet server connection sleep 1 # wait for things to settle echo >&4 "^]" # break back to telnet prompt WaitFor "$Prompt" Send "quit" Read } OpenServer() { # Open the telnet connection to server echo "Contacting $Server on $Port..." pty -d0E telnet recv & exec 4>send 5&- 5<&-; exit 1; } CheckRead "Connected*" || { QuitServer; exec 4>&- 5<&-; exit 1; } CheckRead "Escape*" || { QuitServer; exec 4>&- 5<&-; exit 1; } echo "Connected!" } # ---- Preparation/Cleanup for above --- Cleanup() { exec 4>&- 5<&- 9<&- rm -f $tmpfiles if [ "$DEBUG" ] ; then echo >&6 "TRAP: aborting" exec 6>&- fi } # the abort trap trap 'Cleanup; exit 1;' 1 2 3 15 # Normal exit trap trap 'Cleanup; exit 0;' 0 # create the named pipes required tmpfiles="$tmpfiles send recv" mknod send p mknod recv p exec 6>&2 # set where error are to go. # ---------------------------------------------------------- OpenServer exec <&5; read I; # read the servers first response (if it does) set - $I # and examine it SendRead "TESTING 1 2 3" CheckRead "TESTING*" || { QuitServer; Cleanup; exit; } # ... etc ... QuitServer