summaryrefslogtreecommitdiffstats
path: root/private/nw/nwscript/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/nwscript/script.c')
-rw-r--r--private/nw/nwscript/script.c3968
1 files changed, 3968 insertions, 0 deletions
diff --git a/private/nw/nwscript/script.c b/private/nw/nwscript/script.c
new file mode 100644
index 000000000..14df55b93
--- /dev/null
+++ b/private/nw/nwscript/script.c
@@ -0,0 +1,3968 @@
+
+/*************************************************************************
+*
+* SCRIPT.C
+*
+* Script routines, ported from DOS
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+*************************************************************************/
+
+#include "common.h"
+#include <direct.h>
+#include <time.h>
+#include <ctype.h>
+#include <process.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <time.h>
+
+extern VOID nwShowLastLoginTime( VOID );
+
+#define MAXLEN 256
+#define MAX_NUM_IF 10
+
+#define NUMCOMMAND 44
+
+#define CM_IF 20
+#define CM_ELSE 21
+#define CM_END 22
+
+//
+// 3X and 4X variables
+//
+
+#define IDS_DAY_OF_WEEK 0
+#define IDS_DAY 1
+#define IDS_MONTH_NAME 2
+#define IDS_MONTH 3
+#define IDS_NDAY_OF_WEEK 4
+#define IDS_SHORT_YEAR 5
+#define IDS_YEAR 6
+#define IDS_AM_PM 7
+#define IDS_GREETING_TIME 8
+#define IDS_HOUR24 9
+#define IDS_HOUR 10
+#define IDS_MINUTE 11
+#define IDS_SECOND 12
+#define IDS_FULL_NAME 13
+#define IDS_LOGIN_NAME 14
+#define IDS_USER_ID 15
+#define IDS_PASSWORD_EXPIRES 16
+#define IDS_NETWORK_ADDRESS 17
+#define IDS_FILE_SERVER 18
+#define IDS_ACCESS_SERVER 19
+#define IDS_ERROR_LEVEL 20
+#define IDS_ERRORLEVEL 21
+#define IDS_MACHINE 22
+#define IDS_OS_VERSION 23
+#define IDS_OS 24
+#define IDS_SMACHINE 25
+#define IDS_SHELL_TYPE 26
+#define IDS_STATION 27
+#define IDS_P_STATION 28
+#define IDS_SHELL_VERSION 29
+#define NUMVAR_3X IDS_SHELL_VERSION + 1
+
+#define IDS_LAST_NAME 30
+#define IDS_LOGIN_CONTEXT 31
+#define IDS_NETWARE_REQUESTER 32
+#define IDS_REQUESTER_CONTEXT 33
+#define IDS_ACCOUNT_BALANCE 34
+#define IDS_CN 35
+#define IDS_REQUESTER_VERSION 36
+#define IDS_SURNAME 37
+#define IDS_DOS_REQUESTER 38
+#define IDS_REQUESTER 39
+#define IDS_ADMINISTRATIVE_ASSISTANT 40
+#define IDS_ALLOW_UNLIMITED_CREDIT 41
+#define IDS_DESCRIPTION 42
+#define IDS_EMAIL_ADDRESS 43
+#define IDS_EMPLOYEE_ID 44
+#define IDS_FACSIMILE_TELEPHONE_NUMBER 45
+#define IDS_GROUP_MEMBERSHIP 46
+#define IDS_HIGHER_PRIVILEGES 47
+#define IDS_HOME_DIRECTORY 48
+#define IDS_INITIALS 49
+#define IDS_LANGUAGE 50
+#define IDS_LOCKED_BY_INTRUDER 51
+#define IDS_LOGIN_DISABLED 52
+#define IDS_LOGIN_GRACE_LIMIT 53
+#define IDS_LOGIN_GRACE_REMAINING 54
+#define IDS_LOGIN_INTRUDER_ATTEMPTS 55
+#define IDS_LOGIN_MAXIMUM_SIMULTANEOUS 56
+#define IDS_MAILSTOP 57
+#define IDS_MESSAGE_SERVER 58
+#define IDS_MINIMUM_ACCOUNT_BALANCE 59
+#define IDS_NETWORK 60
+#define IDS_OBJECT_CLASS 61
+#define IDS_OU 62
+#define IDS_PASSWORD_ALLOW_CHANGE 63
+#define IDS_PASSWORD_MINIMUM_LENGTH 64
+#define IDS_PASSWORD_REQUIRED 65
+#define IDS_PASSWORD_UNIQUE_REQUIRED 66
+#define IDS_PASSWORDS_USED 67
+#define IDS_PHYSICAL_DELIVERY_OFFICE_NAME 68
+#define IDS_POSTAL_ADDRESS 69
+#define IDS_POSTAL_CODE 70
+#define IDS_POSTAL_OFFICE_BOX 71
+#define IDS_PRIVATE_KEY 72
+#define IDS_PROFILE 73
+#define IDS_REVISION 74
+#define IDS_SECURITY_EQUALS 75
+#define IDS_SECURITY_FLAGS 76
+#define IDS_SEE_ALSO 77
+#define IDS_SERVER_HOLDS 78
+#define IDS_SUPERVISOR 79
+#define IDS_TELEPHONE_NUMBER 80
+#define IDS_TITLE 81
+#define IDS_CERTIFICATE_VALIDITY_INTERVAL 82
+#define IDS_EQUIVALENT_TO_ME 83
+#define IDS_GENERATIONAL_QUALIFIER 84
+#define IDS_GIVEN_NAME 85
+#define IDS_MAILBOX_ID 86
+#define IDS_MAILBOX_LOCATION 87
+#define IDS_PROFILE_MEMBERSHIP 88
+#define IDS_SA 89
+#define IDS_S 90
+#define IDS_L 91
+#define IDS_ACCESS 92
+#define NUMVAR IDS_ACCESS + 1
+
+/*
+ * String constants.
+ */
+
+/*
+ * Text for default Login Script. Don't change.
+ */
+BYTE DefaultLoginScript[] =
+ "WRITE \"Good %GREETING_TIME, %LOGIN_NAME.\\n\"\n"
+ "MAP DISPLAY OFF\n"
+ "MAP ERRORS OFF\n"
+ "Rem: Set 1st drive to most appropriate directory.\n"
+ "MAP *1:=%FILE_SERVER/SYS:;*1:=%FILE_SERVER/SYS:%LOGIN_NAME\n"
+ "If LOGIN_NAME=\"SUPERVISOR\" || LOGIN_NAME=\"ADMIN\" || LOGIN_NAME=\"SUPERVIS\" THEN MAP *1:=%FILE_SERVER/SYS:SYSTEM\n"
+ "Rem: Set search drives (S2 machine-OS dependent).\n"
+ "MAP INS S1:=%FILE_SERVER/SYS:PUBLIC\n"
+ "MAP INS S2:=%FILE_SERVER/SYS:\n"
+ "Rem: Now display all the current drive settings.\n"
+ "MAP DISPLAY ON\n"
+ "MAP\n"
+ "\0";
+
+char *__SPACES__=" \t";
+
+/*
+ * Do not change the order of this array.
+ */
+char * COMPARE_OPERATORS[] =
+{
+ "!=",
+ "<>",
+ "NOT EQUAL TO",
+ "DOES NOT EQUAL",
+ "NOT EQUAL",
+ "IS NOT EQUAL",
+ "#",
+ "IS NOT", // 7
+ ">=", // 8
+ "IS GREATER THAN OR EQUAL TO",
+ "IS GREATER THAN OR EQUAL",
+ "GREATER THAN OR EQUAL TO",
+ "GREATER THAN OR EQUAL",
+ ">", // 13
+ "IS GREATER THAN",
+ "GREATER THAN",
+ "<=", // 16
+ "IS LESS THAN OR EQUAL TO",
+ "IS LESS THAN OR EQUAL",
+ "LESS THAN OR EQUAL TO",
+ "LESS THAN OR EQUAL",
+ "<", // 21
+ "IS LESS THAN",
+ "LESS THAN",
+ "==", // 24
+ "=",
+ "EQUALS",
+ "EQUAL",
+ "IS",
+ "\0"
+};
+
+int IsNotEqual (int nIndex)
+{
+ return(nIndex < 8);
+}
+
+int IsGreaterOrEqual (int nIndex)
+{
+ return(nIndex >= 8 && nIndex < 13);
+}
+
+int IsGreater (int nIndex)
+{
+ return(nIndex >= 13 && nIndex < 16);
+}
+
+int IsLessOrEqual (int nIndex)
+{
+ return(nIndex >= 16 && nIndex < 21);
+}
+
+int IsLess (int nIndex)
+{
+ return(nIndex >= 21 && nIndex < 24);
+}
+
+/*
+ * Type defs.
+ */
+typedef int (*PFCommandHandler) (char *lpParam);
+
+typedef struct tagCOMMANDTABLE
+{
+ char *commandStr0;
+ char *commandStr1;
+ char *commandStr2;
+ PFCommandHandler commandhandler;
+}COMMANDTABLE;
+
+typedef struct tagLABEL_LIST
+{
+ char *pLabel;
+ char *pNextLine;
+ struct tagLABEL_LIST *pNext;
+}LABEL_LIST, *PLABEL_LIST;
+
+/*
+ * Functions that are in command dispatch table.
+ */
+int AttachHandler (char *lpParam);
+int BreakHandler (char *lpParam);
+int ComspecHandler (char *lpParam);
+int DisplayHandler (char *lpParam);
+int DosBreakHandler (char *lpParam);
+int SetHandler (char *lpParam);
+int LocalSetHandler (char *lpParam);
+int DosVerifyHandler (char *lpParam);
+int DriveHandler (char *lpParam);
+int FireHandler (char *lpParam);
+int ExitHandler (char *lpParam);
+int IfHandler (char *lpParam);
+int ElseHandler (char *lpParam);
+int EndHandler (char *lpParam);
+int IncludeHandler (char *lpParam);
+int MapHandler (char *lpParam);
+int PauseHandler (char *lpParam);
+int WriteHandler (char *lpParam);
+int NullHandler (char *lpParam);
+int GotoHandler (char *lpParam);
+int ShiftHandler (char *lpParam);
+int MachineHandler (char *lpParam);
+int CompatibleHandler(char *lpParam);
+int ClearHandler (char *lpParam);
+int LastLoginTimeHandler(char *lpParam);
+int ContextHandler (char *lpParam);
+int ScriptServerHandler(char *lpParam);
+int NoDefaultHandler (char *lpParam);
+
+/*
+ * Command dispatch table. Do not change.
+ *
+ * If you do, you must change CM_IF, CM_ELSE, and CM_END
+ */
+COMMANDTABLE nwCommand[NUMCOMMAND] =
+{
+ "LOCAL", "DOS", "SET", LocalSetHandler,
+ "TEMP", "DOS", "SET", LocalSetHandler,
+ "TEMPORARY", "DOS", "SET", LocalSetHandler,
+ "LOCAL", "SET", NULL, LocalSetHandler,
+ "TEMP", "SET", NULL, LocalSetHandler,
+ "TEMPORARY", "SET", NULL, LocalSetHandler,
+ "DOS", "SET", NULL, SetHandler,
+ "DOS", "VERIFY", NULL, DosVerifyHandler,
+ "DOS", "BREAK", NULL, DosBreakHandler,
+ "FIRE", "PHASERS", NULL, FireHandler,
+ "ATTACH", NULL, NULL, AttachHandler,
+ "BREAK", NULL, NULL, BreakHandler,
+ "COMSPEC", NULL, NULL, NullHandler,
+ "DISPLAY", NULL, NULL, DisplayHandler,
+ "SET_TIME", NULL, NULL, NullHandler,
+ "SET", NULL, NULL, SetHandler,
+ "DRIVE", NULL, NULL, DriveHandler,
+ "FDISPLAY", NULL, NULL, DisplayHandler,
+ "FIRE", NULL, NULL, FireHandler,
+ "EXIT", NULL, NULL, ExitHandler,
+ "IF", NULL, NULL, IfHandler, // CM_IF
+ "ELSE", NULL, NULL, ElseHandler, // CM_ELSE
+ "END", NULL, NULL, EndHandler, // CM_END
+ "INCLUDE", NULL, NULL, IncludeHandler,
+ "MACHINE", NULL, NULL, MachineHandler,
+ "MAP", NULL, NULL, MapHandler,
+ "PAUSE", NULL, NULL, PauseHandler,
+ "COMPATIBLE", NULL, NULL, CompatibleHandler,
+ "PCCOMPATIBLE", NULL, NULL, CompatibleHandler,
+ "REMARK", NULL, NULL, NullHandler,
+ "REM", NULL, NULL, NullHandler,
+ "SHIFT", NULL, NULL, ShiftHandler,
+ "WAIT", NULL, NULL, PauseHandler,
+ "WRITE", NULL, NULL, WriteHandler,
+ "GOTO", NULL, NULL, GotoHandler,
+ "CLS", NULL, NULL, ClearHandler,
+ "CLEAR", NULL, NULL, ClearHandler,
+ "SWAP", NULL, NULL, NullHandler,
+ "LASTLOGIN", NULL, NULL, LastLoginTimeHandler, // 38
+ "CONTEXT", NULL, NULL, ContextHandler, // 39
+ "SCRIPT_SERVER", NULL, NULL, ScriptServerHandler, // 40
+ "NO_DEFAULT", NULL, NULL, NoDefaultHandler, // 41
+ "CX", NULL, NULL, ContextHandler, // 42
+ "PATH", NULL, NULL, MapHandler, // 43
+};
+
+typedef struct tagVARTABLE
+{
+ char *VarName;
+}VARTABLE;
+
+VARTABLE varTable[NUMVAR] =
+{
+ "DAY_OF_WEEK",
+ "DAY",
+ "MONTH_NAME",
+ "MONTH",
+ "NDAY_OF_WEEK",
+ "SHORT_YEAR",
+ "YEAR",
+ "AM_PM",
+ "GREETING_TIME",
+ "HOUR24",
+ "HOUR",
+ "MINUTE",
+ "SECOND",
+ "FULL_NAME",
+ "LOGIN_NAME",
+ "USER_ID",
+ "PASSWORD_EXPIRES",
+ "NETWORK_ADDRESS",
+ "FILE_SERVER",
+ "ACCESS_SERVER",
+ "ERROR_LEVEL",
+ "ERRORLEVEL",
+ "MACHINE",
+ "OS_VERSION",
+ "OS",
+ "SMACHINE",
+ "SHELL_TYPE",
+ "STATION",
+ "P_STATION",
+ "SHELL_VERSION",
+ "LAST_NAME",
+ "LOGIN_CONTEXT",
+ "NETWARE_REQUESTER",
+ "REQUESTER_CONTEXT",
+ "ACCOUNT_BALANCE",
+ "CN",
+ "REQUESTER_VERSION",
+ "SURNAME",
+ "DOS_REQUESTER",
+ "REQUESTER",
+ "ADMINISTRATIVE_ASSISTANT",
+ "ALLOW_UNLIMITED_CREDIT",
+ "DESCRIPTION",
+ "EMAIL_ADDRESS",
+ "EMPLOYEE_ID",
+ "FACSIMILE_TELEPHONE_NUMBER",
+ "GROUP_MEMBERSHIP",
+ "HIGHER_PRIVILEGES",
+ "HOME_DIRECTORY",
+ "INITIALS",
+ "LANGUAGE",
+ "LOCKED_BY_INTRUDER",
+ "LOGIN_DISABLED",
+ "LOGIN_GRACE_LIMIT",
+ "LOGIN_GRACE_REMAINING",
+ "LOGIN_INTRUDER_ATTEMPTS",
+ "LOGIN_MAXIMUM_SIMULTANEOUS",
+ "MAILSTOP",
+ "MESSAGE_SERVER",
+ "MINIMUM_ACCOUNT_BALANCE",
+ "NETWORK",
+ "OBJECT_CLASS",
+ "OU",
+ "PASSWORD_ALLOW_CHANGE",
+ "PASSWORD_MINIMUM_LENGTH",
+ "PASSWORD_REQUIRED",
+ "PASSWORD_UNIQUE_REQUIRED",
+ "PASSWORDS_USED",
+ "PHYSICAL_DELIVERY_OFFICE_NAME",
+ "POSTAL_ADDRESS",
+ "POSTAL_CODE",
+ "POSTAL_OFFICE_BOX",
+ "PRIVATE_KEY",
+ "PROFILE",
+ "REVISION",
+ "SECURITY_EQUALS",
+ "SECURITY_FLAGS",
+ "SEE_ALSO",
+ "SERVER_HOLDS",
+ "SUPERVISOR",
+ "TELEPHONE_NUMBER",
+ "TITLE",
+ "CERTIFICATE_VALIDITY_INTERVAL",
+ "EQUIVALENT_TO_ME",
+ "GENERATIONAL_QUALIFIER",
+ "GIVEN_NAME",
+ "MAILBOX_ID",
+ "MAILBOX_LOCATION",
+ "PROFILE_MEMBERSHIP",
+ "SA",
+ "S",
+ "L",
+ "ACCESS",
+};
+
+/*
+ * Local functions.
+ */
+void SmartCap(char *ptr);
+int NWGetFileSize (char * lpFileName);
+void LoadFile (char *lpFileName, char *lpFileBuffer, int nFileSize);
+int ProcessLoginScriptFile (char *lpLoginScriptFile);
+void ProcessLoginScript (char *lpLoginScript);
+int ProcessLoginScriptProperty (unsigned char *);
+
+int CreateLabelList (PLABEL_LIST *ppLabelList, char *lpLoginScript);
+void FreeLabelList (LABEL_LIST *pLabelList);
+
+void ExternalCmdHandler(char *lpCommand);
+void BadCommandHandler (char *lpCommand);
+
+void CommandDispatch (char *lpCommand);
+int GetTableIndex(char *lpCommand, char ** prestbuffer);
+
+DWORD SwapLong(DWORD number);
+int EndOfLine (char *buffer);
+char *RemoveSpaces (char * buffer);
+int IsOn (char *lpParam);
+int IsOff (char *lpParam);
+int VarTranslate(char *vartext);
+int QuotedStringTranslate (char *buffer);
+void NotQuotedStringTranslate(char *buffer, BOOL remove_dbs);
+void SetLocalEnv(char *buffer);
+int SetEnv (char *lpEnvLine);
+char *ConvertPercent (char *buffer);
+void GetShellVersion(char *buffer, int index);
+
+/*
+ * Global Defines
+ */
+#define IsWhiteSpace(x) ((x==' ')||(x=='\t')||(x=='\n')||(x=='\r')||(x==0))
+
+/*
+ * Global variables.
+ */
+
+//
+// The following globals are used for goto processing... this allows us
+// to manipulate the line we're processing outside ProcessLoginScript.
+//
+
+LABEL_LIST *pGlobalLabelList;
+char *lpGlobalLine;
+char *lpGlobalLineSeparator;
+int fGlobalHaveNulledLineSeparator;
+int fGlobalExitFlag;
+int fGlobalIfTooDeep;
+
+int fBreakOn = TRUE;
+
+int nCondIndex;
+int aCondVal[MAX_NUM_IF];
+
+int ARGC;
+char **ARGV;
+int nGlobalShiftDelta = 0;
+int fGlobalCompatible = FALSE;
+int fNoDefaultLoginScript = FALSE;
+
+char *LOGIN_NAME;
+char *LAST_NAME;
+char *LOGIN_CONTEXT;
+char *REQUESTER_CONTEXT;
+char *COMMON_NAME;
+char *TYPED_USER_NAME;
+PWCHAR TYPED_USER_NAME_w;
+PBYTE NDSTREE;
+PBYTE PREFERRED_SERVER;
+
+HANDLE hconout = INVALID_HANDLE_VALUE;
+
+unsigned int CONNECTION_ID;
+unsigned int CONNECTION_NUMBER;
+unsigned int SCRIPT_ERROR = 0;
+
+#define REQUESTER_VERSION "V1.20"
+
+extern DWORD GUserObjectID;
+
+int IsEmptyFile (char *lpFile)
+{
+ while (*lpFile != 0)
+ {
+ if (*lpFile != ' ' &&
+ *lpFile != '\t'&&
+ *lpFile != '\n'&&
+ *lpFile != '\r')
+ {
+ return(FALSE);
+ }
+ lpFile++;
+ }
+
+ return(TRUE);
+}
+
+/*
+ * Login was successful. Process both Login Scripts: the System Login
+ * Script and the User Login Script. If there is an EXIT command in the
+ * System Login Script, then we do not process the User Login Script.
+ * If there is no User Login Script, we process a default Login Script,
+ * which is hard-coded internally. See the Login Script appendix in
+ * the NetWare Installation guide for more info.
+ */
+void ProcessLoginScripts (unsigned int conn, char *UserName, int argc, char ** argv, char *lpScript)
+{
+ unsigned int iRet = 0;
+ unsigned long userID ;
+ char pchUserLoginScriptFile[24];
+
+ // Initalize LOGIN_NAME, CONNECTION_ID and CONNECTION_NUMBER.
+ ARGC = argc;
+ ARGV = argv;
+ LOGIN_NAME = UserName;
+ CONNECTION_ID = conn;
+
+ // Initialize some 4X variables
+ if ( fNDS )
+ {
+ COMMON_NAME = UserName;
+
+ LOGIN_CONTEXT = malloc ( CONTEXT_MAX );
+ strcpy( LOGIN_CONTEXT, REQUESTER_CONTEXT );
+
+ LAST_NAME = malloc( MAXLEN );
+ NDSGetVar ( "SURNAME", LAST_NAME, MAXLEN );
+ }
+ else {
+ LAST_NAME = UserName;
+ COMMON_NAME = UserName;
+ LOGIN_CONTEXT = "";
+ REQUESTER_CONTEXT = "";
+ }
+
+ if (iRet = GetConnectionNumber (conn, &CONNECTION_NUMBER))
+ {
+ DisplayError (iRet, "GetConnectionNumber");
+ return;
+ }
+
+ if (lpScript)
+ {
+ if (!ProcessLoginScriptFile(lpScript))
+ DisplayMessage(IDR_NO_SCRIPT_FILE, lpScript);
+ }
+ else
+ {
+ if ( fNDS )
+ {
+ unsigned char Object[128];
+ unsigned char ProfileObject[256];
+ PBYTE p;
+ int err;
+
+ // Browse back from user's node to first occurrence
+ // or organizational unit or organization and look for
+ // system script there. If the nearest OU or O doesn't have
+ // a system script, don't run one.
+
+ for ( p = TYPED_USER_NAME; p ; p = strchr ( p, '.' ) )
+ {
+
+ p++;
+
+ if ( *p == 'O' && *(p+1) == 'U' && *(p+2) == '=' )
+ break;
+
+ if ( *p == 'O' && *(p+1) == '=' )
+ break;
+ }
+
+ if ( p != NULL )
+ {
+ ProcessLoginScriptProperty( p );
+ }
+
+ // profile login script.
+
+ if ( !NDSGetUserProperty ( "Profile", ProfileObject, 256, NULL, NULL) )
+ {
+ ConvertUnicodeToAscii( ProfileObject );
+ ProcessLoginScriptProperty( ProfileObject );
+ }
+
+ // user login script
+
+ if ( (!ProcessLoginScriptProperty( TYPED_USER_NAME )) &&
+ (!fNoDefaultLoginScript) )
+ {
+ ProcessLoginScript (DefaultLoginScript);
+ }
+ }
+ else
+ {
+ static char SysLoginScriptFile[] = "SYS:PUBLIC/NET$LOG.DAT" ;
+
+ // Process system login script file.
+ ProcessLoginScriptFile (SysLoginScriptFile);
+
+ // Check if user login script exists.
+ if (iRet = GetBinderyObjectID (conn, UserName, OT_USER,
+ &userID))
+ return;
+
+ sprintf(pchUserLoginScriptFile, "SYS:MAIL/%lx/LOGIN", SwapLong(userID));
+
+ if ( (!ProcessLoginScriptFile (pchUserLoginScriptFile)) &&
+ (!fNoDefaultLoginScript) )
+ {
+ ProcessLoginScript (DefaultLoginScript);
+ }
+ }
+ }
+}
+
+int ProcessLoginScriptFile (char *lpLoginScriptFile)
+{
+ int nFileSize = 0, bEmpty;
+ char *lpLoginScript;
+
+ nFileSize = NWGetFileSize (lpLoginScriptFile);
+
+ if (nFileSize <= 2)
+ return(FALSE);
+
+ // system login script exists.
+ lpLoginScript = malloc (nFileSize);
+ if (lpLoginScript == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ LoadFile (lpLoginScriptFile, lpLoginScript, nFileSize);
+
+ bEmpty = IsEmptyFile(lpLoginScript);
+
+ if (!bEmpty)
+ ProcessLoginScript (lpLoginScript);
+
+ free (lpLoginScript);
+
+ return(!bEmpty);
+}
+
+
+/*
+ * Retrieve and process the Login Script property
+ */
+int ProcessLoginScriptProperty ( unsigned char * Object )
+{
+ unsigned int nFileSize = 0;
+ unsigned int Actual = 0;
+ unsigned int bEmpty;
+ char *lpLoginScript;
+ HANDLE Stream;
+ int err;
+ unsigned int i,j;
+
+ if ( NDSfopenStream ( Object, "Login Script", &Stream, &nFileSize ) )
+ return(FALSE);
+
+ if ( nFileSize <= 2)
+ return(FALSE);
+
+ // login script exists.
+ lpLoginScript = malloc (nFileSize+2);
+ if (lpLoginScript == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ memset(lpLoginScript, 0, nFileSize+2);
+
+ if ( !ReadFile ( Stream, lpLoginScript, nFileSize, &Actual, NULL ) )
+ {
+ bEmpty = TRUE;
+ }
+#ifdef BUGBUG // ReadFile is returning wrong lengths
+ else if ( Actual != nFileSize )
+ {
+ bEmpty = TRUE;
+ }
+#endif
+ else if ( IsEmptyFile(lpLoginScript) )
+ bEmpty = TRUE;
+ else
+ bEmpty = FALSE;
+
+ for ( i = 0, j = 0; i < nFileSize; i++, j++ )
+ {
+ if (( lpLoginScript[i] == '\r' ) &&
+ ( lpLoginScript[i+1] == '\n' ) )
+ i++;
+
+ lpLoginScript[j] = lpLoginScript[i];
+ }
+
+ while ( j < nFileSize )
+ {
+ lpLoginScript[j++] = 0;
+ }
+
+ CloseHandle( Stream );
+
+ if (!bEmpty)
+ ProcessLoginScript (lpLoginScript);
+
+ free (lpLoginScript);
+
+ return(!bEmpty);
+}
+
+/*
+ * Return the size of the file.
+ */
+int NWGetFileSize (char * lpFileName)
+{
+ int nFileSize = 0;
+ FILE * stream;
+
+ do
+ {
+ if ((stream = fopen (NTNWtoUNCFormat(lpFileName), "r")) == NULL)
+ break;
+
+ while (feof (stream) == 0)
+ {
+ fgetc (stream);
+ nFileSize++;
+ }
+
+ if (fclose (stream))
+ nFileSize = 0;
+ }while (FALSE);
+
+
+ return(nFileSize);
+}
+
+/*
+ * Read the file into memory pointed by lpFileBuffer.
+ */
+void LoadFile (char *lpFileName, char *lpFileBuffer, int nFileSize)
+{
+ FILE * stream;
+
+ if ((stream = fopen (NTNWtoUNCFormat(lpFileName), "r")) != NULL)
+ {
+ fread (lpFileBuffer, sizeof (char), nFileSize, stream);
+ fclose (stream);
+ }
+
+ *(lpFileBuffer+nFileSize-1) = 0;
+
+}
+
+/*
+ * Process Login Script that is in memory pointed by lpLoginScript
+ * line by line.
+ */
+void ProcessLoginScript (char *lpLoginScript)
+{
+ nCondIndex = -1;
+ fGlobalExitFlag = FALSE;
+ fGlobalIfTooDeep = FALSE;
+
+ lpGlobalLine = lpLoginScript; // we start at the top of the login script
+
+ if (!CreateLabelList (&pGlobalLabelList, lpLoginScript))
+ {
+ if (pGlobalLabelList != NULL) {
+
+ FreeLabelList (pGlobalLabelList);
+ pGlobalLabelList = NULL;
+ }
+ return;
+ }
+
+ while (*lpGlobalLine != 0) {
+
+ //
+ // search for the end of the current line and replace with a null
+ //
+
+ if (lpGlobalLineSeparator = strchr(lpGlobalLine, '\n')) {
+
+ //
+ // we may reset this manually in the goto handler, remember so that
+ // we don't trample anything needlessly.
+ //
+
+ *lpGlobalLineSeparator = 0;
+ fGlobalHaveNulledLineSeparator = TRUE;
+
+ } else {
+
+ fGlobalHaveNulledLineSeparator = FALSE;
+ }
+
+ //
+ // Now lpGlobalLine points to one line only.
+ //
+
+ CommandDispatch (lpGlobalLine);
+
+ if (fGlobalExitFlag)
+ {
+ if (fGlobalIfTooDeep)
+ DisplayMessage(IDR_ORIGINAL_LINE_WAS, lpGlobalLine);
+ break;
+ }
+
+ if (lpGlobalLineSeparator) {
+
+ if ( fGlobalHaveNulledLineSeparator ) {
+
+ *lpGlobalLineSeparator = '\n'; // recover the changes made.
+ fGlobalHaveNulledLineSeparator = FALSE;
+ }
+
+ lpGlobalLine = lpGlobalLineSeparator + 1; // next line please
+
+ } else {
+
+ break;
+ }
+ }
+
+ if (pGlobalLabelList != NULL) {
+ FreeLabelList (pGlobalLabelList);
+ pGlobalLabelList = NULL;
+ }
+}
+
+/*
+ * Scan the login script, put labels in a link list and comment out
+ * those label lines.
+ */
+int CreateLabelList (PLABEL_LIST *ppLabelList, char *lpLoginScript)
+{
+ char *lpLine = lpLoginScript, *lpEnd, *lpLabel, *lpTemp;
+ int nLen;
+ PLABEL_LIST *ppNext = ppLabelList;
+
+ while (*lpLine != 0)
+ {
+ if (lpEnd = strchr (lpLine, '\n'))
+ *lpEnd = 0;
+
+ // Now lpLine points to one line only.
+ lpLabel = RemoveSpaces (lpLine);
+ if (isalnum (*lpLabel) || (*lpLabel == '%'))
+ {
+ lpTemp = lpLabel;
+ nLen = 0;
+ while (*lpTemp != 0 && *lpTemp != ' ' && *lpTemp != '\t' && *lpTemp != ':')
+ {
+ if (IsDBCSLeadByte(*lpTemp))
+ {
+ lpTemp++;
+ nLen++;
+ }
+
+ lpTemp++;
+ nLen++;
+ }
+
+ lpTemp = RemoveSpaces (lpTemp);
+ if (*lpTemp == ':' && EndOfLine (lpTemp+1))
+ {
+ // The Line is label line.
+ if ((*ppNext = malloc (sizeof (LABEL_LIST))) == NULL ||
+ ((*ppNext)->pLabel = malloc (nLen+1)) == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return(FALSE);
+ }
+
+ SmartCap(lpLabel);
+ strncpy ((*ppNext)->pLabel, lpLabel, nLen);
+ *((*ppNext)->pLabel+nLen) = 0;
+ (*ppNext)->pNextLine = lpEnd? lpEnd+1 : lpEnd;
+ (*ppNext)->pNext = NULL;
+ ppNext = &((*ppNext)->pNext);
+
+ // Comment out the label line.
+ *(lpLine) = ';';
+ }
+ }
+
+ if (lpEnd)
+ {
+ *lpEnd = '\n'; // recover the changes made.
+ lpLine = lpEnd+1;
+ }
+ else
+ break;
+ }
+
+ return(TRUE);
+}
+
+/*
+ * Free up the memory allocated for the link list.
+ */
+void FreeLabelList (LABEL_LIST *pLabelList)
+{
+ LABEL_LIST *pNext = pLabelList;
+
+ while (pLabelList)
+ {
+ pNext = pLabelList->pNext;
+ free (pLabelList->pLabel);
+ free (pLabelList);
+ pLabelList = pNext;
+ }
+}
+
+/*
+ * Dispatch to command hander according to the command.
+ */
+void CommandDispatch (char *lpCommand)
+{
+ char buffer[MAXLEN];
+ char *restBuffer;
+ int index, fCommandHandled = FALSE;
+ int nTemp = -1;
+
+ // Get rid of leading spaces.
+ lpCommand = RemoveSpaces(lpCommand);
+
+ // Don't do anything if it's a comment line or empty line.
+ if (*lpCommand == ';' || *lpCommand == '*' || *lpCommand == '\0' ||
+ *lpCommand == '\r'|| *lpCommand == '\n')
+ return;
+
+ do // FALSE loop.
+ {
+ // Make sure the command line is not too long to process.
+ if (strlen (lpCommand) > MAXLEN -1) {
+ break;
+ }
+
+ // Make a copy of the command line to buffer.
+ strcpy (buffer, lpCommand);
+
+ // external command line.
+ if (*buffer == '#')
+ {
+ ExternalCmdHandler (buffer);
+ return;
+ }
+
+ // Get the command index in the command table.
+ if ((index = GetTableIndex(buffer, &restBuffer)) == -1)
+ break;
+
+ // Dispatch to the corresponding command handler.
+ if (nCondIndex > -1 &&
+ !aCondVal[nCondIndex] &&
+ index != CM_IF &&
+ index != CM_ELSE &&
+ index != CM_END)
+ fCommandHandled = TRUE;
+ else
+ fCommandHandled = (*nwCommand[index].commandhandler)(restBuffer);
+
+ } while (FALSE);
+
+ if (!fCommandHandled) {
+ BadCommandHandler (lpCommand);
+ }
+}
+
+/*
+ * Used by GetTableIndex().
+ * This function should capitalize the entire command string except
+ * those in quotes.
+ */
+void SmartCap(char *ptr)
+{
+ int inquotes = (*ptr == '\"');
+ char *pNext;
+
+ while (*ptr)
+ {
+ if (!inquotes)
+ {
+ if (IsDBCSLeadByte(*ptr))
+ *((int *)ptr) = toupper ((int)*ptr);
+ else
+ *ptr = (char) toupper((int)*ptr);
+ }
+
+ pNext = NWAnsiNext(ptr);
+
+ if (*pNext == '\"' && *ptr != '\\')
+ inquotes = !inquotes;
+
+ ptr = pNext;
+ }
+}
+
+/*
+ * Return the index of the command in the command dispatch table.
+ * Return -1 if the command is not found in the command dispatch table.
+ */
+int GetTableIndex(char *buffer, char **prestBuffer)
+{
+ int i, nStrLen;
+
+ // Upcase every thing except those in quotes.
+ SmartCap (buffer);
+
+ for (i=0; i<NUMCOMMAND; i++)
+ {
+ if (*(WORD *)nwCommand[i].commandStr0 != *(WORD *)buffer)
+ continue;
+
+ nStrLen = strlen (nwCommand[i].commandStr0);
+
+ if (strncmp(nwCommand[i].commandStr0, buffer, nStrLen))
+ continue;
+
+ *prestBuffer = buffer + nStrLen;
+ *prestBuffer = RemoveSpaces (*prestBuffer);
+
+ if (nwCommand[i].commandStr1)
+ {
+ nStrLen = strlen (nwCommand[i].commandStr1);
+
+ if (strncmp(nwCommand[i].commandStr1, *prestBuffer, nStrLen))
+ continue;
+
+ *prestBuffer += nStrLen;
+ *prestBuffer = RemoveSpaces (*prestBuffer);
+
+ if (nwCommand[i].commandStr2)
+ {
+ nStrLen = strlen (nwCommand[i].commandStr2);
+
+ if (strncmp(nwCommand[i].commandStr2, *prestBuffer, nStrLen))
+ continue;
+
+ *prestBuffer += nStrLen;
+ *prestBuffer = RemoveSpaces (*prestBuffer);
+ }
+ }
+
+ return (i);
+ }
+
+ return(-1);
+}
+
+/*
+ * Goto label... We modify the globals controlling what line we're on.
+ */
+int GotoHandler (char *lpParam)
+{
+ int fLabelFound = FALSE;
+ char *lpLabel, *lpEnd, chEnd;
+ LABEL_LIST *pLabelList = pGlobalLabelList;
+
+ lpLabel = lpParam;
+ lpLabel = RemoveSpaces (lpLabel);
+
+ //
+ // find the end of the label, we'll slam in a null for the search and
+ // restore the char after we're done searching.
+ //
+
+ lpEnd = lpLabel;
+ while (*lpEnd != 0 &&
+ *lpEnd != ' ' &&
+ *lpEnd != '\t' &&
+ *lpEnd != '\r' &&
+ *lpEnd != '\n')
+ {
+ if (*lpEnd == ':')
+ return(FALSE);
+ else
+ lpEnd = NWAnsiNext(lpEnd);
+ }
+
+ chEnd = *lpEnd;
+ *lpEnd = 0;
+
+ while (pLabelList)
+ {
+ if (!_stricmp (pLabelList->pLabel, lpLabel))
+ {
+ if ( fGlobalHaveNulledLineSeparator )
+ {
+
+ *lpGlobalLineSeparator = '\n'; // recover the changes made.
+ fGlobalHaveNulledLineSeparator = FALSE;
+ }
+
+ lpGlobalLine = pLabelList->pNextLine;
+
+ lpGlobalLineSeparator = lpGlobalLine ? (lpGlobalLine - 1) : NULL;
+
+ fLabelFound = TRUE;
+ break;
+ }
+
+ pLabelList = pLabelList->pNext;
+ }
+
+ if (!fLabelFound)
+ {
+ DisplayMessage (IDR_LABEL_NOT_FOUND, lpLabel);
+ fGlobalExitFlag = TRUE;
+ }
+
+ *lpEnd = chEnd;
+ return( TRUE );
+}
+
+/*
+ * Attach [FileServer[/UserName[;Password]]]
+ */
+int AttachHandler (char *lpParam)
+{
+ unsigned int iRet = 0;
+ int fCommandHandled = FALSE;
+ char serverName[MAX_NAME_LEN] = "";
+ char userName[MAX_NAME_LEN] = "";
+ char password[MAX_PASSWORD_LEN] = "";
+ char *lpSlash, *lpSemiColon, *lpServerName, *lpUserName;
+ unsigned int conn;
+ int bAlreadyAttached = FALSE, bReadPassword = TRUE;
+
+ do // FALSE loop.
+ {
+ NotQuotedStringTranslate (lpParam, TRUE);
+
+ // Make sure that there is at most 1 slash.
+ lpSlash = strchr (lpParam, '\\');
+
+ if (lpSlash == NULL)
+ {
+ lpSlash = strchr (lpParam, '/');
+ if (lpSlash != NULL && strchr (lpSlash+1, '/'))
+ break;
+ }
+ else
+ {
+ if (strchr (lpParam, '/') ||
+ strchr (lpSlash+1, '/') ||
+ strchr (lpSlash+1, '\\'))
+ break;
+ }
+
+ // Break the string at slash.
+ if (lpSlash)
+ *lpSlash = 0;
+
+ // Server name should not contain semicolon.
+ if (strchr (lpParam, ';'))
+ break;
+
+ lpServerName = strtok (lpParam, __SPACES__);
+
+ if (lpServerName = NULL)
+ {
+ if (lpSlash)
+ break;
+ }
+ else
+ {
+ // Make sure that there is only one name in front of the slash.
+ if (strtok (NULL, __SPACES__))
+ break;
+
+ // Copy the server name to the buffer.
+ if (strlen (lpParam) > MAX_NAME_LEN-1)
+ break;
+
+ strcpy (serverName, lpParam);
+
+ if (lpSlash)
+ {
+ lpSemiColon = strchr (lpSlash+1, ';');
+ if (lpSemiColon)
+ *lpSemiColon = 0;
+
+ lpUserName = strtok (lpSlash+1, __SPACES__);
+ if (lpUserName)
+ {
+ if ( strtok (NULL, __SPACES__))
+ break;
+
+ if (strlen (lpUserName) > MAX_NAME_LEN-1 )
+ break;
+
+ strcpy (userName, lpUserName);
+ }
+
+ if (lpSemiColon)
+ {
+ if (strlen (lpSemiColon+1) > MAX_PASSWORD_LEN-1)
+ break;
+ strcpy (password, strtok (lpSemiColon+1, __SPACES__));
+ xstrupr (password);
+ bReadPassword = FALSE;
+ }
+ }
+ }
+
+ fCommandHandled = TRUE;
+
+ if (serverName[0] == 0)
+ {
+ DisplayMessage(IDR_ENTER_SERVER_NAME);
+ if (!ReadName(serverName))
+ break;
+
+ DisplayMessage(IDR_ENTER_LOGIN_NAME, serverName);
+ if (!ReadName(userName))
+ break;
+ }
+ else if (userName[0] == 0)
+ strcpy (userName, LOGIN_NAME);
+
+ if (iRet = CAttachToFileServer(serverName, &conn, &bAlreadyAttached))
+ {
+ if (!SCRIPT_ERROR)
+ SCRIPT_ERROR = iRet;
+ break;
+ }
+
+ // Do not need this connection
+ DetachFromFileServer (conn);
+
+#ifdef BUGBUG // not reliable
+ if (bAlreadyAttached)
+ {
+ DisplayMessage(IDR_ATTACHED, serverName);
+ break;
+ }
+#endif
+
+ if (Login(userName, serverName, password, bReadPassword))
+ {
+ // Clear out the password
+ memset( password, 0, sizeof( password ) );
+
+ // Ask for user name
+
+ DisplayMessage(IDR_ENTER_LOGIN_NAME, serverName);
+ if (!ReadName(userName))
+ break;
+
+ if (Login(userName, serverName, password, bReadPassword))
+ {
+ // Clear out the password
+ memset( password, 0, sizeof( password ) );
+ break;
+ }
+ }
+
+ // Clear out the password
+
+ memset( password, 0, sizeof( password ) );
+
+ AddServerToAttachList( serverName, LIST_3X_SERVER );
+
+ } while (FALSE);
+
+ return(fCommandHandled);
+}
+
+/*
+ * BREAK ON, enable ctrl-c, ctrl-break
+ * BREAK OFF, disable ctrl-c, ctrl-break
+ */
+int BreakHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (IsOn(lpParam))
+ {
+ if (!fBreakOn)
+ BreakOn();
+ }
+ else if (IsOff(lpParam))
+ {
+ if (fBreakOn)
+ BreakOff();
+ }
+ else
+ fCommandHandled = FALSE;
+
+ return(fCommandHandled);
+}
+
+
+/*
+ * DISPLAY [pathname]file
+ * FDISPLAY [pathname]file
+ */
+int DisplayHandler (char *lpParam)
+{
+ FILE * stream;
+
+ NotQuotedStringTranslate (lpParam, TRUE);
+
+ if ((stream = fopen (lpParam, "r")) != NULL)
+ {
+ while (feof (stream) == 0)
+ _fputchar(fgetc (stream));
+
+ fclose (stream);
+ DisplayMessage(IDR_NEWLINE);
+ }
+
+ return(TRUE);
+}
+
+/*
+ * DOS BREAK ON, enable ctrl-break checking for DOS
+ * DOS BREAK OFF, disable ctrl-break checking for DOS
+ */
+int DosBreakHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (IsOn (lpParam))
+ system ("BREAK ON");
+ else if(IsOff (lpParam))
+ system ("BREAK OFF");
+ else
+ fCommandHandled = FALSE;
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by SetHandler() and LocalSetHandler()
+ * Return TRUE if lpParam points to name = "value", and set
+ * lpParam to "name=value" on return.
+ * Return FALSE otherwise.
+ */
+int VerifySetFormat (char *lpParam)
+{
+ int fCorrect = FALSE;
+ char buffer[MAXLEN];
+ char *lpBuffer = buffer;
+
+ strcpy (buffer, lpParam);
+
+ do
+ {
+ while (*lpBuffer != 0 && *lpBuffer != '=' && *lpBuffer != ' ' && *lpBuffer != '\t')
+ lpBuffer = NWAnsiNext(lpBuffer);
+
+ lpParam[lpBuffer-buffer]=0;
+ strcat (lpParam, "=");
+
+ if (*lpBuffer != '=')
+ lpBuffer = RemoveSpaces (lpBuffer);
+
+ if (*lpBuffer != '=')
+ break;
+
+ lpBuffer = RemoveSpaces (lpBuffer+1);
+
+ if (*lpBuffer)
+ {
+ if (!QuotedStringTranslate (lpBuffer))
+ break;
+
+ strcat (lpParam, lpBuffer);
+ }
+
+ fCorrect = TRUE;
+ }while (FALSE);
+
+ return(fCorrect);
+}
+
+/*
+ * Used by SetHandler() and LocalSetHandler()
+ * Set the local environment variable.
+ * Don't free the memory allocated because the environment variable will
+ * point to free space otherwise.
+ */
+void SetLocalEnv(char *buffer)
+{
+ char *lpEnvString;
+ lpEnvString = malloc(strlen (buffer) + 1);
+
+ if (lpEnvString == NULL)
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ else
+ {
+ strcpy (lpEnvString, buffer);
+ _putenv (lpEnvString);
+ }
+}
+
+/*
+ * Set Dos environment variable.
+ * [DOS] SET name = "value"
+ */
+int SetHandler (char *lpParam)
+{
+
+ int fCommandHandled;
+
+ fCommandHandled = VerifySetFormat(lpParam);
+
+ if (fCommandHandled)
+ {
+
+ if ( _strnicmp( "COMSPEC=", lpParam, strlen( "COMSPEC=" ) ) )
+ {
+ SetLocalEnv(lpParam);
+ SetEnv (lpParam);
+ }
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Set local Dos environment variable.
+ * [OPTION] [DOS] SET name = "value"
+ */
+int LocalSetHandler (char *lpParam)
+{
+ int fCommandHandled;
+
+ fCommandHandled = VerifySetFormat(lpParam);
+
+ if (fCommandHandled)
+ if ( _strnicmp( "COMSPEC=", lpParam, strlen( "COMSPEC=" ) ) )
+ {
+ SetLocalEnv (lpParam);
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by DosVerifyHandler().
+ * Turn /V option of copy on.
+ */
+void DosVerifyOn(void)
+{
+}
+
+/*
+ * Used by DosVerifyHandler().
+ * Turn /V option of copy off.
+ */
+void DosVerifyOff(void)
+{
+}
+
+/*
+ * DOS VERYFY [ON|OFF], Turn /V option of copy on or off.
+ */
+int DosVerifyHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (IsOn(lpParam))
+ DosVerifyOn();
+ else if (IsOff(lpParam))
+ DosVerifyOff();
+ else
+ fCommandHandled = FALSE;
+
+ return(fCommandHandled);
+}
+
+/*
+ * DRIVE [driveletter: | n*:], set the default drive to the one specified.
+ */
+int DriveHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+ WORD driveNum=0, n;
+ char *pColon;
+
+ do // FALSE loop.
+ {
+ if ((pColon = strchr (lpParam, ':')) == NULL ||
+ !EndOfLine (pColon + 1))
+ break;
+
+ if (*lpParam == '*')
+ {
+ *pColon = 0;
+ if ((n = atoi (lpParam+1)) < 1)
+ break;
+
+ GetFirstDrive (&driveNum);
+ driveNum += (n-1);
+ }
+ else if (pColon == lpParam+1 && isupper(*lpParam))
+ driveNum = *lpParam - 'A' + 1;
+ else
+ break;
+
+ if (_chdrive (driveNum))
+ DisplayMessage(IDR_ERROR_SET_DEFAULT_DRIVE, 'A'+driveNum-1);
+ else
+ ExportCurrentDrive( driveNum );
+
+ fCommandHandled = TRUE;
+
+ } while (FALSE);
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by FireHandler()
+ * Return TRUE if lpTemp points to the legal end of fire statement, ie
+ * [TIMES][COMMENTS]. It also set the *lpTemp to 0 if lpTemp is not NULL.
+ * Return FALSE otherwise.
+ */
+int IsEndOfFireCmd (char *lpTemp)
+{
+ int fEnd = FALSE;
+ do
+ {
+ if (*lpTemp != 0)
+ {
+ if (*lpTemp != ' ' && *lpTemp != '\t' && *lpTemp != '\r')
+ break;
+
+ *lpTemp = 0;
+
+ lpTemp = RemoveSpaces (lpTemp+1);
+
+ if (!strncmp (lpTemp, "TIMES", 5))
+ lpTemp += 5;
+
+ if (!EndOfLine (lpTemp))
+ break;
+ }
+
+ fEnd = TRUE;
+ }while (FALSE);
+
+ return(fEnd);
+}
+
+/*
+ * [FIRE | FIRE PHASERS] n TIMES.
+ */
+int FireHandler (char *lpParam)
+{
+ char *lpTemp, vartext[MAXLEN];
+ int n = 0, nLen;
+ time_t ltimeStart, ltimeEnd;
+
+ if (EndOfLine (lpParam))
+ n = 1;
+ else if (isdigit(*lpParam))
+ {
+ lpTemp = lpParam;
+ while (isdigit(*lpTemp))
+ lpTemp++;
+
+ if (IsEndOfFireCmd (lpTemp))
+ n = atoi (lpParam);
+ }
+ else if (*lpParam == '%')
+ {
+ strcpy (vartext, lpParam+1);
+ if (((nLen = VarTranslate (lpParam)) != 0) &&
+ EndOfLine (lpParam+1+nLen))
+ n = atoi (vartext);
+ }
+
+ if (n < 0)
+ return(FALSE);
+ else if (n == 0) // Compatible with NetWare.
+ n = 1;
+
+ while (n--)
+ {
+ _beep( 610, 100 );
+ _beep( 440, 50 );
+ time(&ltimeStart);
+ do
+ {
+ time(&ltimeEnd);
+ }while (ltimeEnd-ltimeStart == 0);
+ }
+
+ return(TRUE);
+}
+
+/*
+ * EXIT, terminate login script processing.
+ */
+int ExitHandler (char *lpParam)
+{
+ int n;
+ char buffer[16], *argv[10];
+
+ if (EndOfLine (lpParam))
+ CleanupExit(0);
+ else if (QuotedStringTranslate (lpParam))
+ {
+ if (!fGlobalCompatible)
+ {
+ GetShellVersion (buffer, IDS_MACHINE);
+ if (_stricmp (buffer, "IBM_PC"))
+ {
+ DisplayMessage(IDR_EXIT_NOT_SUPPORTED);
+ return(TRUE);
+ }
+ }
+
+ argv[0] = strtok (lpParam, __SPACES__);
+
+ for (n = 1; n < 9; n++)
+ {
+ if ((argv[n] = strtok (NULL, __SPACES__)) == NULL)
+ break;
+ }
+
+ argv[9] = NULL;
+
+ if ((SCRIPT_ERROR = _spawnvp (P_WAIT, argv[0], argv)) == -1)
+ DisplayMessage(IDR_BAD_COMMAND);
+
+ CleanupExit (0);
+ }
+ else
+ return(FALSE);
+}
+
+BOOL nwVarNameCompare(LPCSTR src,LPCSTR target)
+{
+ CHAR szTempName[64];
+ LPSTR pT = szTempName;
+
+ if (!_strnicmp(src,target,strlen(target))) {
+ //
+ // try to reject obvious problems like
+ // %LJUNK where %L would be fine
+ //
+ if ( !isalpha(src[strlen(target)]) )
+ return 0;
+ else
+ return 1;
+ }
+
+ strcpy(szTempName,target);
+
+ while (*pT) {
+ if (!IsDBCSLeadByte(*pT)) {
+ if ('_' == *pT)
+ *pT = ' ';
+ }
+ pT = NWAnsiNext(pT);
+ }
+
+ if (!_strnicmp(src,szTempName,strlen(szTempName))) {
+ //
+ // try to reject obvious problems like
+ // %LJUNK where %L would be fine
+ //
+ if ( !isalpha(src[strlen(target)]) )
+ return 0;
+ else
+ return 1;
+ }
+
+ return 1;
+}
+
+
+/*
+ * Used by the EvalSingleCond() in IfHandler()
+ * Return TRUE if buffer is the right member of condition statement.
+ * *pfCondition is TRUE if the condition meet, FALSE if not.
+ * *ppRest points to the end of the condition statement.
+ * Return FALSE if buffer is not the right member of condition statement.
+ */
+int MemberOf (char *buffer, int *pfCondition, char **ppRest)
+{
+ int i, nChar, fSucceed = FALSE;
+ char *lpTemp;
+ BYTE dataBuffer[128];
+ unsigned char moreFlag;
+ unsigned char propertyType;
+ unsigned long dwObjectId, *pdwGroups;
+ char GroupName[MAXLEN];
+ unsigned char segment;
+
+ *pfCondition = FALSE;
+ do
+ {
+ if ((buffer = strchr (buffer, '\"')) == NULL)
+ break;
+
+ if ((lpTemp = strchr (buffer+1, '\"')) == NULL)
+ break;
+
+ nChar = lpTemp - buffer + 1;
+
+ if (nChar >= MAXLEN)
+ break;
+
+ strncpy (GroupName, buffer, nChar);
+ GroupName[nChar] = 0;
+ if (!QuotedStringTranslate (GroupName))
+ break;
+
+ fSucceed = TRUE;
+ *pfCondition = FALSE;
+ *ppRest = RemoveSpaces (lpTemp+1);
+
+ if (strlen(GroupName) > MAX_NAME_LEN)
+ break;
+
+ if ( fNDS )
+ {
+ if ( IsMemberOfNDSGroup( GroupName ) )
+ {
+ *pfCondition = TRUE;
+ return(TRUE);
+ }
+
+ }
+ else
+ {
+ if (GetBinderyObjectID (CONNECTION_ID,
+ _strupr(GroupName),
+ OT_USER_GROUP,
+ &dwObjectId) )
+ goto done;
+
+ //
+ // For all the group ID's, try and find a match
+ //
+ for ( segment = 1, moreFlag = TRUE; moreFlag && segment; segment++ )
+ {
+ if ( NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "GROUPS_I'M_IN",
+ segment,
+ dataBuffer,
+ &moreFlag,
+ &propertyType))
+ goto done;
+
+ pdwGroups = (unsigned long *) dataBuffer;
+
+ for (i = 0; i < 32 && *(pdwGroups+i); i++)
+ {
+ if (*(pdwGroups+i) == dwObjectId)
+ {
+ *pfCondition = TRUE;
+ return(TRUE);
+ }
+ }
+ }
+ }
+
+ *pfCondition = FALSE;
+ fSucceed = TRUE;
+ } while (FALSE);
+
+done:
+
+ return(fSucceed);
+}
+
+/*
+ * Used by IsCompare() in EvalSingleCond() in IfHandler()
+ * Return the next token.
+ */
+char *GetNextPart (char *lpTemp)
+{
+ INT i;
+
+ if (strncmp (lpTemp, "VALUE", 5) == 0)
+ lpTemp = RemoveSpaces (lpTemp+5);
+
+ if (*lpTemp == '\"')
+ {
+ lpTemp++;
+ while (*lpTemp != 0 && *lpTemp != '\"')
+ lpTemp = NWAnsiNext(lpTemp);
+
+ if (*lpTemp == 0)
+ return(NULL);
+ else
+ lpTemp++;
+ }
+ else if (*lpTemp == '<')
+ {
+ while (*lpTemp != 0 && *lpTemp != '>')
+ lpTemp = NWAnsiNext(lpTemp);
+
+ if (*lpTemp == 0)
+ return(NULL);
+ else
+ lpTemp++;
+ }
+ else
+ {
+ if (*lpTemp == '%')
+ lpTemp++;
+
+ for (i = 0; i < (fNDS ? NUMVAR : NUMVAR_3X); i++)
+ {
+ if (!nwVarNameCompare(lpTemp, varTable[i].VarName))
+ {
+ lpTemp += strlen(varTable[i].VarName);
+ break;
+ }
+ }
+
+ if (i == (fNDS ? NUMVAR : NUMVAR_3X))
+ return(NULL);
+ }
+
+ return(lpTemp);
+}
+
+/*
+ * Used by EvalSingleCond() in IfHandler()
+ * left part of buffer could be "...", <...>, or ... for variables.
+ * Return TRUE if buffer consists of <left> <compare operator> <right part> +
+ * optional rest parts.
+ * Return FALSE otherwise.
+ */
+int IsCompare (char *buffer, char **ppright,
+ int *pnLeftLen, int *pnRightLen,
+ int *pindex, char **ppRest)
+{
+ int i, nLen;
+ char *lpTemp;
+
+ if ((lpTemp = GetNextPart (buffer)) == NULL)
+ return (FALSE);
+
+ *pnLeftLen = lpTemp-buffer;
+ lpTemp = RemoveSpaces (lpTemp);
+
+ for (i = 0; COMPARE_OPERATORS[i][0]; i++)
+ {
+ nLen = strlen (COMPARE_OPERATORS[i]);
+
+ if (!strncmp(lpTemp, COMPARE_OPERATORS[i], nLen))
+ {
+ *lpTemp = 0;
+ lpTemp += nLen;
+ *ppright = RemoveSpaces (lpTemp);
+ *pindex = i;
+ *ppRest = GetNextPart (*ppright);
+ if ( *ppRest == NULL )
+ return (FALSE);
+ *pnRightLen = *ppRest - *ppright;
+ *ppRest = RemoveSpaces (*ppRest);
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+/*
+ * Used by EvalSingleCond() in IfHandler()
+ * Evaluate lpLeft and lpRight and do the compare operation of index
+ * and put the result in *pfCondition.
+ * Return TRUE if succeed, FALSE otherwise.
+ */
+int Compare (char *lpLeft, char *lpRight,
+ int nLeftLen, int nRightLen,
+ int index, int *pfCondition)
+{
+ char szLeft[MAXLEN], szRight[MAXLEN], *lpTemp;
+ int nCompare, fValue = FALSE;
+
+ if (strncmp (lpLeft, "VALUE", 5) == 0)
+ {
+ fValue = TRUE;
+ lpTemp = RemoveSpaces (lpLeft+5);
+ nLeftLen -= (lpTemp - lpLeft);
+ lpLeft = lpTemp;
+ }
+ if (strncmp (lpRight, "VALUE", 5) == 0)
+ {
+ fValue = TRUE;
+ lpTemp = RemoveSpaces (lpRight+5);
+ nRightLen -= (lpTemp - lpRight);
+ lpRight = lpTemp;
+ }
+
+ strncpy (szLeft, lpLeft, nLeftLen);
+ strncpy (szRight, lpRight, nRightLen);
+
+ szLeft[nLeftLen] = 0;
+ szRight[nRightLen] = 0;
+
+ if (!QuotedStringTranslate (szLeft) ||
+ !QuotedStringTranslate (szRight))
+ return(FALSE);
+
+ if (fValue)
+ nCompare = atoi(szLeft)-atoi(szRight);
+ else
+ nCompare = _stricmp (szLeft, szRight);
+
+ if (IsNotEqual(index))
+ *pfCondition = (nCompare != 0);
+ else if (IsGreaterOrEqual(index))
+ *pfCondition = (nCompare >= 0);
+ else if (IsGreater(index))
+ *pfCondition = (nCompare > 0);
+ else if (IsLessOrEqual(index))
+ *pfCondition = (nCompare <= 0);
+ else if (IsLess(index))
+ *pfCondition = (nCompare < 0);
+ else
+ *pfCondition = (nCompare == 0);
+
+ return(TRUE);
+}
+
+int IsMemberOf (char *buffer)
+{
+ int fIsMemberOf = FALSE;
+
+ if (!strncmp (buffer, "MEMBER", 6))
+ {
+ buffer += 6;
+ if (*buffer == ' ' || *buffer == '\t')
+ {
+ buffer = RemoveSpaces (buffer);
+ if (!strncmp (buffer, "OF", 2))
+ {
+ buffer += 2;
+ if (*buffer == ' ' || *buffer == '\t')
+ buffer = RemoveSpaces (buffer);
+ }
+ }
+
+ fIsMemberOf = (*buffer == '"');
+ }
+
+ return(fIsMemberOf);
+}
+
+int NotMemberOf (char *buffer)
+{
+ int fNotMemberOf = FALSE;
+ if (!strncmp (buffer, "NOT", 3))
+ {
+ buffer += 3;
+ if (*buffer == ' ' || *buffer == '\t')
+ {
+ buffer = RemoveSpaces (buffer);
+ fNotMemberOf = IsMemberOf (buffer);
+ }
+ }
+
+ return(fNotMemberOf);
+}
+
+
+/*
+ * Used by IfHandler()
+ * Evaluate one condition clause and put result in *pfCondition, *ppRest
+ * points to the rest part of buffer.
+ * Return TRUE if succeed, FALSE otherwise.
+ */
+int EvalSingleCond (char *buffer, int *pfCondition)
+{
+ int index, fSuccess = FALSE, nLeftLen, nRightLen;
+ char *pright, *pRest;
+
+ if (IsMemberOf(buffer))
+ fSuccess = MemberOf (buffer, pfCondition, &pRest);
+ else if (NotMemberOf (buffer))
+ {
+ fSuccess = MemberOf (buffer, pfCondition, &pRest);
+ *pfCondition = !(*pfCondition);
+ }
+ else if (IsCompare (buffer, &pright, &nLeftLen, &nRightLen, &index, &pRest))
+ fSuccess = Compare (buffer, pright, nLeftLen, nRightLen, index, pfCondition);
+ else if ( !_strnicmp ("ACCESS_SERVER", buffer, strlen("ACCESS_SERVER")) )
+ {
+ fSuccess = TRUE;
+ *pfCondition = FALSE;
+ pRest = buffer + strlen ("ACCESS_SERVER");
+ }
+
+ if (fSuccess)
+ memmove (buffer, pRest, strlen (pRest)+1);
+
+ return(fSuccess);
+}
+
+int EvaluateCondExpression(char *lpCondExpression, int *pfCondition)
+{
+ int fSuccess = FALSE, fCond;
+ char *lpRight, *lpLeft, *lpOp;
+
+ if (lpRight = strchr (lpCondExpression, ')'))
+ {
+ *lpRight = 0;
+ if ((lpLeft = strrchr (lpCondExpression, '(')) == NULL ||
+ !EvaluateCondExpression(lpLeft+1, pfCondition))
+ return(FALSE);
+
+ *lpLeft = (*pfCondition)? '1' : '0';
+ memmove (lpLeft+1, lpRight+1, strlen (lpRight+1)+1);
+ return(EvaluateCondExpression (lpCondExpression, pfCondition));
+ }
+
+ if (lpOp = strrchr (lpCondExpression, '+'))
+ {
+ *lpOp = 0;
+
+ if (!EvaluateCondExpression (lpCondExpression, pfCondition) ||
+ !EvaluateCondExpression (lpOp+1, &fCond))
+ return(FALSE);
+
+ *pfCondition = (*pfCondition || fCond);
+ return(TRUE);
+ }
+
+ if (lpOp = strrchr (lpCondExpression, '*'))
+ {
+ *lpOp = 0;
+
+ if (!EvaluateCondExpression (lpCondExpression, pfCondition) ||
+ !EvaluateCondExpression (lpOp+1, &fCond))
+ return(FALSE);
+
+ *pfCondition = (*pfCondition && fCond);
+ return(TRUE);
+ }
+
+ if (lpOp = strrchr (lpCondExpression, '^'))
+ {
+ *lpOp = 0;
+
+ if (!EvaluateCondExpression (lpCondExpression, pfCondition) ||
+ !EvaluateCondExpression (lpOp+1, &fCond))
+ return(FALSE);
+
+ *pfCondition = !(*pfCondition && fCond);
+ return(TRUE);
+ }
+
+ if (!strcmp (lpCondExpression, "1"))
+ {
+ *pfCondition = TRUE;
+ return(TRUE);
+ }
+ else if (!strcmp (lpCondExpression, "0"))
+ {
+ *pfCondition = FALSE;
+ return(TRUE);
+ }
+ else
+ return(FALSE);
+}
+
+/*
+ * Used by IfHandler()
+ * Evaluate up to 10 conditions.
+ * Return TRUE if succeed, FALSE otherwise.
+ * On return, buffer stores whatever after conditional expressions
+ * without leading spaces.
+ */
+int EvaluateCond(char *buffer, int *pfCondition)
+{
+ int fCondition = TRUE, fCurrent, fSucceed = FALSE, nCount;
+ char CondExpression[MAXLEN], *lpCond = CondExpression, *lpBuffer = buffer;
+
+ for (nCount = 0; nCount < 10; nCount++)
+ {
+ while (*lpBuffer == '(')
+ {
+ *lpCond = *lpBuffer;
+ lpCond++;
+ lpBuffer++;
+ }
+
+ lpBuffer = RemoveSpaces (lpBuffer);
+
+ if (!EvalSingleCond (lpBuffer, &fCurrent))
+ break;
+
+ *lpCond = fCurrent? '1' : '0';
+ lpCond++;
+
+ while (*lpBuffer == ')')
+ {
+ *lpCond = *lpBuffer;
+ lpCond++;
+ lpBuffer++;
+ }
+
+ lpBuffer = RemoveSpaces (lpBuffer);
+
+ if (*lpBuffer == ',')
+ {
+ *lpCond = '*';
+ lpCond++;
+
+ lpBuffer = RemoveSpaces (lpBuffer+1);
+
+ if (!strncmp (lpBuffer, "AND", 3))
+ lpBuffer = RemoveSpaces (lpBuffer+3);
+ }
+ else if (!strncmp (lpBuffer, "AND", 3))
+ {
+ *lpCond = '*';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+3);
+ }
+ else if (!strncmp (lpBuffer, "&&", 2))
+ {
+ *lpCond = '*';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+2);
+ }
+ else if ( (!strncmp (lpBuffer, "OR", 2)) ||
+ (!strncmp (lpBuffer, "||", 2)) )
+ {
+ *lpCond = '+';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+2);
+ }
+ /*
+ * A NOR expression is documented in some books, but isn't
+ * implemented in the 4X login.exe I have.
+ */
+ else if (!strncmp (lpBuffer, "NOR", 3))
+ {
+ *lpCond = '^';
+ lpCond++;
+ lpBuffer = RemoveSpaces (lpBuffer+3);
+ }
+ else
+ {
+ fSucceed = TRUE;
+ *lpCond = 0;
+ lpBuffer = RemoveSpaces (lpBuffer);
+ memmove (buffer, lpBuffer, strlen (lpBuffer)+1);
+ break;
+ }
+ }
+
+ if (fSucceed)
+ fSucceed = EvaluateCondExpression (CondExpression, pfCondition);
+
+ return(fSucceed);
+}
+
+/*
+ * If statement handler.
+ */
+int IfHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE, fCondition;
+
+ do
+ {
+ if (nCondIndex+1 == MAX_NUM_IF)
+ {
+ DisplayMessage(IDR_IF_TOO_DEEP);
+ fGlobalExitFlag = TRUE;
+ fGlobalIfTooDeep = TRUE;
+ return TRUE;
+ }
+
+ if (EndOfLine (lpParam))
+ break;
+
+ if (!EvaluateCond (lpParam, &fCondition))
+ break;
+
+ if (!strncmp (lpParam, "THEN", 4))
+ {
+ lpParam = RemoveSpaces (lpParam+4);
+
+ if (!strncmp (lpParam, "BEGIN", 5))
+ {
+ lpParam += 5;
+
+ if (!EndOfLine (lpParam))
+ break;
+ }
+ else if((!strncmp (lpParam, "DO", 2)) &&
+ (strncmp (lpParam, "DOS", 3)))
+ {
+ lpParam += 2;
+ if (!EndOfLine (lpParam))
+ break;
+ }
+ }
+ else if (!strncmp (lpParam, "BEGIN", 5))
+ {
+ lpParam += 5;
+
+ if (!EndOfLine (lpParam))
+ break;
+ }
+
+ if (EndOfLine (lpParam))
+ {
+ nCondIndex++;
+ aCondVal[nCondIndex] =
+ (nCondIndex > 0 && !aCondVal[nCondIndex-1])?
+ FALSE : fCondition;
+ }
+ else
+ {
+ if (fCondition && (nCondIndex == -1 || aCondVal[nCondIndex]))
+ CommandDispatch (lpParam);
+ }
+
+ fCommandHandled = TRUE;
+
+ }while (FALSE);
+
+ return(fCommandHandled);
+}
+
+/*
+ * Else statement handler.
+ */
+int ElseHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+
+ if (EndOfLine (lpParam))
+ {
+ if (nCondIndex == 0 ||
+ nCondIndex > 0 && aCondVal[nCondIndex-1])
+ aCondVal[nCondIndex] = !aCondVal[nCondIndex];
+
+ fCommandHandled = TRUE;
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * End statement handler.
+ */
+int EndHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+
+ if (EndOfLine (lpParam))
+ {
+ if (nCondIndex > -1)
+ nCondIndex--;
+
+ fCommandHandled = TRUE;
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * INCLUDE [pathname]filename
+ */
+int IncludeHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE, nFileSize;
+ char *lpLoginScript, *lpTemp;
+ int i, nCondIndexCopy;
+ int aCondValCopy[MAX_NUM_IF];
+ int iRet;
+
+ //
+ // Save off the old globals that track where we are.
+ //
+
+ LABEL_LIST *pLabelList = pGlobalLabelList;
+ char *lpLine = lpGlobalLine;
+ char *lpLineSeparator = lpGlobalLineSeparator;
+ int fHaveNulledLineSeparator = fGlobalHaveNulledLineSeparator;
+
+ pGlobalLabelList = NULL; // so that we don't free it.
+
+ do
+ {
+ if (strtok (lpParam, __SPACES__) == NULL)
+ break;
+
+ lpTemp = strtok(NULL, __SPACES__);
+ if (lpTemp && !EndOfLine (lpTemp))
+ break;
+
+ fCommandHandled = TRUE;
+ NotQuotedStringTranslate(lpParam, TRUE);
+
+ nCondIndexCopy = nCondIndex;
+ for (i = 0; i < MAX_NUM_IF; i++)
+ aCondValCopy[i] = aCondVal[i];
+
+ /*
+ * First we try a NDS object and then a file
+ */
+ iRet = FALSE;
+ if ( fNDS )
+ {
+ iRet = ProcessLoginScriptProperty( lpParam );
+ if ( !iRet )
+ {
+ char Fixup[MAXLEN];
+ char * ptr;
+ /*
+ * Strip off the . in front and add context at end
+ */
+ ptr = RemoveSpaces (lpParam);
+ if ( *ptr == '.' ) {
+ ptr++;
+ strncpy( Fixup, ptr, MAXLEN );
+ }
+ else {
+ strncpy( Fixup, ptr, MAXLEN );
+ if ( Fixup[strlen(Fixup)-1] != '.' )
+ strcat( Fixup, "." );
+ strcat( Fixup, LOGIN_CONTEXT );
+ }
+ iRet = ProcessLoginScriptProperty( Fixup );
+ }
+ }
+
+ if ( !fNDS || !iRet )
+ {
+ nFileSize = NWGetFileSize (lpParam);
+ if (nFileSize == 0)
+ {
+ DisplayMessage(IDR_ERROR_OPEN_SCRIPT, lpParam);
+ break;
+ }
+
+ // user login script exists.
+ lpLoginScript = malloc (nFileSize);
+ if (lpLoginScript == NULL)
+ {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ break;
+ }
+
+ LoadFile (lpParam, lpLoginScript, nFileSize);
+
+ ProcessLoginScript (lpLoginScript);
+
+ free (lpLoginScript);
+ }
+
+ fGlobalExitFlag = FALSE;
+
+ nCondIndex = nCondIndexCopy;
+ for (i = 0; i < MAX_NUM_IF; i++)
+ aCondVal[i] = aCondValCopy[i];
+
+ }while (FALSE);
+
+ //
+ // restore the globals that track where we are in the file.
+ //
+
+ pGlobalLabelList = pLabelList;
+ lpGlobalLine = lpLine;
+ lpGlobalLineSeparator = lpLineSeparator;
+ fGlobalHaveNulledLineSeparator = fHaveNulledLineSeparator;
+
+
+ return(fCommandHandled);
+}
+
+/*
+ * Map command handler.
+ */
+int MapHandler (char *lpParam)
+{
+ char buffer[MAXLEN]="";
+
+ strcpy( buffer, lpParam );
+
+ NotQuotedStringTranslate( buffer, TRUE );
+
+ Map( buffer );
+
+ return(TRUE);
+}
+
+/*
+ * PAUSE or WAIT.
+ */
+int PauseHandler (char *lpParam)
+{
+ int fCommandHandled = FALSE;
+
+ if (EndOfLine (lpParam))
+ {
+ //Empty kb buffer first.
+ while (_kbhit())
+ _getch();
+
+ DisplayMessage(IDR_STRIKE_KEY);
+ _getch();
+ DisplayMessage(IDR_NEWLINE);
+ fCommandHandled = TRUE;
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Used by WriteHandler().
+ * Return TRUE if buffer ends with ';'. Set it to 0
+ * Return FALSE otherwise.
+ */
+int EndWithSemicolon (char *buffer)
+{
+ char *lpLastSemicolon, *lpRest;
+ lpLastSemicolon = strrchr (buffer, ';');
+ if (lpLastSemicolon)
+ {
+ lpRest = RemoveSpaces (lpLastSemicolon+1);
+ if (*lpRest == 0)
+ {
+ *lpLastSemicolon = 0;
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+char *ConvertPercent (char *buffer)
+{
+ char *lpPercent, *lpBuffer = buffer;
+ int nPercent = 0;
+
+ while (lpPercent = strchr (lpBuffer, '%'))
+ {
+ nPercent++;
+ lpBuffer = lpPercent+1;
+ }
+
+ if (nPercent == 0)
+ return(NULL);
+
+ lpBuffer = malloc (strlen(buffer)+nPercent+1);
+ if (lpBuffer == NULL)
+ return(NULL);
+
+ strcpy (lpBuffer, buffer);
+
+ lpPercent = strchr (lpBuffer, '%');
+
+ while (lpPercent)
+ {
+ memmove (lpPercent+1, lpPercent, strlen (lpPercent)+1);
+ lpPercent = strchr ( lpPercent+2, '%');
+ }
+
+ return(lpBuffer);
+}
+
+/*
+ * WRITE text, display a text message on the screen.
+ */
+int WriteHandler (char *lpParam)
+{
+ int fNewLine;
+ char *lpBuffer;
+
+ if (*lpParam == 0)
+ {
+ DisplayMessage(IDR_NEWLINE);
+ return(TRUE);
+ }
+
+ fNewLine = !EndWithSemicolon (lpParam);
+
+ if (!QuotedStringTranslate (lpParam))
+ return FALSE;
+
+ lpBuffer = ConvertPercent (lpParam);
+ if (lpBuffer == NULL)
+ {
+ DisplayOemString(lpParam);
+ }
+ else
+ {
+ DisplayOemString(lpBuffer);
+ free (lpBuffer);
+ }
+
+ if (fNewLine)
+ DisplayMessage(IDR_NEWLINE);
+
+ return(TRUE);
+}
+
+/*
+ * Used by ShiftHandler().
+ * Return TURE if the line is all numbers + [comments]
+ * Return FALSE otherwise.
+ */
+int AreAllNumbers(char *buffer)
+{
+ while (isdigit(*buffer))
+ buffer++;
+
+ return(EndOfLine (buffer));
+}
+
+/*
+ * Set the nGlobalShiftDelta variable.
+ */
+int ShiftHandler (char *lpParam)
+{
+ int fCommandHandled = TRUE;
+
+ if (EndOfLine (lpParam))
+ nGlobalShiftDelta++;
+ else if (*lpParam == '-')
+ {
+ lpParam = RemoveSpaces (lpParam+1);
+ if (!AreAllNumbers(lpParam))
+ fCommandHandled = FALSE;
+ else
+ nGlobalShiftDelta -= atoi (lpParam);
+ }
+ else
+ {
+ if (*lpParam == '+')
+ lpParam = RemoveSpaces (lpParam+1);
+
+ if (!AreAllNumbers(lpParam))
+ fCommandHandled = FALSE;
+ else
+ nGlobalShiftDelta += atoi (lpParam);
+ }
+
+ return(fCommandHandled);
+}
+
+/*
+ * Set the machine name.
+ */
+int MachineHandler (char *lpParam)
+{
+ int nLen, i;
+
+ if (*lpParam != '=')
+ return(FALSE);
+
+ lpParam = RemoveSpaces (lpParam+1);
+ if (!QuotedStringTranslate(lpParam))
+ return(FALSE);
+
+ nLen = strlen (lpParam);
+ for (i = nLen; i < 15; i++)
+ *(lpParam+i) = ' ';
+
+ *(lpParam+15) = 0;
+
+ return(TRUE);
+}
+
+/*
+ * Set the fGlobalCompatible variable.
+ */
+int CompatibleHandler(char *lpParam)
+{
+ if (!EndOfLine (lpParam))
+ return(FALSE);
+
+ fGlobalCompatible = TRUE;
+ return(TRUE);
+}
+
+/*
+ * Clear the screen
+ */
+int ClearHandler(char *lpParam)
+{
+ CONSOLE_SCREEN_BUFFER_INFO coninfo;
+ COORD scrolltarget;
+ CHAR_INFO chinfo;
+ SMALL_RECT scrollrect;
+
+ if ( hconout == INVALID_HANDLE_VALUE )
+ {
+ hconout = CreateFile( L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, 0, NULL );
+ }
+
+ if ( hconout == INVALID_HANDLE_VALUE )
+ return TRUE;
+
+ GetConsoleScreenBufferInfo( hconout, &coninfo );
+
+ scrolltarget.Y = (SHORT)(0 - coninfo.dwSize.Y);
+ scrolltarget.X = 0;
+
+ scrollrect.Top = 0;
+ scrollrect.Left = 0;
+ scrollrect.Bottom = coninfo.dwSize.Y;
+ scrollrect.Right = coninfo.dwSize.X;
+ chinfo.Char.AsciiChar = ' ';
+ chinfo.Attributes = coninfo.wAttributes;
+ ScrollConsoleScreenBufferA( hconout, &scrollrect, NULL,
+ scrolltarget, &chinfo);
+
+ coninfo.dwCursorPosition.X = 0;
+ coninfo.dwCursorPosition.Y = 0;
+
+ SetConsoleCursorPosition( hconout, coninfo.dwCursorPosition );
+ return(TRUE);
+}
+
+/*
+ * Display the Last Login Time
+ */
+int LastLoginTimeHandler(char *lpParam)
+{
+ BYTE dataBuffer[128];
+ unsigned char moreFlag;
+ unsigned char propertyType;
+
+ if ( fNDS )
+ {
+ nwShowLastLoginTime();
+ }
+ else
+ {
+ NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "MISC_LOGIN_INFO",
+ 1,
+ dataBuffer,
+ &moreFlag,
+ &propertyType);
+ /*
+ * 0 = year
+ * 1 = month
+ * 2 = day
+ * 3 = hour
+ * 4 = minute
+ * 5 = second
+ */
+
+ if ( dataBuffer[3] >= 12 )
+ {
+ DisplayMessage( IDR_LASTLOGIN_PM,
+ dataBuffer[1],
+ dataBuffer[2],
+ dataBuffer[0],
+ dataBuffer[3] - 12,
+ dataBuffer[4],
+ dataBuffer[5] );
+ }
+ else
+ {
+ DisplayMessage( IDR_LASTLOGIN_AM,
+ dataBuffer[1],
+ dataBuffer[2],
+ dataBuffer[0],
+ dataBuffer[3],
+ dataBuffer[4],
+ dataBuffer[5] );
+ }
+ }
+
+ return(TRUE);
+}
+
+
+
+/*
+ * Change and/or display the current context.
+ */
+int ContextHandler (char *lpParam)
+{
+ unsigned char Buffer[MAXLEN];
+ unsigned char * ptr;
+ unsigned char CurrentContext[MAXLEN];
+
+ if ( *lpParam )
+ {
+ NotQuotedStringTranslate(lpParam, TRUE);
+
+ ptr = RemoveSpaces (lpParam);
+
+ if ( NDSCanonicalizeName( lpParam, Buffer, MAXLEN, TRUE ) )
+ {
+ DisplayMessage(IDR_CHANGE_CONTEXT_ERROR, lpParam);
+ return(TRUE);
+ }
+
+ if ( NDSChangeContext( Buffer ) )
+ {
+ DisplayMessage(IDR_CHANGE_CONTEXT_ERROR, lpParam);
+ return(TRUE);
+ }
+ }
+
+ if ( NDSGetContext( CurrentContext, MAXLEN ) )
+ {
+ DisplayMessage(IDR_GET_CONTEXT_ERROR);
+ }
+ else
+ {
+ DisplayMessage(IDR_DISPLAY_CONTEXT, CurrentContext);
+ }
+ return(TRUE);
+}
+
+/*
+ * Do nothing. Return TRUE so the the command will not
+ * be considered as bad.
+ */
+int ScriptServerHandler (char *lpParam)
+{
+ return(TRUE);
+}
+
+/*
+ * If this is a 4X login, do not execute the default login script.
+ */
+int NoDefaultHandler (char *lpParam)
+{
+ if ( fNDS )
+ fNoDefaultLoginScript = TRUE;
+ return(TRUE);
+}
+
+/*
+ * Do nothing. Return TRUE so the the command will not
+ * be considered as bad.
+ */
+int NullHandler (char *lpParam)
+{
+ return(TRUE);
+}
+
+#define NUMBER_ARGUMENTS 20
+
+/*
+ * External commands start with '#', such as #command /c cls
+ */
+void ExternalCmdHandler (char *lpCommand)
+{
+ int n;
+ int i;
+ unsigned int CommandLength;
+ char *lpCmdName, *argv[NUMBER_ARGUMENTS];
+
+ for ( n = 0; n < NUMBER_ARGUMENTS; n++ )
+ argv[n] = NULL;
+
+ if ((nCondIndex == -1) || aCondVal[nCondIndex])
+ {
+ //Convert variables first.
+ NotQuotedStringTranslate(lpCommand, FALSE);
+
+ lpCommand = RemoveSpaces(lpCommand+1);
+ lpCmdName = strtok (lpCommand, __SPACES__);
+
+ lpCmdName = NTNWtoUNCFormat(lpCmdName);
+
+ argv[0] = lpCmdName;
+
+ for (n = 1; n < NUMBER_ARGUMENTS - 1; n++)
+ {
+ if ((argv[n] = strtok (NULL, __SPACES__)) == NULL)
+ break;
+ }
+
+ argv[9] = NULL;
+
+ /*
+ * Capture command
+ */
+ CommandLength = strlen( lpCommand );
+
+ /*
+ * First see if a COMMAND.COM is invoked
+ */
+ if ( ( ( CommandLength >= strlen("COMMAND.COM") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("COMMAND.COM")], "COMMAND.COM") ) ) ||
+ ( ( CommandLength >= strlen("COMMAND") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("COMMAND")], "COMMAND") ) ) )
+ {
+ /*
+ * Search for the CAPTURE argument
+ */
+ for ( i = 1; i < n; i++ )
+ {
+ CommandLength = strlen( argv[i] );
+ if ( ( ( CommandLength >= strlen("CAPTURE.EXE") ) &&
+ ( !_stricmp( &(argv[i])[CommandLength-strlen("CAPTURE.EXE")], "CAPTURE.EXE") ) ) ||
+ ( ( CommandLength >= strlen("CAPTURE") ) &&
+ ( !_stricmp( &(argv[i])[CommandLength-strlen("CAPTURE")], "CAPTURE") ) ) ) {
+ Capture( argv + i, n - i );
+ return;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Is this a CAPTURE command?
+ */
+ if ( ( ( CommandLength >= strlen("CAPTURE.EXE") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("CAPTURE.EXE")], "CAPTURE.EXE") ) ) ||
+ ( ( CommandLength >= strlen("CAPTURE") ) &&
+ ( !_stricmp( &lpCommand[CommandLength-strlen("CAPTURE")], "CAPTURE") ) ) ) {
+ Capture( argv, n );
+ return;
+ }
+ }
+
+ if ((SCRIPT_ERROR = _spawnvp (P_WAIT, lpCmdName, argv)) == -1)
+ {
+ if (errno == ENOENT)
+ DisplayMessage(IDR_ENOENT, lpCommand);
+ else
+ DisplayMessage(IDR_CANNOT_EXECUTE, lpCommand);
+ }
+ }
+}
+
+/*
+ * Printe out the bad command line.
+ */
+void BadCommandHandler (char *lpCommand)
+{
+ DisplayMessage(IDR_SCRIPT_ERROR);
+ DisplayMessage(IDR_ORIGINAL_LINE_WAS, lpCommand);
+}
+
+
+/*
+ * Swap the object id.
+ */
+DWORD SwapLong(DWORD number)
+{
+ BYTE *p, tmp[4];
+
+ p = (BYTE *)&number;
+
+ tmp[0] = p[3];
+ tmp[1] = p[2];
+ tmp[2] = p[1];
+ tmp[3] = p[0];
+
+ return(*(DWORD *)tmp);
+}
+
+/*
+ * Remove leading spaces, including tabs.
+ */
+char *RemoveSpaces (char * buffer)
+{
+ while (*buffer == ' ' || *buffer == '\t')
+ buffer++;
+ return(buffer);
+}
+
+/*
+ * Return TRUE if buffer points to the end of the lind, FALSE otherwise.
+ */
+int EndOfLine (char *buffer)
+{
+ int fEndOfLine = FALSE;
+
+ buffer = RemoveSpaces (buffer);
+
+ if (*buffer == '\0' ||
+ *buffer == ';' ||
+ *buffer == '*' ||
+ *buffer == '\r')
+ fEndOfLine = TRUE;
+
+ return(fEndOfLine);
+}
+
+/*
+ * Return TRUE if lpParam points to "ON", FALSE otherwise.
+ */
+int IsOn (char *lpParam)
+{
+ int fOn = FALSE;
+
+ if (!strncmp (lpParam, "ON", 2))
+ {
+ lpParam += 2;
+ fOn = EndOfLine (lpParam);
+ }
+
+ return(fOn);
+}
+
+/*
+ * Return TRUE if lpParam points to "OFF", FALSE otherwise.
+ */
+int IsOff (char *lpParam)
+{
+ int fOff = FALSE;
+
+ if (!strncmp (lpParam, "OFF", 3))
+ {
+ lpParam += 3;
+ fOff = EndOfLine (lpParam);
+ }
+
+ return(fOff);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the value of time variable specified by index.
+ */
+void GetTime (char *buffer, int index)
+{
+ time_t currentTime;
+ struct tm *tmCurrentTime;
+
+ time (&currentTime);
+ tmCurrentTime = localtime(&currentTime);
+
+ switch (index)
+ {
+ case IDS_DAY:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_mday);
+ break;
+ case IDS_DAY_OF_WEEK:
+ strcpy (buffer, __Day__[tmCurrentTime->tm_wday]);
+ break;
+ case IDS_MONTH:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_mon+1);
+ break;
+ case IDS_MONTH_NAME:
+ strcpy (buffer, __Month__[tmCurrentTime->tm_mon]);
+ break;
+ case IDS_NDAY_OF_WEEK:
+ sprintf (buffer, "%d\0", tmCurrentTime->tm_wday+1);
+ break;
+ case IDS_SHORT_YEAR:
+ sprintf (buffer, "%04d\0", tmCurrentTime->tm_year+1900);
+ strcpy (buffer, buffer+2);
+ break;
+ case IDS_YEAR:
+ sprintf (buffer, "%04d\0", tmCurrentTime->tm_year+1900);
+ break;
+ case IDS_AM_PM:
+ strcpy (buffer, __AMPM__[tmCurrentTime->tm_hour > 12? 1:0]);
+ break;
+ case IDS_GREETING_TIME:
+ if (tmCurrentTime->tm_hour >= 6 && tmCurrentTime->tm_hour < 12)
+ index=0;
+ else if (tmCurrentTime->tm_hour >= 12 && tmCurrentTime->tm_hour < 18)
+ index=1;
+ else
+ index=2;
+
+ strcpy (buffer, __GREETING__[index]);
+ break;
+ case IDS_HOUR:
+ if (tmCurrentTime->tm_hour > 12)
+ tmCurrentTime->tm_hour -= 12;
+ sprintf (buffer, "%d\0", tmCurrentTime->tm_hour);
+ break;
+ case IDS_HOUR24:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_hour);
+ break;
+ case IDS_MINUTE:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_min);
+ break;
+ case IDS_SECOND:
+ sprintf (buffer, "%02d\0", tmCurrentTime->tm_sec);
+ break;
+ default:
+ *buffer = 0;
+ }
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer login user's full name.
+ */
+void GetFullName (char *buffer)
+{
+ unsigned int iRet = 0;
+ unsigned char moreFlag;
+ unsigned char propertyType;
+
+ if ( fNDS )
+ {
+ NDSGetVar ( "Full Name", buffer, 128 );
+ if ( buffer[0] == '\0' )
+ strcpy (buffer, "* Unknown *");
+ }
+ else
+ {
+ iRet = NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "IDENTIFICATION",
+ 1,
+ buffer,
+ &moreFlag,
+ &propertyType);
+ if (iRet)
+ strcpy (buffer, "* Unknown *");
+ }
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer login user's object id.
+ */
+void GetUserID (char *buffer)
+{
+ unsigned long dwObjectID = 0;
+
+ if ( fNDS )
+ dwObjectID = GUserObjectID;
+ else
+ NTGetUserID( CONNECTION_ID, &dwObjectID );
+ sprintf (buffer, "%lx\0", SwapLong(dwObjectID));
+ _strupr (buffer);
+}
+
+unsigned int GetDays (unsigned int year, BYTE month, BYTE date)
+{
+ unsigned int i, days = 0;
+
+ for (i = 1; i < month; i++)
+ {
+ if (i == 2)
+ days += (year%4)? 28 : 29;
+ else if (i == 4 || i == 6 || i == 9 || i == 11)
+ days += 30;
+ else
+ days += 31;
+ }
+
+ days += date;
+ return(days);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the days in which the password expires.
+ */
+void GetPasswordExpires (char *buffer)
+{
+ unsigned int iRet = 0;
+ unsigned int iRet2 = 0;
+ unsigned char moreFlag;
+ unsigned int yearCurrent, yearEnd, days;
+ BYTE monthCurrent, dayCurrent, monthEnd, dayEnd;
+ unsigned int exptime, logintime;
+ unsigned char propertyType;
+
+
+ if ( fNDS )
+ {
+ iRet = NDSGetUserProperty ("Password Expiration Time", (PBYTE)&exptime,
+ 4, NULL, NULL);
+ iRet2 = NDSGetUserProperty ("Login Time", (PBYTE)&logintime,
+ 4, NULL, NULL);
+
+ if ( ( exptime && logintime ) && !iRet && !iRet2 )
+ {
+ if ( exptime <= logintime )
+ strcpy( buffer, "0" );
+ else
+ sprintf( buffer, "%u", ((exptime-logintime)/(60*60*24)) + 1 );
+ }
+ else
+ {
+ sprintf( buffer, "%u", 0x7FFF );
+ }
+ }
+ else
+ {
+ NTGetTheDate( &yearCurrent, &monthCurrent, &dayCurrent );
+ NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "LOGIN_CONTROL",
+ 1,
+ buffer,
+ &moreFlag,
+ &propertyType);
+
+ yearEnd = 1900 + buffer[4];
+ monthEnd = buffer[5];
+ dayEnd = buffer[6];
+
+ if (monthEnd == 0)
+ days = (((yearCurrent%4)? 365 : 366) - GetDays (yearCurrent, monthCurrent, dayCurrent));
+ else if (yearEnd == yearCurrent)
+ {
+ if (monthEnd < monthCurrent ||
+ (monthEnd == monthCurrent && dayEnd <= dayCurrent))
+ days = 0;
+ else
+ days = GetDays (yearEnd, monthEnd, dayEnd) - GetDays (yearCurrent, monthCurrent, dayCurrent) - 1;
+ }
+ else
+ days = ((yearCurrent%4)? 364 : 365) + GetDays (yearEnd, monthEnd, dayEnd) - GetDays (yearCurrent, monthCurrent, dayCurrent);
+
+ sprintf (buffer, "%u", days);
+ }
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer value of the dos environment variable.
+ * If the variable is not found, buffer is set to be empty string.
+ */
+void GetDosEnv (char *buffer)
+{
+ char *lpTemp;
+
+ // This could be called from "%<x>" where x is not upcase. capitalize
+ // the string first to be sure.
+ _strupr(buffer);
+
+ lpTemp = strchr (buffer, '>');
+ *lpTemp = 0;
+
+ lpTemp = getenv (buffer+1);
+
+ if (lpTemp && strlen (lpTemp) < MAXLEN )
+ strcpy (buffer, lpTemp);
+ else
+ *buffer = 0;
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the 8 bytes network address.
+ */
+void GetNetWorkAddr (char *buffer)
+{
+ unsigned char internetAddress[10];
+
+ GetInternetAddress (CONNECTION_ID,
+ CONNECTION_NUMBER,
+ internetAddress);
+
+ sprintf (buffer,
+ "%02X%02X%02X%02X\0",
+ internetAddress[0],
+ internetAddress[1],
+ internetAddress[2],
+ internetAddress[3] );
+}
+
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the 12 bytes node address to buffer.
+ */
+void GetPStation (char *buffer)
+{
+ unsigned char internetAddress[10];
+
+ GetInternetAddress (CONNECTION_ID,
+ CONNECTION_NUMBER,
+ internetAddress);
+
+ sprintf (buffer,
+ "%02X%02X%02X%02X%02X%02X\0",
+ internetAddress[4],
+ internetAddress[5],
+ internetAddress[6],
+ internetAddress[7],
+ internetAddress[8],
+ internetAddress[9]);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer the decimal string representing the remaining account
+ * balance
+ */
+void GetAccountBalance (char *buffer)
+{
+ DWORD balance;
+ BYTE dataBuffer[128];
+ unsigned char moreFlag;
+ unsigned char propertyType;
+ unsigned int err;
+
+ if ( fNDS )
+ {
+ err = NDSGetUserProperty ("Account Balance", dataBuffer,128, NULL, NULL);
+ }
+ else
+ {
+ err = NWReadPropertyValue ((NWCONN_HANDLE)CONNECTION_ID,
+ LOGIN_NAME,
+ OT_USER,
+ "ACCOUNT_BALANCE",
+ 1,
+ dataBuffer,
+ &moreFlag,
+ &propertyType);
+ }
+
+ if ( err )
+ balance = 0;
+ else
+ balance = *((DWORD *)dataBuffer);
+
+ sprintf (buffer, "%d", balance);
+}
+
+/*
+ * Used by VarTranslate().
+ * Copy to buffer MACHINE, SMACHINE, OS, OS_VERSION or SHELL_TYPE
+ * to buffer according to index.
+ */
+void GetShellVersion(char *buffer, int index)
+{
+ static char szTemp[40];
+ char *lpTemp;
+ BYTE shellmajor, shellminor, shellnum;
+
+ NTGetVersionOfShell( szTemp, &shellmajor, &shellminor, &shellnum );
+
+ lpTemp = szTemp;
+
+ switch (index)
+ {
+ case IDS_OS:
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_OS_VERSION:
+ lpTemp += (strlen (lpTemp)+1);
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_MACHINE:
+ lpTemp += (strlen (lpTemp)+1);
+ lpTemp += (strlen (lpTemp)+1);
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_SMACHINE:
+ lpTemp += (strlen (lpTemp)+1);
+ lpTemp += (strlen (lpTemp)+1);
+ lpTemp += (strlen (lpTemp)+1);
+ strcpy (buffer, lpTemp);
+ break;
+ case IDS_SHELL_TYPE:
+ case IDS_SHELL_VERSION:
+ sprintf (buffer, "V%d.%d%d%c", shellmajor, shellminor/10, shellminor%10, 'A'+shellnum);
+ break;
+ default:
+ *buffer = 0;
+ break;
+ }
+}
+
+void GetArgv(char *buffer)
+{
+ int n;
+
+ n = atoi (buffer)+nGlobalShiftDelta;
+
+ if (n == 0)
+ strcpy (buffer, PREFERRED_SERVER);
+ else if (n == 1)
+ strcpy (buffer, LOGIN_NAME);
+ else if (n > 1 && n < ARGC)
+ strcpy (buffer, ARGV[n]);
+ else
+ *buffer = 0;
+}
+
+/*
+ * vartext is an array of size MAXLEN.
+ * vartext points to a string starts with a variable on enter.
+ * vartext stores the value of the variable on exit.
+ * Return the lenth of the variable.
+ */
+int VarTranslate(char *vartext)
+{
+ int i, nVarLen = 0;
+
+ for (i = 0; i < (fNDS ? NUMVAR : NUMVAR_3X); i++)
+ {
+ if (!nwVarNameCompare(vartext, varTable[i].VarName))
+ {
+ nVarLen = strlen(varTable[i].VarName);
+
+ switch ( i )
+ {
+ case IDS_DAY_OF_WEEK:
+ case IDS_DAY:
+ case IDS_MONTH_NAME:
+ case IDS_MONTH:
+ case IDS_NDAY_OF_WEEK:
+ case IDS_SHORT_YEAR:
+ case IDS_YEAR:
+ case IDS_AM_PM:
+ case IDS_GREETING_TIME:
+ case IDS_HOUR24:
+ case IDS_HOUR:
+ case IDS_MINUTE:
+ case IDS_SECOND:
+ GetTime (vartext, i);
+ break;
+ case IDS_FULL_NAME:
+ GetFullName (vartext);
+ break;
+ case IDS_LOGIN_NAME:
+ strcpy (vartext, LOGIN_NAME);
+ /*
+ * 4X LOGIN.EXE always truncates and replaces spaces
+ * with underscores. There was a report that some
+ * versions of 3X LOGIN.EXE do this also.
+ */
+ if ( fNDS )
+ {
+ int i;
+ vartext[8] = '\0';
+ for ( i = 0; i < 8; i++ )
+ if ( vartext[i] == ' ' )
+ vartext[i] = '_';
+ }
+ break;
+ case IDS_USER_ID:
+ GetUserID (vartext);
+ break;
+ case IDS_PASSWORD_EXPIRES:
+ GetPasswordExpires (vartext);
+ break;
+ case IDS_NETWORK_ADDRESS:
+ case IDS_NETWORK:
+ GetNetWorkAddr (vartext);
+ break;
+ case IDS_FILE_SERVER:
+ strcpy (vartext, PREFERRED_SERVER);
+ break;
+ case IDS_ACCESS_SERVER:
+ case IDS_ACCESS:
+ strcpy (vartext, "0");
+ break;
+ case IDS_ERROR_LEVEL:
+ case IDS_ERRORLEVEL:
+ sprintf (vartext, "%u", SCRIPT_ERROR);
+ break;
+ case IDS_MACHINE:
+ case IDS_OS_VERSION:
+ case IDS_OS:
+ case IDS_SMACHINE:
+ case IDS_SHELL_TYPE:
+ case IDS_SHELL_VERSION:
+ GetShellVersion (vartext, i);
+ break;
+ case IDS_STATION:
+ sprintf (vartext, "%d", CONNECTION_NUMBER);
+ break;
+ case IDS_P_STATION:
+ GetPStation (vartext);
+ break;
+ case IDS_LAST_NAME:
+ case IDS_SURNAME:
+ strcpy (vartext, LAST_NAME);
+ break;
+ case IDS_LOGIN_CONTEXT:
+ strcpy (vartext, LOGIN_CONTEXT);
+ break;
+ case IDS_NETWARE_REQUESTER:
+ case IDS_REQUESTER_VERSION:
+ case IDS_DOS_REQUESTER:
+ case IDS_REQUESTER:
+ strcpy (vartext, REQUESTER_VERSION);
+ break;
+ case IDS_REQUESTER_CONTEXT:
+ strcpy (vartext, REQUESTER_CONTEXT);
+ break;
+ case IDS_ACCOUNT_BALANCE:
+ GetAccountBalance (vartext);
+ break;
+ case IDS_CN:
+ strcpy (vartext, COMMON_NAME);
+ break;
+ case IDS_HOME_DIRECTORY:
+ {
+ char buffer[MAXLEN];
+
+ vartext[0] = '\0';
+ NDSGetVar ( varTable[i].VarName, buffer, MAXLEN );
+ if ( buffer[0] )
+ ConverNDSPathToNetWarePathA( buffer, NULL, vartext );
+ }
+ break;
+ case IDS_ADMINISTRATIVE_ASSISTANT:
+ case IDS_ALLOW_UNLIMITED_CREDIT:
+ case IDS_DESCRIPTION:
+ case IDS_EMAIL_ADDRESS:
+ case IDS_EMPLOYEE_ID:
+ case IDS_FACSIMILE_TELEPHONE_NUMBER:
+ case IDS_GROUP_MEMBERSHIP:
+ case IDS_HIGHER_PRIVILEGES:
+ case IDS_INITIALS:
+ case IDS_LANGUAGE:
+ case IDS_LOCKED_BY_INTRUDER:
+ case IDS_LOGIN_DISABLED:
+ case IDS_LOGIN_GRACE_LIMIT:
+ case IDS_LOGIN_GRACE_REMAINING:
+ case IDS_LOGIN_INTRUDER_ATTEMPTS:
+ case IDS_LOGIN_MAXIMUM_SIMULTANEOUS:
+ case IDS_MAILSTOP:
+ case IDS_MESSAGE_SERVER:
+ case IDS_MINIMUM_ACCOUNT_BALANCE:
+ case IDS_OBJECT_CLASS:
+ case IDS_OU:
+ case IDS_PASSWORD_ALLOW_CHANGE:
+ case IDS_PASSWORD_MINIMUM_LENGTH:
+ case IDS_PASSWORD_REQUIRED:
+ case IDS_PASSWORD_UNIQUE_REQUIRED:
+ case IDS_PASSWORDS_USED:
+ case IDS_PHYSICAL_DELIVERY_OFFICE_NAME:
+ case IDS_POSTAL_ADDRESS:
+ case IDS_POSTAL_CODE:
+ case IDS_POSTAL_OFFICE_BOX:
+ case IDS_PRIVATE_KEY:
+ case IDS_PROFILE:
+ case IDS_REVISION:
+ case IDS_SECURITY_EQUALS:
+ case IDS_SECURITY_FLAGS:
+ case IDS_SEE_ALSO:
+ case IDS_SERVER_HOLDS:
+ case IDS_SUPERVISOR:
+ case IDS_TELEPHONE_NUMBER:
+ case IDS_TITLE:
+ case IDS_CERTIFICATE_VALIDITY_INTERVAL:
+ case IDS_EQUIVALENT_TO_ME:
+ case IDS_GENERATIONAL_QUALIFIER:
+ case IDS_GIVEN_NAME:
+ case IDS_MAILBOX_ID:
+ case IDS_MAILBOX_LOCATION:
+ case IDS_PROFILE_MEMBERSHIP:
+ case IDS_SA:
+ case IDS_S:
+ case IDS_L:
+ NDSGetVar ( varTable[i].VarName, vartext, MAXLEN );
+ break;
+ }
+ return(nVarLen);
+ }
+ }
+
+ if (isdigit(*vartext))
+ {
+ while (isdigit(vartext[nVarLen]))
+ nVarLen++;
+ GetArgv(vartext);
+ }
+ else if (*vartext == '<')
+ {
+ nVarLen = 1;
+ while (vartext[nVarLen] != '>' && vartext[nVarLen] != 0)
+ {
+ if (IsDBCSLeadByte(vartext[nVarLen]))
+ nVarLen++;
+ nVarLen++;
+ }
+
+ if (vartext[nVarLen] == 0)
+ nVarLen = 0;
+ else
+ {
+ nVarLen++;
+ GetDosEnv (vartext);
+ }
+ }
+
+ return(nVarLen);
+}
+
+/*
+ * Parse path string.
+ * If find the %variable value, replace it, otherwise keep as it is.
+ */
+void NotQuotedStringTranslate(char *buf, BOOL Remove_dbs)
+{
+ char *pPercentSign, *pRest, vartext[MAXLEN];
+ int nVarLen, nInsertlen;
+
+ if ( Remove_dbs )
+ {
+ // Convert \\ to \.
+ pRest = buf;
+ for (pRest = buf; *pRest; pRest = NWAnsiNext(pRest))
+ {
+ if (*pRest == '\\' && *(pRest+1) == '\\')
+ memmove (pRest, pRest+1, strlen (pRest));
+ }
+ }
+
+ // Convert variables following '%' sign.
+ pRest = buf;
+ while (pPercentSign = strchr(pRest, '%'))
+ {
+ pRest = pPercentSign+1;
+
+ strcpy (vartext, pRest);
+
+ nVarLen = VarTranslate(vartext);
+
+ if (nVarLen == 0)
+ continue;
+
+ nInsertlen = strlen (vartext);
+ if (strlen (buf) + nInsertlen - nVarLen < MAXLEN)
+ {
+ pRest = pPercentSign+1+nVarLen;
+
+ memmove (pPercentSign+nInsertlen, pRest, strlen (pRest)+1);
+ memmove (pPercentSign, vartext, nInsertlen);
+ pRest = pPercentSign+nInsertlen;
+ }
+ }
+}
+
+/*
+ * Used by QuotedStringTranslate()
+ * On enter, *ppTemp point to a variable, on exit *ppTemp points to the
+ * charecter next to the variable. *ppBuffer points to the end of the
+ * value of the variable.
+ */
+int DoVarTranslate (char **ppTemp, char **ppBuffer, unsigned int nMaxLen, int fInquotes)
+{
+ int nVarLen;
+ char vartext[MAXLEN];
+
+ strcpy (vartext, *ppTemp);
+
+ nVarLen = VarTranslate (vartext);
+
+ if (nVarLen != 0)
+ {
+ if (strlen(vartext) >= nMaxLen)
+ return(FALSE);
+
+ strcpy (*ppBuffer, vartext);
+ (*ppBuffer) = (*ppBuffer) + strlen (vartext);
+ (*ppTemp) += nVarLen;
+ }
+ else if (fInquotes)
+ {
+ strcpy (*ppBuffer, "%");
+ (*ppBuffer) += 1;
+ }
+ else
+ return(FALSE);
+
+ return(TRUE);
+}
+
+/*
+ * Used by QuotedStringTranslate()
+ * On entry, *(*ppTemp -1) is '\', if **ppTemp is one of those special
+ * characters, put the value in **ppBuffer, otherwise copy '\\\ and
+ * whatever is in *ppBuffer to *ppBuffer.
+ */
+void TranslateSpecialChar (char **ppTemp, char **ppBuffer)
+{
+ (*ppTemp)++;
+
+ if (**ppTemp == '\\')
+ **(ppBuffer) = '\\';
+ else if (**ppTemp == 'n')
+ **(ppBuffer) ='\n';
+ else if (**ppTemp == 'r')
+ **(ppBuffer) ='\r';
+ else if (**ppTemp == '\"')
+ **(ppBuffer) ='\"';
+ else if (**ppTemp == '7')
+ **(ppBuffer) ='\7';
+ else
+ {
+ **(ppBuffer) = '\\';
+ (*ppBuffer)++;
+ return;
+ }
+
+ (*ppBuffer)++;
+ (*ppTemp)++;;
+}
+
+/*
+ * Used by QuotedStringTranslate().
+ * Return TRUE if there are more interesting strings and it's seperated by ';'
+ * FALSE otherwise.
+ */
+int GetNextString (char **ppTemp, int *pfEnd)
+{
+ int fMore = FALSE;
+
+ (*ppTemp) = RemoveSpaces (*ppTemp);
+
+ *pfEnd = (**ppTemp == 0);
+
+ if (**ppTemp == ';')
+ {
+ (*ppTemp) = RemoveSpaces (*ppTemp+1);
+ fMore = TRUE;
+ }
+
+ return(fMore);
+}
+
+
+int GetLastShiftOp (char *buffer, char *pchOp, char *lpRest)
+{
+ int i, inquotes = FALSE;
+
+ // NetWare compatibility fix.
+ // for (i = strlen (buffer)-1; i >= 0; i--)
+
+ for (i = 0; buffer[i]; i++)
+ {
+ if (buffer[i] == '\"' && buffer [i-1] != '\\')
+ inquotes = !inquotes;
+ if (!inquotes &&
+ ( (buffer[i] == '>' && buffer[i+1] == '>')
+ ||(buffer[i] == '<' && buffer[i+1] == '<')))
+ {
+ *pchOp = buffer[i];
+ buffer[i] = 0;
+ strcpy (lpRest, RemoveSpaces(buffer+i+2));
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+int GetLastAddOp (char *buffer, char *pchOp, char *lpRest)
+{
+ int i, inquotes = FALSE;
+
+ // NetWare compatibility fix.
+ // for (i = strlen (buffer)-1; i >= 0; i--)
+
+ for (i = 0; buffer[i]; i++)
+ {
+ if (buffer[i] == '\"' && buffer [i-1] != '\\')
+ inquotes = !inquotes;
+ if (!inquotes &&
+ (buffer[i] == '+' || buffer[i] == '-') )
+ {
+ *pchOp = buffer[i];
+ buffer[i] = 0;
+ strcpy (lpRest, RemoveSpaces(buffer+i+1));
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+int GetLastMultiplyOp (char *buffer, char *pchOp, char *lpRest)
+{
+ int i, inquotes = FALSE;
+
+ // NetWare compatibility fix.
+ // for (i = strlen (buffer)-1; i >= 0; i--)
+ for (i = 0; buffer[i]; i++)
+ {
+ if (buffer[i] == '\"' && buffer [i-1] != '\\')
+ inquotes = !inquotes;
+ if (!inquotes &&
+ (buffer[i] == '*' || buffer[i] == '/' || buffer[i] == '%') )
+ {
+
+ *pchOp = buffer[i];
+ buffer[i] = 0;
+ strcpy (lpRest, RemoveSpaces(buffer+i+1));
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+/*
+ * Used by QuotedStringTranslate.
+ * Return TRUE if input buffer is right format, FALSE otherwise.
+ */
+int SingleStringTranslate (char *buffer)
+{
+ int inquotes = FALSE, fEnd = FALSE, nShift, nLen;
+ char szRest[MAXLEN], chOp;
+ char *lpTemp = szRest, *lpBuffer=buffer;
+
+ buffer = RemoveSpaces (buffer);
+
+ if (GetLastShiftOp (buffer, &chOp, szRest))
+ {
+ if (!QuotedStringTranslate (buffer))
+ return(FALSE);
+
+ while (isdigit (*lpTemp))
+ lpTemp++;
+
+ if (!EndOfLine(lpTemp))
+ return(FALSE);
+
+ *lpTemp = 0;
+
+ nShift = atoi (szRest);
+ nLen = strlen (buffer);
+
+ if (nShift >= nLen)
+ *buffer = 0;
+ else
+ {
+ if (chOp == '<')
+ memmove (buffer, buffer+nShift, nLen-nShift);
+
+ *(buffer+nLen-nShift) = 0;
+ }
+ }
+ else if (GetLastAddOp (buffer, &chOp, szRest))
+ {
+ if (!QuotedStringTranslate (buffer) ||
+ !QuotedStringTranslate (szRest))
+ return(FALSE);
+
+ sprintf (buffer, "%d", (chOp == '+')? (atoi (buffer) + atoi (szRest))
+ : (atoi (buffer) - atoi (szRest)));
+ }
+ else if (GetLastMultiplyOp (buffer, &chOp, szRest))
+ {
+ if (!QuotedStringTranslate (buffer) ||
+ !QuotedStringTranslate (szRest))
+ return(FALSE);
+
+ if (chOp == '*')
+ sprintf (buffer, "%d", atoi (buffer) * atoi (szRest));
+ else
+ {
+ if (atoi (szRest) == 0)
+ {
+ DisplayMessage(IDR_DIVIDE_BY_ZERO);
+ strcpy (buffer, "0");
+ }
+ else
+ {
+ sprintf (buffer, "%d",(chOp == '/')? (atoi (buffer) / atoi (szRest))
+ : (atoi (buffer) % atoi (szRest)));
+ }
+ }
+ }
+ else
+ {
+ strcpy (szRest, buffer);
+ *buffer = 0;
+
+ while (*lpTemp)
+ {
+ if (inquotes)
+ {
+ if (*lpTemp == '\\')
+ TranslateSpecialChar (&lpTemp, &buffer);
+ else if (*lpTemp == '\"')
+ {
+ inquotes = !inquotes;
+ lpTemp++;
+ if (!GetNextString (&lpTemp, &fEnd))
+ break;
+ }
+ else if (*lpTemp == '%')
+ {
+ lpTemp++;
+ DoVarTranslate (&lpTemp, &buffer, MAXLEN-(buffer-lpBuffer), TRUE);
+ }
+ else
+ {
+ *buffer = *lpTemp;
+ if (IsDBCSLeadByte(*buffer))
+ {
+ buffer++;
+ lpTemp++;
+ *buffer = *lpTemp;
+ }
+ buffer++;
+ lpTemp++;
+ }
+ }
+ else
+ {
+ if (*lpTemp == '\"')
+ {
+ inquotes = !inquotes;
+ lpTemp++;
+ }
+ else
+ {
+ if (!DoVarTranslate (&lpTemp, &buffer, MAXLEN-(buffer-lpBuffer), FALSE) ||
+ !GetNextString (&lpTemp, &fEnd))
+ break;
+ }
+ }
+ }
+ if (!fEnd)
+ {
+ if ( inquotes )
+ DisplayMessage( IDR_NO_END_QUOTE );
+ return(FALSE);
+ }
+ *buffer = 0;
+ }
+
+ return(TRUE);
+}
+
+/*
+ * Replace the variables in the string with their value.
+ * Use this function when the input string is quoted format.
+ * Return TRUE if input buffer is right format, FALSE otherwise.
+ */
+int QuotedStringTranslate (char *buffer)
+{
+ char szTemp[MAXLEN], *lpLeft, *lpRight, *ptr = buffer, *pNext;
+ int inquotes;
+
+ lpLeft = *buffer == '('? buffer : NULL;
+ lpRight = *buffer == ')'? buffer : NULL;
+ inquotes = (*ptr == '"');
+
+ while (*ptr)
+ {
+ pNext = NWAnsiNext (ptr);
+
+ if (*pNext == '"' && *(ptr) != '\\')
+ {
+ pNext++;
+ inquotes = !inquotes;
+ }
+
+ ptr = pNext;
+
+ if (!inquotes)
+ {
+ if (*ptr == '(')
+ lpLeft = ptr;
+ else if (*ptr == ')')
+ {
+ lpRight = ptr;
+
+ *lpRight = 0;
+
+ if (lpLeft == NULL)
+ return(FALSE);
+
+ if (lpRight - lpLeft <= 1) //There should be something in the backets.
+ return(FALSE);
+
+ *lpLeft = 0;
+
+ strncpy (szTemp, lpLeft+1, lpRight-lpLeft);
+
+ if (!SingleStringTranslate (szTemp))
+ return(FALSE);
+
+ if (strlen (buffer) + strlen(szTemp) + strlen (lpRight+1) + 2 >= MAXLEN)
+ return(FALSE);
+
+ *lpLeft = '"';
+ *(lpLeft+1+strlen(szTemp)) = '"';
+ memmove (lpLeft+2+strlen(szTemp), lpRight+1, strlen (lpRight+1)+1);
+ memmove (lpLeft+1, szTemp, strlen(szTemp));
+
+ lpLeft = *buffer == '('? buffer : NULL;
+ lpRight = *buffer == ')'? buffer : NULL;
+ ptr = buffer;
+ inquotes = (*ptr == '"');
+ }
+ }
+ }
+
+ if (lpLeft != NULL || lpRight != NULL)
+ return(FALSE);
+ return(SingleStringTranslate (buffer));
+}
+
+
+void BreakOff(void)
+{
+ fBreakOn = FALSE;
+
+ NTBreakOff();
+}
+
+void BreakOn(void)
+{
+ fBreakOn = TRUE;
+
+ NTBreakOn();
+}
+
+/*
+ * Used by ComspecHandler() and SetHandler()
+ * Set dos environment variable.
+ */
+int SetEnv (char *lpEnvLine)
+{
+ ExportEnv( lpEnvLine );
+ return(TRUE);
+}