// IfsLeafOpen.bcpl - Leaf Open - SWAPPABLE // Copyright Xerox Corporation 1979, 1980, 1981 // Last modified November 20, 1981 11:12 AM by Taft get "IfsLeaf.decl"; get Sequin, fhQ, state, brokenLeaf, timedOutState from "IfsSequin.decl" get "IfsDirs.decl"; external [ //outgoing procedures OpenLeaf; LeafLogin; LeafToIfsString; //incoming procedures SysAllocateZero; MoveBlock; Zero; Enqueue; ExtractSubstring; InsertBefore; StringCompare; OpenLeafVMem; CloseFH; FindLVMD; FreeLeafVMem; LeafError; Login; Connect; CreateFD; LookupFD; OpenIFSFile; AnswerSetOp; NextLockedSequin; SequinDestroy; UnlockSequin; //incoming statics CtxRunning; leafOpLim; system; ] structure String: [ length byte; char↑1,1 byte ] //---------------------------------------------------------------------------- let OpenLeaf(sequin, answerPBI, op) = valof //---------------------------------------------------------------------------- [ let fh = SysAllocateZero(lenFH); let queue = lv sequin>>Sequin.fhQ; let queueTop = @queue; test queueTop ne 0 ifso InsertBefore(queue, queueTop, fh) ifnot Enqueue(queue, fh) let mode = op>>OpenRequest.mode; fh>>FH.mode = mode; let leafstring = lv op>>OpenRequest.strings; let ui = lv fh>>FH.ui; let ec = valof [ let ec = LeafLogin(lv leafstring, ui, true); if ec ne 0 then resultis ec; let filename = LeafToIfsString(lv leafstring) let lc = selecton mode<<Mode.vDefault into [ case vLowest: lcVLowest case vDontDefault: case vHighest: lcVHighest case vNext: lcVNext + lcCreate ] let openMode = (mode<<Mode.write eq 0? modeRead, (mode<<Mode.multipleWriters eq 0? modeReadWrite, modeReadWriteShared)); if mode<<Mode.create then lc<<LC.create = true; if (openMode eq modeReadWrite) ne (mode<<Mode.extend ne 0) % (openMode ne modeReadWrite & lc<<LC.create ne 0) then resultis ecIllegalLookupControl; let fd = CreateFD(filename, lc, lv ec); if fd eq 0 then resultis ec; fh>>FH.fd = fd; [ // Repeat for ecFileBusy cleanup. ec = LookupFD(fd); if ec ne 0 % fd>>FD.lookupStatus eq lsNonexistent & not mode<<Mode.create % (fd>>FD.lc.vc ne lcVExplicit? mode<<Mode.vDefault eq vDontDefault, mode<<Mode.vExplicit ne anyExplicit) then resultis (ec ne 0? ec, ecIllegalLookupControl); fh>>FH.lvmd = OpenLeafVMem(fd, openMode, lv ec); ] repeatwhile ec eq ecFileBusy & UnlockFHs(fd) resultis ec; ] CtxRunning>>RSCtx.userInfo = system; if ec ne 0 then [ CloseFH(sequin, fh); resultis LeafError(answerPBI, op, ec); ] let answer = AnswerSetOp(answerPBI, op, 2*lenOpenAnswer); answer>>OpenAnswer.handle = fh MoveBlock(lv answer>>OpenAnswer.length, lv fh>>FH.lvmd>>LVMD.lastAddress, 2) resultis leafOpComplete; ] //---------------------------------------------------------------------------- and LeafLogin(lvleafstring, ui, connect; numargs na) = valof //---------------------------------------------------------------------------- [ if na ls 3 then connect = false; Zero(ui, lenUserInfo); CtxRunning>>RSCtx.userInfo = ui; let name = LeafToIfsString(lvleafstring); let password = LeafToIfsString(lvleafstring) let result = Login(name, password, ui) if result eq 0 & connect then [ let cName = LeafToIfsString(lvleafstring); let cPassword = LeafToIfsString(lvleafstring); if cName>>String.length ne 0 then result = Connect(cName, cPassword, ui); ] resultis result ] //---------------------------------------------------------------------------- and LeafToIfsString(lvstring) = valof //---------------------------------------------------------------------------- [ let string = @lvstring; // see if string is too long for op test (leafOpLim - string)*2 gr @string ifnot @string = #777; // Yes, insert a string of one 'delete' char. ifso [ string>>String.length = @string; for i = 1 to string>>String.length do string>>String.char↑i = string>>String.char↑(i+1) ] @lvstring = string + (string>>String.length + 3)/2; resultis string ] //---------------------------------------------------------------------------- and UnlockFHs(fd) = valof //---------------------------------------------------------------------------- [ // See if this file is locked under a timed out handle/sequin. // If it is, unlock it. Return true if the existing lvmd gets flushed. let lvmd = FindLVMD(lv fd>>FD.dr>>DR.fp); if lvmd eq 0 then resultis false; // Return if locked by non-Leaf user. let sequin = 0; [ // loop through all sequins sequin = NextLockedSequin(sequin); if sequin eq 0 break; if sequin>>Sequin.state ne timedOutState then loop; let fh = @(lv sequin>>Sequin.fhQ); while fh ne 0 do [ if lvmd eq fh>>FH.lvmd then [ fh>>FH.lvmd = 0; sequin>>Sequin.brokenLeaf = true; if FreeLeafVMem(fh>>FH.fd, lvmd) then [ UnlockSequin(sequin); resultis true; ] ] fh = fh>>FH.link; ] ] repeat resultis false; ]