// IfsTelnetPress.bcpl -- Executive Press-printing commands // Copyright Xerox Corporation 1979, 1980, 1981 // Last modified November 30, 1981 10:15 AM by Taft get "Ifs.decl" get "IfsPress.decl" get "IfsFiles.decl" get "IfsDirs.decl" get "IfsRs.decl" get "Pup0.decl" get "Streams.d" external [ // outgoing procedures ExecPress; EnqueuePressRequest; // incoming procedures TelnetCommandLoop; TelnetSubcommandPrompt; TelnetAborting; TelnetConfirm CollectFilenames; NextFile; DestroyFGD; Subcommands CreateKeywordTable; InsertKeyword; DestroyKeywordTable GetString; GetNumber IFSOpenFile; OpenIFSStream; CloseIFSStream; GetDIF; WheelCall EnumeratePupAddresses; ResetStrings FileLength; SetFilePos; KsBufferAddress; CurrentPos; WriteBlock ExtractSubstring; ConcatenateStrings; CopyString; StringCompare Ws; Wss; Puts; Closes; Errors; IFSPrintError; DoubleIncrement; PutTemplate SysAllocateZero; SysFree; FreePointer; MoveBlock; Zero ReadCalendar; TruePredicate // incoming statics @pps; dsp; CtxRunning ] //---------------------------------------------------------------------------- let ExecPress(cs) be //---------------------------------------------------------------------------- // Press <filenames> [, <subcommands> ] [ unless pps>>PPS.enable do Errors(cs, 0) Wss(cs, " (files) ") let fgd = CollectFilenames(cs) let options = vec lenPressOpt; Zero(options, lenPressOpt) options>>PressOpt.copies = 1 options>>PressOpt.requestorName = ExtractSubstring(CtxRunning>>RSCtx.userInfo>>UserInfo.userName) let dif = GetDIF(options>>PressOpt.requestorName, true) // find only real DIF if dif ne 0 then [ if dif>>DIF.defaultPrinter.length ne 0 then [ options>>PressOpt.host = ExtractSubstring(lv dif>>DIF.defaultPrinter) PutTemplate(dsp, "*n[Sending to $S]", options>>PressOpt.host) ] SysFree(dif) ] let warn = options>>PressOpt.host eq 0 & not Subcommands(fgd) [ // repeat if warn then Ws("*n[Use the 'Server' sub-command to specify a printing server]") if options>>PressOpt.host eq 0 % Subcommands(fgd) then [ let kt = CreateKeywordTable(5) InsertKeyword(kt, "Server")!0 = 0 InsertKeyword(kt, "Copies")!0 = 1 InsertKeyword(kt, "Printed-by")!0 = 2 InsertKeyword(kt, "Duplex")!0 = 3 InsertKeyword(kt, "Password")!0 = 4 TelnetCommandLoop(kt, TelnetSubcommandPrompt(), true, options, 0, 0, PressSubcommand) DestroyKeywordTable(kt) ] warn = true ] repeatuntil options>>PressOpt.host ne 0 % TelnetAborting() ResetStrings() until TelnetAborting() do [ let fd = NextFile(fgd) if fd eq 0 break let ec = EnqueuePressRequest(fd, options, TelnetConfirm, true) if ec ne 0 then IFSPrintError(dsp, ec); ] FreePointer(lv options>>PressOpt.host, lv options>>PressOpt.requestorName, lv options>>PressOpt.holdPassword) DestroyFGD(fgd) ] //---------------------------------------------------------------------------- and EnqueuePressRequest(fd, options, ConfirmProc, display) = valof //---------------------------------------------------------------------------- [ // (Send misc text to dsp if 'display' is true.) let ec = nil let stream = OpenIFSStream(fd, lv ec) if display ne 0 then PutTemplate(dsp, "*n $S -- ", lv fd>>FD.dr>>DR.pathName) if stream eq 0 then resultis ec // Check if file is in Press format. let pos = vec 1 FileLength(stream, pos) let ok = (pos!1 & 777B) eq 0 & (pos!0 ne 0 % pos!1 ne 0) let nPages = nil if ok then [ DoubleIncrement(pos, -512) SetFilePos(stream, pos) let ddv = KsBufferAddress(stream) + CurrentPos(stream) rshift 1 ok = ok & ddv>>DDV.Passwd eq PressPasswd nPages = ddv>>DDV.nParts-1 ] CloseIFSStream(stream) unless ok do resultis ecPressFormat if display then PutTemplate(dsp, "$D-page document", nPages) unless ConfirmProc() do resultis 0 // Construct PQE let pqe = SysAllocateZero(maxLenPQE) pqe>>PQE.length = offset PQE.vlArgs/16 pqe>>PQE.fileName = AppendStringToPQE(pqe, lv fd>>FD.dr>>DR.pathName) pqe>>PQE.requestorName = AppendStringToPQE(pqe, options>>PressOpt.requestorName) pqe>>PQE.status = ecPQEPending pqe>>PQE.copies = options>>PressOpt.copies pqe>>PQE.pages = nPages ReadCalendar(lv pqe>>PQE.time) if options>>PressOpt.holdPassword ne 0 then pqe>>PQE.holdPassword = AppendStringToPQE(pqe,options>>PressOpt.holdPassword) pqe>>PQE.duplex = options>>PressOpt.duplex if pqe>>PQE.duplex % pqe>>PQE.holdPassword ne 0 then pqe>>PQE.spruce11 = true; // Attempt to append it to the Press queue file for host for i = 1 to 10 do [ stream = WheelCall(IFSOpenFile, options>>PressOpt.host, lv ec, modeAppend, 0, 0, 0, "System>Press") if stream ne 0 then [ WriteBlock(stream, pqe, pqe>>PQE.length) Closes(stream) pps>>PPS.somethingToDo = true pps>>PPS.timer = 0 break ] if ec ne ecFileBusy break ] SysFree(pqe) if ec ne 0 & display then Ws("*n -- failed:"); resultis ec; ] //---------------------------------------------------------------------------- and PressSubcommand(cs, entry, options) be //---------------------------------------------------------------------------- [ Puts(dsp, $*s) switchon entry!0 into [ case 0: // Server [ let host = GetString(cs, 0, Wss, "host name or net#host#") let port = vec lenPort if EnumeratePupAddresses(host, 0, port, true) ne 0 % port>>Port.host eq 0 then [ SysFree(host); Errors(cs, 0) ] FreePointer(lv options>>PressOpt.host) options>>PressOpt.host = host endcase ] case 1: // Copies [ let copies = GetNumber(cs) if copies le 0 % copies gr 1000 then Errors(cs, 0) options>>PressOpt.copies = copies endcase ] case 2: // Printed-by [ let name = GetString(cs, 0, Wss, "user name") if name>>String.length gr maxLenRequestorName then [ SysFree(name); Errors(cs, 0); ] FreePointer(lv options>>PressOpt.requestorName) options>>PressOpt.requestorName = name endcase ] case 3: [ options>>PressOpt.duplex = true endcase ] case 4: [ let password = GetString(cs, 0, Wss, "password") if password>>String.length gr maxLenHoldPassword then [ SysFree(password); Errors(cs, 0); ] FreePointer(lv options>>PressOpt.holdPassword) options>>PressOpt.holdPassword = password endcase ] ] ] //---------------------------------------------------------------------------- and AppendStringToPQE(pqe, string) = valof //---------------------------------------------------------------------------- // Appends string to vlArgs portion of pqe, updates pqe.length, and // returns the pqe-relative offset of the copied string. // pqe had better be long enough, as no bounds check is done. [ let lenPQE = pqe>>PQE.length let lenString = string>>String.length rshift 1 +1 MoveBlock(pqe+lenPQE, string, lenString) pqe>>PQE.length = lenPQE+lenString resultis lenPQE ]