-- Transport mechanism: Maintain: error messages

-- [Juniper]<Grapevine>Maintain>MaintainErrors.mesa

-- Andrew Birrell  14-Jan-82  9:37:23

DIRECTORY
BodyDefs	USING[ maxRNameLength, RName ],
MaintainPrivate	USING[ Failed, Handle, ProposalType ],
NameInfoDefs	USING[ CheckStamp, StampInfo ],
ProtocolDefs	USING[ ReturnCode, RSOperation ],
String		USING[ AppendChar, AppendString, LowerCase,
		        StringBoundsFault ];

MaintainErrors: PROGRAM
IMPORTS MaintainPrivate, NameInfoDefs, String
EXPORTS MaintainPrivate =

BEGIN

TypeRC: PUBLIC PROC[handle: MaintainPrivate.Handle,
                    op: ProtocolDefs.RSOperation,
                    rc: ProtocolDefs.ReturnCode,
                    name: BodyDefs.RName,
                    value: STRING] =
   BEGIN
   OPEN handle.glass;
   SELECT rc.code FROM
     done => WriteString["done"L];
     outOfDate =>
       WriteString["out-of-date: consult LaurelSupport.pa"L];
     NotAllowed =>
       WriteString["You don't have permission to do that.  Consult your local Grapevine administrator"L];
     BadOperation =>
       WriteString["bad-operation: consult LaurelSupport.pa"L];
     BadProtocol =>
       WriteString["bad-protocol: consult LaurelSupport.pa"L];
     BadRName =>
       BEGIN
       WriteChar['"]; WriteString[name];
       IF op = CreateIndividual OR op = CreateGroup OR op = NewName
       THEN SELECT rc.type FROM
              group =>
                WriteString[""" is an existing group"L];
              individual =>
                WriteString[""" is an existing individual"L];
              dead =>
                WriteString[""" has recently been deleted - can't recreate it yet.  Consult LaurelSupport.pa if necessary."L];
              notFound =>
                WriteString[""" does not have a valid registry"L];
            ENDCASE => ERROR
       ELSE BEGIN
            wanted: MaintainPrivate.ProposalType;
            WriteString[""" is not a valid "L];
            SELECT op FROM
              ReadConnect, Authenticate, DeleteIndividual,
              ChangePassword, ChangeConnect, AddMailBox, AddForward,
              DeleteMailBox, DeleteForward, IdentifyCaller =>
                { WriteString["individual."L]; wanted ← individual };
              ReadMembers, ReadOwners, ReadFriends, ReadRemark,
              DeleteGroup, ChangeRemark, AddMember, AddOwner,
              AddFriend, DeleteMember, DeleteOwner, DeleteFriend,
              AddSelf, DeleteSelf, AddListOfMembers =>
                 { wanted ← group; WriteString["group."L] };
            ENDCASE => { wanted ← either; WriteString["name."L] };
            IF rc.type = notFound THEN ProposeName[handle, name, wanted];
            END;
       END;
     BadPassword =>
       WriteString["incorrect password."L];
     WrongServer =>
       WriteString["wrong-server: consult LaurelSupport.pa."L];
     AllDown =>
       WriteString["couldn't contact needed server.  Try later."L];
     noChange =>
       BEGIN
       Val: PROC[s: STRING] =
         { WriteChar['"]; WriteString[value]; WriteString[""" is "L];
           WriteString[s]; WriteString[" of """L]; WriteString[name];
           WriteChar['"] };
       SELECT op FROM
         AddMember =>
           Val["already a member"L];
         AddMailBox =>
           Val["already a mailbox-site"L];
         AddForward =>
           Val["already a forwardee"L];
         AddOwner =>
           Val["already an owner"L];
         AddFriend =>
           Val["already a friend"L];
         DeleteMember =>
           Val["not a member"L];
         DeleteMailBox =>
           Val["not a mailbox-site"L];
         DeleteForward =>
           Val["not a forwardee"L];
         DeleteOwner =>
           Val["not an owner"L];
         DeleteFriend =>
           Val["not a friend"L];
         AddSelf =>
           WriteString["you're already a member of that group."L];
         DeleteSelf =>
           WriteString["you're not a member of that group."L];
       ENDCASE =>
         WriteString["no-change: consult LaurelSupport.pa."L];
       END;
   ENDCASE =>
     WriteString["bad return-code: consult LaurelSupport.pa."L];
   IF rc.code # done THEN ERROR MaintainPrivate.Failed[];
   END;

ProposeName: PUBLIC PROC[handle: MaintainPrivate.Handle,
                         name: BodyDefs.RName,
                         wanted: MaintainPrivate.ProposalType] =
   BEGIN
   OPEN handle.glass;
   dotDL: BOOLEAN ← FALSE;
   IF name.length = 0 THEN RETURN;
   IF name[0] = '. OR name[0] = '↑ THEN RETURN;
   IF name[0] = '@
   THEN { WriteString["  ""Maintain"" doesn't handle ""@"" distribution lists."L]; RETURN };
   IF wanted = either
   THEN FOR i: CARDINAL IN [0..name.length)
        DO IF name[i] = '↑ THEN wanted ← group; ENDLOOP;
   IF name.length >= 3
   AND name[name.length-3] = '.
   AND String.LowerCase[name[name.length-2]] = 'd
   AND String.LowerCase[name[name.length-1]] = 'l
   THEN BEGIN
        dotDL ← TRUE;
        IF wanted = either THEN wanted ← group;
        END;
   BEGIN
        ENABLE String.StringBoundsFault => CONTINUE;
        newName: BodyDefs.RName = [BodyDefs.maxRNameLength];
        dot: BOOLEAN;
        GenerateName: PROC[group: BOOLEAN] RETURNS[ok: BOOLEAN] =
           BEGIN
           newName.length ← 0;
           dot ← FALSE;
           FOR j: CARDINAL IN [0..name.length)
           DO IF name[j] = '.
              THEN BEGIN
                   IF dotDL THEN EXIT;
                   dot ← TRUE;
                   IF group THEN String.AppendChar[newName, '↑];
                   END;
              IF name[j] # '↑ THEN String.AppendChar[newName, name[j]];
           ENDLOOP;
           IF NOT dot
           THEN BEGIN
                IF group THEN String.AppendChar[newName, '↑];
                FOR k: CARDINAL DECREASING
                IN [0..handle.caller.length)
                DO IF handle.caller[k] = '.
                   THEN BEGIN
                        FOR x: CARDINAL IN [k..handle.caller.length)
                        DO String.AppendChar[newName, handle.caller[x]] ENDLOOP;
                        EXIT
                        END;
                ENDLOOP;
                END;
           BEGIN
              info: NameInfoDefs.StampInfo = NameInfoDefs.CheckStamp[newName];
              IF (ok ← SELECT info FROM
                    notFound => FALSE,
                    allDown => FALSE,
                    individual => NOT group,
                    group => group,
                  ENDCASE => ERROR)
              THEN BEGIN
                   WriteString["  """L];
                   WriteString[newName];
                   WriteString[""" is a valid "];
                   WriteString[IF group THEN "group."L ELSE "individual."L];
                   name.length ← 0; String.AppendString[name, newName];
                   END;
           END;
           END;
        proposed: BOOLEAN ← FALSE;
        IF wanted # individual AND GenerateName[TRUE] THEN proposed ← TRUE;
        IF wanted # group AND GenerateName[FALSE] THEN proposed ← TRUE;
        IF NOT proposed AND NOT dot
        THEN BEGIN
             WriteString["  Names should be of the form ""firstPart.Registry"""L];
             IF wanted # individual
             THEN WriteString[" or ""firstPart↑.Registry"""L];
             WriteChar['.];
             END;
   END;
   END;

END.