Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. Argument
  5. Abstract:
  6. Argument processing for the Replace utility
  7. Author:
  8. Ramon Juan San Andres (ramonsa) 01-May-1991
  9. Notes:
  10. The arguments accepted by the Replace utility are:
  11. Source path.- Source path.
  12. Destination path.- Destination path.
  13. Add switch.- Adds new files to the target directory instead of
  14. replacing existing one. Cannot use with Subdir
  15. switch or CompareTime switch.
  16. Prompt switch.- Prompts before adding/replacing a file.
  17. ReadOnly switch.- Replaces red-only files as well as regular files.
  18. Subdir switch.- Recurses along the destination path.
  19. CompareTime switch.-Replaces only thos files on the target path that
  20. are older than the corresponding file in the
  21. source path.
  22. Wait switch.- Waits for the user to type any key before starting.
  23. Help switch.- Displays usage
  24. Revision History:
  25. --*/
  26. #include "ulib.hxx"
  27. #include "arg.hxx"
  28. #include "arrayit.hxx"
  29. #include "file.hxx"
  30. #include "system.hxx"
  31. #include "replace.hxx"
  32. #define MATCH_ALL_PATTERN "*"
  33. #define CURRENT_DIRECTORY (LPWSTR)L"."
  34. //
  35. // Global variables (global to the module)
  36. //
  37. PPATH_ARGUMENT SourcePathArgument = NULL;
  38. PPATH_ARGUMENT DestinationPathArgument = NULL;
  39. PFLAG_ARGUMENT AddArgument = NULL;
  40. PFLAG_ARGUMENT PromptArgument = NULL;
  41. PFLAG_ARGUMENT ReadOnlyArgument = NULL;
  42. PFLAG_ARGUMENT SubdirArgument = NULL;
  43. PFLAG_ARGUMENT CompareTimeArgument = NULL;
  44. PFLAG_ARGUMENT WaitArgument = NULL;
  45. PFLAG_ARGUMENT HelpArgument = NULL;
  46. BOOLEAN HelpSwitch;
  47. VOID
  48. REPLACE::SetArguments(
  49. )
  50. /*++
  51. Routine Description:
  52. Obtains the arguments for the Replace utility
  53. Arguments:
  54. None.
  55. Return Value:
  56. None.
  57. Notes:
  58. --*/
  59. {
  60. //
  61. // Allocate things
  62. //
  63. if (//
  64. // Get the argument patterns
  65. //
  66. !_AddPattern.Initialize( (LPWSTR)L"/A" ) ||
  67. !_PromptPattern.Initialize( (LPWSTR)L"/P" ) ||
  68. !_ReadOnlyPattern.Initialize( (LPWSTR)L"/R" ) ||
  69. !_SubdirPattern.Initialize( (LPWSTR)L"/S" ) ||
  70. !_CompareTimePattern.Initialize( (LPWSTR)L"/U" ) ||
  71. !_WaitPattern.Initialize( (LPWSTR)L"/W" ) ||
  72. !_HelpPattern.Initialize( (LPWSTR)L"/?" ) ||
  73. //
  74. // Get our parsing preferences
  75. //
  76. !_Switches.Initialize( (LPWSTR)L"/-" ) ||
  77. !_MultipleSwitch.Initialize( (LPWSTR)L"/APRSUW?" ) ||
  78. //
  79. // Create the arguments
  80. //
  81. ((SourcePathArgument = NEW PATH_ARGUMENT) == NULL ) ||
  82. ((DestinationPathArgument = NEW PATH_ARGUMENT) == NULL ) ||
  83. ((AddArgument = NEW FLAG_ARGUMENT) == NULL ) ||
  84. ((PromptArgument = NEW FLAG_ARGUMENT) == NULL ) ||
  85. ((ReadOnlyArgument = NEW FLAG_ARGUMENT) == NULL ) ||
  86. ((SubdirArgument = NEW FLAG_ARGUMENT) == NULL ) ||
  87. ((CompareTimeArgument = NEW FLAG_ARGUMENT) == NULL ) ||
  88. ((WaitArgument = NEW FLAG_ARGUMENT) == NULL ) ||
  89. ((HelpArgument = NEW FLAG_ARGUMENT) == NULL )
  90. ) {
  91. DisplayMessageAndExit ( REPLACE_ERROR_NO_MEMORY,
  92. NULL,
  93. EXIT_NO_MEMORY );
  94. }
  95. //
  96. // Parse the arguments
  97. //
  98. GetArgumentsCmd();
  99. //
  100. // Verify the arguments
  101. //
  102. CheckArgumentConsistency();
  103. //
  104. // Clean up
  105. //
  106. DELETE( SourcePathArgument );
  107. DELETE( DestinationPathArgument );
  108. DELETE( AddArgument );
  109. DELETE( PromptArgument );
  110. DELETE( ReadOnlyArgument );
  111. DELETE( SubdirArgument );
  112. DELETE( CompareTimeArgument );
  113. DELETE( WaitArgument );
  114. DELETE( HelpArgument );
  115. }
  116. VOID
  117. REPLACE::GetArgumentsCmd(
  118. )
  119. /*++
  120. Routine Description:
  121. Obtains the arguments from the Command line
  122. Arguments:
  123. None.
  124. Return Value:
  125. None
  126. Notes:
  127. --*/
  128. {
  129. ARRAY ArgArray;
  130. PATH_ARGUMENT ProgramNameArgument;
  131. DSTRING CmdLine;
  132. //
  133. // Prepare for parsing
  134. //
  135. if (//
  136. // Initialize the arguments
  137. //
  138. !(CmdLine.Initialize( GetCommandLine() )) ||
  139. !(ArgArray.Initialize( 10, 10 )) ||
  140. !(ProgramNameArgument.Initialize( MATCH_ALL_PATTERN )) ||
  141. !(SourcePathArgument->Initialize( MATCH_ALL_PATTERN, FALSE)) ||
  142. !(DestinationPathArgument->Initialize( MATCH_ALL_PATTERN, TRUE )) ||
  143. !(AddArgument->Initialize( &_AddPattern )) ||
  144. !(PromptArgument->Initialize( &_PromptPattern )) ||
  145. !(ReadOnlyArgument->Initialize( &_ReadOnlyPattern )) ||
  146. !(SubdirArgument->Initialize( &_SubdirPattern )) ||
  147. !(CompareTimeArgument->Initialize( &_CompareTimePattern )) ||
  148. !(WaitArgument->Initialize( &_WaitPattern )) ||
  149. !(HelpArgument->Initialize( &_HelpPattern )) ||
  150. //
  151. // Put the arguments in the argument array
  152. //
  153. !(ArgArray.Put( &ProgramNameArgument )) ||
  154. !(ArgArray.Put( AddArgument )) ||
  155. !(ArgArray.Put( PromptArgument )) ||
  156. !(ArgArray.Put( ReadOnlyArgument )) ||
  157. !(ArgArray.Put( SubdirArgument )) ||
  158. !(ArgArray.Put( CompareTimeArgument )) ||
  159. !(ArgArray.Put( WaitArgument )) ||
  160. !(ArgArray.Put( HelpArgument )) ||
  161. !(ArgArray.Put( SourcePathArgument )) ||
  162. !(ArgArray.Put( DestinationPathArgument ))
  163. ) {
  164. DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
  165. NULL,
  166. EXIT_NO_MEMORY );
  167. }
  168. //
  169. // Parse the arguments
  170. //
  171. ParseArguments( &CmdLine, &ArgArray );
  172. //
  173. // Set the switches
  174. //
  175. _AddSwitch = AddArgument->QueryFlag();
  176. _PromptSwitch = PromptArgument->QueryFlag();
  177. _ReadOnlySwitch = ReadOnlyArgument->QueryFlag();
  178. _SubdirSwitch = SubdirArgument->QueryFlag();
  179. _CompareTimeSwitch = CompareTimeArgument->QueryFlag();
  180. _WaitSwitch = WaitArgument->QueryFlag();
  181. HelpSwitch = HelpArgument->QueryFlag();
  182. //
  183. // Set the source and destination paths.
  184. //
  185. if ( SourcePathArgument->IsValueSet() ) {
  186. if ((_SourcePath = SourcePathArgument->GetPath()->QueryPath()) == NULL ) {
  187. DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY, NULL, EXIT_NO_MEMORY );
  188. }
  189. } else {
  190. _SourcePath = NULL;
  191. }
  192. if ( DestinationPathArgument->IsValueSet() ) {
  193. if ((_DestinationPath = DestinationPathArgument->GetPath()->QueryFullPath()) == NULL ) {
  194. DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY, NULL, EXIT_NO_MEMORY );
  195. }
  196. } else {
  197. _DestinationPath = NULL;
  198. }
  199. }
  200. VOID
  201. REPLACE::ParseArguments(
  202. IN PWSTRING CmdLine,
  203. OUT PARRAY ArgArray
  204. )
  205. /*++
  206. Routine Description:
  207. Parses a group of arguments
  208. Arguments:
  209. CmdLine - Supplies pointer to a command line to parse
  210. ArgArray - Supplies pointer to array of arguments
  211. Return Value:
  212. none
  213. Notes:
  214. --*/
  215. {
  216. ARGUMENT_LEXEMIZER ArgLex;
  217. ARRAY LexArray;
  218. //
  219. // Initialize lexeme array and the lexemizer.
  220. //
  221. if ( !(LexArray.Initialize( 8, 8 )) ||
  222. !(ArgLex.Initialize( &LexArray )) ) {
  223. DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
  224. NULL,
  225. EXIT_NO_MEMORY );
  226. }
  227. //
  228. // Set our parsing preferences
  229. //
  230. ArgLex.PutMultipleSwitch( &_MultipleSwitch );
  231. ArgLex.PutSwitches( &_Switches );
  232. ArgLex.SetCaseSensitive( FALSE );
  233. ArgLex.PutSeparators( " /\t" );
  234. ArgLex.PutStartQuotes( "\"" );
  235. ArgLex.PutEndQuotes( "\"" );
  236. //
  237. // Parse the arguments
  238. //
  239. if ( !(ArgLex.PrepareToParse( CmdLine ))) {
  240. DisplayMessageAndExit( REPLACE_ERROR_PARSE,
  241. NULL,
  242. EXIT_COMMAND_LINE_ERROR );
  243. }
  244. if ( !ArgLex.DoParsing( ArgArray ) ) {
  245. DisplayMessageAndExit( REPLACE_ERROR_INVALID_SWITCH,
  246. ArgLex.QueryInvalidArgument(),
  247. EXIT_COMMAND_LINE_ERROR );
  248. }
  249. }
  250. VOID
  251. REPLACE::CheckArgumentConsistency (
  252. )
  253. /*++
  254. Routine Description:
  255. Checks the consistency of the arguments
  256. Arguments:
  257. none
  258. Return Value:
  259. none
  260. Notes:
  261. --*/
  262. {
  263. PFSN_FILE File = NULL;
  264. if ( HelpSwitch ) {
  265. //
  266. // Help requested
  267. //
  268. Usage();
  269. }
  270. //
  271. // Make sure that we have a source path
  272. //
  273. if ( _SourcePath == NULL ) {
  274. DisplayMessageAndExit( REPLACE_ERROR_SOURCE_PATH_REQUIRED,
  275. NULL,
  276. EXIT_COMMAND_LINE_ERROR );
  277. }
  278. //
  279. // The add switch cannot be specified together with the Subdir or the
  280. // CompareTime switch.
  281. //
  282. if ( _AddSwitch && (_SubdirSwitch || _CompareTimeSwitch)) {
  283. DisplayMessageAndExit( REPLACE_ERROR_INVALID_PARAMETER_COMBINATION,
  284. NULL,
  285. EXIT_COMMAND_LINE_ERROR );
  286. }
  287. //
  288. // If destination path is null, then the destination path is the
  289. // current directory
  290. //
  291. if ( _DestinationPath == NULL ) {
  292. if ( ((_DestinationPath = NEW PATH) == NULL ) ||
  293. !_DestinationPath->Initialize( CURRENT_DIRECTORY, TRUE ) ) {
  294. DisplayMessageAndExit( REPLACE_ERROR_NO_MEMORY,
  295. NULL,
  296. EXIT_NO_MEMORY );
  297. }
  298. } else if ( (_DestinationPath->HasWildCard()) ||
  299. ((File = SYSTEM::QueryFile( _DestinationPath )) != NULL) ) {
  300. DisplayMessageAndExit( REPLACE_ERROR_PATH_NOT_FOUND,
  301. _DestinationPath->GetPathString(),
  302. EXIT_PATH_NOT_FOUND );
  303. }
  304. DELETE( File );
  305. }