diff --git a/include/core/include/parse.h b/include/core/include/parse.h new file mode 100644 index 0000000..cbd65ac --- /dev/null +++ b/include/core/include/parse.h @@ -0,0 +1,414 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $ + | + | $RCSfile$ + | $Revision: 465 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | NSS Library source for Parsing Routines + | + | WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! + | + | This header file should ONLY be used for NSS internal development. + | This includes Semantic Agents (SA) and Loadable Storage Services (LSS). + | Any other use may cause conflicts which NSS will NOT fix. + +-------------------------------------------------------------------------*/ +#ifndef _PARSE_H_ +#define _PARSE_H_ + +#ifndef _OMNI_H_ +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Pre-define struct(s) so Linux compiler doesn't complain */ +struct PCLSwitchDef_s; + +#define MAX_TOKEN zMAX_FULL_NAME /* maximum size of individual token string*/ + +/*======================================================================== + * Command Line Parsing Structures + * + * This is used to parse command line strings and extract all of the + * switch values. + *========================================================================*/ + +/*------------------------------------------------------------------------- + * Typedef for the routine that may be called to finish processing an + * individual switch. It receives a pointer to the PCLSwitchDef_s + * structure for this given switch value along with it's index into the + * original array of PCLSwitchDef_s structure that the user passed + * in. This returns zOK if everything is fine with the switch. It returns + * zFAILURE if something is wrong with it. Returning zFAILURE will cause + * the command line parser to fail. It is up to the "process" routine to + * report what is wrong with the switch value. All process routines will + * be called even if an error is reported for one of them. + *-------------------------------------------------------------------------*/ +typedef STATUS (*PCLFunction_t)( + struct PCLSwitchDef_s *switchDef, + NINT parseOptions, /* parse options given to parse routine */ + void *userParm); + +/*------------------------------------------------------------------------- + * You need to create an array of this structure which defines all of the + * switch values that are valid for this parsing sequence. Anywhere in + * this document where it refers the the "switch array" it is refereing to + * and array of this structure. The array MUST be terminated by a TYPE + * field value of SWTYPE_ENDOFLIST. + *-------------------------------------------------------------------------*/ +typedef struct PCLSwitchDef_s +{ + char *name; /* The name of this switch*/ + char *setParmName; /* The name of this switch in set parameters + * Set to NULL if the option does not require + * a OS set parameter entry + */ + NINT type; /* Type and options for the switch (see below) */ + NINT setParmType; /* Type of the switch as passed to setParms */ + NINT setParmFlags; /* Optional flags as defined in setparms.h */ + /* Currently we don't support the process + * option for set parameters. Another + * setParmProcess field will need to be + * added to do this. + */ + PCLFunction_t process; /* Routine that is called to finish + * processing the switch value, set to NULL + * if no routine needs to be called. Note + * that this routine will be called only + * after all values in the switch array have + * been parsed and placed into the given + * "ret_value" fields. This means that this + * routine may look at any of the fields. + * This routine will be called on ALL + * switches that are given.*/ + void *ret_value; /* Address of where to put the value of + * this switch. If NULL the value is stored + * in a MALLOCed array that is freed before + * the "ParseCmdline" routine returns. This + * means that it will only be filled in + * while the "process" routines are being + * called. Note that the "process" routines + * are called ONLY after ALL switches have + * been parsed and all the "ret_value" fields + * have been set. */ + union + { + struct + { + NINT ret_valueSize; /* Contains size of "ret_value" buffer in + * characters, only used for CHAR and UNICODE + * types when a non-null "ret_value" field is + * given. This is given in characters.*/ + NINT ret_valueLen; /* Receives the length of the given string in + * characters. Only used for CHAR and UNICODE + * types when a valid value has been set. This + * is given in characters.*/ + } string; + struct + { + NINT minValue; /* Defines the minimum numeric value */ + NINT maxValue; /* Defines the maximum maximum value */ + } numeric; + } vtype; /* value type*/ + NINT groupValue; /* This is used to group sub-switches with + * a parent switch. This can be any non-zero + * value and all switches with the same + * non-zero value will be in the same group. + * The first switch in the switch array with + * a given value will be the parent switch. + * All other array elements with the same + * value (they do not have to be contiguous + * in the array) will be sub-switches. This + * means that the parent switch must be + * encountered in the command line string + * before the sub-switches will be valid. + * You can have multiple parent/sub switch + * groupings as long as the group value is + * different*/ + ADDR userInfo; /* field for user specific info about this switch*/ + LangEnabledStruct_s helpStr;/* This contains the HELP strings, they are in + * a languaged enabled form */ + PCLFunction_t PCLSD_PreFunction; + /* Function to call before ANY process + * functions are called. Called in the + * same order as process functions. If any + * PreFunction returns an error then no + * process function will be called. On an + * error the rest of the pre functions will + * be called. + */ + PCLFunction_t PCLSD_PostFunction; + /* Function to call after all process + * functions are called. Called in the + * same order as process functions. If we + * call a PRE function then we will call + * the POST function in all cases. This + * includes the PRE or process function + * returning an error. + */ +} PCLSwitchDef_s; + + +#define PCMDLINE_ENDOFLIST 0 /* defines the end of the switches array*/ + +extern LONG NSSSetParmCategory; +/*------------------------------------------------------------------------- + * This defines the different types of switches there are. These + * options are ORED with each other. Note that the "process" routine will + * is always called on all switch types of the routine is defined and + * the given switch is specified. + *-------------------------------------------------------------------------*/ +#define SWTYPE_REQUIRED 0 /* this is a position dependent parameter + * that is required, if not given it will + * be promted for. This value may be + * enclosed in double quotes which are + * stripped by this parser. */ +#define SWTYPE_OPTIONAL 1 /* this is a position dependent parameter + * that is optional, if not given nothing + * will happen. This value may be + * enclosed in double quotes which are + * stripped by this parser. */ +#define SWTYPE_NAME 2 /* this is a NAMED parameter. This has + * no value. It only makes sense to use + * this type with a "process" routine. + * The command line syntax has just the + * switch name optionally preceded by a + * '/' or '-'. No value is place in + * the ret_value field for this type of + * switch.*/ +#define SWTYPE_BOOLEAN 3 /* this is a boolean switch. It defines + * a TRUE(1)/FALSE(0) state. The command + * line syntax has just the name being + * TRUE and the name preceded by NO + * being FALSE. The switch name must be + * preceded by a '/' or '-'*/ +#define SWTYPE_VALUE 4 /* this is a valued parameter. This has + * an arbitrary value. The command line + * syntax is the switch name followed + * by '=' and then the switch value. The + * switch value may be enclosed in double + * quotes which are stripped by this + * parser. The switch name must be + * preceded by a '/' or '-'*/ + +#define SWTYPE_MASK 0x0000000f /* range of type values*/ +#define GET_SWTYPE(value) ((value) & SWTYPE_MASK) + +/*------------------------------------------------------------------------- + * This defines the datatypes that can be returned for the switch values. + * All binary data types will convert the given string to binary and return + * it. You can give binary values in decimal or hex. It follows the + * standard parsing guidelines define by the ansii standard library + * routine "strtol". + *-------------------------------------------------------------------------*/ +#define SWVAL_NINT 0x00000000 /* a binary NINT will be returned*/ +#define SWVAL_SNINT 0x00000010 /* a binary SNINT will be returned*/ +#define SWVAL_QUAD 0x00000020 /* a binary QUAD will be returned*/ +#define SWVAL_SQUAD 0x00000030 /* a binary SQUAD will be returned*/ +#define SWVAL_LONG 0x00000040 /* a binary LONG will be returned*/ +#define SWVAL_SLONG 0x00000050 /* a binary SLONG will be returned*/ +#define SWVAL_WORD 0x00000060 /* a binary WORD will be returned*/ +#define SWVAL_SWORD 0x00000070 /* a binary SWORD will be returned*/ +#define SWVAL_BYTE 0x00000080 /* a binary BYTE will be returned*/ +#define SWVAL_SBYTE 0x00000090 /* a binary SBYTE will be returned*/ +#define SWVAL_CHAR 0x000000a0 /* an ASCII string will be returned*/ +#define SWVAL_UNICODE 0x000000b0 /* a UNICODE string will be returned*/ +#define SWVAL_BOOL 0x000000c0 /* a binary BOOLEAN will be returned*/ + +#define SWVAL_MASK 0x000000f0 /* range of data values*/ +#define GET_SWVAL(value) ((value) & SWVAL_MASK) + +/*------------------------------------------------------------------------- + * These are additional options that may be defined. + *-------------------------------------------------------------------------*/ +#define SWOPT_MAPUPPER 0x00010000 /* if SET do map value string to + * UPPPER case, by default strings + * are NOT mapped to upper case*/ +#define SWOPT_HELP_ADD_SLASH 0x00020000 /* for NAME switches add '/'on HELP*/ +#define SWOPT_IGNORE_STATUS 0x00040000 /* if SET, the process function does + * not return a status value*/ +#define SWOPT_HAS_NUMERIC_RANGE 0x00080000 /* if set, use the given numeric + * range limits*/ +#define SWOPT_DEBUG 0x00100000 /* this is a DEBUG time switch */ +#define SWOPT_NO_HELP_VALUE 0x00200000 /* if set, don't display the value + * when displaying help */ +#define SWOPT_HIDDEN 0x00400000 /* if set, don't display the switch + * when displaying help */ + + /*------------------------------------------------------------------------- + * The following bits define a display category for each help parameter. + * Help commands may be a member of more than one group, in which case + * they will appear under each category during a help display. If no bit + * is set, the command line will not appear in the help list(s). If additional + * categories are added, additional titles must be added to the array + * CmdLineCategories in pcmdline.c. These bits MUST be contiguouos if new + * categories are added. + *-------------------------------------------------------------------------*/ + +#define SWHELP_CAT_MAINT 0x01000000 /* if set, display switch in the + * maintenance category */ +#define SWHELP_CAT_STATUS 0x02000000 /* if set, display switch in the + * status category */ +#define SWHELP_CAT_CONTROL 0x04000000 /* if set, display switch in the + * control category */ +#define SWHELP_CAT_TUNING 0x08000000 /* if set, display switch in the + * tuning category */ +#define SWHELP_CAT_MISC 0x10000000 /* if set, display switch in the + * maintenance category */ +#define SWHELP_CAT_FIRST SWHELP_CAT_MAINT +#define SWHELP_CAT_COUNT 5 /* number of help categories */ + +#if zLINUX +/* This bit is used to tell Linux that these command lines are to be parsed at + * the end of comnStart, but NOT at the beginning. If this bit is not present, + * it is assumed that SWOPT_RUNTIME_ONLY and SWOPT_STARTUP_ONLY dictate when + * the command line is valid. +*/ +#define SWOPT_FINISHOFSTARTUP 0x20000000 /* command is valid at startup finish */ +#endif + +/* The system defines two different times when the command line parser is + * called: STARTUP (when the app loads) and RUNTIME (while the app is running). + * These two options allow you to specify when a given switch is enabled. By + * default the switch is enabled for both types. You can suppress it for either + * mode. I suppose you can suppress them at both time but then what would be + * the point of the switch? */ + +#define SWOPT_RUNTIME_ONLY 0x40000000 /* suppress switch at RUNTIME */ +#define SWOPT_STARTUP_ONLY 0x80000000 /* suppress switch at STARTUP time*/ + +#define SWOPT_MASK_VALUES 0xffff0000 /* mask for switch options from the + * user */ + +/*------------------------------------------------------------------------- + * These are internal switch values. These values are cleared upon entry + * into the parsing routines. + *-------------------------------------------------------------------------*/ +#define SWPRV_MALLOCED 0x00000100 /* if SET we malloced the structure*/ +#define SWPRV_GROUP_CHILD 0x00000200 /* if SET this is a child of a group, + * if not set this is the parent of + * the group*/ +#define SWPRV_GROUP_ACTIVE 0x00000400 /* if SET this group switch is now + * active, only set on child members*/ +#define SWPRV_SPECIFIED 0x00000800 /* this is SET by the parsing routine + * for each switch that has a value + * it is cleared for each switch that + * does NOT have a value.*/ + +/*------------------------------------------------------------------------- + * This is a mask that is used to set the TYPE field to the list of + * valid defined external values. (preserve these bits) + *-------------------------------------------------------------------------*/ +#define SWTYPE_SET_START (SWTYPE_MASK | \ + SWVAL_MASK | \ + SWOPT_MASK_VALUES) + +/*------------------------------------------------------------------------- + * When you have multiple comand line definition list (which could happen + * if you have multiple NLMs that want to share the command line), you + * must fill out an array of this structure which identifies each switch + * list and a module name for each switch list. + *-------------------------------------------------------------------------*/ +typedef struct PCLMultiSwitchList_s +{ + PCLSwitchDef_s *swList/*[]*/; /* pointer to switch arrays */ + char *moduleName; /* module name */ + char **messageTable; /* message table for this module + * (may be NULL if not language enabled) */ +} PCLMultiSwitchList_s; + + +/*------------------------------------------------------------------------- + * Function prototypes + *-------------------------------------------------------------------------*/ +extern STATUS LB_ParseCmdlineMulti( + PCLMultiSwitchList_s *multiSwitchDef,/* pointer to array of switch + * definitions for multiple modules */ + NINT parseOptions, /* specify parsing options */ + char *parseStr, /* the string to parse*/ + void *userParm, /* a parameter defined by the user that + * is passed to the "process" routines*/ + BOOL (*validateswlist)(PCLSwitchDef_s *checkswdef)); + /* used as a callback to validate if the + * module for the switch settings is still + * loaded*/ + +extern STATUS LB_ParseCmdline( + PCLSwitchDef_s *swDef, /* pointer to array of switch definitions*/ + NINT parseOptions, /* specify parsing options */ + char *parseStr, /* the string to parse*/ + void *userParm); /* a parameter defined by the user that + * is passed to the "process" routines*/ + +#define POPT_AT_RUNTIME 0x00000000 /* Defines we are at RUNTIME */ +#define POPT_NO_UNKNOWN_SWITCH_ERRORS 0x00000001 /* Defines we don't want to + * report unknown switch + * errors */ +#define POPT_AT_STARTUP 0x00000002 /* Defines we are at STARTUP TIME */ +#define POPT_FIRST_PARSE 0x00000004 /* Defines we are PARSING the cmdline the first time */ +#define POPT_AT_FINISH_STARTUP 0x00000008 /* Defines we are on the finishup parse of STARTUP TIME */ +#define POPT_NO_PARSE_TIME_ERRORS 0x00000010 /* Tells parser to ignore errors caused by parsing a command at the wrong time */ + + + + +extern void LB_DisplayCmdlineHelpMulti( + PCLMultiSwitchList_s *multiSwitchDef,/* pointer to array of switch + * definitions for multiple modules */ + NINT options, /* specify parsing options */ + NINT hiddenFlag, /* if true, display hidden switches, if false, display visible only */ + char *title, /* title string for help */ + ...); /* parameters to TITLE string*/ + +extern void LB_DisplayCmdlineHelp( + PCLSwitchDef_s *swdefp, /* switch definition array*/ + char **messageTable, /* language enabled message table + * (may be NULL if not language enabled) */ + NINT options, /* specify parsing options */ + char *title, /* title string for help*/ + ...); /* parameters to TITLE string*/ + + +extern void LB_RegisterSetParmsForNSS( + PCLSwitchDef_s *swlist, + char **msgTable); + +extern void LB_UnRegisterSetParmsForNSS( + PCLSwitchDef_s *swlist); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/core/support/lnxmbINC/setparms.h b/include/core/support/lnxmbINC/setparms.h new file mode 100644 index 0000000..6fb95ac --- /dev/null +++ b/include/core/support/lnxmbINC/setparms.h @@ -0,0 +1,253 @@ +#ifndef __SETPARMS_H__ +#define __SETPARMS_H__ + +/***************************************************************************** + * + * (C) Copyright 1988-2002 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + ****************************************************************************/ + +///////////////////////////////////////////////////////////////////////////// +// Exported APIS // +///////////////////////////////////////////////////////////////////////////// + +extern int CheckSetParameterValue(char *varName, int valueTextFlag, char *value); + +extern LONG RegisterSetParameterCategory( + LONG moduleHandle, + struct ResourceTagStructure *RTag, + BYTE *newCategoryName, + LONG *categoryNumber); + +extern LONG DeRegisterSetParameterCategory( + LONG moduleHandle, + struct ResourceTagStructure *RTag, + BYTE *delCategoryName); + +extern LONG RegisterSetParameter( + LONG moduleHandle, + struct ResourceTagStructure *RTag, + LONG categoryNumber, + void (*spControlProcedure)(LONG oldValue), + LONG spFlags, + LONG *spParameter, + BYTE *spParameterName, + BYTE *spParameterDescription, + LONG spParameterType, + LONG spLowerLimit, + LONG spUpperLimit); + +extern LONG DeRegisterSetParameter( + LONG moduleHandle, + struct ResourceTagStructure *RTag, + LONG categoryNumber, + BYTE *ParameterName); + +extern LONG ReturnSetParameterCategoryInfo( + LONG infoLevel, + LONG *totalCategories, + ...); + +extern LONG GetSetableParameterValue( + LONG Station, + BYTE *setableParameterString, /* NULL terminated */ + void *returnValue); +extern LONG GetSetableParameterValueEx( + BYTE *setableParameterString, + void *returnValue, + int *returnType); + +extern LONG SetSetableParameterValue( + LONG Station, + BYTE *setableParameterString, /* NULL terminated */ + void *newValue); + +extern LONG ScanSetableParameters( + LONG scanCategory, /* -1 for all, COMMUNICATIONS, MEMORY, etc */ + LONG *scanSequence, /* 0 for first time */ + BYTE *rParameterName, + LONG *rType, /* 0 = number, 1 = boolean, 2 = time ticks., etc */ + LONG *rFlags, /* STARTUP, HIDE, etc */ + LONG *rCategory, /* COMMUNICATIONS, MEMORY, etc */ + void *rParameterDescription, /* description string */ + void *rCurrentValue, + LONG *rLowerLimit, + LONG *rUpperLimit); + +extern LONG IsSetableParameterPersistent( + LONG Station, + BYTE *setableParameterString); + +extern LONG ProcessSetCommandForNextReboot(BYTE *commandLine); + +extern LONG ResetSetableParameterValue( + LONG Station, + BYTE *setableParameterString); + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +#define SET_PARAMETER_UPGRADE_TO_V3 1 + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +#define MaximumSetParameterNameLength 96 +#define MaximumTypeStringLength (128+64) // If the string is larger -- then setparm is marked as non-persistent + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +/* define the parameter types. */ +#define SP_TYPE_NUMBER 0 +#define SP_TYPE_BOOLEAN 1 // BOOLEAN (size is UINT8) *************** DO NOT USE FOR NEW SET PARMS +#define SP_TYPE_TICKS 2 +#define SP_TYPE_BLOCK_SHIFT 3 +#define SP_TYPE_TIME_OFFSET 4 /* [+|-]hh:mm:ss converted to seconds */ +#define SP_TYPE_STRING 5 // MaximumTypeStringLength, if longer than max, the set parm marked not persistent +#define SP_TYPE_TRIGGER 6 +#define SP_TYPE_BOOLEAN_UINT32 7 // BOOLEAN (size is UINT32) ******* NEW SET PARMS SHOULD USE THIS BOOLEAN DEFINITION + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +/* define the flags. */ +#define SP_STARTUP_ONLY 0x00000001 +#define SP_HIDE 0x00000002 +#define SP_ADVANCED 0x00000004 +#define SP_STARTUP_OR_LATER 0x00000008 +#define SP_NOT_SECURED_CONSOLE 0x00000010 /* Can't be performed on secured console*/ +#define SP_RPC_LOCKOUT 0x00000020 /* Lockout Console RPC from changing value */ +#define SP_STARTUP_PREFERRED 0x00000040 /* Used with SP_STARTUP_OR_LATER to indicate preferred place to set the parameter is in STARTUP.NCF */ +#define SPValueNotPersistentFlag 0x00000080 /* Indicates that this set parm. is not persistent */ +#define SPDontUpperCaseCmdLineFlag 0x00000100 /* indicates to use standard command line -- not upper case copy when setting value */ +#define SPCallBackStartupCallable 0x00010000 /* Indicates that the call back routine can be call while being registered */ + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// The following flags are for internal use only +#define SPOwnerFlag 0x01000000 /* Used to indicate that the set parameter has been registered by an nlm */ +#define SPDefaultValuePresentFlag 0x02000000 +#define SPPendingValuePresentFlag 0x04000000 +#define SPDirtyFlag 0x08000000 +#define SPReadOnlyFlag 0x10000000 +#define SPRegisteredFromRegistryFlag 0x20000000 /* used to indicate that set parameter was initially registered from the registry */ +#define SPRegByCategoryName 0x40000000 /* when reg. set parm, category number is ptr to category name */ +#define SPOldStyleFlag 0x80000000 + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +#define SP_VALUE_FLAGS_MASK (SP_STARTUP_ONLY | SP_ADVANCED | SP_STARTUP_OR_LATER | SP_NOT_SECURED_CONSOLE | SP_RPC_LOCKOUT | SP_STARTUP_PREFERRED | SPValueNotPersistentFlag | SPDontUpperCaseCmdLineFlag) +#define SP_FLAGS_1 (SP_STARTUP_ONLY | SP_HIDE | SP_ADVANCED | SP_STARTUP_OR_LATER | SP_STARTUP_PREFERRED | SP_NOT_SECURED_CONSOLE | SP_RPC_LOCKOUT) +#define SP_FLAGS_2 (SPOldStyleFlag | SPCallBackStartupCallable | SPValueNotPersistentFlag | SPDontUpperCaseCmdLineFlag) +#define SP_FLAGS_MASK (SP_FLAGS_1 | SP_FLAGS_2) + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +/* * * * * * * * * * * * * * WARNING * * * * * * * * * * * * * * * * +* +* DO NOT USE THIS STRUCTURE -- ONLY FOR Old Set Parameter Registration (backwards compatability) +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +struct SetableParametersStructure +{ + struct SetableParametersStructure *SPLink; + LONG *SPParameter; + struct ResourceTagStructure *SPResourceTag; + void *SPParameterName; + BYTE SPParameterType; /* 0 = number, 1 = boolean, 2 = time ticks. */ + BYTE SPFlags; + BYTE SPCategory; + BYTE SPUnUsed; + LONG SPLowerLimit; + LONG SPUpperLimit; + void (*SPCallBackProcedure)(LONG oldValue); + void *SPParameterDescription; + WORD SPParmNameMsgNum; /* Message number for parameter name */ + WORD SPParmDescMsgNum; /* Message number for parameter description */ +}; +/* --------------------------------------------------------------------------- */ + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +#if SET_PARAMETER_UPGRADE_TO_V3 +///////////////////////////////////////////////////////////////////////////// +// NW6 // +///////////////////////////////////////////////////////////////////////////// +#define SET_PARMS_VERSION_NUMBER 3 +#define SP_COMMUNICATIONS 0 +#define SP_MEMORY 1 +#define SP_LOCKS 5 +#define SP_DISK 7 +#define SP_TIME 8 +#define SP_NCP 9 +#define SP_MISCELLANEOUS 10 +#define SP_ERRORS 11 +#define SP_DIRECTORY_SERVICES 12 +#else +///////////////////////////////////////////////////////////////////////////// +// NW5 // +///////////////////////////////////////////////////////////////////////////// +#define SET_PARMS_VERSION_NUMBER 2 +#define SP_COMMUNICATIONS 0 +#define SP_MEMORY 1 +#define SP_FILE_CACHE 2 +#define SP_DIR_CACHE 3 +#define SP_FILE_SYSTEM 4 +#define SP_LOCKS 5 +#define SP_TRANSACTION_TRACKING 6 +#define SP_DISK 7 +#define SP_TIME 8 +#define SP_NCP 9 +#define SP_MISCELLANEOUS 10 +#define SP_ERRORS 11 +#define SP_DIRECTORY_SERVICES 12 +#endif // SET_PARAMETER_UPGRADE_TO_V3 + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +#define MIN_OS_MIN_SERVICE_PROCS 10 +#define MAX_OS_MIN_SERVICE_PROCS 500 +#define MIN_OS_MAX_SERVICE_PROCS 5 +#define MAX_OS_MAX_SERVICE_PROCS 1000 +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + + +#endif /* __SETPARMS_H__ */ diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 64a4cc8..88bf5d9 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -22,6 +22,7 @@ nwcore_copy_public_header("include/core/include/id.h" "id.h") nwcore_copy_public_header("include/core/include/mailbox.h" "mailbox.h") nwcore_copy_public_header("include/core/include/pssDebug.h" "pssDebug.h") nwcore_copy_public_header("include/core/include/pssmpk.h" "pssmpk.h") +nwcore_copy_public_header("include/core/include/parse.h" "parse.h") nwcore_copy_public_header("include/core/include/register.h" "register.h") nwcore_copy_public_header("include/core/include/schedule.h" "schedule.h") nwcore_copy_public_header("include/core/include/utc.h" "utc.h") @@ -45,6 +46,7 @@ nwcore_copy_public_header("include/core/public/zOmni.h" "zOmni.h") nwcore_copy_public_header("include/core/public/zWhere.h" "zWhere.h") nwcore_copy_public_header("include/core/support/lnxmbINC/enable.h" "enable.h") nwcore_copy_public_header("include/core/support/lnxmbINC/procdefs.h" "procdefs.h") +nwcore_copy_public_header("include/core/support/lnxmbINC/setparms.h" "setparms.h") configure_file( "${MARS_NWE_YYJSON_SOURCE_DIR}/src/yyjson.h" "${NWCORE_BUILD_INCLUDE_DIR}/yyjson.h" @@ -133,6 +135,7 @@ add_library(nwcore SHARED library/misc/register.c library/misc/displayVersion.c library/os/delay.c + library/parse/pcmdline.c library/stdio/snprintf.c library/stdio/sprintf.c library/stdio/vsprintf.c diff --git a/src/core/library/parse/pcmdline.c b/src/core/library/parse/pcmdline.c new file mode 100644 index 0000000..8914a4b --- /dev/null +++ b/src/core/library/parse/pcmdline.c @@ -0,0 +1,1679 @@ +/**************************************************************************** + | + | (C) Copyright 1985, 1991, 1993, 1996 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: gpachner $ + | $Date: 2008-08-30 01:43:58 +0530 (Sat, 30 Aug 2008) $ + | + | $RCSfile$ + | $Revision: 2460 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | NSS Library source + +-------------------------------------------------------------------------*/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if zLINUX +#include +#endif + + + +#define aprintf LB_aprintf +#define errPrintf LB_errPrintf +#define memicmp LB_memicmp +#define stricmp LB_stricmp +#define strmcpy LB_strmcpy +#define strupr LB_strupr +#define vaprintf LB_vaprintf + +/*------------------------------------------------------------------------- + * Internal structure used to pass parameter among the internal routines + *-------------------------------------------------------------------------*/ +typedef struct +{ + PCLMultiSwitchList_s *multiList/*[]*/; /* pointer to array of multi switch + * definition pointers*/ + NINT parseOptions; /* parse options */ + NINT tokenLen; /* holds length of current token*/ + char *tokenPtr; /* pointer to current token string*/ + char *str; /* the line we are parsing*/ + char error; /* if TRUE an error has occored*/ + char token[MAX_TOKEN]; /* holds current token*/ +} LocalState_s; + +/*--------------------------------------------------------------------------- + * Internal structure used to sort command paramter names + *---------------------------------------------------------------------------*/ +typedef struct +{ + char **msgTable; + PCLSwitchDef_s *swdef; +} CmdNameSort_s; + +/*--------------------------------------------------------------------------- + * States returned from matching a unique name + *---------------------------------------------------------------------------*/ +#define MATCH_NOT_FOUND (-1) +#define MATCH_NOT_UNIQUE (-2) +#define MATCH_NOT_STARTUP (-3) +#define MATCH_NOT_RUNTIME (-4) + +#define IS_MATCH_ERROR(match) (((SNINT)(match) >= -4) && ((SNINT)(match) <= -1)) +/*------------------------------------------------------------------------- + * Globals + *-------------------------------------------------------------------------*/ +CONST char NullSTR[] = MSGNot(""); + +LONG NSSSetParmCategory; + + /*------------------------------------------------------------------------- + * Locals + *-------------------------------------------------------------------------*/ + +/* Define a stucture containing the titles that will be used when listing + * the categories of help command. These strings must correspond in number and + * order to the bit positions defined in pcmdline.h */ + +char *CmdLineCategories[SWHELP_CAT_COUNT] = +{ + MSGNot("\nMAINTENANCE PARAMETERS\n"), + MSGNot("\nSTATUS PARAMETERS\n"), + MSGNot("\nCONTROL PARAMETERS\n"), + MSGNot("\nTUNING PARAMETERS\n"), + MSGNot("\nMISC. PARAMETERS\n") +}; + +/************************************************************************** + * This will add the given character to the current TOKEN string. If the + * string gets too long, an error will be reported and an ERROR will be + * flagged. + ***************************************************************************/ +STATIC void pclAddChar( + LocalState_s *state, + char ch) +{ + if (state->tokenLen < (MAX_TOKEN-1)) + { + state->token[state->tokenLen] = ch; + state->tokenLen++; + } + else + { + state->token[state->tokenLen] = '\0'; + errPrintf(WHERE, LibModule, 209, + MSG("Error parsing \"%s\", the specified " + "value is too long.", 142), state->token); + state->error = TRUE; + } +} + +/************************************************************************** + * This will get the next token from the command string. The STATE->FLAGS + * variable will be appropriatly set if an ERROR occurs. This returns TRUE + * if it has a valid token else it returns FALSE. + ***************************************************************************/ +STATIC NINT pclGetNextToken( + LocalState_s *state) +{ + char ch; + BOOL indq; /* if true, in double quoted string*/ + BOOL leadingSpace; /* if TRUE, parsing leading space chars*/ + + indq = FALSE; + leadingSpace=TRUE; + state->tokenLen = 0; /* length of current token */ + + for (;;) + { + ch = *state->str; /* get the next character*/ + if (ch == '\0') + { + if (indq) + pclAddChar(state,'"'); /* add terminating double quote of missing*/ + break; + } + else if (ch == '"') /* double quote*/ + { + indq = !indq; + pclAddChar(state,ch); + leadingSpace = FALSE; + } + else if (indq) + { + pclAddChar(state,ch); + } + else if (isspace(ch)) /* This may need to also use IsDoubleByteSpace() */ + { + if (!leadingSpace) + break; + } + else + { + pclAddChar(state,ch); + leadingSpace = FALSE; + } + state->str++; + } + state->token[state->tokenLen] = '\0'; /* NULL terminate the string*/ + state->tokenPtr = state->token; + return(state->tokenLen > 0); +} + + +/************************************************************************** + * This will check to see if there are DOUBLE quotes at the FRONT and/or + * end of the given string. If so it will remove them. This returns the + * adjusted starting pointer and it also adjusts the length. + ***************************************************************************/ +STATIC char *pclStripQuotes( + char *str, + NINT *len) +{ + if (str[0] == '"') + { + str++; + (*len)--; + } + if ((*len > 0) && (str[*len-1] == '"')) + { + (*len)--; + str[*len] = '\0'; + } + return str; +} + +/************************************************************************** + * This routine handles the assigning of values. It will look to see if + * a value field address is defined. If not then a value field will be + * malloced and a value placed in it. This will set the flag that the + * parameter was defined as well as activating a GROUP when the parent + * of the group has a value set on it. + * Note that we do NOT set values for NAME parameters. They have no value. + ***************************************************************************/ +STATIC void pclAllocSwitchvalue( + LocalState_s *state, + PCLSwitchDef_s *swdef, + CONST char *str, + NINT strlen) +{ + NINT size; + NINT datatype; + NINT value; + QUAD qvalue = 0; + char ch; + zASSERT(!(swdef->type & SWPRV_SPECIFIED)); + datatype = GET_SWVAL(swdef->type); + swdef->type |= SWPRV_SPECIFIED; /* mark as a value given*/ +/*------------------------------------------------------------------------- + * See if we have defined a value for the parent of a GROUP. If so then + * activate all of the children of the group at this time. + *-------------------------------------------------------------------------*/ + if ((swdef->groupValue != 0) && !(swdef->type & SWPRV_GROUP_CHILD)) + { + NINT i; + + for (i=1;swdef[i].name != PCMDLINE_ENDOFLIST;i++) + { + if (swdef[i].groupValue == swdef->groupValue) + swdef[i].type |= SWPRV_GROUP_ACTIVE; + } + } +/*------------------------------------------------------------------------- + * Now set the value if it is NOT a NAME parameter + *-------------------------------------------------------------------------*/ + if (GET_SWTYPE(swdef->type) != SWTYPE_NAME) + { +/*------------------------------------------------------------------------- + * If a buffer was not given for this entry then MALLOC one if it is + * not a NAME type parameter + *-------------------------------------------------------------------------*/ + if (swdef->ret_value == NULL) + { + switch(datatype) + { + case SWVAL_NINT: + case SWVAL_SNINT: + size = sizeof(NINT); + break; + case SWVAL_QUAD: + case SWVAL_SQUAD: + size = sizeof(QUAD); + break; + case SWVAL_LONG: + case SWVAL_SLONG: + size = sizeof(LONG); + break; + case SWVAL_WORD: + case SWVAL_SWORD: + size = sizeof(WORD); + break; + case SWVAL_BYTE: + case SWVAL_SBYTE: + size = sizeof(BYTE); + break; + case SWVAL_CHAR: + size = (strlen+1) * sizeof(char); + swdef->vtype.string.ret_valueSize = strlen + 1; + break; + case SWVAL_UNICODE: + size = (strlen+1) * sizeof(unicode_t); + swdef->vtype.string.ret_valueSize = strlen + 1; + break; + case SWVAL_BOOL: + size = sizeof(BOOL); + break; + default: + zASSERT("Unknown SWVAL" == NULL); + size = 0; + } + if ((swdef->ret_value = malloc(size)) == NULL) + { + state->error = TRUE; + return; + } + swdef->type |= SWPRV_MALLOCED; + } +/*------------------------------------------------------------------------- + * If we are returning a string data type, set it now + *-------------------------------------------------------------------------*/ + if (datatype == SWVAL_UNICODE) + { + LB_ByteToUnicode(NSS_UNI_CONVERSION_RAW, + (unicode_t *)swdef->ret_value, + swdef->vtype.string.ret_valueSize,str,NULL); + swdef->vtype.string.ret_valueLen = strlen; + if ((swdef->type & SWOPT_MAPUPPER)) + { + uniupr((unicode_t *)swdef->ret_value); + } + } + else if (datatype == SWVAL_CHAR) + { + strmcpy((char *)swdef->ret_value,str,swdef->vtype.string.ret_valueSize); + swdef->vtype.string.ret_valueLen = strlen; + if ((swdef->type & SWOPT_MAPUPPER)) + { + strupr((char *)swdef->ret_value); + } + } + else + { +/*------------------------------------------------------------------------- + * We are returning a BINARY value. Get the value. + *-------------------------------------------------------------------------*/ + if (GET_SWTYPE(swdef->type) == SWTYPE_BOOLEAN) + { + ch = tolower(str[0]); + value = (ch != 'f' && ch != '0' && ch != 0) ? TRUE : FALSE; + } + else + { + switch(datatype) + { + case SWVAL_QUAD: + qvalue = strtouq(str,NULL,0); + break; + + case SWVAL_NINT: + case SWVAL_LONG: + case SWVAL_WORD: + case SWVAL_BYTE: + case SWVAL_BOOL: + value = strtoul(str,NULL,0); + break; + + case SWVAL_SQUAD: + qvalue = strtoq(str,NULL,0); + break; + + case SWVAL_SNINT: + case SWVAL_SLONG: + case SWVAL_SWORD: + case SWVAL_SBYTE: + value = strtol(str,NULL,0); + break; + + default: + zASSERT("Unknown SWVAL" == NULL); + value = 0; + break; + } + } +/*------------------------------------------------------------------------- + * Return the desired value. + *-------------------------------------------------------------------------*/ + switch(datatype) + { + case SWVAL_NINT: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((NINT)value < (NINT)swdef->vtype.numeric.minValue) + *(NINT *)&value = (NINT)swdef->vtype.numeric.minValue; + else if ((NINT)value > (NINT)swdef->vtype.numeric.maxValue) + *(NINT *)&value = (NINT)swdef->vtype.numeric.maxValue; + } + *(NINT *)swdef->ret_value = (NINT)value; + break; + case SWVAL_SNINT: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((SNINT)value < (SNINT)swdef->vtype.numeric.minValue) + *(SNINT *)&value = (SNINT)swdef->vtype.numeric.minValue; + else if ((SNINT)value > (SNINT)swdef->vtype.numeric.maxValue) + *(SNINT *)&value = (SNINT)swdef->vtype.numeric.maxValue; + } + *(SNINT *)swdef->ret_value = (SNINT)value; + break; + case SWVAL_LONG: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((LONG)value < (LONG)swdef->vtype.numeric.minValue) + *(LONG *)&value = (LONG)swdef->vtype.numeric.minValue; + else if ((LONG)value > (LONG)swdef->vtype.numeric.maxValue) + *(LONG *)&value = (LONG)swdef->vtype.numeric.maxValue; + } + *(LONG *)swdef->ret_value = (LONG)value; + break; + case SWVAL_SLONG: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((SLONG)value < (SLONG)swdef->vtype.numeric.minValue) + *(SLONG *)&value = (SLONG)swdef->vtype.numeric.minValue; + else if ((SLONG)value > (SLONG)swdef->vtype.numeric.maxValue) + *(SLONG *)&value = (SLONG)swdef->vtype.numeric.maxValue; + } + *(SLONG *)swdef->ret_value = (SLONG)value; + + break; + case SWVAL_WORD: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((WORD)value < (WORD)swdef->vtype.numeric.minValue) + *(WORD *)&value = (WORD)swdef->vtype.numeric.minValue; + else if ((WORD)value > (WORD)swdef->vtype.numeric.maxValue) + *(WORD *)&value = (WORD)swdef->vtype.numeric.maxValue; + } + *(WORD *)swdef->ret_value = (WORD)value; + break; + case SWVAL_SWORD: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((SWORD)value < (SWORD)swdef->vtype.numeric.minValue) + *(SWORD *)&value = (SWORD)swdef->vtype.numeric.minValue; + else if ((SWORD)value > (SWORD)swdef->vtype.numeric.maxValue) + *(SWORD *)&value = (SWORD)swdef->vtype.numeric.maxValue; + } + *(SWORD *)swdef->ret_value = (SWORD)value; + break; + case SWVAL_BYTE: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((BYTE)value < (BYTE)swdef->vtype.numeric.minValue) + *(BYTE *)&value = (BYTE)swdef->vtype.numeric.minValue; + else if ((BYTE)value > (BYTE)swdef->vtype.numeric.maxValue) + *(BYTE *)&value = (BYTE)swdef->vtype.numeric.maxValue; + } + *(BYTE *)swdef->ret_value = (BYTE)value; + break; + case SWVAL_SBYTE: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((SBYTE)value < (SBYTE)swdef->vtype.numeric.minValue) + *(SBYTE *)&value = (SBYTE)swdef->vtype.numeric.minValue; + else if ((SBYTE)value > (SBYTE)swdef->vtype.numeric.maxValue) + *(SBYTE *)&value = (SBYTE)swdef->vtype.numeric.maxValue; + } + *(SBYTE *)swdef->ret_value = (SBYTE)value; + break; + case SWVAL_QUAD: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((QUAD)value < (QUAD)swdef->vtype.numeric.minValue) + *(QUAD *)&value = (QUAD)swdef->vtype.numeric.minValue; + else if ((QUAD)value > (QUAD)swdef->vtype.numeric.maxValue) + *(QUAD *)&value = (QUAD)swdef->vtype.numeric.maxValue; + } + *(QUAD *)swdef->ret_value = (QUAD)qvalue; + break; + case SWVAL_SQUAD: + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + if ((SQUAD)value < (SQUAD)swdef->vtype.numeric.minValue) + *(SQUAD *)&value = (SQUAD)swdef->vtype.numeric.minValue; + else if ((SQUAD)value > (SQUAD)swdef->vtype.numeric.maxValue) + *(SQUAD *)&value = (SQUAD)swdef->vtype.numeric.maxValue; + } + *(SQUAD *)swdef->ret_value = (SQUAD)qvalue; + break; + case SWVAL_BOOL: + *(BOOL *)swdef->ret_value = (BOOL)value; + break; + default: + zASSERT("Unknown SWVAL" == NULL); + break; + } + //swdef->vtype.string.ret_valueLen = 0; + } + } +} + + +/************************************************************************** + * This will see if the SUBSTR matches the front of the MAINSTR doing a + * case independent compare. This returns TRUE if they match else it + * returns FALSE. + ***************************************************************************/ +STATIC NINT pclIMatchFront( + char *mainStr, + char *subStr) +{ + for (;;mainStr++,subStr++) + { + if (*subStr == 0) + return TRUE; + if (tolower(*mainStr) != tolower(*subStr)) + return FALSE; + } +} + + +/************************************************************************** + * This will process the given REQUIRED/OPTIONAL parameter by finding the + * next avaialble slot and inserting it into that slot. An error is + * reported if no slot is available + ***************************************************************************/ +STATIC void pclProcessReqOptParam( + LocalState_s *state) +{ + PCLSwitchDef_s *swdef; + NINT sl; + + for (sl=0;(swdef = state->multiList[sl].swList) != NULL;sl++) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if (!(swdef->type & SWPRV_SPECIFIED) && + (GET_SWTYPE(swdef->type) <= SWTYPE_OPTIONAL) && + ((!(swdef->type & SWOPT_RUNTIME_ONLY)) || + (!(state->parseOptions & POPT_AT_STARTUP))) && + ((!(swdef->type & SWOPT_STARTUP_ONLY)) || + ((state->parseOptions & POPT_AT_STARTUP))) && + ((swdef->groupValue == 0) || + !(swdef->type & SWPRV_GROUP_CHILD) || + (swdef->type & SWPRV_GROUP_ACTIVE))) + { + pclAllocSwitchvalue(state,swdef,state->tokenPtr,state->tokenLen); + return; + } + } + } + errPrintf(WHERE, LibModule, 210, + MSG("Option \"%s\" not available at this time, or\n" + "may require other NSS modules to be loaded.", 143), state->tokenPtr); + + state->error = TRUE; +} + + +/************************************************************************** + * This will scan the list of switch options and see if we can match the + * given name to the given type. It has the following return values: + * MATCH_NOT_FOUND the name was not found + * MATCH_NOT_UNIQUE the name is not a unique abbreviation + * * pointer to the SWDEF array for the found switch + ***************************************************************************/ +STATIC PCLSwitchDef_s *pclMatchUnique( + LocalState_s *state, + NINT swtype, + char *str) +{ + PCLSwitchDef_s *found; + PCLSwitchDef_s *swdef; + NINT sl; + + found = (PCLSwitchDef_s *)MATCH_NOT_FOUND; + for (sl=0;(swdef = state->multiList[sl].swList) != NULL;sl++) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if ((swtype == GET_SWTYPE(swdef->type)) && + /*((!(swdef->type & SWOPT_RUNTIME_ONLY)) || + (!(state->parseOptions & POPT_AT_STARTUP))) && */ + /*((!(swdef->type & SWOPT_STARTUP_ONLY)) || + ((state->parseOptions & POPT_AT_STARTUP))) && */ + ((swdef->groupValue == 0) || + !(swdef->type & SWPRV_GROUP_CHILD) || + (swdef->type & SWPRV_GROUP_ACTIVE))) + { + if (stricmp(str,swdef->name) == 0) /* check for EXACT match first*/ + { + found = swdef; /* yes, always match and quit */ + goto doneChecking; + } + else + { + if (pclIMatchFront(swdef->name,str)) + { + if (found == (PCLSwitchDef_s *)MATCH_NOT_FOUND) + { + found = swdef; /* valid switch*/ + } + else + { + found = (PCLSwitchDef_s *)MATCH_NOT_UNIQUE; /* non-unique abbreviation*/ + break; /* Keep checking in case we find an exact one */ + } + } + } + } + } + } +doneChecking: + if (!IS_MATCH_ERROR(found)) + { +#if zLINUX + + if ((found->type & SWOPT_FINISHOFSTARTUP) && + (state->parseOptions & POPT_AT_STARTUP)) + { + found = (PCLSwitchDef_s *)MATCH_NOT_RUNTIME; + } + else +#endif + if ((found->type & SWOPT_RUNTIME_ONLY) && + (state->parseOptions & POPT_AT_STARTUP)) + { + found = (PCLSwitchDef_s *)MATCH_NOT_RUNTIME; + } + else if ((found->type & SWOPT_STARTUP_ONLY) && + !(state->parseOptions & POPT_AT_STARTUP)) + { + found = (PCLSwitchDef_s *)MATCH_NOT_STARTUP; + } + + } + return found; +} + +/************************************************************************** + * This will process the string in the current token buffer. + ***************************************************************************/ +STATIC void pclProcessToken( + LocalState_s *state) +{ + char *eqchar,*s; + CONST char *v; + NINT swtype; + NINT vlen; + PCLSwitchDef_s *swpos; + typedef struct Stack_s { + char swstr[MAX_TOKEN]; + } Stack_s; + Stack_s *aStack; + + STACK_ALLOC_NO_ASTACK(); + if ((state->tokenPtr[0] != '-') && (state->tokenPtr[0] != '/')) + { +/*------------------------------------------------------------------------- + * Process REQUIRED, OPTIONAL, or NAME parmaeters + *-------------------------------------------------------------------------*/ + state->tokenPtr = pclStripQuotes(state->tokenPtr,&state->tokenLen); +/*------------------------------------------------------------------------- + * See if this matches one of the NAME switches. If so then return that + * it was found. Else process it as a required/optional parameter + *-------------------------------------------------------------------------*/ + swpos = pclMatchUnique(state,SWTYPE_NAME,state->tokenPtr); + if (IS_MATCH_ERROR(swpos)) + { + pclProcessReqOptParam(state); + } + else + { + pclAllocSwitchvalue(state,swpos,NullSTR,0); + } + } + else + { +/*------------------------------------------------------------------------- + * Process BOOLEAN, VALUE or NAME parameters + *-------------------------------------------------------------------------*/ + strcpy(aStack->swstr,&state->tokenPtr[1]); /* remove leading '-' or '/' */ + s = aStack->swstr; + eqchar = strchr(s,'='); + if (eqchar == NULL) /* must be BOOLEAN or NAME*/ + { + swpos = pclMatchUnique(state,SWTYPE_NAME,s); + if (!IS_MATCH_ERROR(swpos)) + { + pclAllocSwitchvalue(state,swpos,NullSTR,0); + STACK_FREE(); + return; + } + swtype = SWTYPE_BOOLEAN; /* assume BOOLEAN switch*/ + if (memicmp(s,MSGNot("no"),2) == 0) + { + v = MSGNot("false"); + s += 2; + } + else + { + v = MSGNot("true"); + } + vlen = strlen(v); + } + else + { + swtype = SWTYPE_VALUE; /* assume value switch */ + *eqchar = '\0'; /* delete all after '=' in "s"*/ + v = eqchar+1; + vlen = strlen(v); + v = pclStripQuotes((char *)v,&vlen); /* at this point we know "v" is not a constant*/ + } +/*------------------------------------------------------------------------- + * We have determined if it is a BOOLEAN or VALUE switch, search for + * a unique abbreviation of the switch name. Report appropriate errors + * if we found the switch or not, if we had a unique abbreviation, or if + * it was multiply defined. If it is good then allocate the string buffer. + *-------------------------------------------------------------------------*/ + if (vlen <= 0) + { + errPrintf(WHERE, LibModule, 211, + MSG("Parsing \"%s\", an invalid switch " + "value was specified.", 144), state->tokenPtr); + + state->error = TRUE; + } + else + { + swpos = pclMatchUnique(state,swtype,s); + switch ((SNINT)swpos) + { + case MATCH_NOT_FOUND: + if (!(state->parseOptions & POPT_NO_UNKNOWN_SWITCH_ERRORS)) + { + errPrintf(WHERE, LibModule, 212, + MSG("Option \"%s\" is unknown for the current NSS configuration\n" + "and may require other NSS modules to be loaded.", + 145), state->tokenPtr); + + state->error = TRUE; + } + break; + + case MATCH_NOT_UNIQUE: + errPrintf(WHERE, LibModule, 213, + MSG("Abbreviation is not unique for option \"%s\", make it longer.", + 146), state->tokenPtr); + + state->error = TRUE; + break; + + case MATCH_NOT_STARTUP: + /* during parse of nssstart.cfg, both startup and finishofstartup commands will be found */ + /* ignore the errors causes by wrong parse time, because the file will be parsed twice */ + if(!(state->parseOptions & POPT_NO_PARSE_TIME_ERRORS)) + { + errPrintf(WHERE, LibModule, 214, + MSG("Option \"%s\" is only valid at STARTUP time.", 147), state->tokenPtr); + state->error = TRUE; + } + break; + + case MATCH_NOT_RUNTIME: + /* during parse of nssstart.cfg, both startup and finishofstartup commands will be found */ + /* ignore the errors causes by wrong parse time, because the file will be parsed twice */ + if(!(state->parseOptions & POPT_NO_PARSE_TIME_ERRORS)) + { + errPrintf(WHERE, LibModule, 215, + MSG("Option \"%s\" is only valid after NSS is running.",148), state->tokenPtr); + state->error = TRUE; + } + break; + + default: + if (swpos->type & SWPRV_SPECIFIED) + { + errPrintf(WHERE, LibModule, 216, + MSG("Multiple definitions of option \"%s\" " + "were specified.\n" + "The second occurrence of this option is ignored. " + "You can change the command\n" + "line or NSSSTART.CFG to not specify this " + "definition twice.", 149), + state->tokenPtr); + +// state->error = TRUE; + } + else + { + pclAllocSwitchvalue(state,swpos,v,vlen); + } + } + } + } + STACK_FREE(); + return; +} + +/************************************************************************** + * Free all of the MALLOCED structures on the command line + ***************************************************************************/ +STATIC void pclFreeMalloced( + LocalState_s *state, + BOOL (*validateswlist)(PCLSwitchDef_s *checkswdef)) +{ + NINT sl; + PCLSwitchDef_s *swdef; /* switch definitions array*/ + + for (sl=0;(swdef = state->multiList[sl].swList) != NULL;sl++) + { + if((validateswlist == NULL) || (validateswlist(swdef))) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if (swdef->type & SWPRV_MALLOCED) + { + free(swdef->ret_value); + swdef->ret_value = NULL; + } + } + } + } +} + +/************************************************************************** + * This routine will take the given switch definition array and the given + * string and will parse the values out of the string. If everything is + * syntactically correct it will return an array which contains all of the + * parsed switch values. Note that all switches get a value whether + * specified or the default. + ***************************************************************************/ +STATUS LB_ParseCmdlineMulti( + PCLMultiSwitchList_s *multiList, /* multi definitions array */ + NINT parseOptions, /* specify parsing options */ + char *parseStr, /* the string to parse*/ + void *userParm, + BOOL (*validateswlist)(PCLSwitchDef_s *checkswdef)) +{ + NINT sl; + NINT j,val; + STATUS status; + PCLSwitchDef_s *swdef; /* switch definitions array*/ + typedef struct Stack_s { + LocalState_s state; + } Stack_s; + Stack_s *aStack; + +/*------------------------------------------------------------------------- + * Loop through and make sure the TYPE field only has valid values. Also + * tag all of the CHILD members of a group as children. + *-------------------------------------------------------------------------*/ + ASSERT_MPKNSS_LOCK(); + STACK_ALLOC_NO_ASTACK(); + for (sl=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + swdef->type &= SWTYPE_SET_START; /* init flag state */ + if ((swdef->groupValue != 0) && !(swdef->type & SWPRV_GROUP_CHILD)) + { + val = swdef->groupValue; + for (j=1;swdef[j].name != PCMDLINE_ENDOFLIST;j++) + { + if (swdef[j].groupValue == val) + swdef[j].type |= SWPRV_GROUP_CHILD; + } + } + } + } +/*------------------------------------------------------------------------- + * Initialise internal STATE variables. + *-------------------------------------------------------------------------*/ + aStack->state.multiList = multiList; + aStack->state.str = parseStr; + aStack->state.error = FALSE; + //aStack->state.swListIndex = 0; + //aStack->state.swDefIndex = 0; + aStack->state.parseOptions = parseOptions; + +/*------------------------------------------------------------------------- + * Get each cmdline token and process it. Note that we will parse the + * entire command line before quitting. This way we will report all + * cmdline errors in one shot. + *-------------------------------------------------------------------------*/ + while (pclGetNextToken(&aStack->state)) + pclProcessToken(&aStack->state); + + if (aStack->state.error) + { + goto cleanup; + } +/*------------------------------------------------------------------------- + * We have processed the command line, prompt for all required parameters. + *-------------------------------------------------------------------------*/ +#ifndef __linux__ // LINUX_CmdLineMultiList + // FixFixFix(Linux) - we do not have a gets in DEMO. In ship code this + // will be in User Space which will have a gets(). Anyway, this form + // of the parser is not used often and will not be used in the DEMO. + for (sl=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if (!(swdef->type & SWPRV_SPECIFIED) && + (GET_SWTYPE(swdef->type) == SWTYPE_REQUIRED)) + { + do + { + printf(MSG("%s> ",150),swdef->name); + gets(state.token); + } + while (state.token[0] == '\0'); + wSyncToInputCursor(wStdout); + printf(MSGNot("\n")); + pclAllocSwitchvalue(&state,swdef,state.token,strlen(state.token)); + if (state.error) + { + goto cleanup; + } + } + } + } +#endif + MPKNSS_UNLOCK(); + + /* All of the value are inserted, call all of the PRE "processing" routines + *-------------------------------------------------------------------------*/ + for (sl=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + if((validateswlist == NULL) || (validateswlist(swdef))) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if ((swdef->PCLSD_PreFunction != NULL) && (swdef->type & SWPRV_SPECIFIED)) + { + status = swdef->PCLSD_PreFunction(swdef,parseOptions,userParm); + if ( status != zOK ) + { + aStack->state.error = TRUE; + } + } + } + } + } + if (aStack->state.error) + { + goto cleanupPost; + } + /* All of the value are inserted, call all of the "processing" routines + *-------------------------------------------------------------------------*/ + for (sl=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + if((validateswlist == NULL) || (validateswlist(swdef))) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if ((swdef->process != NULL) && (swdef->type & SWPRV_SPECIFIED)) + { + status = swdef->process(swdef,parseOptions,userParm); + if (!(swdef->type & SWOPT_IGNORE_STATUS) && (status != zOK)) + { /* On 9/16/2000 Vandana and I agreed to stop + * calling functions if someone returned an error. + * This makes sence for /poolverify=sam /override=dd + * as dd is illegal and we should not attempt + * to run /poolverify. + */ + aStack->state.error = TRUE; + goto cleanupPost; + } + } + } + } + } + +#ifndef __linux__ // LINUX_SetParms + /* If the command line switch has a set param equivalent, call set param + * so it can send events about the value changing. + */ + for (sl=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + if((validateswlist == NULL) || (validateswlist(swdef))) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if ((swdef->setParmName != NULL) && + (swdef->type & SWPRV_SPECIFIED)) + { + status = SetSetableParameterValue(0, + swdef->setParmName, swdef->ret_value); + } + } + } + } +#endif + +cleanupPost: + /* All of the value are inserted, call all of the POST "processing" routines + *-------------------------------------------------------------------------*/ + for (sl=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + if((validateswlist == NULL) || (validateswlist(swdef))) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if ((swdef->PCLSD_PostFunction != NULL) && (swdef->type & SWPRV_SPECIFIED)) + { + status = swdef->PCLSD_PostFunction(swdef,parseOptions,userParm); + if ( status != zOK ) + { + aStack->state.error = TRUE; + } + } + } + } + } + MPKNSS_LOCK(); + +cleanup: + +/*------------------------------------------------------------------------- + * We are done processing, free all of the malloced structures + *-------------------------------------------------------------------------*/ + pclFreeMalloced(&aStack->state, validateswlist); + if (aStack->state.error) + { + STACK_FREE(); + return( zFAILURE ); + } + STACK_FREE(); + return zOK; +} + + +/************************************************************************** + * You can call this routine if you just have one command line array you + * want to parse. This points it into the form the MULTI command line array + * wants and then calls that parser. + ***************************************************************************/ +STATUS LB_ParseCmdline( + PCLSwitchDef_s *swdef, /* pointer to switch definitions array*/ + NINT parseOptions, /* specify parsing options */ + char *parseStr, /* the string to parse*/ + void *userParm) +{ + PCLMultiSwitchList_s multiArray[2]; /* local array to call multi with*/ + ASSERT_MPKNSS_LOCK(); + multiArray[0].swList = swdef; /* put into MULTI form */ + multiArray[0].moduleName = NULL; + multiArray[1].swList = NULL; /* end of list */ + + return LB_ParseCmdlineMulti(&multiArray[0],parseOptions,parseStr,userParm, NULL); +} + + +/************************************************************************** + * This will return a displayable return value. + ***************************************************************************/ +STATIC void pclGetDisplayableReturnValue( + PCLSwitchDef_s *swdef, + char *outstr) +{ + QUAD value = 0; + QUAD svalue; + + if (swdef->ret_value == NULL) + { + strcpy(outstr,MSG("[UNKNOWN]",151)); + return; + } +/*------------------------------------------------------------------------- + * Get the appropriate value into a variable. + *-------------------------------------------------------------------------*/ + switch(GET_SWVAL(swdef->type)) + { + case SWVAL_NINT: + value = *(NINT *)swdef->ret_value; + break; + case SWVAL_SNINT: + svalue = *(SNINT *)swdef->ret_value; + break; + case SWVAL_QUAD: + value = *(QUAD *)swdef->ret_value; + break; + case SWVAL_SQUAD: + svalue = *(SQUAD *)swdef->ret_value; + break; + case SWVAL_LONG: + value = *(LONG *)swdef->ret_value; + break; + case SWVAL_SLONG: + svalue = *(SLONG *)swdef->ret_value; + break; + case SWVAL_WORD: + value = *(WORD *)swdef->ret_value; + break; + case SWVAL_SWORD: + svalue = *(SWORD *)swdef->ret_value; + break; + case SWVAL_BYTE: + value = *(BYTE *)swdef->ret_value; + break; + case SWVAL_SBYTE: + svalue = *(SBYTE *)swdef->ret_value; + break; + } +/*------------------------------------------------------------------------- + * Generate a string for the variable + *-------------------------------------------------------------------------*/ + switch(GET_SWVAL(swdef->type)) + { + case SWVAL_NINT: + case SWVAL_QUAD: + case SWVAL_LONG: + case SWVAL_WORD: + case SWVAL_BYTE: + sprintf(outstr,MSGNot("%u"),(NINT)value); + break; + + case SWVAL_SNINT: + case SWVAL_SQUAD: + case SWVAL_SLONG: + case SWVAL_SWORD: + case SWVAL_SBYTE: + sprintf(outstr,MSGNot("%d"),(SNINT)value); + break; + case SWVAL_CHAR: + strcpy(outstr,swdef->ret_value); + break; + case SWVAL_UNICODE: + sprintf(outstr,MSGNot("%U"),swdef->ret_value); + break; + case SWVAL_BOOL: + strcpy(outstr,((*(BOOL *)swdef->ret_value) ? MSG("ON",154) : MSG("OFF",157))); + break; + } +} + + +/************************************************************************** + * + ***************************************************************************/ +STATIC void pclHelpValuesCheck( + char *buffer, + NINT options +# define HELPOPT_HEADER 0x00000001 +# define HELPOPT_TRAILER 0x00000002 + ) +{ + static BOOL hasHeader = FALSE; + + if (options & HELPOPT_HEADER) + { + if (!hasHeader) + { + if (buffer[0] != 0) + { + strcat(buffer,MSGNot(" ")); + } + strcat(buffer,MSGNot("[")); + hasHeader = TRUE; + } + else + { + strcat(buffer,MSGNot(" ")); /* if has header, add seperator */ + } + } + else if (options & HELPOPT_TRAILER) + { + if (hasHeader) /* only do this if they put in a header */ + { + strcat(buffer,MSGNot("]")); + hasHeader = FALSE; + } + } +} + + +#if zLINUX +/************************************************************************** + * This will display one line of help. + ***************************************************************************/ + STATIC void pclDisplayHelpLine( + PCLSwitchDef_s *swdef, + char **messageTable, + NINT initialIndent, + NINT options) +{ +#define MSG_INDENT 24 +#define SCREEN_WIDTH 79 +#define LINE_BUF_LEN 1024 + char *helpStr; + char *endStr; + int numBlanks; + int nextCharPos = 0; + int remLength; + int spaceAvail; + int indent = MSG_INDENT+initialIndent; + char *strbuf; + + if((strbuf = malloc(LINE_BUF_LEN)) == NULL) + { + aprintf(LRED, MSGNot("Message will not fit in line buffer\n")); + return; + } + + + switch (GET_SWTYPE(swdef->type)) + { + case SWTYPE_NAME: + case SWTYPE_REQUIRED: + case SWTYPE_OPTIONAL: + aprintf(CYAN,MSGNot(" %s "),swdef->name); + nextCharPos = 6; + break; + case SWTYPE_BOOLEAN: + aprintf(CYAN,MSGNot("/(No)%s "),swdef->name); + nextCharPos = 6; + break; + case SWTYPE_VALUE: + aprintf(CYAN,MSGNot(" /%s= "),swdef->name); + nextCharPos = 7; + break; + } + nextCharPos += strlen(swdef->name); + if(nextCharPos < indent) + { + for(numBlanks = indent - nextCharPos; numBlanks>0; numBlanks--) + { + aprintf(CYAN,MSGNot(" ")); + } + spaceAvail = SCREEN_WIDTH - indent; + } + else + { + spaceAvail = SCREEN_WIDTH - nextCharPos; + } +/*------------------------------------------------------------------------- + * Calculate the current default value if available. + *-------------------------------------------------------------------------*/ + + if (!(swdef->type & SWOPT_NO_HELP_VALUE)) + { + /* put in there help string */ + strbuf[0] = 0; /* make it a NULL string */ + helpStr = StructGetMSGStrWithTable(swdef->helpStr,messageTable); + + if (helpStr != NULL) + { + strcpy(strbuf,helpStr); + } + + /* add in STARTUP ONLY info */ + if ((swdef->type & SWOPT_STARTUP_ONLY) && + (!(options & POPT_AT_STARTUP))) + { + pclHelpValuesCheck(strbuf,HELPOPT_HEADER); + strcat(strbuf,MSGNot("NSSSTART.CFG")); + } + if (swdef->ret_value != NULL) + { + pclHelpValuesCheck(strbuf,HELPOPT_HEADER); + strcat(strbuf,MSG("Value=",159)); + pclGetDisplayableReturnValue(swdef,&strbuf[strlen(strbuf)]); + } + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + pclHelpValuesCheck(strbuf,HELPOPT_HEADER); + sprintf(&strbuf[strlen(strbuf)],MSG("Range=%u-%u", 160), + swdef->vtype.numeric.minValue, + swdef->vtype.numeric.maxValue); + } + pclHelpValuesCheck(strbuf,HELPOPT_TRAILER); + helpStr = strbuf; + } + else + { + helpStr = StructGetMSGStrWithTable(swdef->helpStr,messageTable); + helpStr = ((helpStr != NULL) ? helpStr : MSGNot("")); + } + + + if(*helpStr) + { + while(*helpStr) + { + remLength = strlen(helpStr); + /* if the line will fit, print it. If it won't fit, back off to the + * closest space. If not spaces found, enforce a wrap point + */ + if(remLength <= spaceAvail) + { + endStr = helpStr + remLength; + } + else + { + for(endStr = helpStr+spaceAvail; + (endStr != helpStr) && (*endStr != ' '); endStr--); + + if(endStr == helpStr) + { + endStr = helpStr + spaceAvail; + } + } + for(;helpStr != endStr; helpStr++) + aprintf(LGREEN,MSGNot("%c"), *helpStr); + aprintf(LGREEN, MSGNot("\n")); + while(*helpStr == ' ') + helpStr++; + if(*helpStr) + { + aprintf(LGREEN, MSGNot(" ")); + spaceAvail = SCREEN_WIDTH - indent; + } + LB_delay(2); + } + } + else + { + aprintf(LGREEN, MSGNot("\n")); + } + + free(strbuf); + +} +#else +/**************************************************************************** + * This will display one line of help. + ***************************************************************************/ +STATIC void pclDisplayHelpLine( + PCLSwitchDef_s *swdef, + char **messageTable, + NINT indent, + NINT options) +{ + NINT row,col; + char *outstr; + char *helpStr; + char strbuf[1024]; +# define INITIAL_INDENT 0 +# define MSG_INDENT 24 + + aprintf(WHITE,MSGNot("\n")); //wrw /* this forces something out so the line will scroll*/ + wGetPos(wStdout,&row,&col); + wSetPos(wStdout,row,INITIAL_INDENT+indent); + + switch (GET_SWTYPE(swdef->type)) + { + case SWTYPE_NAME: + aprintf(CYAN,MSGNot(" %s "),swdef->name); + break; + case SWTYPE_REQUIRED: + aprintf(CYAN,MSGNot(" %s "),swdef->name); + break; + case SWTYPE_OPTIONAL: + aprintf(CYAN,MSGNot(" %s "),swdef->name); + break; + case SWTYPE_BOOLEAN: + aprintf(CYAN,MSGNot("/(No)%s "),swdef->name); + break; + case SWTYPE_VALUE: + aprintf(CYAN,MSGNot(" /%s= "),swdef->name); + break; + } + wGetPos(wStdout,&row,&col); + if (col < MSG_INDENT) + wSetPos(wStdout,row,MSG_INDENT); +/*------------------------------------------------------------------------- + * Calculate the current default value if available. + *-------------------------------------------------------------------------*/ + if (!(swdef->type & SWOPT_NO_HELP_VALUE)) + { + /* put in there help string */ + strbuf[0] = 0; /* make it a NULL string */ + helpStr = StructGetMSGStrWithTable(swdef->helpStr,messageTable); + + if (helpStr != NULL) + { + strcpy(strbuf,helpStr); + } + + /* add in STARTUP ONLY info */ + if ((swdef->type & SWOPT_STARTUP_ONLY) && + (!(options & POPT_AT_STARTUP))) + { + pclHelpValuesCheck(strbuf,HELPOPT_HEADER); + strcat(strbuf,MSGNot("NSSSTART.CFG")); + } + if (swdef->ret_value != NULL) + { + pclHelpValuesCheck(strbuf,HELPOPT_HEADER); + strcat(strbuf,MSG("Value=",159)); + pclGetDisplayableReturnValue(swdef,&strbuf[strlen(strbuf)]); + } + if (swdef->type & SWOPT_HAS_NUMERIC_RANGE) + { + pclHelpValuesCheck(strbuf,HELPOPT_HEADER); + sprintf(&strbuf[strlen(strbuf)],MSG("Range=%u-%u", 160), + swdef->vtype.numeric.minValue, + swdef->vtype.numeric.maxValue); + } + pclHelpValuesCheck(strbuf,HELPOPT_TRAILER); + outstr = strbuf; + } + else + { + helpStr = StructGetMSGStrWithTable(swdef->helpStr,messageTable); + outstr = ((helpStr != NULL) ? helpStr : MSGNot("")); + } + + LB_wWrapString(wStdout,LGREEN,MSG_INDENT,outstr); +} +#endif + + +/************************************************************************** + * Given a switch defintion structure, this will display help for the + * switches. + ***************************************************************************/ +void LB_DisplayCmdlineHelpMulti( + PCLMultiSwitchList_s *multiList, /* multi definitions array */ + NINT options, + NINT hiddenFlag, /* if true, display hidden only, if false, visible only */ + char *title, + ...) +{ + NINT cmdCnt; + NINT lastIndex; + NINT i,j; + NINT sl; + NINT row,col; + NINT displayMask; + + PCLSwitchDef_s *swdef; /* switch definitions array*/ + CmdNameSort_s (*sortArray)[]; /* sorted list of command pointers */ + + char **msgTable; + va_list args; +# define GROUP_INDENT 2 + + + if (title != NULL) + { + va_start(args,title); + vaprintf(YELLOW,title,args); + } + + aprintf(YELLOW,MSG("Options:", 161)); + wGetPos(wStdout,&row,&col); + wSetPos(wStdout,row,MSG_INDENT); + aprintf(YELLOW,MSG("(are case insensitive, support unique abbreviations)\n", 162)); +/*------------------------------------------------------------------------- + * Loop through and make sure the TYPE field only has valid values. + *-------------------------------------------------------------------------*/ + for (sl=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + swdef->type &= SWTYPE_SET_START; /* init flag state */ + } + } +/* Run through the list to find how many command lines we'll need to keep track of. */ + + for (sl=cmdCnt=0;(swdef = multiList[sl].swList) != NULL;sl++) + { + if (swdef->name != PCMDLINE_ENDOFLIST) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if (((!(swdef->type & SWOPT_RUNTIME_ONLY)) || + (!(options & POPT_AT_STARTUP))) && + /* ((!(swdef->type & SWOPT_STARTUP_ONLY)) || + ((options & POPT_AT_STARTUP))) && */ + + (((!hiddenFlag) && ((swdef->type & SWOPT_HIDDEN) == 0))|| + (hiddenFlag && (swdef->type & SWOPT_HIDDEN))) && + + !(swdef->type & SWPRV_GROUP_ACTIVE)) + + cmdCnt++; + } + } + } + + if((cmdCnt == 0) || ((sortArray = malloc(cmdCnt * sizeof(CmdNameSort_s))) == NULL)) + return; + + /* Create an array or pointers from all the command lines */ + for (sl = cmdCnt = 0;(swdef = multiList[sl].swList) != NULL;sl++) + { + if (swdef->name != PCMDLINE_ENDOFLIST) + { + for (;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if (((!(swdef->type & SWOPT_RUNTIME_ONLY)) || + (!(options & POPT_AT_STARTUP))) && + /* ((!(swdef->type & SWOPT_STARTUP_ONLY)) || + ((options & POPT_AT_STARTUP))) && */ + + (((!hiddenFlag) && ((swdef->type & SWOPT_HIDDEN) == 0))|| + (hiddenFlag && (swdef->type & SWOPT_HIDDEN))) && + + !(swdef->type & SWPRV_GROUP_ACTIVE)) + { + (*sortArray)[cmdCnt].msgTable = multiList[sl].messageTable; + (*sortArray)[cmdCnt].swdef = swdef; + cmdCnt++; + } + } + } + } + + /* bubble sort the array by switch names */ + lastIndex = cmdCnt - 1; + for (sl=0; sl < lastIndex; sl++) + { + for (j=0; j < lastIndex - sl; j++) + { + if(strcmp((*sortArray)[j].swdef->name, (*sortArray)[j+1].swdef->name) > 0) + { + msgTable = (*sortArray)[j].msgTable; + swdef = (*sortArray)[j].swdef; + (*sortArray)[j].msgTable = (*sortArray)[j+1].msgTable; + (*sortArray)[j].swdef = (*sortArray)[j+1].swdef; + (*sortArray)[j+1].msgTable = msgTable; + (*sortArray)[j+1].swdef = swdef; + } + } + } + +/* Now send out each of the command lines */ + for (i=0; itype & displayMask) + { + msgTable = (*sortArray)[sl].msgTable; + pclDisplayHelpLine(swdef,msgTable,0,options); + if (swdef->groupValue != 0) + { + for (j=1;swdef[j].name != PCMDLINE_ENDOFLIST;j++) + { + if ((swdef[j].groupValue == swdef->groupValue) && + ((!(swdef[j].type & SWOPT_RUNTIME_ONLY)) || + (!(options & POPT_AT_STARTUP))) && + /* ((!(swdef[j].type & SWOPT_STARTUP_ONLY)) || + ((options & POPT_AT_STARTUP))) && */ + !(swdef[j].type & SWOPT_HIDDEN) && + !(swdef[j].type & SWPRV_GROUP_ACTIVE)) + { + pclDisplayHelpLine(&swdef[j],msgTable,GROUP_INDENT,options); + swdef[j].type |= SWPRV_GROUP_ACTIVE; + } + } + } + } + } + } + + aprintf(WHITE,MSGNot("\n")); //wrw //add final linefeed +/*------------------------------------------------------------------------- + * Free up to sort array + *-------------------------------------------------------------------------*/ + free (sortArray); +} + +/************************************************************************** + * You can call this routine if you just have one swith definition array + * to display help for. + ***************************************************************************/ +void LB_DisplayCmdlineHelp( + PCLSwitchDef_s *swdef, + char **messageTable, + NINT options, + char *title, + ...) +{ + va_list args; + PCLMultiSwitchList_s multiArray[2]; + + if (title != NULL) + { + va_start(args,title); + vaprintf(LGREEN,title,args); + } + + multiArray[0].swList = swdef; + multiArray[0].messageTable = messageTable; + multiArray[0].moduleName = NULL; + multiArray[1].swList = NULL; + + LB_DisplayCmdlineHelpMulti(&multiArray[0],options,FALSE,NULL); +} + + +#ifndef __linux__ // LINUX_SetParms +/************************************************************************** + * This routine is called to register set parameter options for NSS. + ***************************************************************************/ +void LB_RegisterSetParmsForNSS( + PCLSwitchDef_s *swList, + char **msgTable) +{ + PCLSwitchDef_s *swdef; + LONG ccode; + + ASSERT_MPKNSS_LOCK(); + + if (NSSSetParmCategory == 0) + return; + + for (swdef = swList; swdef->name != PCMDLINE_ENDOFLIST; swdef++) + { + if (swdef->setParmName) + { + zASSERT(swdef->ret_value != NULL); + + ZOS_RegisterSetParameter(ccode, + (LONG)COMN_Resource.moduleHandle, + COMN_Resource.setCmdRTag, + NSSSetParmCategory, + NULL, + swdef->setParmFlags, + (LONG *)swdef->ret_value, + swdef->setParmName, + msgTable ? + StructGetMSGStrWithTable(swdef->helpStr,msgTable) : + StructGetMSGStr(swdef->helpStr), + swdef->setParmType, + swdef->vtype.numeric.minValue, + swdef->vtype.numeric.maxValue); + if (ccode != 0) + { + errPrintf(WHERE, LibModule, 636, + MSG("Could not register (Status = %d) set parameter: %s", + 196), ccode, swdef->setParmName); + } + + } + } +} +#endif + +#ifndef __linux__ // LINUX_SetParms +/************************************************************************** + * This routine is called to register set parameter options for NSS. + ***************************************************************************/ +void LB_UnRegisterSetParmsForNSS( + PCLSwitchDef_s *swlist) +{ + PCLSwitchDef_s *swdef; + LONG ccode; + + ASSERT_MPKNSS_LOCK(); + + if (NSSSetParmCategory == 0) + return; + + for (swdef = swlist;swdef->name != PCMDLINE_ENDOFLIST;swdef++) + { + if (swdef->setParmName) + { + ZOS_DeRegisterSetParameter(ccode, + (LONG)COMN_Resource.moduleHandle, + COMN_Resource.setCmdRTag, + NSSSetParmCategory, + swdef->setParmName); + if (ccode != 0) + { + errPrintf(WHERE, LibModule, 646, + MSG("Could not deregister (Status = %d) set parameter: %s", + 197), ccode, swdef->setParmName); + } + } + } + return; +} +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b0a2bc2..7e1ff26 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,6 +24,7 @@ if(MARS_NWE_BUILD_NWFS_TESTS) add_subdirectory(core/pssdebug) add_subdirectory(core/register) add_subdirectory(core/schedule) + add_subdirectory(core/parse) add_subdirectory(core/zalloc) add_subdirectory(core/stdio) add_subdirectory(core/wio) diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index c9cb484..01d1ddf 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(mailbox) add_subdirectory(pssdebug) add_subdirectory(register) add_subdirectory(schedule) +add_subdirectory(parse) add_subdirectory(bit) add_subdirectory(bitmap) add_subdirectory(crc) diff --git a/tests/core/parse/CMakeLists.txt b/tests/core/parse/CMakeLists.txt new file mode 100644 index 0000000..25ee693 --- /dev/null +++ b/tests/core/parse/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(test_nwcore_parse test_nwcore_parse.c) +target_link_libraries(test_nwcore_parse PRIVATE mars_nwe::core) +add_test(NAME nwcore.parse COMMAND test_nwcore_parse) diff --git a/tests/core/parse/test_nwcore_parse.c b/tests/core/parse/test_nwcore_parse.c new file mode 100644 index 0000000..b366469 --- /dev/null +++ b/tests/core/parse/test_nwcore_parse.c @@ -0,0 +1,56 @@ +#include +#include + +#include +#include + +#define CHECK(expr) \ + do { \ + if (!(expr)) { \ + fprintf(stderr, "CHECK failed at %s:%d: %s\n", __FILE__, __LINE__, #expr); \ + return 1; \ + } \ + } while (0) + +int main(void) +{ + char value[32] = {0}; + NINT flag = -1; + NINT count = 0; + + PCLSwitchDef_s switches[] = { + { + "name", NULL, + SWTYPE_VALUE | SWVAL_CHAR, + 0, 0, NULL, + value, + .vtype.string = {sizeof(value), 0}, + 0, 0, StructMSGNot("name value"), NULL, NULL + }, + { + "enabled", NULL, + SWTYPE_BOOLEAN | SWVAL_NINT, + 0, 0, NULL, + &flag, + .vtype.numeric = {0, 1}, + 0, 0, StructMSGNot("enabled flag"), NULL, NULL + }, + { + "count", NULL, + SWTYPE_VALUE | SWVAL_NINT, + 0, 0, NULL, + &count, + .vtype.numeric = {0, 100}, + 0, 0, StructMSGNot("count value"), NULL, NULL + }, + {PCMDLINE_ENDOFLIST} + }; + + CHECK(LB_ParseCmdline(switches, POPT_AT_RUNTIME, + "/name=demo /enabled /count=42", NULL) == zOK); + CHECK(strcmp(value, "demo") == 0); + CHECK(flag == TRUE); + CHECK(count == 42); + + return 0; +}