DIRECTORY AlpineEnvironment USING[ NeededAccess, OperationFailure, Principal, UnknownType], AlpDirectory USING[ Error ], AlpineDirectory USING[ ErrorType ], AlpineInterimDirectory USING[ DirectoryInconsistent, Error, ErrorType], AlpInstance USING[ AccessFailed, Create, Handle, LockFailed, Failed, OperationFailed, PossiblyDamaged, StaticallyInvalid, Unknown], AlpTransaction USING[ Create, Finish, Handle, OperationFailed, Outcome], AMTypes USING[ IndexToName, Type], FS USING[ Error], IO, PrincOpsUtils USING[ IsBound ], Rope, RPC USING[ CallFailed, CallFailure, EncryptionKey, MakeKey], UserCredentials USING[ Get ], YodelData; YodelSignalsImpl: CEDAR PROGRAM IMPORTS AlpDirectory, AlpineInterimDirectory, AlpInstance, AlpTransaction, AMTypes, FS, IO, PrincOpsUtils, Rope, RPC, UserCredentials EXPORTS YodelData = BEGIN OPEN YodelData; ROPE: TYPE = Rope.ROPE; PerformOp: PUBLIC PROC[ performProc: PerformProc, server: ROPE, user: ROPE _ NIL, password: ROPE _ NIL] RETURNS [LIST OF REF ANY] = { failureName: ROPE _ "" ; userName, userPassword, keyRope: ROPE; caller: AlpineEnvironment.Principal ; key: RPC.EncryptionKey; inst: AlpInstance.Handle _ NIL; trans: AlpTransaction.Handle _ NIL ; outcome: AlpTransaction.Outcome _ unknown; result: LIST OF REF ANY _ NIL ; { ENABLE BEGIN RPC.CallFailed => { type: AMTypes.Type _ CODE[RPC.CallFailure]; failure: RPC.CallFailure; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN RPC.CallFailure DO IF why = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO RPCFailed; }; AlpInstance.StaticallyInvalid => GOTO statInvalid ; AlpInstance.Unknown =>{ type: AMTypes.Type _ CODE[AlpineEnvironment.UnknownType]; failure: AlpineEnvironment.UnknownType; count: CARDINAL _ 1 ; failureName _ "*unknown*"; IF what = AlpineEnvironment.UnknownType.owner THEN GOTO badOwner; IF what = AlpineEnvironment.UnknownType.transID THEN GOTO badTransID; FOR failure IN AlpineEnvironment.UnknownType DO IF what = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO alpUnknown; }; AlpInstance.AccessFailed =>{ type: AMTypes.Type _ CODE[AlpineEnvironment.NeededAccess]; failure: AlpineEnvironment.NeededAccess; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineEnvironment.NeededAccess DO IF missingAccess = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO accFail; }; AlpInstance.OperationFailed => { type: AMTypes.Type _ CODE[AlpineEnvironment.OperationFailure]; failure: AlpineEnvironment.OperationFailure; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineEnvironment.OperationFailure DO IF why = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO opFail; }; AlpineInterimDirectory.DirectoryInconsistent => GOTO dirInconsistent; AlpineInterimDirectory.Error => { type: AMTypes.Type _ CODE[AlpineInterimDirectory.ErrorType]; failure: AlpineInterimDirectory.ErrorType; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineInterimDirectory.ErrorType DO IF why = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO interimDirError; }; AlpDirectory.Error => { typeCode: AMTypes.Type _ CODE[AlpineDirectory.ErrorType]; failure: AlpineDirectory.ErrorType; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineDirectory.ErrorType DO IF type = failure THEN { failureName _ AMTypes.IndexToName[type: typeCode, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO dirError; }; AlpInstance.LockFailed => GOTO lockFail; AlpInstance.PossiblyDamaged => GOTO possDamaged; AlpTransaction.OperationFailed => GOTO alpineBusy; AlpInstance.Failed => { SELECT why FROM alpineDownOrCommunications => { failureName _ " alpine or communications are down"; GOTO alpineError ; }; alpineDown => { failureName _ " alpine server is down"; GOTO alpineError ; }; authenticateFailed => { failureName _ " of authentication error- suspect bad user name or password"; GOTO alpineError ; }; badCallee => { failureName _ " of bad server name"; GOTO alpineError ; }; grapevineDownOrCommunications => { failureName _ " communications or server are down"; GOTO alpineError ; }; mismatch => { failureName _ " mismatch (for example, version incompatibility)"; GOTO alpineError ; }; ENDCASE ; }; FS.Error => { failureName _ error.explanation ; GOTO FSError ; }; IO.Error => { SELECT ec FROM SyntaxError => { failureName _ "Syntax Error"; GOTO syntaxError ;} ; ENDCASE ; }; END; TRUSTED BEGIN IF NOT PrincOpsUtils.IsBound[link: LOOPHOLE[AlpInstance.Create]] THEN GOTO notBound ; END; [userName, userPassword] _ UserCredentials.Get[]; IF (Rope.Equal[user,""] OR Rope.Equal[user,NIL]) THEN caller _ userName ELSE caller _ user ; IF (Rope.Equal[password,""] OR Rope.Equal[password,NIL]) THEN keyRope _ userPassword ELSE keyRope _ password ; TRUSTED BEGIN key _ RPC.MakeKey[keyRope]; END; IF Rope.Match[pattern: "*.alpine", object: server, case: FALSE] THEN { inst _ AlpInstance.Create[fileStore: server, caller: caller, key: key]; trans _ AlpTransaction.Create[inst]; }; result _ performProc[trans: trans, serverForTrans: server, caller: caller, key: key]; IF trans # NIL THEN { outcome _ AlpTransaction.Finish[trans, commit]; }; RETURN[result]; EXITS RPCFailed => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["RPC failure: %g", IO.rope[failureName]],NIL]]; }; alpineBusy => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine server is busy - please try again later", ROPE], NIL]]; }; dirInconsistent => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine Interim Directory: directory is inconsistent",ROPE], NIL]]; }; dirError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Directory Error: %g", IO.rope[failureName]],NIL]]; }; interimDirError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Interim Directory Error: %g", IO.rope[failureName]],NIL]]; }; accFail => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine denied access because client is not in the %g access control list", IO.rope[failureName]],NIL ]]; }; lockFail => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine server has a conflict or timed out a lock - please try again later", ROPE], NIL]]; }; opFail => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Instance Operation Failed: %g", IO.rope[failureName]],NIL]]; }; possDamaged => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine server reports possible damage", ROPE], NIL]]; }; alpUnknown => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Instance Unknown Type: %g", IO.rope[failureName]],NIL]]; }; badOwner => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine Unknown Type: owner -- suspect bad directory, owner or access list name", ROPE], NIL]]; }; badTransID => { RETURN[CONS[ NARROW["Alpine Unknown Type: transID -- suspect transaction has aborted or that the server has crashed and restarted", ROPE], NIL]]; }; statInvalid => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine Statically Invalid error - suspect unreasonable property value or Yodel bug", ROPE], NIL]]; }; notBound => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["unbound error- suspect AlpineUserImpls has not been run", ROPE], NIL]]; }; alpineError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine error because %g",IO.rope[failureName]],NIL]]; }; FSError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["FS could not perform operation because %g", IO.rope[failureName]], NIL]]; }; syntaxError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Syntax error in input: %g", IO.rope[failureName]],NIL]]; }; }; }; END. YodelSignalsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Yodel: Signal Handler Last Edited by: Bob Hagmann June 11, 1985 9:51:23 am PDT This procedure checks to be sure Alpine is bound, and then calls the PerformProc. Most signals from Alpine are caught, and appropiate lists of ropes are returned. Bob Hagmann June 10, 1985 4:57:53 pm PDT reformatted Bob Hagmann January 9, 1986 5:17:23 pm PST Added catch phrases for RPC.CallFailed inside the EXIT clauses changes to: PerformOp Κ ™˜šœ™Icodešœ Οmœ1™<—Jšœ™šœ™K™(—J˜J˜JšΟk ˜ ˜šžœ,˜1J˜ —Jšœžœ˜)Jšœžœ˜#—˜šžœ˜J˜——šœ žœ3˜EJ˜>—Jšœžœ4˜HJšœ žœ˜#Jšžœžœ ˜Jšžœ˜Jšœžœ ˜J˜Jšžœžœ3˜?Jšœžœ˜J˜ J˜Jšœžœž˜JšžœMžœžœžœ˜…J˜šžœ ˜J˜J˜—J˜šžœžœ ˜J˜—˜J˜—J˜J˜Jšžœžœžœ˜˜JšœQ™QJšœP™P—šΟn œžœžœ$žœ˜?Jš œžœžœ žœžœ˜'š žœžœžœžœžœ˜Jšœ žœ˜Jšœ!žœ˜&J˜%Jšœžœ˜Jšœžœ˜Jšœžœ˜$J˜*š œžœžœžœžœžœ˜J˜———˜šžœžœ˜ šžœ˜Jšœžœžœ˜+Jšœ žœ ˜Jšœžœ˜J˜šžœ žœžœ ž˜!šžœžœ˜J˜<—J˜J˜—Jšžœ˜Jšžœ ˜—J˜Jšœ!žœ˜3˜Jšœžœ ˜9J˜'Jšœžœ˜J˜Jšžœ-žœžœ ˜BJšžœ/žœžœ ˜Fšžœ žœž˜/šžœžœ˜J˜<—J˜J˜—Jšžœ˜Jšžœ ˜J˜˜Jšœžœ!˜:J˜(Jšœžœ˜J˜šžœ žœ ž˜0šžœžœ˜!J˜<—J˜J˜—Jšžœ˜Jšžœ ˜ —J˜˜ Jšœžœ%˜>J˜,Jšœžœ˜J˜šžœ žœ$ž˜4šžœžœ˜J˜<—J˜J˜—Jšžœ˜Jšžœ˜ —J˜Jšœ0žœ˜E˜!Jšœžœ#˜™>Kšœ Οr ™—K™—…—#/·