home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/kermit
-
- ; r e m o t e a c c e s s
- ;
- ; How to conduct a dialog with a user when Kermit does not have a controlling
- ; terminal; for example, when Kermit has accepted an incoming Internet ("set
- ; host *") or modem ("answer") connection, or when a Kermit script is started
- ; under inetd. This script shows how to handle echoing and rudimentary
- ; keyboard editing:
- ;
- ; . Prints a prompt and waits for a line of text.
- ; . Ordinary characters echo.
- ; . Rubout, Delete, or Backspace removes the rightmost character from the line.
- ; . Ctrl-U removes the current line, if any.
- ; . Ctrl-R repaints the current line.
- ; . The prompt is protected.
- ;
- ; To make it more interesting, lines are interpreted as commands, validated,
- ; and executed.
- ;
- ; Note that when printing lines to the user's screen, both carriage (\13)
- ; and linefeed (\10) are included for when there is no terminal driver
- ; to supply them. In case there IS a terminal driver, the SET INPUT ECHO OFF
- ; command allows the script to work there too.
- ;
- ; F. da Cruz, Columbia University, January 2003
-
- ; First make a command keyword table and then sort it for \tablelook().
- ;
- declare \&k[] = exit:5 quit:5 help:2 ?:2 echo:1 send:3 list:4 directory:4
- sort &k
-
- ; Make an array of help strings keyed on keyword value.
- ;
- dcl \&h[5]
- .\&h[1] = ECHO [text] echos its arguments.
- .\&h[2] = HELP prints this message; Synonym: "?".
- .\&h[3] = SEND filename [as-name] sends the given file under the given name.
- .\&h[4] = LIST [filespec] lists files; Synonym: DIRECTORY.
- .\&h[5] = EXIT exits; Synonym: QUIT.
-
- ; Define command service routines
-
- define DOEXIT { ; Service routine for EXIT command
- output "\13\10Bye.\13\10"
- sleep 1
- exit
- }
-
- define DOSEND { ; Service routine for SEND command
- if not defined \%1 {
- output "Filename required\13\10"
- end 1
- } else if not exist \%1 {
- output "File not found: "\%1"\13\10"
- end 1
- }
- send \%1 \%2
- }
-
- define DOLIST { ; Service routine for LIST command
- local \&d[] \%i \%f \%m
- directory /array:&d \%1 ; Get filenames into array &d[]
- output "\13\10"
- if not \fdim(&d) {
- output "(No files match)\13\10"
- } else {
- .\%m := 0 ; Quickly get length of longest name
- for \%i 1 \fdim(&d) 1 {
- .\%m := \fmax(\%m,\flen(\&d[\%i]))
- }
- incr \%m
- for \%i 1 \fdim(&d) 1 { ; Print listing
- .\%f := \&d[\%i]
- if not readable \%f continue
- output " \frpad(\%f,\%m) \flpad(\fsize(\%f),9) \fdate(\%f)\13\10"
- }
- }
- output "\13\10"
- }
-
- define DOHELP { ; Service routine for HELP command
- local \%i
- output "\13\10"
- output "Commands are:\13\10\13\10"
- for \%i 1 \fdim(&h) 1 {
- output " \&h[\%i]\13\10"
- }
- output "\13\{10}Commands may be abbreviated.\13\10"
- output "\13\10"
- }
-
- ; Command parser and dispatcher
-
- define DOCOMMAND {
- if not def \%1 return ; Ignore blank lines
- void \fsplit(\%1,&a,\32) ; Split line into words
- .\%k := \ftablelook(\&a[1],&k) ; Look up first word
- switch \%k { ; Handle lookup error
- :-1
- output "Command not found: "\&a[1]"\13\10"
- output "Type HELP for help\13\10"
- continue
- :-2
- output "Ambiguous: "\&a[1]"\13\10"
- output "Type HELP for help\13\10"
- continue
- }
- switch \fword(\&k[\%k],2,:) { ; Dispatch on keyword value
- :1 ; ECHO prints its arguments
- output "\fjoin(&a[2:])\13\10"
- break
- :2 ; HELP prints help text
- dohelp
- break
- :3 ; SEND sends a file
- dosend \&a[2] \&a[3] ; with an optional as-name
- output "\13\10"
- break
- :4 ; LIST prints a file list
- dolist \&a[2]
- break
- :5 ; QUIT and EXIT quit
- doexit
- }
- }
-
- set case off ; Commands are case-independent
- set input echo off ; In case there is a controlling tty
- set root . ; Restrict users to this directory tree
-
- define prompt "Command: " ; Define prompt
- output "\13\10" ; Start on a new line
- output "Type HELP for help.\13\10" ; Greet
-
- ; Loop to read lines and pass them to the command interpreter.
- ; This is where we handle echoing and editing.
-
- while true { ; Outer loop for lines
- undef buf ; Line buffer
- .\%n = 0 ; Line length
- output "\m(prompt)" ; Prompt
- set flag off ; Inner loop control
- while not flag { ; Inner loop for characters
- input -1 ; Get a character
- if fail stop 1 INPUT Error ; Make sure we did
- .\%c := \v(inchar) ; This is the character
- .\%x := \fcode(\%c) ; This is its code
- switch \%x { ; switch on its code
- :3 ; Ctrl-C
- doexit ; Exit immediately
- :13 ; Carriage Return
- :10 ; or Line Feed
- :12 ; or Form Feed
- output "\13\10" ; Echo CRLF
- set flag on ; Set inner-loop exit flag
- docommand "\m(buf)" ; Process the user's command
- continue
- :8 ; Backspace
- :127 ; or Rubout
- if not def buf { ; Nothing to delete
- output "\7" ; just beep
- continue
- }
- output "\8 \8" ; Erase char from user's screen
- decr \%n ; And from line buffer
- .buf := \s(buf[1:\%n])
- continue
- :18 ; Ctrl-R
- output "\13\10" ; Refresh line
- output "\m(prompt)\m(buf)"
- continue
- :21 ; Ctrl-U
- for \%i 1 \%n 1 { ; Erase line from screen
- output "\8 \8"
- }
- .\%n = 0
- undef buf
- continue
- :9 ; Ctrl-I (Tab)
- .\%c := \32 ; Convert to space
- .\%x := 32 ; and fall thru.
- :default ; Anything else
- if > \%x 31 { ; If char is printable
- output \%c ; echo it
- .buf := \m(buf)\%c ; add it to line buffer
- incr \%n ; and count it
- } else output "\7" ; Beep for nonprintables
- }
- }
- }
-