<> <> <> <> <> DIRECTORY Args USING [Arg, ArgsGet, NArgs], BasicTime USING [GMT, ToNSTime], CHNameP2V0 USING [Name], Commander USING [CommandProc, Register], CommandTool USING [ArgumentVector, Failed, Parse], File USING [GetVolumeName, SystemVolume], FileNames USING [ResolveRelativePath], FS USING [ComponentPositions, Error, ErrorDesc, ExpandName, FileInfo, StreamOpen], FSPseudoServers USING [TranslateForRead, TranslateForWrite], IO USING [Close, PutF, PutRope, rope, STREAM], Process USING [CheckForAbort], Rope USING [Cat, Concat, Equal, Length, ROPE, Substr], ThisMachine USING [Name], PrintingP4V3 USING [PrinterProperties, PrinterStatus, RequestID], PrintingP4V3Aux USING [ExposePrinterProperties, ExposePrinterStatus, ExposeRequestID], XNSPrintRequestManager; XNSPrintCommands: CEDAR PROGRAM IMPORTS Args, BasicTime, Commander, CommandTool, File, FileNames, FS, FSPseudoServers, IO, PrintingP4V3Aux, Process, Rope, ThisMachine, XNSPrintRequestManager ~ { OPEN CHName: CHNameP2V0, Printing: PrintingP4V3, PrintingAux: PrintingP4V3Aux; ROPE: TYPE ~ Rope.ROPE; <> <<>> GetPrintStatus: ROPE = "GetPrintStatus"; statusdoc: ROPE = "{Printer}*\nFind out the status of an XNS based printer."; statususage: ROPE = Rope.Concat["Usage: GetPrintStatus ", statusdoc]; <> <<>> GetPrintProperties: ROPE = "GetPrintProperties"; propdoc: ROPE = "{Printer}*\nFind out the properties of an XNS based printer.\nSwitches: "; propusage: ROPE = Rope.Concat["Usage: GetPrintProperties ", propdoc]; SendIPMaster: ROPE ~ "SendIPMaster"; senddoc: ROPE ~ " [-c -h -1 -2 -f -l ]\nTransmit a master to an XNS based printer.\nSwitches:\n -c print multiple copies\n -h print on that service\n -1 print one-sided\n -2 print two-sided\n -f \n -l "; sendusage: ROPE ~ Rope.Concat["Usage: SendIPMaster ", senddoc]; <> DecodeRequestID: PROC [out: IO.STREAM, request: XNSPrintRequestManager.PrintRequest] ~ { msg: ROPE; IO.PutF[out, " Service: [%g:%g:%g]\n ", IO.rope[request.distinguishedName.object], IO.rope[request.distinguishedName.domain], IO.rope[request.distinguishedName.organization] ]; msg _ Rope.Concat[PrintingAux.ExposeRequestID[request.requestID, 1], "\n"]; -- nest 2 spaces IO.PutRope[out, msg]; }; DecodeProperties: PROC [out: IO.STREAM, service: CHName.Name, status: Printing.PrinterProperties] ~ { msg: ROPE _ NIL; IO.PutF[out, " Service: [%g:%g:%g]\n ", IO.rope[service.object], IO.rope[service.domain], IO.rope[service.organization] ]; msg _ Rope.Concat[PrintingAux.ExposePrinterProperties[status, 1], "\n"]; -- nest 2 spaces IO.PutRope[out, msg]; }; DecodeStatus: PROC [out: IO.STREAM, service: CHName.Name, status: Printing.PrinterStatus] ~ { msg: ROPE _ NIL; IO.PutF[out, " Service: [%g:%g:%g]\n ", IO.rope[service.object], IO.rope[service.domain], IO.rope[service.organization] ]; msg _ Rope.Concat[PrintingAux.ExposePrinterStatus[status, 1], "\n"]; -- nest 2 spaces IO.PutRope[out, msg]; }; <> FSErrorMsg: PROC [error: FS.ErrorDesc] RETURNS [ROPE] ~ { RETURN[Rope.Concat[FSErrorMsgBrief[error], "\n"]]; }; FSErrorMsgBrief: PROC [error: FS.ErrorDesc] RETURNS [ROPE] ~ { SELECT error.group FROM lock => { RETURN[" -- locked!"]; }; ENDCASE => { IF (error.code = $unknownFile) THEN RETURN [" -- not found!"] ELSE RETURN[Rope.Concat["\n -- FS.Error: ", error.explanation]]; }; }; FixUpFilename: PROC [name: ROPE _ NIL, copyFrom: BOOL] RETURNS [newName: ROPE] ~ { body: ROPE; platformHost: ROPE _ ThisMachine.Name[]; platformVolume: ROPE _ File.GetVolumeName[File.SystemVolume[]]; prefix: ROPE; cp: FS.ComponentPositions; [fullFName: newName, cp: cp] _ FS.ExpandName[name]; prefix _ Rope.Substr[newName, 0, 4]; body _ Rope.Substr[newName, 4, Rope.Length[newName]]; IF Rope.Equal[prefix, "[]<>"] THEN { newName _ Rope.Cat["[", platformHost, "]<", platformVolume, ">"]; newName _ Rope.Cat[newName, body]; } ELSE newName _ Rope.Cat[ "[", IF copyFrom THEN FSPseudoServers.TranslateForRead[Rope.Substr[newName, cp.server.start, cp.server.length]].first ELSE FSPseudoServers.TranslateForWrite[Rope.Substr[newName, cp.server.start, cp.server.length]], "]<", Rope.Substr[newName, cp.dir.start, Rope.Length[newName]]]; }; <> <<>> GetPrintPropertiesProc: Commander.CommandProc ~ { argsProcessed: NAT _ 0; argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd, starExpand: FALSE ! CommandTool.Failed => {msg _ errorMsg; GO TO failed}]; out: IO.STREAM ~ cmd.out; CheckProperties: PROC [arg: ROPE] ~ { service: CHName.Name; status: Printing.PrinterProperties; argsProcessed _ argsProcessed + 1; Process.CheckForAbort[]; [service, status] _ XNSPrintRequestManager.GetPrinterProperties[arg]; DecodeProperties[out, service, status]; }; FOR i: NAT IN [1..argv.argc) DO printerName: ROPE ~ argv[i]; Process.CheckForAbort[]; IF (Rope.Length[printerName] = 0) THEN LOOP; CheckProperties[printerName]; ENDLOOP; SELECT argsProcessed FROM 0 => { context: XNSPrintRequestManager.Context; context _ XNSPrintRequestManager.GetDefaults[]; IF (context.printerName = NIL) THEN msg _ propusage ELSE CheckProperties[context.printerName]; }; ENDCASE => { NULL }; EXITS failed => {result _ $Failure}; }; GetPrintStatusProc: Commander.CommandProc ~ { argsProcessed: NAT _ 0; argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd, starExpand: FALSE ! CommandTool.Failed => { msg _ errorMsg; GO TO failed; }]; out: IO.STREAM ~ cmd.out; CheckPrinter: PROC [arg: ROPE] = { service: CHName.Name; status: Printing.PrinterStatus; argsProcessed _ argsProcessed + 1; Process.CheckForAbort[]; [service, status] _ XNSPrintRequestManager.GetPrinterStatus[arg]; DecodeStatus[out, service, status]; }; FOR i: NAT IN [1..argv.argc) DO printerName: ROPE ~ argv[i]; Process.CheckForAbort[]; IF (Rope.Length[printerName] = 0) THEN LOOP; CheckPrinter[printerName]; ENDLOOP; SELECT argsProcessed FROM 0 => { context: XNSPrintRequestManager.Context; context _ XNSPrintRequestManager.GetDefaults[]; IF (context.printerName = NIL) THEN msg _ statususage ELSE CheckPrinter[context.printerName]; }; ENDCASE => NULL; EXITS failed => {result _ $Failure}; }; SendMasterProc: Commander.CommandProc ~ { context: XNSPrintRequestManager.Context; request: XNSPrintRequestManager.PrintRequest; ok: BOOL; out: IO.STREAM ~ cmd.out; name, copies, host, oneSided, twoSided, first, last, pages: Args.Arg; PrintAFile: PROC [name: ROPE] RETURNS [request: XNSPrintRequestManager.PrintRequest] ~ { s: IO.STREAM; Process.CheckForAbort[]; s _ FS.StreamOpen[name ! FS.Error => IF (error.group # $bug) THEN { msg _ FSErrorMsg[error]; ERROR CommandTool.Failed[msg]; } ]; request _ XNSPrintRequestManager.PrintFromStream[s, context]; DecodeRequestID[out, request]; IF (s # NIL) THEN IO.Close[s]; }; IF Args.NArgs[cmd] = 0 THEN RETURN[$Failure, sendusage]; [ok, name, copies, host, oneSided, twoSided, first, last, pages] _ Args.ArgsGet[cmd, "%s-c%i-h%s-1%b-2%b-f%i-l%i-p%i"]; IF NOT ok THEN RETURN[$Failure, "Command syntax error."]; context _ XNSPrintRequestManager.GetDefaults[]; IF copies.ok THEN context.copyCount _ copies.int; IF host.ok THEN context.printerName _ host.rope; IF twoSided.ok AND twoSided.bool THEN context.twoSided _ TRUE; IF oneSided.ok AND oneSided.bool THEN context.twoSided _ FALSE; IF first.ok THEN context.pageFirst _ first.int; IF last.ok THEN context.pageLast _ last.int; IF pages.ok THEN context.pageLast _ context.pageFirst+pages.int; name.rope _ FileNames.ResolveRelativePath[name.rope]; context.printObjectName _ FixUpFilename[name.rope, FALSE]; { fullFName: ROPE; attachedTo: ROPE; keep: CARDINAL; bytes: INT; created: BasicTime.GMT; [fullFName, attachedTo, keep, bytes, created] _ FS.FileInfo[name~name.rope, remoteCheck~FALSE]; context.printObjectCreateDate _ BasicTime.ToNSTime[created]; }; IO.PutF[out, " Sending %s to %s\n", IO.rope[context.printObjectName], IO.rope[context.printerName] ]; request _ PrintAFile[name.rope]; XNSPrintRequestManager.RegisterPrintRequest[request]; -- registered for later status requests! request _ NIL; }; Init: PROC ~ { Commander.Register[GetPrintProperties, GetPrintPropertiesProc, propdoc]; Commander.Register[GetPrintStatus, GetPrintStatusProc, statusdoc]; Commander.Register[SendIPMaster, SendMasterProc, senddoc]; }; Init[]; }... <<>>