-- Yodel: Signal Handler
-- YodelSignals.mesa
-- Last Edited by: Hagmann, April 4, 1984 4:26:49 pm PST
DIRECTORY
AlpineEnvironment
USING[ NeededAccess, OperationFailure, Principal,
UnknownType],
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;
YodelSignals: CEDAR PROGRAM
IMPORTS AlpineInterimDirectory, AlpInstance, AlpTransaction, AMTypes, FS, IO, PrincOpsUtils, Rope, RPC, UserCredentials
EXPORTS YodelData
=
BEGIN OPEN YodelData;
ROPE: TYPE = Rope.ROPE;
-- 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.
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;
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 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, 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];
RETURN[CONS[
NARROW["Alpine server is busy - please try again later",ROPE]
,NIL]];
};
dirInconsistent => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
RETURN[CONS[NARROW[
"Alpine Interim Directory: directory is inconsistent",ROPE],NIL]];
};
dirError => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
RETURN[CONS[IO.PutFR["Alpine Interim Directory Error: %g",
IO.rope[failureName]],NIL]];
};
accFail => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
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];
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];
RETURN[CONS[IO.PutFR["Alpine Instance Operation Failed: %g",
IO.rope[failureName]],NIL]];
};
possDamaged => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
RETURN[CONS[
NARROW["Alpine server reports possible damage",ROPE]
,NIL]];
};
alpUnknown => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
RETURN[CONS[IO.PutFR["Alpine Instance Unknown Type: %g",
IO.rope[failureName]],NIL]];
};
badOwner => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
RETURN[CONS[
NARROW[
"Alpine Unknown Type: owner -- suspect bad directory, owner or access list name",
ROPE]
,NIL]];
};
statInvalid => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
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];
RETURN[CONS[IO.PutFR[
"Alpine error because %g",IO.rope[failureName]],NIL]];
};
FSError => {
IF trans # NIL THEN outcome ← AlpTransaction.Finish[trans, abort];
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];
RETURN[CONS[IO.PutFR["Syntax error in input: %g",
IO.rope[failureName]],NIL]];
};
};
};
END.