BEGIN
fingerErrorCode: FingerOps.Reason;
SetifyList: PROC [list: LIST OF Rope.ROPE] RETURNS [LIST OF Rope.ROPE]
Removes duplicate entries of list ( ie makes it a "set" ). Does so by entering everything into a symbol table. If it isn't already in the symbol table then add it to the list, otherwise forget it.
~ {
table: SymTab.Ref ← SymTab.Create[];
newList: LIST OF Rope.ROPE ← NIL;
FOR ropeList:
LIST
OF Rope.
ROPE ← list, ropeList.rest
UNTIL ropeList =
NIL
DO
IF SymTab.Store[table, ropeList.first, NIL] THEN newList ← CONS[ropeList.first, newList]
ENDLOOP;
RETURN[newList]
}; -- SetifyList
PerformFingerAtExec:
ENTRY Commander.CommandProc =
BEGIN
The nothingToDo flag is used to determine if someone tried to do a finger on nothing. However the way this thing works is it blasts along the command line and exits when IO.EndOfStream is raised and you can't tell if there was anything there or not! Hence the extra scoping level and nothingToDo. (hack hack hack... )
nothingToDo:BOOLEAN ← TRUE;
BEGIN
ENABLE
BEGIN
IO.EndOfStream => { IF nothingToDo THEN IO.Put[cmd.out, IO.rope["Usage: Finger usernamePattern-list\n"]]; CONTINUE };
FingerOps.FingerError => {
fingerErrorCode ← reason; GOTO FingerProblem };
END;
Break:
IO.BreakProc =
BEGIN
RETURN[IF char IN [IO.NUL..IO.SP] THEN sepr ELSE other]
END;
stream: IO.STREAM ← IO.RIS[cmd.commandLine];
WHILE
TRUE
DO
-- stop when command line is exhausted and IO.EndOfStream is raised
userNamePattern: Rope.ROPE ← IO.GetTokenRope[stream, Break].token;
fingerResult: LIST OF Rope.ROPE ← FingerOps.GetMatchingPersons[pattern: userNamePattern];
matches: CARDINAL ← 0;
nothingToDo ← FALSE;
FOR list:
LIST
OF Rope.
ROPE ← fingerResult, list.rest
WHILE list #
NIL
DO
matches ← matches + 1
ENDLOOP;
SELECT matches
FROM
0 => IO.PutRope[cmd.out, Rope.Cat["\nThere were no matches on the pattern \"", userNamePattern, "\".\n"]];
1 => IO.PutRope[cmd.out, Rope.Cat["\nThere was 1 match on the pattern \"", userNamePattern, "\":\n"]];
ENDCASE => IO.PutRope[cmd.out, Rope.Cat["\nThere were ", Convert.RopeFromCard[matches], " matches on the pattern \"", userNamePattern, "\":\n"]];
UNTIL fingerResult =
NIL
DO
propList: LIST OF FingerOps.PropPair = FingerOps.GetUserProps[fingerResult.first];
output results
IO.PutRope[cmd.out, Rope.Cat["\n\"", fingerResult.first, "\""]];
FOR p:
LIST
OF FingerOps.PropPair ← propList, p.rest
UNTIL p =
NIL
DO
IO.Put[cmd.out, IO.rope["\n "], IO.atom[p.first.prop]];
IO.Put[cmd.out, IO.rope[": "], IO.rope[p.first.val]]
ENDLOOP;
fingerResult ← fingerResult.rest;
IO.PutRope[cmd.out, "\n"]
ENDLOOP;
ENDLOOP;
EXITS FingerProblem => {
IO.PutRope[cmd.out,
SELECT fingerErrorCode FROM
Aborted => "\n... Transaction Aborted; Retry Finger Operation",
Error => "\n... Internal Finger Error; Contact Implementor",
Failure => "\n... Connection with server broken; try again later",
ENDCASE => NIL ] };
END
END;
GetActiveUsers:
ENTRY Commander.CommandProc = {
ENABLE FingerOps.FingerError => { fingerErrorCode ← reason; GOTO FingerProblem };
users: LIST OF Rope.ROPE = SetifyList[FingerOps.CurrentUsers[]];
now: BasicTime.GMT = BasicTime.Now[];
IO.PutF[cmd.out, "Login TTY When\n"];
IF users = NIL THEN RETURN;
FOR u:
LIST
OF Rope.
ROPE ← users, u.rest
UNTIL u =
NIL
DO
machines: LIST OF Rope.ROPE = FingerOps.GetUserData[u.first];
FOR m:
LIST
OF Rope.
ROPE ← machines, m.rest
UNTIL m =
NIL
DO
lastChange: FingerOps.StateChange;
time: BasicTime.GMT;
[lastChange ~ lastChange, time ~ time ] ← FingerOps.GetMachineData[m.first];
IO.PutF[cmd.out, "%-20g %-20g %g\n", IO.rope[u.first], IO.rope[m.first], IO.time[time]];
ENDLOOP;
ENDLOOP;
EXITS FingerProblem => {
IO.PutRope[cmd.out,
SELECT fingerErrorCode FROM
Aborted => "\n... Transaction Aborted; Retry Finger Operation",
Error => "\n... Internal Finger Error; Contact Implementor",
Failure => "\n... Connection with server broken; try again later",
ENDCASE => NIL ] };
};
FindUser:
ENTRY Commander.CommandProc = {
ENABLE {
FingerOps.FingerError => { fingerErrorCode ← reason; GOTO FingerProblem };
IO.EndOfStream => { IO.Put[cmd.out, IO.rope["Usage: WhereIs username\n"]]; CONTINUE }
};
who: Rope.ROPE = IO.GetTokenRope[IO.RIS[cmd.commandLine], IO.IDProc].token;
users: LIST OF Rope.ROPE = FingerOps.CurrentUsers[];
FOR u:
LIST
OF Rope.
ROPE ← users, u.rest
UNTIL u =
NIL
DO
IF Rope.Equal[u.first, who,
FALSE]
THEN {
machines: LIST OF Rope.ROPE = FingerOps.GetUserData[u.first];
FOR m:
LIST
OF Rope.
ROPE ← machines, m.rest
UNTIL m =
NIL
DO
lastChange: FingerOps.StateChange;
time: BasicTime.GMT;
[lastChange ~ lastChange, time ~ time ] ← FingerOps.GetMachineData[m.first];
IF lastChange = logout THEN LOOP;
IO.Put[cmd.out, IO.rope[u.first]];
IO.Put[cmd.out, IO.rope[" on machine: "], IO.rope[m.first]];
IO.Put[cmd.out, IO.rope[" \n logged in at: "], IO.time[time], IO.rope["\n"]]
ENDLOOP;
RETURN }
ENDLOOP;
IO.Put[cmd.out, IO.rope["\n"], IO.rope[who], IO.rope[" is not logged in on any machine\n"]];
EXITS FingerProblem => {
IO.PutRope[cmd.out,
SELECT fingerErrorCode FROM
Aborted => "\n... Transaction Aborted; Retry Finger Operation",
Error => "\n... Internal Finger Error; Contact Implementor",
Failure => "\n... Connection with server broken; try again later",
ENDCASE => NIL ] };
};
FindMachine:
ENTRY Commander.CommandProc = {
ENABLE {
FingerOps.FingerError => { fingerErrorCode ← reason; GOTO FingerProblem };
IO.EndOfStream => { IO.Put[cmd.out, IO.rope["Usage: Host machinename\n"]]; CONTINUE }
};
machine: Rope.ROPE = IO.GetTokenRope[IO.RIS[cmd.commandLine], IO.IDProc].token;
data: LIST OF FingerOps.PropPair ← FingerOps.GetMachineProps[machine];
IO.Put[cmd.out, IO.rope[machine]];
FOR lp:
LIST
OF FingerOps.PropPair ← data, lp.rest
UNTIL lp =
NIL
DO
p: FingerOps.PropPair ← lp.first;
IF p.prop = $Owner THEN IO.Put[cmd.out, IO.rope[" Owner: "], IO.rope[p.val]];
IF p.prop = $Location THEN IO.Put[cmd.out, IO.rope[" Location: "], IO.rope[p.val]];
IF p.prop = $Gateway
AND Rope.Equal[p.val, "TRUE"]
THEN
IO.PutF[cmd.out, " GATEWAY"];
IF p.prop = $Network
AND Rope.Equal[p.val, "TRUE"]
THEN
IO.PutF[cmd.out, " NETWORK"];
ENDLOOP;
IO.Put[cmd.out, IO.rope["\n"]];
EXITS FingerProblem => {
IO.PutRope[cmd.out,
SELECT fingerErrorCode FROM
Aborted => "\n... Transaction Aborted; Retry Finger Operation\n",
Error => "\n... Internal Finger Error; Contact Implementor\n",
Failure => "\n... Connection with server broken; try again later\n",
ENDCASE => NIL ] };
};
FreeMachines:
ENTRY Commander.CommandProc = {
ENABLE FingerOps.FingerError => { fingerErrorCode ← reason; GOTO FingerProblem };
machines: LIST OF Rope.ROPE = FingerOps.FreeMachines[];
FOR u:
LIST
OF Rope.
ROPE ← machines, u.rest
UNTIL u =
NIL
DO
time: BasicTime.GMT = FingerOps.GetMachineData[u.first].time;
IO.PutF[cmd.out, "%-20g last used at: %g\n", IO.rope[u.first], IO.time[time]];
ENDLOOP;
IO.Put[cmd.out, IO.rope["\n"]];
EXITS FingerProblem => {
IO.PutRope[cmd.out,
SELECT fingerErrorCode FROM
Aborted => "\n... Transaction Aborted; Retry Finger Operation\n",
Error => "\n... Internal Finger Error; Contact Implementor\n",
Failure => "\n... Connection with server broken; try again later\n",
ENDCASE => NIL ] };
};
FingerServer:
ENTRY Commander.CommandProc = {
ENABLE UNWIND => NULL;
action: Rope.ROPE = IO.GetTokenRope[IO.RIS[cmd.commandLine], IO.IDProc].token;
SELECT
TRUE
FROM
Rope.Equal[action, "on", FALSE] => RemoteFingerOpsRpcControl.ExportInterface[user: NIL, password: [0,0,0,0]];
Rope.Equal[action, "off", FALSE] => RemoteFingerOpsRpcControl.UnexportInterface[];
ENDCASE => IO.PutRope[cmd.out, "FingerServer on to export the RemoteFingerOps interface, FingerServer off to unexport"];
};
Register commands with the Exec to perform finger and create an instance of the Finger Tool.
Commander.Register[key: "Finger", proc: PerformFingerAtExec, doc: "Perform a finger." ];
Commander.Register[key: "Who", proc: GetActiveUsers, doc: "lists all of the active machines and who's using each one"];
Commander.Register[key: "WhereIs", proc: FindUser, doc: "gives all of the machines currently used by the given user"];
Commander.Register[key: "Host", proc: FindMachine, doc: "provides information on a host"];
Commander.Register[key: "FreeMachines", proc: FreeMachines, doc: "list all of the currently unused Cedar machines"];
Commander.Register[key: "FingerServer", proc: FingerServer, doc: "FingerServer on to export the RemoteFingerOps interface, FingerServer off to unexport"];