NSExecImpl.mesa
Copyright (C) 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Tim Diebert: December 11, 1986 1:22:02 pm PST
DIRECTORY
CHNameP2V0 USING [Name],
IO USING [STREAM],
NSString USING [AppendString, CopyString, EquivalentStrings, FreeString, LogicalLength, MakeString, nullString, ScanForCharacter, String, StringFromMesaString],
NSExec,
NSTTY USING [PutLine, SetPagination],
Process USING [Detach],
Rope USING [FromRefText, ROPE],
TTY USING [Handle, NewLine, PutCR, PutLine, PutString, UserAbort],
TTYExtras USING [],
XFormat USING [Handle],
XNS USING [Address, unknownAddress],
XNSAuth USING [Identity];
NSExecImpl: CEDAR MONITOR
IMPORTS NSExec, NSString, NSTTY, Rope, TTY, TTYExtras
EXPORTS NSExec
= BEGIN
OPEN CHName: CHNameP2V0;
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Copied Types
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Types
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Handle: PUBLIC TYPE = RECORD [session: CARDINAL];
Client: TYPE = REF ClientData;
ClientData: TYPE = RECORD [
name: NSString.String ← NSString.nullString, -- generic name of this client
command: NSExec.Command, -- the "primary" command registered to identify the client in the NSExec and executed by the user to switch to the client's context.
acronym: NSString.String ← NSString.nullString,
id: NSExec.ClientID,
procs: NSExec.ClientProcs,
initialized: BOOLEANFALSE,
next: Client ← NIL]; -- pointer to next node in list
ExecData: TYPE = REF RECORD [data: SEQUENCE length: CARDINAL OF ExecObject];
ExecObject: TYPE = RECORD [
tty: TTY.Handle,
output: XFormat.Handle,
currentClient: Client ← NIL,
okForAsyncMessage: BOOLEANFALSE, -- between commands
qTop: CARDINAL ← 0, -- index of first free queue slot in asyncQ
asyncQList: AsyncQList,
hostName: NSString.String ← NSString.nullString, -- of connected m/c
user: SELECT loggedOnStatus: * FROM
loggedOn => [
userName: CHName.Name ← [NIL, NIL, NIL],
userIdentity: XNSAuth.Identity ← NIL,
userFilingSession: NSFile.Session ← NSFile.nullSession,
userAServerSA, userEnabled: BOOLEANFALSE],
notLoggedOn => NULL,
ENDCASE ← notLoggedOn[]];
AsyncQList: TYPE = RECORD[q: QArray];
QArray: TYPE = ARRAY [0..qSize) OF QEntry;
QEntry: TYPE = RECORD [time: CARD ← 0, message: NSString.String ← NIL];
qSize: CARDINAL = 3;
ActiveServices: TYPE = REF ActiveStatus;
ActiveStatus: TYPE = RECORD [name: NSString.String, next: ActiveServices];
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Constants :
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Variables :
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
localExec: PUBLIC READONLY Handle; -- handle for the local TTY
totalClients: CARDINAL ← 0;
firstClient: PUBLIC Client ← NIL;
execData: ExecData ← NIL;
serverName: CHName.Name ← [NIL, NIL, NIL];
serverDesc: NSString.String ← NSString.nullString;
serverIdentity: XNSAuth.Identity;
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Errors:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Error: PUBLIC ERROR [type: NSExec.Errortype] = CODE;
NotFound: ERROR = CODE;
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Creating and Manipulating Exec Clients:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
AssignClientID: PUBLIC ENTRY PROCEDURE RETURNS [NSExec.ClientID] = {
ENABLE UNWIND => NULL; RETURN[[totalClients ← totalClients + 1]]};
CreateClient: PUBLIC ENTRY PROCEDURE [id: NSExec.ClientID, command: NSExec.Command,
procs: NSExec.ClientProcs, acronym: NSString.String] = BEGIN
ENABLE UNWIND => NULL;
IF NOT ValidID[id] THEN RETURN WITH ERROR NSExec.Error[invalidID];
IF command.name.length = 0 OR acronym.length = 0 THEN
RETURN WITH ERROR NSExec.Error[invalidString];
BEGIN
clientName: NSString.String ← NSString.CopyString[command.name];
firstClient ← NEW[ClientData ← [name: clientName,
command: [clientName, command.proc, command.activityCheck, command.helpProc],
acronym: NSString.CopyString[acronym], id: id, procs: procs,
next: firstClient]];
END;
END; -- CreateClient
DestroyClient: PUBLIC ENTRY PROCEDURE [id: NSExec.ClientID] = BEGIN
ENABLE UNWIND => NULL;
client, predecessor: Client;
[client, predecessor] ← FindClient[id ! NotFound => ERROR NSExec.Error[invalidID]];
RemoveClientCommands[id];
IF predecessor = NIL THEN firstClient ← client.next ELSE predecessor.next ← client.next;
END; -- DestroyClient
EnumerateClients: PUBLIC PROCEDURE [enumProc: NSExec.EnumerateClientProc] = BEGIN
continue: BOOLEANTRUE;
FOR client: Client ← firstClient, client.next UNTIL client = NIL OR NOT continue DO
IF ~client.initialized THEN LOOP;
continue ←
enumProc[client.id, client.command, Rope.FromRefText[client.acronym], client.procs]
ENDLOOP;
END; -- EnumerateClients
ClientState: PUBLIC PROCEDURE [id: NSExec.ClientID]
RETURNS
[activated, initialized: BOOLEAN] = BEGIN
client: Client ← FindClient[id ! NotFound => ERROR NSExec.Error[invalidID]].client;
activated ← Activated[client.name];
initialized ← client.initialized;
END; -- ClientState
AddClientCommands: PUBLIC PROCEDURE [id: NSExec.ClientID, commands: NSExec.Commands] = BEGIN
ENABLE UNWIND => NULL;
client: Client ← FindClient[id ! NotFound => ERROR NSExec.Error[invalidID]].client;
FOR i: CARDINAL IN [0..commands.length) DO
AddCommand[commands[i], client] ENDLOOP
END; -- AddClientCommands
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Creating and Manipulating Execs:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
CreateExec: PUBLIC PROCEDURE [tty: TTY.Handle, host: XNS.Address] = BEGIN
ENABLE ABORTED => CONTINUE;
<< ASSERT: 1) All calls to this proc are for OTHER than the local exec. 2) The server profile has been established. >>
TTYExtras.SetDataFile[tty, LOOPHOLE[UserProfile.GetEnumeratedValue[[XM[keyServer], XM[keyRemoteTerminalType]]]]];
DisplayHerald[tty: tty, displayTime: FALSE]; -- may raise ABORTED
ExecProcess[CreateExecInternal[tty, host].exec];
END; -- CreateExec
EnumerateExecs: PUBLIC PROCEDURE [enumProc: NSExec.EnumerateExecProc] = {};
Aborted: SIGNAL = CODE;
EnumerateProc: NSSession.EnumerateProc = {
proc: PROCEDURE = {IF ~enumProc[LOOPHOLE[session]] THEN SIGNAL Aborted};
EnterSessionAndExecute[session, proc ! NSSession.Error => CONTINUE]};
NSSession.Enumerate[sessionId, EnumerateProc ! Aborted => CONTINUE]};
AddExecCommand: PUBLIC PROCEDURE [command: NSExec.Command,
unload: PROCEDURENIL] =
BEGIN AddCommand[command: command, client: NIL, unload: unload]; END; -- AddExecCommand
RemoveExecCommand: PROCEDURE [name: NSString.String];
removes name as an exec command, having no effect if name is not a command.
GetTTY: PUBLIC PROCEDURE [exec: NSExec.Handle] RETURNS [tty: TTY.Handle] = {
RETURN[execData.data[exec.session].tty]};
CheckForAbort: PUBLIC PROCEDURE [exec: NSExec.Handle] RETURNS [abort: BOOLEAN] =
{RETURN[TTY.UserAbort[NSExec.GetTTY[exec]]]};
SetContext: PUBLIC PROCEDURE [exec: Handle, id: NSExec.ClientID, context: NSExec.Context,
terminationHandler: NSExec.TerminationHandler] = BEGIN
noContext: BOOLEANFALSE;
newContext: LONG POINTER TO ClientContext;
IF ~NSExecInternal.ValidID[id] THEN NSExec.Error[invalidID];
newContext ← NSSession.GetContext[exec, sessionId, id ! NSSession.Error => {noContext ← TRUE; CONTINUE}];
IF noContext THEN
newContext ← NEW[
ClientContext ← [
clientData: context, clientTerminateProc: terminationHandler]]
ELSE
newContext^ ← [clientData: context, clientTerminateProc: terminationHandler];
NSSession.SetContext[exec, sessionId, newContext, TerminationHandler, id];
END; -- SetContext
GetContext: PUBLIC PROCEDURE [exec: Handle, id: NSExec.ClientID]
RETURNS
[context: LONG UNSPECIFIED] = BEGIN
clientContext: LONG POINTER TO ClientContext;
IF ~NSExecInternal.ValidID[id] THEN NSExec.Error[invalidID];
clientContext ← NSSession.GetContext[exec.session, sessionId, LOOPHOLE[id]
! NSSession.Error => IF type = notSet THEN NSExec.Error[noContextSet]];
RETURN[clientContext.clientData];
RETURN[LONG[0]];
END; -- of GetContext
DestroyContext: PUBLIC PROCEDURE [exec: Handle, id: NSExec.ClientID] = BEGIN
IF ~NSExecInternal.ValidID[id] THEN NSExec.Error[invalidID];
NSSession.DestroyContext[exec, sessionId, id ! NSSession.Error => GOTO NoContext];
EXITS NoContext => ERROR NSExec.Error[noContextSet];
END; -- of DestroyContext
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
String Output:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
BroadcastAsyncMessage: PUBLIC PROCEDURE [string: NSString.String, id: NSExec.ClientID] = {
broadcastMessage: NSExec.EnumerateExecProc = {PutAsyncMessage[exec, string, id]};
NSExec.EnumerateExecs[broadcastMessage]}; -- of BroadcastAsyncMessage
PutAsyncMessage: PUBLIC PROCEDURE [exec: NSExec.Handle, string: NSString.String,
id: NSExec.ClientID] = BEGIN
client: Client ← FindClient[id ! NotFound => ERROR NSExec.Error[invalidID]].client;
msg: NSString.String ← NSString.MakeString[client.acronym.length + 2 + string.length];
tty: TTY.Handle; -- should be initialized within the catch phase for NSSession.Error
BEGIN ENABLE --NSSession.Error, --ABORTED => {NSString.FreeString[msg]; CONTINUE};
msg ← NSString.AppendString[msg, client.acronym];
msg ← NSString.AppendString[msg, NSString.StringFromMesaString[": "]];
msg ← NSString.AppendString[msg, string];
IF TTY.NewLine[tty ← NSExec.GetTTY[exec]] OR OkForAsyncMsg[exec]
THEN {
oldPageLength: CARDINALNSTTY.SetPagination[h: tty, pageLength: 0]; -- eliminates (more)
PutMessage[exec, msg];
[] ← NSTTY.SetPagination[h: tty, pageLength: oldPageLength];
NSString.FreeString[msg]}
ELSE TRUSTED {Process.Detach[FORK PutAsyncMessageEntry[exec, msg]]};
END; -- ENABLE
END; -- PutAsyncMessage
PutErrorMessage, PutIndentedMessage: PUBLIC PROCEDURE [exec: NSExec.Handle,
string: NSString.String] = BEGIN
tty: TTY.Handle ← NSExec.GetTTY[exec];
IF ~TTY.NewLine[tty] THEN TTY.PutCR[tty];
TTY.PutString[tty, " "];
NSTTY.PutLine[tty, string];
END; -- PutErrorMessage, PutIndentedMessage
PutMessage: PUBLIC PROCEDURE [exec: NSExec.Handle, string: NSString.String] = BEGIN
tty: TTY.Handle ← NSExec.GetTTY[exec];
IF ~TTY.NewLine[tty] THEN TTY.PutCR[tty];
NSTTY.PutLine[tty, string];
END; -- PutMessage
OutputHandle: PUBLIC PROCEDURE [exec: NSExec.Handle]
RETURNS [output: XFormat.Handle] = {RETURN[(execData[exec.session].output)]};
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
User Data:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
UserName: PUBLIC PROCEDURE [exec: NSExec.Handle] RETURNS [name: CHName.Name ← [NIL, NIL, NIL]] = {RETURN[LoggedOnData[exec].userName]};
UserIdentity: PUBLIC PROCEDURE [exec: NSExec.Handle]
RETURNS
[identity: XNSAuth.Identity] = {RETURN[LoggedOnData[exec].userIdentity]};
UserFilingSession: PROCEDURE [exec: Handle] RETURNS [session: NSFile.Session];
UserState: PUBLIC PROCEDURE [exec: NSExec.Handle]
RETURNS [loggedOn, serverSA, enabled: BOOLEANFALSE] = TRUSTED {
data: ExecObject = execData[exec.session];
WITH d: data SELECT FROM
loggedOn => {loggedOn ← TRUE; serverSA ← d.userAServerSA; enabled ← d.userEnabled};
ENDCASE => NULL;
};
UserAServerSA: PUBLIC NSExec.Predicate = {RETURN[UserState[exec].serverSA]};
UserEnabled: PUBLIC NSExec.Predicate = {RETURN[UserState[exec].enabled]};
UserLoggedOn: PUBLIC NSExec.Predicate = {RETURN[UserState[exec].loggedOn]};
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Genesis:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
These predicates are used when commands should be available during Genesis.
Genesis: PUBLIC NSExec.Predicate = {RETURN[FALSE]};
GenesisOrEnabledSA: PUBLIC NSExec.Predicate = {RETURN[TRUE]};
GenesisOrSA: PUBLIC NSExec.Predicate = {RETURN[TRUE]};
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Server and System Data:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
ServerName: PUBLIC PROCEDURE RETURNS [name: CHName.Name] = {
RETURN[serverName]};
ServerIdentity: PUBLIC PROCEDURE RETURNS [identity: XNSAuth.Identity] = {
RETURN[serverIdentity]};
SystemFilingSession: PROCEDURE RETURNS [session: NSFile.Session];
SystemDirectory: PUBLIC PROCEDURE RETURNS [directory: Rope.ROPE] = {
RETURN["///System/"]};
WorkingDirectory: PUBLIC PROCEDURE RETURNS [directory: Rope.ROPE] = {
RETURN["///Working/"]};
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Running Additional Software:
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Run: PROCEDURE [name: ROPE, exec: Handle, codeLinks: BOOLEANFALSE] = {};
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Local Procedures
-- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
Activated: PUBLIC --NSExecInternal-- PROCEDURE [name: NSString.String]
RETURNS
[BOOLEANFALSE] = BEGIN
FOR s: ActiveServices ← activeServices, s.next UNTIL s = NIL DO
IF NSString.EquivalentStrings[name, s.name] THEN RETURN[TRUE];
ENDLOOP;
END; -- Activated
AddCommand: ENTRY PROCEDURE [command: NSExec.Command,
client: Client, clientName: BOOLEANFALSE,
unload: PROCEDURENIL] = BEGIN
ENABLE UNWIND => NULL;
length: CARDINAL ← NSString.LogicalLength[command.name];
pos, offset: CARDINAL ← 0;
list: Entry ← topEntry;
commandWord: NSString.SubStringDescriptor;
IF length = 0 THEN ERROR NSExec.Error[invalidString];
DO
pos ← NSString.ScanForCharacter[c: [0, LOOPHOLE[Ascii.SP]], s: command.name, start: offset];
SELECT pos FROM
offset => {offset ← offset + 1; LOOP}; -- skip spaces
LAST[CARDINAL] => {
commandWord ← [command.name, offset, length - offset];
list ← InsertWordInList[list, commandWord];
EXIT};
ENDCASE => {
commandWord ← [command.name, offset, pos - offset];
list ← InsertWordInList[list, commandWord];
offset ← pos + 1};
ENDLOOP;
BEGIN -- begin exits DuplicateCommand
IF clientName
THEN {IF list.commandProcs # NIL
THEN GOTO DuplicateCommand
ELSE {list.commandProcs ← NEW[clientName ProcData ← [
execute: command.proc, activityProc: command.activityCheck,
helpProc: command.helpProc, commandType: clientName[client]]]}}
ELSE BEGIN
p: NSExecInternal.Procs;
FOR p ← list.commandProcs, p.next UNTIL p = NIL DO
WITH commandProc: p SELECT FROM
exec, clientName => GOTO DuplicateCommand;
client => IF commandProc.client = client THEN GOTO DuplicateCommand;
ENDCASE
ENDLOOP;
IF client = NIL
THEN -- exec command
p ← NEW[exec ProcData ← [execute: command.proc,
activityProc: command.activityCheck, helpProc: command.helpProc, commandType: exec[unload]]]
ELSE -- client command
p ← NEW[client ProcData ← [next: list.commandProcs, execute: command.proc,
activityProc: command.activityCheck, helpProc: command.helpProc,
commandType: client[client]]];
list.commandProcs ← p;
END;
EXITS
DuplicateCommand => {
s: LONG STRING ← [128];
nss: NSString.String ← NSString.StringFromMesaString[s];
o: XFormat.Object ← XFormat.NSStringObject[@nss];
SCSCommon.FormatExpandedMsg[@o, M[keyDuplicateCommand], command.name];
NSExec.BroadcastAsyncMessage[nss, NSExec.nullClientID]};
END; -- of exits DuplicateCommand
END; -- AddCommand
CreateExecInternal: PUBLIC PROCEDURE [tty: TTY.Handle,
hostName: XNS.Address ← XNS.unknownAddress]
RETURNS
[exec: Handle, execData: ExecData] = BEGIN
nss: NSString.String ← NSString.MakeString[100];
object: XFormat.Handle ← XFormat.NSStringObject[nss];
asyncQ: AsyncQList;
XFormat.NetworkAddress[object, hostName, productSoftware];
execData ← NEW[ExecObject ← [tty: tty, asyncQList: asyncQ, output: XFormat.TTYObject[tty],
hostName: NSString.CopyString[nss]]];
exec.session ← NSSession.Create[id: sessionId, name: NIL];
NSSession.SetContext[exec.session, sessionId, execData];
END; -- of CreateExecInternal
DisplayHerald: PUBLIC -- NSExecInternal -- PROCEDURE [tty: TTY.Handle, displayTime: BOOLEANTRUE] = BEGIN
o: XFormat.Handle ← XFormat.TTYObject[tty];
PutHerald: PROCEDURE [s: NSString.String] = {NSTTY.PutString[tty, s]};
PutBcdTime: PROCEDURE = BEGIN
XFormat.Date[h: o, time: Loader.BCDBuildTime[DisplayHerald]];
END; -- PutBcdTime
beginning of DisplayHerald
TTY.PutCR[tty];
NSHerald.GetExecHerald[PutHerald];
NSTTY.PutString[tty, " of "];
PutBcdTime[];
IF displayTime THEN XFormat.Date[o, BasicTime.Now[], dateAndTime];
TTY.PutCR[tty];
NSHerald.GetCopyrightMsg[PutHerald];
END; -- DisplayHerald
ExecProcess: PUBLIC PROCEDURE [exec: Handle] = BEGIN
ENABLE UNWIND => {}; -- FreeExecData[exec];
[] ← NSTTY.SetPagination[NSExec.GetTTY[exec], 23];
IF NSExec.ServerName[] # NIL AND exec # LOOPHOLE[NSExec.localExec] THEN
DisplayServerName[exec]; -- may raise ABORTED
ProcessCommands[exec];
FreeExecData[exec];
END; -- ExecProcess
FindClient: PUBLIC --NSExecInternal-- PROCEDURE [id: CARDINAL]
RETURNS
[client, predecessor: Client ← NIL] = BEGIN
FOR client ← firstClient, client.next UNTIL client = NIL DO
IF client.id = id THEN RETURN; predecessor ← client; ENDLOOP;
ERROR NotFound;
END; -- FindClient
LoggedOnData: PROCEDURE [exec: Handle] RETURNS [REF loggedOn ExecObject] = {
data: ExecObject = execData[exec];
WITH d: data SELECT FROM
loggedOn => {data: REF loggedOn ExecObject ← d; RETURN[data]};
ENDCASE => NSExec.Error[noUser]};
OkForAsyncMsg: PROC [exec: Handle] RETURNS [okForAsyncMessage: BOOLEANFALSE] = {
proc: ExecDataProc = {okForAsyncMessage ← execData.okForAsyncMessage};
Execute[exec, proc];
};
PutAsyncMessageEntry: ENTRY PROCEDURE [exec: Handle, s: NSString.String] = BEGIN
ENABLE UNWIND => NULL;
ENABLE {UNWIND => NULL; NSSession.Error => CONTINUE};
MustDisplayQ: PROCEDURE RETURNS [BOOLEANFALSE] = BEGIN
IF qTop = NSExecInternal.qSize -- queue is full
OR PulsesToMilliSec[System.GetClockPulses[]] - PulsesToMilliSec[
asyncQ[qTop - 1].time] >= longAsyncDelayInMilliSec -- queue is old
THEN RETURN[TRUE];
END; -- of MustDisplayQ
tty: TTY.Handle = NSExec.GetTTY[exec]; -- raises NSSession.Error if the exec has already been destroyed.
qTop: CARDINAL ¬ GetQTop[exec];
qEntry: NSExecInternal.QEntry ¬ [
time: System.GetClockPulses[], message: s];
asyncQ: NSExecInternal.AsyncQList;
IF TTYAborted[tty] THEN RETURN;
SetQTop[exec, qTop ← qTop + 1];
SetQEntry[exec, qEntry];
asyncQ ¬ GetAsyncQ[exec];
BEGIN ENABLE ABORTED => CONTINUE; -- can be raised by ANY call to TTY
output msgs if we are between commands, between output lines, or the queue is full
IF OkForAsyncMsg[exec] OR TTY.NewLine[tty] OR MustDisplayQ[] THEN
DisplayQ[exec, qTop, asyncQ];
END; -- ENABLE
END; -- PutAsyncMessageEntry
ValidID: PUBLIC --NSExecInternal-- PROCEDURE [id: NSExec.ClientID]
RETURNS [BOOLEAN] = {RETURN[id IN [1..totalClients]]};
END.
LOG [Time - Person - Action]
14-Nov-83 8:54:49 - McManis - Created file.
3-Jan-84 15:16:44 - McManis - Added nullHandle, nullClientID, Context and TerminationHandler. Changed SetContext and GetContext to use Context and TerminationHandler. Renamed OutputObject to OutputHandle and changed it to return XFormat.Handle. Changed CreateExec to take "host: System.NetworkAddress" rather than credentials.
29-Apr-85 15:52:51 - McManis - Added cannotExpunge and cannotInitialize to ErrorType. Removed notInitialized from ClientStatus. Added predicates for Genesis.