/********************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1990-1991 **/ /********************************************************************/ //*** // // Filename: Parse.c // // Description: // This module contains the entry point of DIAL.EXE. // This module will parse the command line. It will validate the syntax // and the arguments on the command line. On any error, the exit // module will be invoked with the appropriate error code. // If any default values are required, they will be supplied by // this module. // // History: // September 1, 1990 Narendra Gidwani Created original version // #include #include #include #ifdef DBCS #include #endif /* DBCS */ #include "cmd.h" //** Global data structures and variables used. ** //* These variables are pointers to ASCIIZ which will be set to // point to switch values of the command line by GetSwitchValue. // These pointers are global within this module. CHAR * gblEntity = NULL; CHAR * gblCommand = NULL; CHAR * gblServer = NULL; CHAR * gblName = NULL; CHAR * gblPath = NULL; CHAR * gblPassword = NULL; CHAR * gblReadOnly = NULL; CHAR * gblMaxUses = NULL; CHAR * gblOwnerName = NULL; CHAR * gblGroupName = NULL; CHAR * gblPermissions = NULL; CHAR * gblLoginMessage = NULL; CHAR * gblMaxSessions = NULL; CHAR * gblGuestsAllowed = NULL; CHAR * gblMacServerName = NULL; CHAR * gblUAMRequired = NULL; CHAR * gblAllowSavedPasswords = NULL; CHAR * gblType = NULL; CHAR * gblCreator = NULL; CHAR * gblDataFork = NULL; CHAR * gblResourceFork = NULL; CHAR * gblTargetFile = NULL; CHAR * gblHelp = NULL; // Non translatable text // CHAR * pszVolume = "Volume"; CHAR * pszAdd = "/Add"; CHAR * pszDelete = "/Remove"; CHAR * pszSet = "/Set"; CHAR * pszDirectory = "Directory"; CHAR * pszServer = "Server"; CHAR * pszForkize = "Forkize"; CMD_FMT DelVolArgFmt[] = { { "/Server", (CHAR *)&gblServer, 0}, { "/Name", (CHAR *)&gblName, 0}, { "/Help", (CHAR *)&gblHelp, 0}, { "/?", (CHAR *)&gblHelp, 0}, { NULL, (CHAR *)NULL, 0} }; CMD_FMT AddVolArgFmt[] = { { "/Server", (CHAR *)&gblServer, 0}, { "/Name", (CHAR *)&gblName, 0}, { "/Path", (CHAR *)&gblPath, 0}, { "/Password", (CHAR *)&gblPassword, 0}, { "/ReadOnly", (CHAR *)&gblReadOnly, 0}, { "/MaxUsers", (CHAR *)&gblMaxUses, 0}, { "/Help", (CHAR *)&gblHelp, 0}, { "/?", (CHAR *)&gblHelp, 0}, { NULL, (CHAR *)NULL, 0} }; CMD_FMT SetVolArgFmt[] = { { "/Server", (CHAR *)&gblServer, 0}, { "/Name", (CHAR *)&gblName, 0}, { "/Password", (CHAR *)&gblPassword, 0}, { "/ReadOnly", (CHAR *)&gblReadOnly, 0}, { "/MaxUsers", (CHAR *)&gblMaxUses, 0}, { "/Help", (CHAR *)&gblHelp, 0}, { "/?", (CHAR *)&gblHelp, 0}, { NULL, (CHAR *)NULL, 0} }; CMD_FMT DirArgFmt[] = { { "/Server", (CHAR *)&gblServer, 0}, { "/Path", (CHAR *)&gblPath, 0}, { "/Owner", (CHAR *)&gblOwnerName, 0}, { "/Group", (CHAR *)&gblGroupName, 0}, { "/Permissions", (CHAR *)&gblPermissions, 0}, { "/Help", (CHAR *)&gblHelp, 0}, { "/?", (CHAR *)&gblHelp, 0}, { NULL, (CHAR *)NULL, 0} }; CMD_FMT ServerArgFmt[] = { { "/Server", (CHAR *)&gblServer, 0}, { "/MaxSessions", (CHAR *)&gblMaxSessions, 0}, { "/LoginMessage", (CHAR *)&gblLoginMessage, 0}, { "/UAMRequired", (CHAR *)&gblUAMRequired, 0}, { "/AllowSavedPasswords",(CHAR *)&gblAllowSavedPasswords,0}, { "/MacServerName", (CHAR *)&gblMacServerName, 0}, { "/Help", (CHAR *)&gblHelp, 0}, { "/?", (CHAR *)&gblHelp, 0}, { NULL, (CHAR *)NULL, 0} }; CMD_FMT ForkizeArgFmt[] = { { "/Server", (CHAR *)&gblServer, 0}, { "/Type", (CHAR *)&gblType, 0}, { "/Creator", (CHAR *)&gblCreator, 0}, { "/DataFork", (CHAR *)&gblDataFork, 0}, { "/ResourceFork", (CHAR *)&gblResourceFork, 0}, { "/TargetFile", (CHAR *)&gblTargetFile, 0}, { "/Help", (CHAR *)&gblHelp, 0}, { "/?", (CHAR *)&gblHelp, 0}, { NULL, (CHAR *)NULL, 0} }; //** // // Call: main // // Entry: int argc; - Number of command line arguments // char *argv[]; - Array of pointers to ASCIIZ command line // arguments. // // Exit: none. // // Returns: none. // // Description: Calls the command line parser with the command line // arguments. // VOID _cdecl main( INT argc, CHAR * argv[] ) { #ifdef DBCS setlocale( LC_ALL, "" ); #endif /* DBCS */ // This will act like xacc or yacc. It will parse the command line // and call the appropriate function to carry out an action. // Thus this procedure will never return. ParseCmdArgList( argc, argv ); } //** // // Call: ParseCmdArgList // // Entry: int argc; - Number of command line arguments. // char *argv[]; - Array of pointers to ASCIIZ command line // arguments. // // Exit: none. // // Returns: none. // // Description: // Will parse command line for any errors and determine // from the syntax what the user wishes to do. Command // line arguments will be validated. // VOID ParseCmdArgList( INT argc, CHAR * argv[] ) { DWORD ArgCount = 0; if ( argc == 1 ) PrintMessageAndExit( IDS_GENERAL_SYNTAX, NULL ); // // What is the entity being operated on ? // gblEntity = argv[++ArgCount]; if ( _strnicmp( pszVolume, gblEntity, strlen( gblEntity ) ) == 0 ) { if ( argc == 2 ) PrintMessageAndExit( IDS_VOLUME_SYNTAX, NULL ); gblCommand = argv[++ArgCount]; if ( _strnicmp( pszAdd, gblCommand, strlen( gblCommand ) ) == 0 ) { GetArguments( AddVolArgFmt, argv, argc, ArgCount ); if ( gblHelp != (CHAR*)NULL ) PrintMessageAndExit( IDS_VOLUME_SYNTAX, NULL ); DoVolumeAdd( gblServer, gblName, gblPath, gblPassword, gblReadOnly, gblGuestsAllowed, gblMaxUses ); } else if ( _strnicmp( pszDelete, gblCommand, strlen( gblCommand ) ) == 0 ) { GetArguments( DelVolArgFmt, argv, argc, ArgCount ); if ( gblHelp != (CHAR*)NULL ) PrintMessageAndExit( IDS_VOLUME_SYNTAX, NULL ); DoVolumeDelete( gblServer, gblName ); } else if ( _strnicmp( pszSet, gblCommand, strlen( gblCommand ) ) == 0 ) { GetArguments( SetVolArgFmt, argv, argc, ArgCount ); if ( gblHelp != (CHAR*)NULL ) PrintMessageAndExit( IDS_VOLUME_SYNTAX, NULL ); DoVolumeSet( gblServer, gblName, gblPassword, gblReadOnly, gblGuestsAllowed, gblMaxUses ); } else PrintMessageAndExit( IDS_VOLUME_SYNTAX, NULL ); } else if ( _strnicmp( pszDirectory, gblEntity, strlen( gblEntity ) ) == 0 ) { if ( argc == 2 ) PrintMessageAndExit( IDS_DIRECTORY_SYNTAX, NULL ); GetArguments( DirArgFmt, argv, argc, ArgCount ); if ( gblHelp != (CHAR*)NULL ) PrintMessageAndExit( IDS_DIRECTORY_SYNTAX, NULL ); DoDirectorySetInfo( gblServer, gblPath, gblOwnerName, gblGroupName, gblPermissions ); } else if ( _strnicmp( pszServer, gblEntity, strlen( gblEntity ) ) == 0 ) { if ( argc == 2 ) PrintMessageAndExit( IDS_SERVER_SYNTAX, NULL ); GetArguments( ServerArgFmt, argv, argc, ArgCount ); if ( gblHelp != (CHAR*)NULL ) PrintMessageAndExit( IDS_SERVER_SYNTAX, NULL ); DoServerSetInfo( gblServer, gblMaxSessions, gblLoginMessage, gblGuestsAllowed, gblUAMRequired, gblAllowSavedPasswords, gblMacServerName ); } else if ( _strnicmp( pszForkize, gblEntity, strlen( gblEntity ) ) == 0 ) { GetArguments( ForkizeArgFmt, argv, argc, ArgCount ); if ( gblHelp != (CHAR*)NULL ) PrintMessageAndExit( IDS_FORKIZE_SYNTAX, NULL ); DoForkize( gblServer, gblType, gblCreator, gblDataFork, gblResourceFork, gblTargetFile ); } else PrintMessageAndExit( IDS_GENERAL_SYNTAX, NULL ); } VOID GetArguments( CMD_FMT * pArgFmt, CHAR * argv[], DWORD argc, DWORD ArgCount ) { // // To determine by the syntax what the user wishes to do we first // run through the arguments and get switch values. // while ( ++ArgCount < argc ) { // // If it is a switch, get its value. // if ( argv[ArgCount][0] == '/' ) GetSwitchValue( pArgFmt, argv[ArgCount] ); else PrintMessageAndExit( IDS_GENERAL_SYNTAX, NULL ); } } //** // // Call: GetSwitchValue // // Entry: CHAR * SwitchPtr; - Pointer to ASCIIZ containing a command // line argument. // ex. - /phoneb:c:\subdir // // CHAR ** LastArg; - Nothing. // // Exit: CHAR * SwitchPtr; - same as entry. // // CHAR ** LastArg; - Pointer to a pointer to ASCIIZ containig // the text of the first bad switch if // there were any. // // Returns: 0 - Success. // AMBIGIOUS_SWITCH_ERRROR - failure. // UNKNOWN_SWITCH_ERROR - failure. // MEM_ALLOC_ERROR - failure. // MULTIPLE_SWITCH_ERROR - failure. // // Description: This procedure will run through all the valid switches // in the cmdfmt structure and retrieve the value of the // the switch. The value of the switch will be inserted into the // cmdfmt structure. It will expand abbreviated switches. If // the switch had no value, it will insert a null character // as the value. If the switch did not appear, the value // pointer of the switch (in the cmdfmt structure) // will remain unchanged ( should be initialized to NULL ). // This procedure uses the same data structure as GetCmdArgs5, // hence some fields may be ignored. This is done to make the // functionality of this procedure extendable. // // VOID GetSwitchValue( CMD_FMT * pArgFmt, IN CHAR * pchSwitchPtr ) { INT intFound = -1; DWORD dwIndex; DWORD dwSwitchLen; CHAR * pchSeparatorPtr; // // Get length of the switch part of the argument. // if ( ( pchSeparatorPtr = strchr( pchSwitchPtr, ':' )) != NULL ) dwSwitchLen = (DWORD)(pchSeparatorPtr - pchSwitchPtr); else // // If the switch had no value. // dwSwitchLen = strlen( pchSwitchPtr ); // // Run through all switches. // for ( dwIndex = 0; pArgFmt[dwIndex].cf_parmstr != NULL; dwIndex++ ) { // // If this switch matches (partly or completely) one of the // valid switches. // if ( !_strnicmp( pArgFmt[dwIndex].cf_parmstr, pchSwitchPtr, dwSwitchLen ) ) { if ( intFound < 0 ) intFound = dwIndex; else { // // If this argument has matched another switch also. // if ( pchSeparatorPtr ) *pchSeparatorPtr = '\0'; PrintMessageAndExit( IDS_AMBIGIOUS_SWITCH_ERROR, pchSwitchPtr ); } } } // // If we could not find a match for this switch. // if ( intFound < 0 ) { if ( pchSeparatorPtr ) *pchSeparatorPtr = '\0'; PrintMessageAndExit( IDS_UNKNOWN_SWITCH_ERROR, pchSwitchPtr ); } // // If this switch is appearing for the second time. // if ( pArgFmt[intFound].cf_usecount > 0 ) { if ( pchSeparatorPtr ) *pchSeparatorPtr = '\0'; PrintMessageAndExit( IDS_DUPLICATE_SWITCH_ERROR, pchSwitchPtr ); } else pArgFmt[intFound].cf_usecount++; // // Get the switch value if there is one. // if ( ( pchSeparatorPtr ) && ((CHAR *)(pchSeparatorPtr + 1)) ) { *(CHAR **)pArgFmt[intFound].cf_ptr = ++pchSeparatorPtr; } else { *(CHAR **)pArgFmt[intFound].cf_ptr = (CHAR *)""; } } /******************************************************************* NAME: IsDriveGreaterThan2Gig SYNOPSIS: Determines if the disk is bigger than 2Gig. If it, return TRUE so that a warning can be displayed to the user RETURNS: TRUE if disk is larger than 2Gig FALSE otherwise HISTORY: NarenG 11/18/92 Modified for AFPMGR ********************************************************************/ BOOL IsDriveGreaterThan2Gig( LPSTR lpDrivePath ) { DWORD SectorsPerCluster; DWORD BytesPerSector; DWORD NumberOfFreeClusters; DWORD TotalNumberOfClusters; DWORDLONG DriveSize; DWORDLONG TwoGig = MAXLONG; // // If this drive volume is greater than 2G then we print warning // if ( !GetDiskFreeSpace( lpDrivePath, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters )) { // some error: can't do much, so just assume this drive is smaller than 2GB. That's // probably better than alarming the customer by putting the warning? return FALSE; } DriveSize = UInt32x32To64( SectorsPerCluster * BytesPerSector, TotalNumberOfClusters ) ; if ( DriveSize > TwoGig ) { return TRUE; } else { return FALSE; } }