// DLSUtilb.bcpl -- Utility and program overflow procs for Alto DLS // Last modified January 15, 1985 9:07 AM by Diebert get "DLSDriver.decl" get "Pup.decl" get "DLSControl.decl" get "AltoDefs.d" get "Grapevine.decl" get "DLSUtil.decl" external [ // outgoing procedures GetString; Echo; Confirm; Error; Ws; Wss; Wns; Login; Set7BitProcs; DLSReturnFrom HangUp; DLSCommandError; DLSTopAbort; CheckConnection; DLSCommand; LoginServer StatusToLog; OtherPupProc; DialOutBSPError; TimeCallStart; TimeCallStop GetNumber; Grapevine; OnListCheck // Procedures defined in other packages Dismiss; PutTemplate; PutNum; SendAbort; ControlOut; UpdateCarrierOn MakeKey; Authenticate; GVDestroyStream; InitGrapevine; IsMemberClosure DLSInput7; DLSOutputTI; DLSOutput7; Block; LeaveRemoteMode; ReleasePBI DialOutTop; Unqueue; UDiv; BSPForceOutput; FindServer; MakeBSP // Procedures defined in operating system Gets; Puts; Endofs; Resets; Allocate; Free; AddToZone; Zero; CallSwat; MyFrame; GotoFrame; ReturnFrom; Noop; DefaultArgs; ReadCalendar; DoubleAdd // incoming statics dlsName; dlsRegistry; dlsWizardList @lbTable; ctxTable; mainCtx; CtxRunning; postedNotice; crlf; ndbQ sysZone; loginServerCB; logstream ] // --------------------------------------------------------------------------- let GetString(stream, string, maxChars, endOnSpace, echoOff; numargs n) = valof // --------------------------------------------------------------------------- // Input and edit a string of length up to maxChars. // Return true if terminated by return, false if by delete. [ DefaultArgs(lv n, 3, false, false) let i = 0 [ let char = Gets(stream) if endOnSpace & (char eq $*S) then char = $*n switchon char into [ case $*n: case $*l: string>>String.length = i unless endOnSpace then Wss(stream, crlf) resultis true case 177B: // Delete case 3: //Control-C because the fucking IBM PC does not have a Del key!! Wss(stream, " XXX*n*l") resultis false case $A-100B: case $H-100B: // Control-A, backspace test i gr 0 ifso [ Puts(stream, $\) test echoOff ifso Puts(stream, $**) ifnot Echo(stream, string>>String.char↑i) i = i - 1 ] ifnot Puts(stream, $*007) // Ding endcase default: test i ls maxChars ifso [ test echoOff ifso Puts(stream, $**) ifnot Echo(stream, char) i = i + 1 string>>String.char↑i = char ] ifnot Wss(stream, " [too long]") ] ] repeat ] // --------------------------------------------------------------------------- and Confirm(stream) = valof // --------------------------------------------------------------------------- // Wait for user to confirm command with carriage return or y Y // Return true if so, false if cancelled with Delete [ let char = Gets(stream) switchon char into [ case $Y: case $y: case $*n: case $*l: Wss(stream, " Yes*n*l") resultis true case $?: Wss(stream, "? Confirm with carriage return, Y or y ") endcase default: Wss(stream, " XXX*n*l") resultis false ] ] repeat // --------------------------------------------------------------------------- and Echo(stream, char) be // --------------------------------------------------------------------------- // Print char on str in a manner suitable for echoing [ if char ls 40B then [ Puts(stream, $↑); char = char+100B ] Puts(stream, char) ] // --------------------------------------------------------------------------- and Error(stream, string, char; numargs na) be // --------------------------------------------------------------------------- // Output string to terminal dlb, then clear input buffer. // If char is supplied, it is printed before the string // (this is useful for echoing the character that caused the error) [ if na ge 3 then Echo(stream, char) Wss(stream, string) Dismiss(40) // Pause for 400 ms Resets(stream) ] // --------------------------------------------------------------------------- and Wss(s, str) be // --------------------------------------------------------------------------- for i = 1 to str>>String.length do Puts(s, str>>String.char↑i) //// --------------------------------------------------------------------------- //and Ws(str) be Wss(keyDsp, str) //// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and Wns(s, num, wid, rdx; numargs na) be // --------------------------------------------------------------------------- [ DefaultArgs(lv na, -2, 1, -10) // Use unadvertised procedure in Template package. // *** Beware: the following 5 variables must be declared in this order. let radix = (rdx gr 0? rdx, -rdx) let width = wid let signed = rdx ls 0 let double = false let fill = $*s PutNum(s, num, lv radix) ] // --------------------------------------------------------------------------- and Grapevine(ctx) = valof // --------------------------------------------------------------------------- [ if ctx>>CTX.socketOpen then [ Error(ctx>>CTX.dlb, " Connection already open*n*l"); resultis false ] until loginServerCB>>LSCB.ctx eq 0 do Block() loginServerCB>>LSCB.Function = ltFindGrapevine loginServerCB>>LSCB.ec = 0 loginServerCB>>LSCB.ctx = ctx until loginServerCB>>LSCB.ctx eq 0 do Dismiss(1) if loginServerCB>>LSCB.ec ne 0 do [ Wss(ctx>>CTX.dlb, "*n*lAll servers are down, try latter.*n*l"); resultis false ] resultis true ] // --------------------------------------------------------------------------- and OnListCheck(ctx, tstr, list) = valof // --------------------------------------------------------------------------- [ let lclName = ctx>>CTX.name if lclName eq 0 then resultis false Wss(tstr, "Checking to see if you are on list ... ") BSPForceOutput(lv ctx>>CTX.socket) // this may take a while let the user know until loginServerCB>>LSCB.ctx eq 0 do Block() loginServerCB>>LSCB.Function = ltCheckOnList loginServerCB>>LSCB.Name = lclName loginServerCB>>LSCB.ec = 0 loginServerCB>>LSCB.List = list loginServerCB>>LSCB.ctx = ctx until loginServerCB>>LSCB.ctx eq 0 do Dismiss(1) PutTemplate(tstr, "$S*n*l", selecton loginServerCB>>LSCB.ec into [ case ecIndividual: case ecIsMember: "ok" case ecBadRName: "Invalid name" case ecBadPassword: "Invalid password" case ecAllDown: "All R-Servers are down" case ecIsNotMember: "*n*lSorry you are not on list" default: "Unknown response from Grapevine" ]) if loginServerCB>>LSCB.ec eq ecIsMember do resultis true resultis false ] // --------------------------------------------------------------------------- and Login(ctx, tstr, list, message) = valof // --------------------------------------------------------------------------- [ let char = nil let findOgin = true let lcogin = "ogin" let fubar = ctx>>CTX.name if fubar ne 0 do [ Free(sysZone, fubar); ctx>>CTX.name = 0 findOgin = false ] fubar = ctx>>CTX.password if fubar ne 0 do [ Free(sysZone, fubar); ctx>>CTX.password = 0 findOgin = false ] let lclName = vec maxRNameLength/2 + 1 let password = vec maxRNameLength/2 + 1 PutTemplate(tstr, "*n*lYour name please (include registry if not $S): ", dlsRegistry) unless GetString(tstr, lclName, maxRNameLength, true, false) do resultis false let oginFound = false if findOgin then if lclName>>String.length eq 4 then [ oginFound = true for i = 1 to 4 then if lclName>>String.char↑i ne lcogin>>String.char↑i then oginFound = false ] if oginFound do [ Wss(tstr, "← ") unless GetString(tstr, lclName, maxRNameLength, true, false) do resultis false ] let periodSeen = false for i = 1 to lclName>>String.length do if lclName>>String.char↑i eq $. then periodSeen = true unless periodSeen do [ let last = lclName>>String.length if (last + dlsRegistry>>String.length) gr maxRNameLength do [ Wss(tstr, "User name too long.*n*l"); resultis false ] lclName>>String.char↑(last + 1) = $.; Puts(tstr, $.) for i = 1 to dlsRegistry>>String.length do [ lclName>>String.char↑(last + 1 + i) = dlsRegistry>>String.char↑i Puts(tstr, dlsRegistry>>String.char↑i) ] lclName>>String.length = last + 1 + dlsRegistry>>String.length ] Wss(tstr, "*n*lYour password: ") unless GetString(tstr, password, maxRNameLength, true, true) do resultis false if oginFound do until char eq $*n do char = Gets(tstr) Wss(tstr, " ... Grapevine ") BSPForceOutput(lv ctx>>CTX.socket) // this may take a while let the user know until loginServerCB>>LSCB.ctx eq 0 do Block() loginServerCB>>LSCB.Function = ltNameAuthenticate loginServerCB>>LSCB.Name = lclName loginServerCB>>LSCB.Password = password loginServerCB>>LSCB.List = list loginServerCB>>LSCB.ec = 0 loginServerCB>>LSCB.ctx = ctx Wss(tstr, "... ") BSPForceOutput(lv ctx>>CTX.socket) // this may take a while let the user know until loginServerCB>>LSCB.ctx eq 0 do Dismiss(1) oginFound = selecton loginServerCB>>LSCB.ec into [ case ecIndividual: case ecIsMember: "ok" case ecBadRName: "Invalid name" case ecBadPassword: "Invalid password" case ecAllDown: "All R-Servers are down" case ecIsNotMember: "*n*lSorry you are not on the access list" default: "Unknown response from Grapevine" ] if (loginServerCB>>LSCB.ec eq ecIndividual) % (loginServerCB>>LSCB.ec eq ecIsMember) do [ let name = Allocate(sysZone, lclName>>String.length/2 + 1) for i = 1 to lclName>>String.length do name>>String.char↑i = lclName>>String.char↑i name>>String.length = lclName>>String.length ctx>>CTX.name = name name = Allocate(sysZone, password>>String.length/2 + 1) for i = 1 to password>>String.length do name>>String.char↑i = password>>String.char↑i name>>String.length = password>>String.length ctx>>CTX.password = name StatusToLog(ctx, message) PutTemplate(tstr, "$S*n*l", oginFound) resultis true ] PutTemplate(tstr, "$S*n*l", oginFound) resultis false ] // --------------------------------------------------------------------------- and LoginServer() be // --------------------------------------------------------------------------- [ until loginServerCB>>LSCB.ctx ne 0 do Block() let lclName = loginServerCB>>LSCB.Name switchon (loginServerCB>>LSCB.Function) into [ case ltNameAuthenticate: [ let key = vec lenPassword MakeKey(loginServerCB>>LSCB.Password, key) let ec = Authenticate(lclName, key) if ec eq ecIndividual do if loginServerCB>>LSCB.List ne 0 do ec = IsMemberClosure(loginServerCB>>LSCB.List, lclName) loginServerCB>>LSCB.ec = ec endcase ] case ltFindGrapevine: [ loginServerCB>>LSCB.ec = FindServer("Lily↑.ms", 53B, MakeBSP, loginServerCB>>LSCB.ctx) endcase ] case ltCheckOnList: [ loginServerCB>>LSCB.ec = IsMemberClosure(loginServerCB>>LSCB.List, lclName) endcase ] ] loginServerCB>>LSCB.ctx = 0 ] repeat // --------------------------------------------------------------------------- and Set7BitProcs(dlb) be // --------------------------------------------------------------------------- [ dlb>>DLB.gets = DLSInput7 dlb>>DLB.puts = (dlb>>DLB.baud eq 300 & dlb>>DLB.noPad eq 0) ? DLSOutputTI, DLSOutput7 ] // --------------------------------------------------------------------------- and HangUp(dlb, raiseDTR) be // --------------------------------------------------------------------------- // If this is a dial-up or Telenet line, drop Data Terminal Ready to hang // up the connection, then raise it again if raiseDTR is true. if dlb>>DLB.lineType ne ltHardwired then [ let controlLine = dlb>>DLB.otherLine ControlOut(controlLine, false) Dismiss(50) // Keep DTR low for at least 500 ms if raiseDTR then ControlOut(controlLine, true) UpdateCarrierOn(Noop) // Ensure carrierOff flag is up to date ] // --------------------------------------------------------------------------- and StatusToLog(ctx, reason) be // --------------------------------------------------------------------------- [ until logstream>>DLB.logBusy eq 0 do Dismiss(10) logstream>>DLB.logBusy = ctx PutTemplate(logstream, "Line #$O $D baud $S $S*n*l", ctx>>CTX.dlb>>DLB.line, ctx>>CTX.dlb>>DLB.baud, ctx>>CTX.name, reason) logstream>>DLB.logBusy = 0 ] // --------------------------------------------------------------------------- and TimeCallStart(ctx) be // --------------------------------------------------------------------------- [ let time = vec 2 time = ReadCalendar(time) ctx>>CTX.startTime = time!1 ctx>>CTX.callInProgress = 1 ] // --------------------------------------------------------------------------- and TimeCallStop(ctx) = valof // --------------------------------------------------------------------------- [ if ctx>>CTX.callInProgress eq 0 then resultis 0 let Now = vec 2 Now = ReadCalendar(Now) let Then = vec 2 Then!0 = 0 Then!1 = ctx>>CTX.startTime Then!1 = Now!1 - Then!1 let dur = UDiv(Then, 60, Then) + 1 until logstream>>DLB.logBusy eq 0 do Dismiss(10) PutTemplate(logstream, "Line #$O $S duration = $UD min.*n*l", ctx>>CTX.dlb>>DLB.line, ctx>>CTX.name, dur) logstream>>DLB.logBusy = 0 ctx>>CTX.callInProgress = 0 resultis dur ] // --------------------------------------------------------------------------- and GetNumber(tstr) = valof // --------------------------------------------------------------------------- // Returns -1 if aborted by delete, -2 if illegal number [ let string = vec 10 unless GetString(tstr, string, 20) resultis -1 let num = -2 for i = 1 to string>>String.length do [ let digit = string>>String.char↑i - $0 if digit ls 0 % digit gr 9 resultis -2 if num eq -2 then num = 0 num = 10*num + digit ] resultis num ]