423 lines
13 KiB
C++
423 lines
13 KiB
C++
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Argument
|
||
|
||
Abstract:
|
||
|
||
Argument processing for the Replace utility
|
||
|
||
Author:
|
||
|
||
Ramon Juan San Andres (ramonsa) 01-May-1991
|
||
|
||
Notes:
|
||
|
||
The arguments accepted by the Replace utility are:
|
||
|
||
Source path.- Source path.
|
||
|
||
Destination path.- Destination path.
|
||
|
||
Add switch.- Adds new files to the target directory instead of
|
||
replacing existing one. Cannot use with Subdir
|
||
switch or CompareTime switch.
|
||
|
||
Prompt switch.- Prompts before adding/replacing a file.
|
||
|
||
ReadOnly switch.- Replaces red-only files as well as regular files.
|
||
|
||
Subdir switch.- Recurses along the destination path.
|
||
|
||
CompareTime switch.-Replaces only thos files on the target path that
|
||
are older than the corresponding file in the
|
||
source path.
|
||
|
||
Wait switch.- Waits for the user to type any key before starting.
|
||
|
||
Help switch.- Displays usage
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
|
||
#include "ulib.hxx"
|
||
#include "arg.hxx"
|
||
#include "arrayit.hxx"
|
||
#include "file.hxx"
|
||
#include "system.hxx"
|
||
#include "replace.hxx"
|
||
|
||
|
||
#define MATCH_ALL_PATTERN "*"
|
||
#define CURRENT_DIRECTORY (LPWSTR)L"."
|
||
|
||
|
||
|
||
//
|
||
// Global variables (global to the module)
|
||
//
|
||
|
||
PPATH_ARGUMENT SourcePathArgument = NULL;
|
||
PPATH_ARGUMENT DestinationPathArgument = NULL;
|
||
PFLAG_ARGUMENT AddArgument = NULL;
|
||
PFLAG_ARGUMENT PromptArgument = NULL;
|
||
PFLAG_ARGUMENT ReadOnlyArgument = NULL;
|
||
PFLAG_ARGUMENT SubdirArgument = NULL;
|
||
PFLAG_ARGUMENT CompareTimeArgument = NULL;
|
||
PFLAG_ARGUMENT WaitArgument = NULL;
|
||
PFLAG_ARGUMENT HelpArgument = NULL;
|
||
|
||
BOOLEAN HelpSwitch;
|
||
|
||
|
||
|
||
VOID
|
||
REPLACE::SetArguments(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Obtains the arguments for the Replace utility
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Allocate things
|
||
//
|
||
if (//
|
||
// Get the argument patterns
|
||
//
|
||
!_AddPattern.Initialize( (LPWSTR)L"/A" ) ||
|
||
!_PromptPattern.Initialize( (LPWSTR)L"/P" ) ||
|
||
!_ReadOnlyPattern.Initialize( (LPWSTR)L"/R" ) ||
|
||
!_SubdirPattern.Initialize( (LPWSTR)L"/S" ) ||
|
||
!_CompareTimePattern.Initialize( (LPWSTR)L"/U" ) ||
|
||
!_WaitPattern.Initialize( (LPWSTR)L"/W" ) ||
|
||
!_HelpPattern.Initialize( (LPWSTR)L"/?" ) ||
|
||
|
||
//
|
||
// Get our parsing preferences
|
||
//
|
||
!_Switches.Initialize( (LPWSTR)L"/-" ) ||
|
||
!_MultipleSwitch.Initialize( (LPWSTR)L"/APRSUW?" ) ||
|
||
|
||
//
|
||
// Create the arguments
|
||
//
|
||
((SourcePathArgument = NEW PATH_ARGUMENT) == NULL ) ||
|
||
((DestinationPathArgument = NEW PATH_ARGUMENT) == NULL ) ||
|
||
((AddArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
||
((PromptArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
||
((ReadOnlyArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
||
((SubdirArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
||
((CompareTimeArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
||
((WaitArgument = NEW FLAG_ARGUMENT) == NULL ) ||
|
||
((HelpArgument = NEW FLAG_ARGUMENT) == NULL )
|
||
) {
|
||
|
||
DisplayMessageAndExit ( REPLACE_ERROR_NO_MEMORY,
|
||
NULL,
|
||
EXIT_NO_MEMORY );
|
||
}
|
||
|
||
|
||
//
|
||
// Parse the arguments
|
||
//
|
||
GetArgumentsCmd();
|
||
|
||
//
|
||
// Verify the arguments
|
||
//
|
||
CheckArgumentConsistency();
|
||
|
||
//
|
||
// Clean up
|
||
//
|
||
DELETE( SourcePathArgument );
|
||
DELETE( DestinationPathArgument );
|
||
DELETE( AddArgument );
|
||
DELETE( PromptArgument );
|
||
DELETE( ReadOnlyArgument );
|
||
DELETE( SubdirArgument );
|
||
DELETE( CompareTimeArgument );
|
||
DELETE( WaitArgument );
|
||
DELETE( HelpArgument );
|
||
}
|
||
|
||
VOID
|
||
REPLACE::GetArgumentsCmd(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Obtains the arguments from the Command line
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ARRAY ArgArray;
|
||
PATH_ARGUMENT ProgramNameArgument;
|
||
DSTRING CmdLine;
|
||
|
||
//
|
||
// Prepare for parsing
|
||
//
|
||
if (//
|
||
// Initialize the arguments
|
||
//
|
||
!(CmdLine.Initialize( GetCommandLine() )) ||
|
||
!(ArgArray.Initialize( 10, 10 )) ||
|
||
!(ProgramNameArgument.Initialize( MATCH_ALL_PATTERN )) ||
|
||
!(SourcePathArgument->Initialize( MATCH_ALL_PATTERN, FALSE)) ||
|
||
!(DestinationPathArgument->Initialize( MATCH_ALL_PATTERN, TRUE )) ||
|
||
!(AddArgument->Initialize( &_AddPattern )) ||
|
||
!(PromptArgument->Initialize( &_PromptPattern )) ||
|
||
!(ReadOnlyArgument->Initialize( &_ReadOnlyPattern )) ||
|
||
!(SubdirArgument->Initialize( &_SubdirPattern )) ||
|
||
!(CompareTimeArgument->Initialize( &_CompareTimePattern )) ||
|
||
!(WaitArgument->Initialize( &_WaitPattern )) ||
|
||
!(HelpArgument->Initialize( &_HelpPattern )) ||
|
||
|
||
//
|
||
// Put the arguments in the argument array
|
||
//
|
||
!(ArgArray.Put( &ProgramNameArgument )) ||
|
||
!(ArgArray.Put( AddArgument )) ||
|
||
!(ArgArray.Put( PromptArgument )) ||
|
||
!(ArgArray.Put( ReadOnlyArgument )) ||
|
||
!(ArgArray.Put( SubdirArgument )) ||
|
||
!(ArgArray.Put( CompareTimeArgument )) ||
|
||
!(ArgArray.Put( WaitArgument )) ||
|
||
!(ArgArray.Put( HelpArgument )) ||
|
||
!(ArgArray.Put( SourcePathArgument )) ||
|
||
!(ArgArray.Put( DestinationPathArgument ))
|
||
) {
|
||
|
||
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
|
||
NULL,
|
||
EXIT_NO_MEMORY );
|
||
}
|
||
|
||
//
|
||
// Parse the arguments
|
||
//
|
||
ParseArguments( &CmdLine, &ArgArray );
|
||
|
||
//
|
||
// Set the switches
|
||
//
|
||
_AddSwitch = AddArgument->QueryFlag();
|
||
_PromptSwitch = PromptArgument->QueryFlag();
|
||
_ReadOnlySwitch = ReadOnlyArgument->QueryFlag();
|
||
_SubdirSwitch = SubdirArgument->QueryFlag();
|
||
_CompareTimeSwitch = CompareTimeArgument->QueryFlag();
|
||
_WaitSwitch = WaitArgument->QueryFlag();
|
||
HelpSwitch = HelpArgument->QueryFlag();
|
||
|
||
//
|
||
// Set the source and destination paths.
|
||
//
|
||
if ( SourcePathArgument->IsValueSet() ) {
|
||
if ((_SourcePath = SourcePathArgument->GetPath()->QueryPath()) == NULL ) {
|
||
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY, NULL, EXIT_NO_MEMORY );
|
||
}
|
||
} else {
|
||
_SourcePath = NULL;
|
||
}
|
||
|
||
if ( DestinationPathArgument->IsValueSet() ) {
|
||
if ((_DestinationPath = DestinationPathArgument->GetPath()->QueryFullPath()) == NULL ) {
|
||
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY, NULL, EXIT_NO_MEMORY );
|
||
}
|
||
} else {
|
||
_DestinationPath = NULL;
|
||
}
|
||
|
||
}
|
||
|
||
VOID
|
||
REPLACE::ParseArguments(
|
||
IN PWSTRING CmdLine,
|
||
OUT PARRAY ArgArray
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Parses a group of arguments
|
||
|
||
Arguments:
|
||
|
||
CmdLine - Supplies pointer to a command line to parse
|
||
ArgArray - Supplies pointer to array of arguments
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
ARGUMENT_LEXEMIZER ArgLex;
|
||
ARRAY LexArray;
|
||
|
||
//
|
||
// Initialize lexeme array and the lexemizer.
|
||
//
|
||
if ( !(LexArray.Initialize( 8, 8 )) ||
|
||
!(ArgLex.Initialize( &LexArray )) ) {
|
||
|
||
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
|
||
NULL,
|
||
EXIT_NO_MEMORY );
|
||
|
||
}
|
||
|
||
//
|
||
// Set our parsing preferences
|
||
//
|
||
ArgLex.PutMultipleSwitch( &_MultipleSwitch );
|
||
ArgLex.PutSwitches( &_Switches );
|
||
ArgLex.SetCaseSensitive( FALSE );
|
||
ArgLex.PutSeparators( " /\t" );
|
||
ArgLex.PutStartQuotes( "\"" );
|
||
ArgLex.PutEndQuotes( "\"" );
|
||
|
||
|
||
//
|
||
// Parse the arguments
|
||
//
|
||
if ( !(ArgLex.PrepareToParse( CmdLine ))) {
|
||
|
||
DisplayMessageAndExit( REPLACE_ERROR_PARSE,
|
||
NULL,
|
||
EXIT_COMMAND_LINE_ERROR );
|
||
|
||
}
|
||
|
||
if ( !ArgLex.DoParsing( ArgArray ) ) {
|
||
|
||
DisplayMessageAndExit( REPLACE_ERROR_INVALID_SWITCH,
|
||
ArgLex.QueryInvalidArgument(),
|
||
EXIT_COMMAND_LINE_ERROR );
|
||
}
|
||
|
||
|
||
}
|
||
|
||
VOID
|
||
REPLACE::CheckArgumentConsistency (
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks the consistency of the arguments
|
||
|
||
Arguments:
|
||
|
||
none
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PFSN_FILE File = NULL;
|
||
|
||
if ( HelpSwitch ) {
|
||
//
|
||
// Help requested
|
||
//
|
||
Usage();
|
||
}
|
||
|
||
|
||
//
|
||
// Make sure that we have a source path
|
||
//
|
||
if ( _SourcePath == NULL ) {
|
||
|
||
DisplayMessageAndExit( REPLACE_ERROR_SOURCE_PATH_REQUIRED,
|
||
NULL,
|
||
EXIT_COMMAND_LINE_ERROR );
|
||
}
|
||
|
||
//
|
||
// The add switch cannot be specified together with the Subdir or the
|
||
// CompareTime switch.
|
||
//
|
||
if ( _AddSwitch && (_SubdirSwitch || _CompareTimeSwitch)) {
|
||
|
||
DisplayMessageAndExit( REPLACE_ERROR_INVALID_PARAMETER_COMBINATION,
|
||
NULL,
|
||
EXIT_COMMAND_LINE_ERROR );
|
||
|
||
}
|
||
|
||
//
|
||
// If destination path is null, then the destination path is the
|
||
// current directory
|
||
//
|
||
if ( _DestinationPath == NULL ) {
|
||
|
||
if ( ((_DestinationPath = NEW PATH) == NULL ) ||
|
||
!_DestinationPath->Initialize( CURRENT_DIRECTORY, TRUE ) ) {
|
||
|
||
DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
|
||
NULL,
|
||
EXIT_NO_MEMORY );
|
||
}
|
||
} else if ( (_DestinationPath->HasWildCard()) ||
|
||
((File = SYSTEM::QueryFile( _DestinationPath )) != NULL) ) {
|
||
DisplayMessageAndExit( REPLACE_ERROR_PATH_NOT_FOUND,
|
||
_DestinationPath->GetPathString(),
|
||
EXIT_PATH_NOT_FOUND );
|
||
}
|
||
|
||
DELETE( File );
|
||
}
|