code: 9ferno

ref: b548687a8ed1d0a159c9d3f3f921d93bbb56908e
dir: /appl/cmd/ip/ppp/pppclient.b/

View raw version
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);
}