DIRECTORY BasicTime, BridgeComm, BridgeFTPOps, Convert, IO, NetworkStream, Process, Rope ; BridgeFTPOpsImpl: CEDAR PROGRAM IMPORTS BasicTime, BridgeComm, Convert, IO, NetworkStream, Process, Rope EXPORTS BridgeFTPOps ~ { ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; NetworkStreamPair: TYPE ~ BridgeComm.NetworkStreamPair; ActionProc: TYPE ~ BridgeFTPOps.ActionProc; RetrieveStream: PUBLIC PROC [nsp: NetworkStreamPair, remoteName: ROPE, action: ActionProc, clientData: REF ¬ NIL, msgStream: STREAM ¬ NIL] RETURNS [excuse: ROPE ¬ NIL] ~ { ENABLE { ABORTED => { excuse ¬ "aborted"; CONTINUE }; BridgeComm.Error => { PutMsg[msgStream, "Communication error: %g\n", msg]; excuse ¬ "Bridge communication error"; CONTINUE }; IO.Error, NetworkStream.Error => { PutMsg[msgStream, "I/O error\n"]; excuse ¬ "I/O error"; CONTINUE }; }; ansMsg: CHAR; ansArg: ROPE; ansArgNumeric: CARD; actionProcQuit: BOOL; PutMsg[msgStream, "Retrieving from %g ... ", remoteName]; [ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'I, remoteName]; -- Open for input. SELECT ansMsg FROM 'Y => NULL; -- ansArg is really aaa.bbb where aaa is the iNode and bbb is the mtime 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; -- ansArg = error like not found ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; [ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'R]; -- Read current file SELECT ansMsg FROM 'D => NULL; -- ansArg is the number of bytes in the file as reported by stat 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; -- stat error ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; ansArgNumeric ¬ Convert.CardFromRope[ansArg -- really bytes in the file ! Convert.Error => ansArgNumeric ¬ CARD.LAST]; IF ansArgNumeric = 0 THEN { Process.PauseMsec[500] -- Kludge -- ; actionProcQuit ¬ FALSE; } ELSE { actionProcQuit ¬ action[nsp, ansArgNumeric, NIL]; -- send the bits. Should only get ansArgNumeric (byte count) IF actionProcQuit THEN IO.Reset[nsp.in]; }; WHILE NetworkStream.GetStreamState[nsp.in, TRUE].streamState # open DO NULL ENDLOOP; [] ¬ BridgeComm.PutMsgWithReply[nsp, 'i]; -- close the file PutMsg[msgStream, IF actionProcQuit THEN "aborted\n" ELSE "ok\n"]; }; MkTempName: PROC [name: ROPE] RETURNS [tempName: ROPE] ~ { tempName ¬ IO.PutFR["%g.%g", [rope[name]], [cardinal[BasicTime.ToNSTime[BasicTime.Now[]]]] ]; }; StoreStream: PUBLIC PROC [nsp: NetworkStreamPair, remoteName: ROPE, overwrite: BOOL, action: ActionProc, clientData: REF ¬ NIL, msgStream: STREAM ¬ NIL] RETURNS [excuse: ROPE ¬ NIL] ~ { ENABLE { ABORTED => { excuse ¬ "aborted"; CONTINUE }; BridgeComm.Error => { PutMsg[msgStream, "Communication error: %g\n", msg]; excuse ¬ "Bridge communication error"; CONTINUE }; IO.Error, NetworkStream.Error => { PutMsg[msgStream, "I/O error\n"]; excuse ¬ "I/O error"; CONTINUE }; }; ansMsg: CHAR; ansArg: ROPE; tempName: ROPE; actionProcQuit: BOOL; IF overwrite THEN { PutMsg[msgStream, "Writing %g ... ", remoteName]; [ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'O, remoteName]; SELECT ansMsg FROM 'Y => NULL; 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; BridgeComm.PutMsg[nsp, 'W]; actionProcQuit ¬ action[nsp, -1, NIL]; NetworkStream.SendEndOfMessage[nsp.out]; [ansMsg, ansArg] ¬ BridgeComm.GetMsg[nsp]; SELECT ansMsg FROM 'Y => NULL; 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; [] ¬ BridgeComm.PutMsgWithReply[nsp, 'o]; PutMsg[msgStream, IF actionProcQuit THEN "aborted\n" ELSE "ok\n"]; } ELSE { PutMsg[msgStream, "Storing to temporary ... "]; tempName ¬ MkTempName[remoteName]; [ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'N, tempName]; SELECT ansMsg FROM 'Y => NULL; 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; BridgeComm.PutMsg[nsp, 'W]; actionProcQuit ¬ action[nsp, -1, NIL]; NetworkStream.SendEndOfMessage[nsp.out]; [ansMsg, ansArg] ¬ BridgeComm.GetMsg[nsp]; SELECT ansMsg FROM 'Y => NULL; 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; [ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'o]; SELECT ansMsg FROM 'Y => NULL; 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; IF actionProcQuit THEN { PutMsg[msgStream, "aborted\n"]; } ELSE { PutMsg[msgStream, "renaming temporary to %g ... ", remoteName]; [ansMsg, ansArg] ¬ BridgeComm.PutMsgWithReply[nsp, 'M, Rope.Cat[tempName, " ", remoteName]]; SELECT ansMsg FROM 'Y => NULL; 'N => { PutMsg[msgStream, "%g\n", ansArg]; RETURN [ansArg] }; ENDCASE => { PutMsg[msgStream, "Protocol error\n"]; RETURN ["Protocol error"] }; PutMsg[msgStream, "ok\n"]; }; }; }; PutMsg: PROC [s: STREAM, fmt: ROPE, msg: ROPE ¬ NIL] ~ { ENABLE IO.Error => CONTINUE; IF (s # NIL) THEN IO.PutF1[s, fmt, IF msg # NIL THEN [rope[msg]] ELSE [null[]]]; }; }... ’ BridgeFTPOpsImpl.mesa Copyright Σ 1987, 1988, 1989, 1992 by Xerox Corporation. All rights reserved. Demers, October 12, 1990 12:22 pm PDT Tim Diebert: September 11, 1989 9:49:57 am PDT Willie-s, January 29, 1992 6:21 pm PST The following tries to work around host failure to send back-to-back EOM's reliably ... TODO: IF actionProcQuit then delete the file! (someday we'll have file delete?) ΚK–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœC™NK™%K™.K™&K™—šΟk ˜ K˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšžœ˜K˜Kšœ˜Kšœ˜K˜K˜—šΟnœžœž˜Kšžœ!žœ˜HKšžœ ˜K˜K˜Kšžœžœžœ˜Kšžœžœžœžœ˜Kšœžœ ˜7K˜Kšœ žœ˜+K˜šΠbnœžœžœ&žœ"žœžœ žœžœžœ žœžœ˜§K˜šžœ˜šžœ˜ K˜Kšžœ˜ —šœ˜Kšœ4˜4K˜&Kšžœ˜ —šžœ ˜"Kšœ!˜!K˜Kšžœ˜ —K˜—Kšœžœ˜ Kšœžœ˜ Kšœžœ˜Kšœžœ˜Kšœ9˜9KšœDΟc˜Všžœž˜Kšœžœ‘G˜SKšœ+žœ ‘ ˜^Kšžœ-žœ˜P—Kšœ8‘˜Lšžœž˜Kšœžœ‘@˜LKšœ+žœ ‘ ˜KKšžœ-žœ˜P—K™Wšœ,‘˜GKšœ#žœžœ˜.—šžœ˜šžœ˜Kšœ‘ œžœ˜=Kšœ˜—šžœ˜Kšœ,žœ‘=˜oKšžœžœžœ˜(K˜——Kš žœ&žœžœžœžœ˜TKšœ*‘˜;Kšœžœžœ žœ ˜BK˜K˜K˜—š Ÿ œžœžœžœ žœ˜:Kšœ žœP˜]K˜K˜—š  œžœžœ&žœ žœ"žœžœ žœžœžœ žœžœ˜΅K˜šžœ˜šžœ˜ K˜Kšžœ˜ —šœ˜Kšœ4˜4K˜&Kšžœ˜ —šžœ ˜"Kšœ!˜!K˜Kšžœ˜ —K˜—Kšœžœ˜ Kšœžœ˜ Kšœ žœ˜Kšœžœ˜K˜šžœ ˜ šžœ˜Kšœ1˜1K˜Cšžœž˜Kšœžœ˜ Kšœ+žœ ˜=Kšžœ-žœ˜P—Kšœ˜Kšœ!žœ˜&Kšœ(˜(K˜*šžœž˜Kšœžœ˜ Kšœ+žœ ˜=Kšžœ-žœ˜P—K˜)KšžœžœH™PKšœžœžœ žœ ˜BK˜—šžœ˜Kšœ/˜/K˜"K˜Ašžœž˜Kšœžœ˜ Kšœ+žœ ˜=Kšžœ-žœ˜P—Kšœ˜Kšœ!žœ˜&Kšœ(˜(K˜*šžœž˜Kšœžœ˜ Kšœ+žœ ˜=Kšžœ-žœ˜P—K˜7šžœž˜Kšœžœ˜ Kšœ+žœ ˜=Kšžœ-žœ˜P—šžœ˜šžœ˜Kšœ˜K˜—šžœ˜Kšœ?˜?K˜\šžœž˜Kšœžœ˜ Kšœ+žœ ˜=Kšžœ-žœ˜P—Kšœ˜K˜——K˜——K˜K˜K˜—š Ÿœžœžœžœžœžœ˜8Kšžœžœ žœ˜Kšžœžœžœžœžœžœžœ žœ ˜PK˜K˜—K˜—K˜—…—F#