/***************************************************************************** /* CLI.c Module to process (interpret) the HTTPD command line. Allows images activated by a "foreign verb" to behave in a way that approximates the CLI$ (Command Line Interpreter) utility calls. VERSION HISTORY --------------- 19-OCT-2017 MGD add /NOTE= annotate server process log 21-JUN-2017 MGD add /INSTANCE=CONFIG ensure config file values used 07-JUL-2016 MGD ParseCommandInteger() accept just an integer 24-JUL-2015 MGD bugfix; ParseCommand() parenthesis parsing 05-OCT-2009 MGD remove /FILBUF 11-JUL-2009 MGD add /ENV= 25-MAY-2005 MGD add /VALBLK[=16|64] 15-APR-2004 MGD obsolete /LOCK 19-JUL-2003 MGD add /[NO]NETWORK 03-MAY-2003 MGD add /SYSUAF=VMS keyword 30-JAN-2003 MGD add /PROFILE=NORULE keyword 23-SEP-2002 MGD add /SCRIPT=AS= 16-SEP-2002 MGD add /PERSONA[=RELAXED|AUTHORIZED|RELAXED=AUTHORIZED], rework qualifier keyword parsing 05-MAY-2002 MGD add /DEMO catch-all for freeware demo use, etc., /GBLSEC=NOPERM for no permanent global section 29-SEP-2001 MGD add /[NO]INSTANCE[=integer] number of per-node instances, /CLUSTER[=integer] grouping (changed from [=resname]) 20-MAY-2001 MGD add /GBLSEC=DELETE= 23-FEB-2001 MGD add /SYSUAF=PROXY 20-DEC-2000 MGD add /PROXY= 02-OCT-2000 MGD add /DETACH, /IDENT=, /PERSONA=, /USER= 18-JUN-2000 MGD add /ALL[=resname] 02-JAN-2000 MGD add /[NO]ODS5, ability to use HTTPD$PARAM 30-OCT-1999 MGD add /SYSPRV 29-SEP-1999 MGD change /SYSUAF= ALL to RELAXED (backward-compatible) 30-JUL-1999 MGD bugfix; /SYSUAF does not need a parameter! 26-MAY-1999 MGD /SSL= now takes a string parameter 24-FEB-1998 MGD /AUTH=ALL, /AUTH=(SSL,ALL), /SYSUAF=WASD_ID 07-NOV-1998 MGD /[NO]WATCH= 07-AUG-1998 MGD /PROMISCUOUS[=password] 06-JUL-1998 MGD v5.1, /SYSUAF=ID 11-MAR-1998 MGD /SYSUAF=(SSL,ALL) 04-FEB-1998 MGD v5.0, /SSL, /SYSUAF=SSL 11-OCT-1997 MGD v4.5, /CACHE, /VERSION 06-SEP-1997 MGD v4.4, /FORMAT, /PROFILE, /SYSUAF, /SOFTWAREID 01-FEB-1997 MGD HTTPd version 4 01-DEC-1995 MGD HTTPd version 3 20-DEC-1994 MGD multi-threaded daemon 20-JUN-1994 MGD single-threaded daemon */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif /* standard C header files */ #include #include #include #include /* VMS header files */ #include #include #include #include #include "wasd.h" #define WASD_MODULE "CLI" /******************/ /* global storage */ /******************/ BOOL CliCacheDisabled, CliCacheEnabled, CliDemo, CliDetach, CliGblSecDelete, CliGblSecNoPerm, CliInstanceConfig, CliInstanceNoCrePrc, CliInstancePassive, CliLoggingDisabled, CliLoggingEnabled, CliMonitorDisabled, CliMonitorEnabled, CliNetworkMode, CliNoNetworkMode, CliOdsExtendedDisabled, CliOdsExtendedEnabled, CliPersonaAuthorized, CliPersonaEnabled, CliPersonaRelaxed, CliPersonaRelaxedAuthorized, CliSoftwareID, CliTests, CliVersion; int CliInstanceMax, CliLockValueBlockSize, CliServerPort; char CommandLine [256], CliParameter [256], CliProcessIdentName [64], CliProxyMaint [128], CliServices [256], CliScriptAs [64], CliUserName [64]; char *CliAcceptHostsPtr = NULL, *CliRejectHostsPtr = NULL; /********************/ /* external storage */ /********************/ #ifdef DBUG extern BOOL Debug; #else #define Debug 0 #endif extern BOOL AccountingZeroOnStartup, AuthPromiscuous, AuthPolicyAuthorizedOnly, AuthPolicySslOnly, AuthPolicySysUafProxy, AuthPolicySysUafSslOnly, AuthPolicySysUafRelaxed, AuthPolicySysUafIdentifiers, AuthPolicySysUafVms, AuthPolicySysUafWasdIdentifiers, AuthSysUafEnabled, AuthSysUafPromiscuous, AuthVmsUserProfileNoRule, AuthVmsUserProfileEnabled, ControlDoAllHttpd, NoSwapOut, OperateWithSysPrv; extern int DclCgiPlusInSize, DclSysCommandSize, DclSysOutputSize, DclCgiVariablePrefixLength, InstanceEnvNumber, NetReadBufferSize, OutputBufferSize, ProcessPriority, ServerPort; extern int ToLowerCase[], ToUpperCase[]; extern char *AuthPromiscuousPwdPtr; extern char ControlBuffer[], DclCgiVariablePrefix[], HttpdServerNote[], LoggingFileName[], LoggingFormatUser[], LoggingPeriodName[], PersonaIdentName[], SesolaParams[], SoftwareID[]; extern HTTPD_PROCESS HttpdProcess; /****************************************************************************/ /* This function allows images activated by a "foreign verb" to behave in a way that approximates the CLI$ (Command Line Interpreter) utility calls. Get the entire command line following the verb that activated the image. The command line is returned in uppercase, space compressed (i.e. maximum of one space between text elements, trimmed of leading and trailing spaces). Returns a warning status if there were no parameters/qualifiers on the command line. The variable CommandLine is global. */ int ParseCommandLine () { int status; unsigned short Length; unsigned long Flags = 0; char *cptr; $DESCRIPTOR (CommandLineDsc, CommandLine); if (!(cptr = getenv ("WASD_HTTPD_PARAM")) && !(cptr = getenv ("HTTPD$PARAM"))) { /* get the entire command line following the verb */ if (VMSnok (status = lib$get_foreign (&CommandLineDsc, 0, &Length, &Flags))) return (status); CommandLine[Length] = '\0'; } else { strncpy (CommandLine, cptr, sizeof(CommandLine)); CommandLine[sizeof(CommandLine)-1] = '\0'; } if (ParseCommand (CommandLine)) return (SS$_NORMAL); else return (STS$K_ERROR | STS$M_INHIB_MSG); } /****************************************************************************/ /* This function allows images activated by a "foreign verb" to behave in a way that approximates the CLI$ (Command Line Interpreter) utility calls. Quoted strings are always indicated by being parsed to include a single leading quote. */ BOOL ParseCommand (char *CommandLine) { BOOL CommandLineOK = true; int ParenCount = 0, QuoteCount = 0; char *cptr, *eptr, *zptr; char Entity [1024] = ""; /* set up any argument defaults */ ParseCommandEntity (NULL); cptr = CommandLine; zptr = (eptr = Entity) + sizeof(Entity)-1; for (;;) { if (eptr >= zptr) exit (SS$_RESULTOVF); if (*cptr == '\"') { QuoteCount++; *eptr++ = *cptr++; continue; } if (QuoteCount & 1 && *cptr) { /* inside quoted text, copy all characters as literals */ *eptr++ = *cptr++; continue; } if (*cptr == '(') { ParenCount++; *eptr++ = *cptr++; continue; } if (ParenCount && *cptr) { if (*cptr == ')') ParenCount--; *eptr++ = *cptr++; continue; } if ((Entity[0] && *cptr == '/') || ISLWS (*cptr) || !*cptr) { if (eptr >= zptr) exit (SS$_RESULTOVF); while (*cptr && ISLWS (*cptr)) cptr++; *eptr = '\0'; if (Entity[0]) if (!ParseCommandEntity (Entity)) CommandLineOK = false; if (!*cptr) break; /* start of new entity */ eptr = Entity; continue; } /* just copy any other character */ *eptr++ = *cptr++; } if (QuoteCount & 1) { FaoToStdout ("%HTTPD-E-QUOTES, unbalanced quotes\n"); return (false); } if (ParenCount) { FaoToStdout ("%HTTPD-E-PARENS, unbalanced parentheses\n"); return (false); } return (CommandLineOK); } /*****************************************************************************/ /* Get a string value from a qualifier, e.g. '/EXAMPLE=TEST'. */ BOOL ParseCommandString ( char *Entity, char *String, BOOL Qualifier, BOOL ReportErrors, BOOL EnsureUpperCase ) { int QuoteCount = 0; char *eptr, *sptr; eptr = Entity; if (Qualifier) { /* scan down to equate symbol */ while (*eptr && *eptr != '=') eptr++; if (*eptr) eptr++; if (!*eptr) { if (ReportErrors) FaoToStdout ("%HTTPD-E-VALREQ, \ missing qualifier or keyword value\n \\!AZ\\\n", Entity+1); return (false); } } sptr = String; while (*eptr) { if (*eptr == '\"') { if (QuoteCount & 1) { /* are inside quotes, check for escaped quotes ("") */ if (*++eptr != '\"') { /* now outside quotes */ QuoteCount++; } /* drop thru to character copy */ } else { /* now inside quotes */ QuoteCount++; eptr++; continue; } } if (ISLWS(*eptr) && !(QuoteCount & 1)) eptr++; else if (EnsureUpperCase) *sptr++ = TOUP(*eptr++); else *sptr++ = *eptr++; } *sptr = '\0'; return (true); } /*****************************************************************************/ /* Get an integer value from a qualifier, e.g. '/EXAMPLE=99'. */ BOOL ParseCommandInteger ( char *Entity, int *IntegerPtr, int Base, BOOL ReportErrors ) { char *eptr, *sptr; /* if not in the form /= assume just an integer */ if (*(eptr = Entity) == '/') { while (*eptr && *eptr != '=') eptr++; if (*eptr) eptr++; } if (*eptr) { *IntegerPtr = strtol (eptr, &sptr, Base); if (sptr > eptr && !*sptr) return (true); else { if (ReportErrors) FaoToStdout ("%HTTPD-E-BADVALUE, \ '!AZ' is an invalid keyword value\n", eptr); return (false); } } else { if (ReportErrors) { FaoToStdout ("%HTTPD-E-VALREQ, \ missing qualifier or keyword value\n \\!AZ\\\n", Entity+1); } return (false); } } /*****************************************************************************/ /* A single command line "entity" has been parsed, check if its recognised. This function is the one modified for the individual requirements of each program. */ BOOL ParseCommandEntity (char *Entity) { BOOL ok; int Length; char Scratch [256]; char *cptr, *sptr, *tptr, *zptr; if (!Entity) { /* set up any argument defaults */ return (true); } ok = false; if (Entity[0] == '/') { if (strsame (Entity, "/ACCEPT=", 4)) { ok = ParseCommandString (Entity, Scratch, true, true, true); for (cptr = Scratch; *cptr && ISLWS(*cptr); cptr++); if (!*cptr) return (ok); CliAcceptHostsPtr = VmGet (Length = strlen(Scratch)+1); memcpy (CliAcceptHostsPtr, Scratch, Length); return (ok); } if (strsame (Entity, "/AUTHORIZE=", 4)) { for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; while (*cptr) { while (*cptr == '(' || *cptr == ',' || *cptr == ')') cptr++; zptr = (sptr = Scratch) + sizeof(Scratch)-1; while (*cptr && *cptr != ',' && *cptr != ')' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (!Scratch[0]) continue; if (strsame (Scratch, "ALL", -1)) AuthPolicyAuthorizedOnly = ok = true; else if (strsame (Scratch, "SSL", -1)) AuthPolicySslOnly = ok = true; else { CliIVKEYW (Scratch); return (false); } } if (!ok) CliVALREQ (Entity); return (true); } if (strsame (Entity, "/CACHE", 4)) { CliCacheEnabled = true; CliCacheDisabled = false; return (true); } if (strsame (Entity, "/NOCACHE", 6)) { CliCacheEnabled = false; CliCacheDisabled = true; return (true); } if (strsame (Entity, "/CGI_PREFIX=", 4)) { ok = ParseCommandString (Entity, DclCgiVariablePrefix, true, true, true); DclCgiVariablePrefixLength = strlen(DclCgiVariablePrefix); return (ok); } if (strsame (Entity, "/CLUSTER=", 4) || strsame (Entity, "/ALL=", 4)) { ControlDoAllHttpd = true; for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (!*cptr) return (true); /* optional grouping number */ return (ParseCommandInteger (Entity, &InstanceEnvNumber, 10, true)); } if (strsame (Entity, "/DCLCGIPLUSIN=", 6)) return (ParseCommandInteger (Entity, &DclCgiPlusInSize, 10, true)); if (strsame (Entity, "/DETACH", 4)) return (CliDetach = true); if (strsame (Entity, "/DO=", 4)) return (ParseCommandString (Entity, ControlBuffer, true, true, false)); #ifdef DBUG /* turns on all "if (Debug)" statements */ if (strsame (Entity, "/DBUG", -1)) return (Debug = true); #endif if (strsame (Entity, "/DEMO", -1)) return (CliDemo = true); if (strsame (Entity, "/ENV=", 4)) return (ParseCommandInteger (Entity, &InstanceEnvNumber, 10, true)); if (strsame (Entity, "/FORMAT=", 4)) return (ParseCommandString (Entity, LoggingFormatUser, true, true, false)); if (strsame (Entity, "/GBLSEC=DELETE", 15)) { CliGblSecDelete = true; return (true); } if (strsame (Entity, "/GBLSEC=NOPERM", 15)) { CliGblSecNoPerm = true; return (true); } if (strsame (Entity, "/IDENT=", 4)) return (ParseCommandString (Entity, CliProcessIdentName, true, true, true)); if (strsame (Entity, "/NOINSTANCE", 6)) return (CliInstanceNoCrePrc = true); if (strsame (Entity, "/INSTANCE=", 4)) { for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; while (*cptr) { while (*cptr == '(' || *cptr == ',' || *cptr == ')') cptr++; zptr = (sptr = Scratch) + sizeof(Scratch)-1; while (*cptr && *cptr != ',' && *cptr != ')' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (!Scratch[0]) continue; if (ok = strsame (Scratch, "CONFIG", 3)) CliInstanceConfig = true; else if (ok = strsame (Scratch, "CPU", 3)) CliInstanceMax = INSTANCE_PER_CPU; else if (ok = strsame (Scratch, "PASSIVE", 3)) CliInstancePassive = true; else if (isdigit(Scratch[0]) || Scratch[0] == '-') { ok = ParseCommandInteger (Scratch, &CliInstanceMax, 10, true); if (ok && CliInstanceMax == 0) CliInstanceMax = -999; } else { CliIVKEYW (Scratch); return (false); } } if (!ok) { CliVALREQ (Entity); return (false); } return (true); } if (strsame (Entity, "/LOG=", 4)) { CliLoggingEnabled = true; CliLoggingDisabled = false; if (Entity[4] == '=') return (ParseCommandString (Entity, LoggingFileName, true, true, true)); else return (true); } if (strsame (Entity, "/NOLOG", 6)) { CliLoggingEnabled = false; CliLoggingDisabled = true; return (true); } if (strsame (Entity, "/MONITOR", 4)) { CliMonitorEnabled = true; CliMonitorDisabled = false; return (true); } if (strsame (Entity, "/NOMONITOR", 6)) { CliMonitorEnabled = false; CliMonitorDisabled = true; return (true); } if (strsame (Entity, "/NETWORK", 5)) { CliNetworkMode = true; CliNoNetworkMode = false; return (true); } if (strsame (Entity, "/NONETWORK", 5)) { CliNetworkMode = false; CliNoNetworkMode = true; return (true); } if (strsame (Entity, "/NETBUF=", 5)) return (ParseCommandInteger (Entity, &NetReadBufferSize, 10, true)); if (strsame (Entity, "/NOTE=", 6)) { strcpy (HttpdServerNote, "/NOTE="); return (ParseCommandString (Entity, HttpdServerNote+6, true, true, false)); } if (strsame (Entity, "/OUTBUF=", 5)) return (ParseCommandInteger (Entity, &OutputBufferSize, 10, true)); if (strsame (Entity, "/PERIOD=", 5)) return (ParseCommandString (Entity, LoggingPeriodName, true, true, false)); if (strsame (Entity, "/PERSONA=", 5)) { for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (!*cptr) return (CliPersonaEnabled = true); cptr++; while (*cptr) { while (*cptr == '(' || *cptr == ',' || *cptr == ')') cptr++; zptr = (sptr = Scratch) + sizeof(Scratch)-1; while (*cptr && *cptr != ',' && *cptr != ')' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (!Scratch[0]) continue; if (strsame (Scratch, "AUTHORIZED", 4)) CliPersonaAuthorized = true; else if (strsame (Scratch, "RELAXED", 5)) { CliPersonaRelaxed = true; for (sptr = Scratch; *sptr && *sptr != '='; sptr++); if (strsame (sptr, "=AUTHORIZED", 5)) CliPersonaRelaxedAuthorized = true; } else if (strsame (Scratch, "IDENT=", 6)) { strcpy (PersonaIdentName, Scratch+6); for (sptr = PersonaIdentName; *sptr; sptr++) *sptr = TOUP(*sptr); } else { strcpy (PersonaIdentName, Scratch); for (sptr = PersonaIdentName; *sptr; sptr++) *sptr = TOUP(*sptr); } } return (CliPersonaEnabled = true); } if (strsame (Entity, "/NOPERSONA", 5)) { CliPersonaAuthorized = CliPersonaEnabled = CliPersonaRelaxed = CliPersonaRelaxedAuthorized = false; return (true); } if (strsame (Entity, "/PORT=", 4)) return (ParseCommandInteger (Entity, &CliServerPort, 10, true)); if (strsame (Entity, "/PRIORITY=", 4)) return (ParseCommandInteger (Entity, &ProcessPriority, 10, true)); if (strsame (Entity, "/PROFILE=", 5)) { for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (*cptr) { cptr++; if (strsame (cptr, "NORULE", -1)) AuthVmsUserProfileNoRule = true; else { CliIVKEYW (cptr); return (AuthVmsUserProfileEnabled = false); } } return (AuthVmsUserProfileEnabled = true); } if (strsame (Entity, "/NOPROFILE", 6)) { AuthVmsUserProfileEnabled = false; return (true); } /* for testing only, also needs /SYSUAF=PROMSICUOUS if using SYSUAF! */ if (strsame (Entity, "/PROMISCUOUS=", 5)) { for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (*cptr) { cptr++; AuthPromiscuousPwdPtr = VmGet (Length = strlen(cptr)+1); memcpy (AuthPromiscuousPwdPtr, cptr, Length); } return (AuthPromiscuous = true); } if (strsame (Entity, "/NOPROMISCUOUS", 7)) { AuthPromiscuous = false; return (true); } if (strsame (Entity, "/PROXY=", 5)) { ok = ParseCommandString (Entity, CliProxyMaint, true, true, true); if (CliProxyMaint[0]) return (ok); CliVALREQ (Entity); return (false); } if (strsame (Entity, "/REJECT=", 4)) { ok = ParseCommandString (Entity, Scratch, true, true, true); for (cptr = Scratch; *cptr && ISLWS(*cptr); cptr++); if (!*cptr) return (ok); CliRejectHostsPtr = VmGet (Length = strlen(Scratch)+1); memcpy (CliRejectHostsPtr, Scratch, Length); return (ok); } if (strsame (Entity, "/SCRIPT=AS=", 4)) { for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; while (*cptr && *cptr != '=') cptr++; if (*cptr) { cptr++; zptr = (sptr = CliScriptAs) + sizeof(CliScriptAs)-1; while (*cptr && sptr < zptr) *sptr++ = TOUP(*cptr++); *sptr = '\0'; if (CliScriptAs[0]) return (true); } CliVALREQ (Entity); return (false); } if (strsame (Entity, "/SERVICES=", 4)) return (ParseCommandString (Entity, CliServices, true, true, false)); /* This qualifier may come in handy if having to use VMS or WASD causes embarressment :^) Seriously, if you consider providing the server identification a security issue use this qualifier to set it to something like "Mine", "Unknown", "?", etc. */ if (strsame (Entity, "/SOFTWAREID=", 4)) { CliSoftwareID = true; return (ParseCommandString (Entity, SoftwareID, true, true, false)); } if (strsame (Entity, "/SSL=", 4)) return (ParseCommandString (Entity, SesolaParams, true, true, false)); if (strsame (Entity, "/NOSSL", 6)) { strcpy (SesolaParams, "/NOSSL"); return (true); } if (strsame (Entity, "/SUBBUF=", 5)) return (ParseCommandInteger (Entity, &DclSysOutputSize, 10, true)); if (strsame (Entity, "/SWAP", -1)) { NoSwapOut = false; return (true); } if (strsame (Entity, "/NOSWAP", -1)) return (NoSwapOut = true); if (strsame (Entity, "/ODS5", -1)) { CliOdsExtendedEnabled = true; CliOdsExtendedDisabled = false; return (true); } if (strsame (Entity, "/NOODS5", -1)) { CliOdsExtendedEnabled = false; CliOdsExtendedDisabled = true; return (true); } if (strsame (Entity, "/SYSPRV", -1)) return (OperateWithSysPrv = true); if (strsame (Entity, "/NOSYSPRV", -1)) { OperateWithSysPrv = false; return (true); } if (strsame (Entity, "/SYSUAF=", 4)) { AuthSysUafEnabled = true; for (cptr = Entity; *cptr && *cptr != '='; cptr++); if (!*cptr) return (true); cptr++; while (*cptr) { while (*cptr == '(' || *cptr == ',' || *cptr == ')') cptr++; zptr = (sptr = Scratch) + sizeof(Scratch)-1; while (*cptr && *cptr != ',' && *cptr != ')' && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (!Scratch[0]) continue; if (strsame (Scratch, "ALL", -1) || strsame (Scratch, "RELAXED", -1)) AuthPolicySysUafRelaxed = true; else if (strsame (Scratch, "ID", -1)) AuthPolicySysUafIdentifiers = true; else if (strsame (Scratch, "PROXY", -1)) AuthPolicySysUafProxy = true; else if (strsame (Scratch, "SSL", -1)) AuthPolicySysUafSslOnly = true; else if (strsame (Scratch, "VMS", -1)) AuthPolicySysUafVms = true; else if (strsame (Scratch, "WASD", -1) || strsame (Scratch, "WASD_ID", -1)) AuthPolicySysUafWasdIdentifiers = true; else { CliIVKEYW (Scratch); return (AuthSysUafEnabled = false); } } return (true); } if (strsame (Entity, "/NOSYSUAF", 6)) { AuthSysUafEnabled = false; return (true); } /* for testing SYSUAF-authenticated security profiles purposes only */ if (strsame (Entity, "/SYSUAF=PROMISCUOUS", -1)) return (AuthSysUafEnabled = AuthSysUafPromiscuous = true); if (strsame (Entity, "/TESTS", 4)) return (CliTests = true); if (strsame (Entity, "/USER=", 4)) return (ParseCommandString (Entity, CliUserName, true, true, true)); if (strsame (Entity, "/VALBLK=", 5)) { /* used without a value set to the default value block size */ CliLockValueBlockSize = -1; ParseCommandInteger (Entity, &CliLockValueBlockSize, 10, false); if (CliLockValueBlockSize == -1 || CliLockValueBlockSize == 16 || CliLockValueBlockSize == 64) return (true); CliIVKEYW (Entity); CliLockValueBlockSize = 0; return (false); } if (strsame (Entity, "/VERSION", 4)) return (CliVersion = true); if (strsame (Entity, "/WATCH=", 4) || strsame (Entity, "/NOWATCH", 6)) return (WatchCliParse (Entity)); if (strsame (Entity, "/ZERO", -1)) return (AccountingZeroOnStartup = true); if (strsame (Entity, "/NOZERO", -1)) { AccountingZeroOnStartup = false; return (true); } for (sptr = Entity; *sptr && *sptr != '='; sptr++); *sptr = '\0'; CliIVQUAL (Entity+1); return (false); } if (!CliParameter[0]) return (ParseCommandString (Entity, CliParameter, false, true, false)); FaoToStdout ("%HTTPD-E-MAXPARM, too many parameters\n \\!AZ\\\n", Entity); return (false); } /*****************************************************************************/ /* */ BOOL CliIVQUAL (char *qual) { FaoToStdout ("%HTTPD-E-IVQUAL, unrecognised qualifier\n \\!AZ\\\n", qual); return (false); } /*****************************************************************************/ /* */ BOOL CliIVKEYW (char *keyw) { FaoToStdout ("%HTTPD-E-IVKEYW, unrecognized keyword\n \\!AZ\\\n", keyw); return (false); } /*****************************************************************************/ /* */ BOOL CliVALREQ (char *qual) { FaoToStdout ("%HTTPD-E-VALREQ, missing qualifier or keyword value\n \ \\!AZ\\\n", qual); return (false); } /*****************************************************************************/