DIRECTORY
BasicTime USING [Now],
Commander USING [CommandProc, Register],
CommandTool USING [ArgumentVector, Failed, Parse],
Convert USING [RopeFromTime],
FS USING [Error, StreamOpen],
IO USING [Close, EndOf, EndOfStream, Error, Flush, GetChar, PutF, PutChar, PutRope, rope, STREAM],
Rope USING [ROPE],
IP USING [Address],
IPName USING [NameToAddress],
TCP USING [AbortTCPStream, CreateTCPStream, Error, neverTimeout, Timeout, WaitForListenerOpen];
BuildNameTable:
CEDAR
PROGRAM
IMPORTS BasicTime, Commander, CommandTool, Convert, FS, IO, IPName, TCP =
BEGIN
nameServerSocket: INT = 145B;
defaultNameServer: Rope.ROPE = "SRI-NIC.ARPA";
defaultFileName: Rope.ROPE = "Hosts.txt";
Version: Commander.CommandProc = {
out: IO.STREAM ← cmd.out;
server: IO.STREAM;
nameServer: Rope.ROPE ← defaultNameServer;
where: LIST OF IP.Address;
out.PutF["Poking ARPA Name Server for current version.\n"];
where ← IPName.NameToAddress[nameServer ! FS.Error => CONTINUE];
IF where =
NIL
THEN {
out.PutF["Can't lookup IP Address for %G.\n", IO.rope[nameServer]];
RETURN; };
BEGIN
ENABLE {
TCP.Timeout => {
out.PutRope["[TCP.Timeout.]\n"];
GO TO GiveUp; };
TCP.Error => {
out.PutRope["[TCP.Error.]\n"];
GO TO GiveUp; };
IO.Error => {
out.PutRope["[IO.Error.]\n"];
GOTO GiveUp; };
};
server ←
TCP.CreateTCPStream[[
matchLocalPort: FALSE,
localPort: 0,
matchForeignAddr: TRUE,
foreignAddress: where.first,
matchForeignPort: TRUE,
foreignPort: nameServerSocket,
active: TRUE,
timeout: 120000]];
TCP.WaitForListenerOpen[server, TCP.neverTimeout];
server.PutRope["VERSION\n\l"];
server.Flush[];
WHILE
NOT server.EndOf[]
DO
c: CHAR ← server.GetChar[ ! IO.EndOfStream => EXIT];
IF c # '\l THEN out.PutChar[c];
ENDLOOP;
server.Close[];
EXITS
GiveUp => IF server # NIL THEN TCP.AbortTCPStream[server];
END;
};
HostName: Commander.CommandProc = {
out: IO.STREAM ← cmd.out;
argv: CommandTool.ArgumentVector = CommandTool.Parse[cmd !
CommandTool.Failed => {out.PutRope[errorMsg]; GOTO CantParse}];
name: Rope.ROPE;
server: IO.STREAM;
nameServer: Rope.ROPE ← defaultNameServer;
where: LIST OF IP.Address;
IF argv.argc > 1 THEN name ← argv[1] ELSE name ← "Xerox";
out.PutF["Poking ARPA Name Server for info on %G.\n", [rope[name]] ];
where ← IPName.NameToAddress[nameServer ! FS.Error => CONTINUE];
IF where =
NIL
THEN {
out.PutF["Can't lookup IP Address for %G.\n", IO.rope[nameServer]];
RETURN; };
BEGIN
ENABLE {
TCP.Timeout => {
out.PutRope["[TCP.Timeout.]\n"];
GO TO GiveUp; };
TCP.Error => {
out.PutRope["[TCP.Error.]\n"];
GO TO GiveUp; };
IO.Error => {
out.PutRope["[IO.Error.]\n"];
GOTO GiveUp; };
};
server ←
TCP.CreateTCPStream[[
matchLocalPort: FALSE,
localPort: 0,
matchForeignAddr: TRUE,
foreignAddress: where.first,
matchForeignPort: TRUE,
foreignPort: nameServerSocket,
active: TRUE,
timeout: 120000]];
TCP.WaitForListenerOpen[server, TCP.neverTimeout];
server.PutRope["HNAME "];
server.PutRope[name];
server.PutChar['\n]; server.PutChar['\l]; -- send the LF as well
server.Flush[];
WHILE
NOT server.EndOf[]
DO
c: CHAR ← server.GetChar[ ! IO.EndOfStream => EXIT];
IF c # '\l THEN out.PutChar[c];
ENDLOOP;
server.Close[];
EXITS
GiveUp => IF server # NIL THEN TCP.AbortTCPStream[server];
END;
};
FetchTable: Commander.CommandProc = {
out: IO.STREAM ← cmd.out;
argv: CommandTool.ArgumentVector = CommandTool.Parse[cmd !
CommandTool.Failed => {out.PutRope[errorMsg]; GOTO CantParse}];
fileName, nameServer: Rope.ROPE;
file, server: IO.STREAM;
where: LIST OF IP.Address;
IF argv.argc > 1 THEN fileName ← argv[1] ELSE fileName ← defaultFileName;
IF argv.argc > 2 THEN nameServer ← argv[2] ELSE nameServer ← defaultNameServer;
out.PutF["Fetching new %G from %G.\n", [rope[fileName]], [rope[nameServer]] ];
where ← IPName.NameToAddress[nameServer ! FS.Error => CONTINUE];
IF where =
NIL
THEN {
out.PutF["Can't lookup IP Address for %G.\n", IO.rope[nameServer]];
RETURN; };
file ← FS.StreamOpen[fileName, create];
BEGIN
ENABLE {
TCP.Timeout => {
out.PutRope["[TCP.Timeout.]\n"];
GO TO GiveUp; };
TCP.Error => {
out.PutRope["[TCP.Error.]\n"];
GO TO GiveUp; };
IO.Error => {
out.PutRope["[IO.Error.]\n"];
GOTO GiveUp; };
};
file.PutRope["FETCHED: "];
file.PutRope[Convert.RopeFromTime[BasicTime.Now[]]];
file.PutRope["\n"];
Include version info in our copy of the file.
server ←
TCP.CreateTCPStream[[
matchLocalPort: FALSE,
localPort: 0,
matchForeignAddr: TRUE,
foreignAddress: where.first,
matchForeignPort: TRUE,
foreignPort: nameServerSocket,
active: TRUE,
timeout: 120000]];
TCP.WaitForListenerOpen[server, TCP.neverTimeout];
server.PutRope["VERSION\n\l"];
server.Flush[];
WHILE
NOT server.EndOf[]
DO
c: CHAR ← server.GetChar[ ! IO.EndOfStream => EXIT];
IF c # '\l THEN file.PutChar[c];
ENDLOOP;
server.Close[];
Now, grab the data.
server ←
TCP.CreateTCPStream[[
matchLocalPort: FALSE,
localPort: 0,
matchForeignAddr: TRUE,
foreignAddress: where.first,
matchForeignPort: TRUE,
foreignPort: nameServerSocket,
active: TRUE,
timeout: 120000]];
TCP.WaitForListenerOpen[server, TCP.neverTimeout];
server.PutRope["ALL\n\l"];
server.Flush[];
WHILE
NOT server.EndOf[]
DO
c: CHAR ← server.GetChar[ ! IO.EndOfStream => EXIT];
IF c # '\l THEN file.PutChar[c];
ENDLOOP;
server.Close[];
EXITS
GiveUp =>
BEGIN
IF server # NIL THEN TCP.AbortTCPStream[server];
END;
END;
out.PutChar['\n];
file.Close[];
EXITS CantParse => NULL;
};
Commander.Register[key: "HostName", proc: HostName, doc: "Look up Host Name at NIC's NameServer"];
Commander.Register[key: "NameTableVersion", proc: Version, doc: "Print out VERSION info from NIC's NameServer"];
Commander.Register[key: "FetchNameTable", proc: FetchTable, doc: "Fetch Source for IP name table from NIC"];
END.