509 lines
13 KiB
C
509 lines
13 KiB
C
|
/********************************************************************/
|
|||
|
/** 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 <windows.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#ifdef DBCS
|
|||
|
#include <locale.h>
|
|||
|
#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},
|
|||
|
{ "/GuestsAllowed", (CHAR *)&gblGuestsAllowed, 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},
|
|||
|
{ "/GuestsAllowed", (CHAR *)&gblGuestsAllowed, 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},
|
|||
|
{ "/GuestsAllowed", (CHAR *)&gblGuestsAllowed, 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;
|
|||
|
}
|
|||
|
}
|