diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/ip/nppp/script.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/cmd/ip/nppp/script.b')
| -rw-r--r-- | appl/cmd/ip/nppp/script.b | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/appl/cmd/ip/nppp/script.b b/appl/cmd/ip/nppp/script.b new file mode 100644 index 00000000..d929ff7a --- /dev/null +++ b/appl/cmd/ip/nppp/script.b @@ -0,0 +1,171 @@ +implement Script; + +include "sys.m"; + sys: Sys; + +include "draw.m"; + +include "string.m"; + str: String; + +include "lock.m"; +include "modem.m"; + modem: Modem; + Device: import modem; + +include "script.m"; + +Scriptlim: con 32*1024; # should be enough for all + +init(mm: Modem): string +{ + sys = load Sys Sys->PATH; + modem = mm; + str = load String String->PATH; + if(str == nil) + return sys->sprint("can't load %s: %r", String->PATH); + return nil; +} + +execute(m: ref Modem->Device, scriptinfo: ref ScriptInfo): string +{ + if(scriptinfo.path != nil) { + if(m.trace) + sys->print("script: using %s\n",scriptinfo.path); + # load the script + err: string; + (scriptinfo.content, err) = scriptload(scriptinfo.path); + if(err != nil) + return err; + }else{ + if(m.trace) + sys->print("script: using inline script\n"); + } + + if(scriptinfo.timeout == 0) + scriptinfo.timeout = 20; + + tend := sys->millisec() + 1000*scriptinfo.timeout; + + for(conv := scriptinfo.content; conv != nil; conv = tl conv){ + e, s: string = nil; + p := hd conv; + if(len p == 0) + continue; + if(m.trace) + sys->print("script: %s\n",p); + if(p[0] == '-') { # just send + if(len p == 1) + continue; + s = p[1:]; + } else { + (n, esl) := sys->tokenize(p, "-"); + if(n > 0) { + e = hd esl; + esl = tl esl; + if(n > 1) + s = hd esl; + } + } + if(e != nil) { + if(match(m, special(e,scriptinfo), tend-sys->millisec()) == 0) { + if(m.trace) + sys->print("script: match failed\n"); + return "script failed"; + } + } + if(s != nil) + m.send(special(s, scriptinfo)); + } + if(m.trace) + sys->print("script: done\n"); + return nil; +} + +match(m: ref Modem->Device, s: string, msec: int): int +{ + for(;;) { + c := m.getc(msec); + if(c == '\r') + c = '\n'; + if(m.trace) + sys->print("%c",c); + if(c == 0) + return 0; + head: + while(c == s[0]) { + i := 1; + while(i < len s) { + c = m.getc(msec); + if(c == '\r') + c = '\n'; + if(m.trace) + sys->print("%c",c); + if(c == 0) + return 0; + if(c != s[i]) + continue head; + i++; + } + return 1; + } + if(c == '~') + return 1; # assume PPP for now + } +} + +# +# Expand special script sequences +# +special(s: string, scriptinfo: ref ScriptInfo): string +{ + if(s == "$username") # special variable + s = scriptinfo.username; + else if(s == "$password") + s = scriptinfo.password; + return deparse(s); +} + +deparse(s: string): string +{ + r: string = ""; + for(i:=0; i < len s; i++) { + c := s[i]; + if(c == '\\' && i+1 < len s) { + c = s[++i]; + case c { + 't' => c = '\t'; + 'n' => c = '\n'; + 'r' => c = '\r'; + 'b' => c = '\b'; + 'a' => c = '\a'; + 'v' => c = '\v'; + '0' => c = '\0'; + '$' => c = '$'; + 'u' => + if(i+4 < len s) { + i++; + (c, nil) = str->toint(s[i:i+4], 16); + i+=3; + } + } + } + r[len r] = c; + } + return r; +} + +scriptload(path: string): (list of string, string) +{ + dfd := sys->open(path, Sys->OREAD); + if(dfd == nil) + return (nil, sys->sprint("can't open script %s: %r", path)); + + b := array[Scriptlim] of byte; + n := sys->read(dfd, b, len b); + if(n < 0) + return (nil, sys->sprint("can't read script %s: %r", path)); + + (nil, script) := sys->tokenize(string b[0:n], "\n"); + return (script, nil); +} |
