DIRECTORY Commander USING [CommandProc, Register], CommandTool USING [Failed, ParseToList], FileNames USING [ResolveRelativePath], FS USING [Error, ErrorDesc, StreamOpen], IO USING [Close, EndOf, EndOfStream, Error, GetBlock, PutBlock, STREAM], Process USING [CheckForAbort], Rope USING [Cat, Concat, Equal, ROPE], Cat, Tee; PipeFittingImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, FileNames, FS, IO, Process, Rope EXPORTS Cat, Tee = { FromNames: PUBLIC PROCEDURE [in: IO.STREAM, nameList: LIST OF Rope.ROPE, out: IO.STREAM] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] = { FSErrorMsg: PROC [error: FS.ErrorDesc] RETURNS [Rope.ROPE] = { SELECT error.group FROM lock => RETURN[" -- locked!\n"]; ENDCASE => IF error.code = $unknownFile THEN RETURN [" -- not found!\n"] ELSE RETURN[Rope.Cat[" -- FS.Error: ", error.explanation, "\n"]]; }; streamList: LIST OF IO.STREAM _ NIL; IF nameList # NIL THEN { FOR left: LIST OF Rope.ROPE _ nameList, left.rest WHILE left # NIL DO IF Rope.Equal[left.first, "-"] THEN { streamList _ CONS[in, streamList]; } ELSE { fileStream: IO.STREAM _ FS.StreamOpen[FileNames.ResolveRelativePath[left.first] ! FS.Error => IF error.group # $bug THEN { msg _ Rope.Concat[left.first, FSErrorMsg[error]]; GO TO Die }]; streamList _ CONS[fileStream, streamList]; } ENDLOOP; [result, msg] _ FromStreams[streamList: streamList, out: out]; FOR left: LIST OF IO.STREAM _ streamList, left.rest WHILE left # NIL DO IF left.first # NIL AND left.first # in THEN IO.Close[left.first]; ENDLOOP; } EXITS Die => result _ $Failure; }; FromStreams: PUBLIC PROCEDURE [streamList: LIST OF IO.STREAM, out: IO.STREAM] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] = { nBytesRead: NAT _ 0; block: REF TEXT _ NEW[TEXT[256]]; FOR left: LIST OF IO.STREAM _ streamList, left.rest WHILE left # NIL DO WHILE NOT IO.EndOf[left.first] DO block.length _ block.maxLength; nBytesRead _ IO.GetBlock[left.first, block, 0, block.maxLength ! IO.EndOfStream => EXIT; IO.Error => EXIT; ]; IO.PutBlock[out, block, 0, nBytesRead ! IO.EndOfStream => EXIT; IO.Error => EXIT;]; Process.CheckForAbort[]; ENDLOOP; ENDLOOP; }; CatCommand: Commander.CommandProc = { arglist: LIST OF Rope.ROPE; argc: NAT; [arglist, argc] _ CommandTool.ParseToList[cmd, TRUE ! CommandTool.Failed => {msg _ errorMsg; GO TO Die}]; IF arglist = NIL THEN { msg _ "Usage: Cat [filename | -] ..."; } ELSE { [result, msg] _ FromNames[cmd^.in, arglist, cmd^.out]; }; EXITS Die => result _ $Failure; }; ToNames: PUBLIC PROCEDURE [in: IO.STREAM, out: IO.STREAM, nameList: LIST OF Rope.ROPE] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] = { FSErrorMsg: PROC [error: FS.ErrorDesc] RETURNS [Rope.ROPE] = { SELECT error.group FROM lock => RETURN[" -- locked!\n"]; ENDCASE => IF error.code = $unknownFile THEN RETURN [" -- not found!\n"] ELSE RETURN[Rope.Cat[" -- FS.Error: ", error.explanation, "\n"]]; }; nBytesRead: NAT _ 0; block: REF TEXT _ NEW[TEXT[256]]; streamList: LIST OF IO.STREAM _ NIL; fileStream: IO.STREAM; FOR left: LIST OF Rope.ROPE _ nameList, left.rest WHILE left # NIL DO fileStream _ FS.StreamOpen[fileName: FileNames.ResolveRelativePath[left.first], accessOptions: $create ! FS.Error => IF error.group # $bug THEN { msg _ Rope.Cat[left.first, FSErrorMsg[error]]; GO TO Die }]; streamList _ CONS[fileStream, streamList]; ENDLOOP; [result, msg] _ ToStreams[in: in, out: out, streamList: streamList]; FOR left: LIST OF IO.STREAM _ streamList, left.rest WHILE left # NIL DO IF left.first # NIL THEN IO.Close[left.first]; ENDLOOP; EXITS Die => result _ $Failure; }; ToStreams: PUBLIC PROCEDURE [in: IO.STREAM, out: IO.STREAM, streamList: LIST OF IO.STREAM] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] = { nBytesRead: NAT _ 0; block: REF TEXT _ NEW[TEXT[256]]; WHILE NOT IO.EndOf[in] DO block.length _ block.maxLength; nBytesRead _ IO.GetBlock[in, block, 0, block.maxLength ! IO.EndOfStream => EXIT; IO.Error => EXIT; ]; IO.PutBlock[out, block, 0, nBytesRead ! IO.EndOfStream => EXIT; IO.Error => EXIT; ]; FOR left: LIST OF IO.STREAM _ streamList, left.rest WHILE left # NIL DO IO.PutBlock[left.first, block, 0, nBytesRead ! IO.EndOfStream => EXIT; IO.Error => EXIT; ]; ENDLOOP; Process.CheckForAbort[]; ENDLOOP; }; TeeCommand: Commander.CommandProc = { arglist: LIST OF Rope.ROPE; argc: NAT; [arglist, argc] _ CommandTool.ParseToList[cmd, TRUE ! CommandTool.Failed => {msg _ errorMsg; GO TO Die}]; IF arglist = NIL THEN { msg _ "Usage: Tee filename ..."; } ELSE { [result, msg] _ ToNames[cmd^.in, cmd^.out, arglist]; }; EXITS Die => result _ $Failure; }; Commander.Register["Cat", CatCommand, "Cat [fileName | -] ... (to cmd^.out)"]; Commander.Register["Tee", TeeCommand, "Tee fileName ... (from cmd^.in)"]; }.  PipeFittingImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by Peter Kessler, December 19, 1985 2:51:58 pm PST [cmd: REF CommandObject] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] CommandObject = [ in, out, err: IO.STREAM, commandLine, command: ROPE, propertyList: List.AList, procData: CommandProcHandle] [cmd: REF CommandObject] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] CommandObject = [ in, out, err: IO.STREAM, commandLine, command: ROPE, propertyList: List.AList, procData: CommandProcHandle] ΚJ˜™Icodešœ Οmœ1™—˜šΟk ˜ Jšœ žœ˜(Jšœ žœ˜(Jšœ žœ˜&Jšžœžœ ˜(Jšžœžœ8žœ˜HJšœžœ˜Jšœžœžœ˜&Jšœ˜Jšœ˜—J˜—šΠlnœžœž˜Jšžœ$žœžœ˜@Jšžœ ˜Jšœ˜K˜šΟn œžœžœžœ žœžœžœžœžœžœ žœžœ žœžœ˜Žš   œžœ žœ žœžœ˜>šžœ ž˜Kšœžœ˜ šžœ˜ šžœ˜Kšžœžœ˜ Kšžœžœ6˜A———Kšœ˜—Kš œ žœžœžœžœžœ˜$šžœ žœ˜š žœžœžœžœžœžœž˜Ešžœ˜šžœ˜Kšœ žœ˜"K˜—šžœ˜šœ ž œ˜šžœ7˜9šžœ ˜ šžœžœ˜Kšœ2žœžœ˜;Kšœ˜————Kšœ žœ˜*K˜——Kšžœ˜—K˜>š žœžœžœžœžœžœž˜GKš žœžœžœžœžœ˜BKšžœ˜—K˜—šž˜K˜—K˜K˜—K˜š  œžœž œžœžœžœžœ žœžœ žœžœ˜ƒKšœ žœ˜Kš œžœžœžœžœ˜!šžœžœžœžœžœžœžœž˜Gšžœžœžœž˜!K˜šœ žœ1˜@KšžœΟrž‘˜Kšžœ‘ ž‘˜Kšœ˜—šžœ%˜'Kšžœ‘ž‘˜Kšžœ‘ ž‘œ˜—Kšœ˜Kšžœ˜—Kšžœ˜—K˜—K˜š  œ˜%Kš œžœžœ žœžœžœžœ™Ešœ™Kšœž œžœ™4Kšœ6™6—Kšœ žœžœž˜Kšœžœ˜ šœ/ž˜3Kšœ)žœžœ˜5—šžœ ž˜šžœ˜K˜&K˜—šžœ˜K˜6K˜——šž˜Kšœ˜—K˜—J˜š œžœžœžœžœžœ žœžœžœžœ žœžœ žœžœ˜Œš   œžœ žœ žœžœ˜>šžœ ž˜Kšœžœ˜!šžœ˜ šžœ˜Kšžœžœ˜!Kšžœžœ6˜A———Kšœ˜—Kšœ žœ˜Kš œžœžœžœžœ˜!Kš œ žœžœžœžœžœ˜$Kšœ žœžœ˜š žœžœžœžœžœžœž˜Ešœ ˜ šžœY˜[šžœ ˜ šžœžœ˜Kšœ/žœžœ˜8Kšœ˜————Kšœ žœ˜*Kšžœ˜—K˜Dš žœžœžœžœžœžœž˜GKšžœžœžœžœ˜.Kšžœ˜—šž˜K˜—K˜—K˜š  œžœžœžœžœžœžœžœžœžœžœ žœžœ žœžœ˜Kšœ žœ˜Kš œžœžœžœžœ˜!šžœžœžœ ž˜K˜šœ žœ)˜8Kšžœ‘ž‘˜Kšžœ‘ ž‘˜Kšœ˜—šžœ%˜'Kšžœ‘ž‘˜Kšžœ‘ ž‘˜Kšœ˜—š žœžœžœžœžœžœž˜Gšžœ,˜.Kšžœ‘ž‘˜Kšžœ‘ ž‘˜Kšœ˜—Kšžœ˜—Kšœ˜Kšžœ˜—K˜—K˜š  œ˜%Kš œžœžœ žœžœžœžœ™Ešœ™Kšœž œžœ™4Kšœ6™6—Kšœ žœžœž˜Kšœžœ˜ šœ/ž˜3Kšœ)žœžœ˜5—šžœ ž˜šžœ˜K˜ K˜—šžœ˜K˜4K˜——šž˜Kšœ˜—K˜—J˜JšœN˜NJšœI˜IJ˜J˜——…—fΠ