implement PPPClient; include "sys.m"; sys : Sys;include "draw.m"; include "lock.m";include "modem.m";include "script.m"; include "pppclient.m"; include "translate.m"; translate : Translate; Dict : import translate; dict : ref Dict; ## Globals (these will have to be removed if we are going multithreaded)# pid := 0;modeminfo: ref Modem->ModemInfo;pppdir: string; ppplog(log: chan of int, errfile: string, pidc: chan of int) { pidc <-= sys->pctl(0, nil); # set reset pid to our pid src := sys->open(errfile, Sys->OREAD); if (src == nil) raise sys->sprint("fail: Couldn't open %s: %r", errfile); LOGBUFMAX: con 1024; buf := array[LOGBUFMAX] of byte; connected := 0; while ((count := sys->read(src, buf, LOGBUFMAX)) > 0) { (n, toklist) := sys->tokenize(string buf[:count],"\n"); for (;toklist != nil;toklist = tl toklist) { case hd toklist { "no error" => log <-= s_SuccessPPP; lasterror = nil; connected = 1; "permission denied" => lasterror = X("Username or Password Incorrect"); log <-= s_Error; "write to hungup channel" => lasterror = X("Remote Host Hung Up"); log <-= s_Error; * => lasterror = X(hd toklist); log <-= s_Error; } } } if(count == 0 && connected && lasterror == nil){ # should change ip/pppmedium.c instead? lasterror = X("Lost Connection"); log <-= s_Error; }} startppp(logchan: chan of int, pppinfo: ref PPPInfo){ ifd := sys->open("/net/ipifc/clone", Sys->ORDWR); if (ifd == nil) raise "fail: Couldn't open /net/ipifc/clone"; buf := array[32] of byte; n := sys->read(ifd, buf, len buf); if(n <= 0) raise "fail: can't read from /net/ipifc/clone"; pppdir = "/net/ipifc/" + string buf[0:n]; pidc := chan of int; spawn ppplog(logchan, pppdir + "/err", pidc); pid = <-pidc; logchan <-= s_StartPPP; if (pppinfo.ipaddr == nil) pppinfo.ipaddr = "-";# if (pppinfo.ipmask == nil)# pppinfo.ipmask = "255.255.255.255"; if (pppinfo.peeraddr == nil) pppinfo.peeraddr = "-"; if (pppinfo.maxmtu == nil) pppinfo.maxmtu = "512"; if (pppinfo.username == nil) pppinfo.username = "-"; if (pppinfo.password == nil) pppinfo.password = "-"; framing := "1"; ifc := "bind ppp "+modeminfo.path+" "+ pppinfo.ipaddr+" "+pppinfo.peeraddr+" "+pppinfo.maxmtu +" "+framing+" "+pppinfo.username+" "+pppinfo.password; # send the add command if (sys->fprint(ifd, "%s", ifc) < 0) { sys->print("pppclient: couldn't write %s/ctl: %r\n", pppdir); raise "fail: Couldn't write /net/ipifc"; return; }} connect(mi: ref Modem->ModemInfo, number: string, scriptinfo: ref Script->ScriptInfo, pppinfo: ref PPPInfo, logchan: chan of int){ sys = load Sys Sys->PATH; translate = load Translate Translate->PATH; if (translate != nil) { translate->init(); dictname := translate->mkdictname("", "pppclient"); (dict, nil) = translate->opendict(dictname); } if (pid != 0) # yikes we are already running reset(); # create a new process group pid = sys->pctl( Sys->NEWPGRP, nil); { logchan <-= s_Initialized; # open & init the modem modeminfo = mi; modem := load Modem Modem->PATH; if (modem == nil) { raise "fail: Couldn't load modem module"; return; } modemdev := modem->init(modeminfo); logchan <-= s_StartModem; modem->dial(modemdev, number); logchan <-= s_SuccessModem; # if script if (scriptinfo != nil) { script := load Script Script->PATH; if (script == nil) { raise "fail: Couldn't load script module"; return; } logchan <-= s_StartScript; script->execute(modem, modemdev, scriptinfo); logchan <-= s_SuccessScript; } mc := modem->close(modemdev); # keep connection open for ppp mode modemdev = nil; modem = nil; # unload modem module # if ppp if (pppinfo != nil) startppp(logchan, pppinfo); else logchan <-= s_Done; } exception e{ "fail*" => lasterror = e; sys->print("PPPclient: fatal exception: %s\n", e); logchan <-= s_Error; kill(pid, "killgrp"); exit; }} reset(){ sys->print("reset..."); if(pid != 0){ kill(pid, "killgrp"); pid = 0; } if(pppdir != nil){ # shut down the PPP link fd := sys->open(pppdir + "/ctl", Sys->OWRITE); if(fd == nil || sys->fprint(fd, "unbind") < 0) sys->print("pppclient: can't unbind: %r\n"); fd = nil; pppdir = nil; } modem := load Modem Modem->PATH; if (modem == nil) { raise "fail: Couldn't load modem module"; return; } modemdev := modem->init(modeminfo); if(modemdev != nil) modem->onhook(modemdev); modem = nil; # clear error buffer lasterror = nil;} kill(pid: int, msg: string){ a := array of byte msg; fd := sys->open("#p/"+string pid+"/ctl", Sys->OWRITE); if(fd == nil || sys->write(fd, a, len a) < 0) sys->print("pppclient: can't %s %d: %r\n", msg, pid);} # Translate a string X(s : string) : string{ if (dict== nil) return s; return dict.xlate(s);}
implement PPPClient;
include "sys.m";
sys : Sys;
include "draw.m";
include "lock.m";
include "modem.m";
include "script.m";
include "pppclient.m";
include "translate.m";
translate : Translate;
Dict : import translate;
dict : ref Dict;
#
# Globals (these will have to be removed if we are going multithreaded)
#
pid := 0;
modeminfo: ref Modem->ModemInfo;
pppdir: string;
ppplog(log: chan of int, errfile: string, pidc: chan of int)
{
pidc <-= sys->pctl(0, nil); # set reset pid to our pid
src := sys->open(errfile, Sys->OREAD);
if (src == nil)
raise sys->sprint("fail: Couldn't open %s: %r", errfile);
LOGBUFMAX: con 1024;
buf := array[LOGBUFMAX] of byte;
connected := 0;
while ((count := sys->read(src, buf, LOGBUFMAX)) > 0) {
(n, toklist) := sys->tokenize(string buf[:count],"\n");
for (;toklist != nil;toklist = tl toklist) {
case hd toklist {
"no error" =>
log <-= s_SuccessPPP;
lasterror = nil;
connected = 1;
"permission denied" =>
lasterror = X("Username or Password Incorrect");
log <-= s_Error;
"write to hungup channel" =>
lasterror = X("Remote Host Hung Up");
log <-= s_Error;
* =>
lasterror = X(hd toklist);
log <-= s_Error;
}
}
}
if(count == 0 && connected && lasterror == nil){ # should change ip/pppmedium.c instead?
lasterror = X("Lost Connection");
log <-= s_Error;
}
}
startppp(logchan: chan of int, pppinfo: ref PPPInfo)
{
ifd := sys->open("/net/ipifc/clone", Sys->ORDWR);
if (ifd == nil)
raise "fail: Couldn't open /net/ipifc/clone";
buf := array[32] of byte;
n := sys->read(ifd, buf, len buf);
if(n <= 0)
raise "fail: can't read from /net/ipifc/clone";
pppdir = "/net/ipifc/" + string buf[0:n];
pidc := chan of int;
spawn ppplog(logchan, pppdir + "/err", pidc);
pid = <-pidc;
logchan <-= s_StartPPP;
if (pppinfo.ipaddr == nil)
pppinfo.ipaddr = "-";
# if (pppinfo.ipmask == nil)
# pppinfo.ipmask = "255.255.255.255";
if (pppinfo.peeraddr == nil)
pppinfo.peeraddr = "-";
if (pppinfo.maxmtu == nil)
pppinfo.maxmtu = "512";
if (pppinfo.username == nil)
pppinfo.username = "-";
if (pppinfo.password == nil)
pppinfo.password = "-";
framing := "1";
ifc := "bind ppp "+modeminfo.path+" "+ pppinfo.ipaddr+" "+pppinfo.peeraddr+" "+pppinfo.maxmtu
+" "+framing+" "+pppinfo.username+" "+pppinfo.password;
# send the add command
if (sys->fprint(ifd, "%s", ifc) < 0) {
sys->print("pppclient: couldn't write %s/ctl: %r\n", pppdir);
raise "fail: Couldn't write /net/ipifc";
return;
}
}
connect(mi: ref Modem->ModemInfo, number: string,
scriptinfo: ref Script->ScriptInfo, pppinfo: ref PPPInfo, logchan: chan of int)
{
sys = load Sys Sys->PATH;
translate = load Translate Translate->PATH;
if (translate != nil) {
translate->init();
dictname := translate->mkdictname("", "pppclient");
(dict, nil) = translate->opendict(dictname);
}
if (pid != 0) # yikes we are already running
reset();
# create a new process group
pid = sys->pctl( Sys->NEWPGRP, nil);
{
logchan <-= s_Initialized;
# open & init the modem
modeminfo = mi;
modem := load Modem Modem->PATH;
if (modem == nil) {
raise "fail: Couldn't load modem module";
return;
}
modemdev := modem->init(modeminfo);
logchan <-= s_StartModem;
modem->dial(modemdev, number);
logchan <-= s_SuccessModem;
# if script
if (scriptinfo != nil) {
script := load Script Script->PATH;
if (script == nil) {
raise "fail: Couldn't load script module";
return;
}
logchan <-= s_StartScript;
script->execute(modem, modemdev, scriptinfo);
logchan <-= s_SuccessScript;
}
mc := modem->close(modemdev); # keep connection open for ppp mode
modemdev = nil;
modem = nil; # unload modem module
# if ppp
if (pppinfo != nil)
startppp(logchan, pppinfo);
else
logchan <-= s_Done;
}
exception e{
"fail*" =>
lasterror = e;
sys->print("PPPclient: fatal exception: %s\n", e);
logchan <-= s_Error;
kill(pid, "killgrp");
exit;
}
}
reset()
{
sys->print("reset...");
if(pid != 0){
kill(pid, "killgrp");
pid = 0;
}
if(pppdir != nil){ # shut down the PPP link
fd := sys->open(pppdir + "/ctl", Sys->OWRITE);
if(fd == nil || sys->fprint(fd, "unbind") < 0)
sys->print("pppclient: can't unbind: %r\n");
fd = nil;
pppdir = nil;
}
modem := load Modem Modem->PATH;
if (modem == nil) {
raise "fail: Couldn't load modem module";
return;
}
modemdev := modem->init(modeminfo);
if(modemdev != nil)
modem->onhook(modemdev);
modem = nil;
# clear error buffer
lasterror = nil;
}
kill(pid: int, msg: string)
{
a := array of byte msg;
fd := sys->open("#p/"+string pid+"/ctl", Sys->OWRITE);
if(fd == nil || sys->write(fd, a, len a) < 0)
sys->print("pppclient: can't %s %d: %r\n", msg, pid);
}
# Translate a string
X(s : string) : string
{
if (dict== nil) return s;
return dict.xlate(s);
}