Leaked source code of windows server 2003
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.

515 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. Argument
  5. Abstract:
  6. Argument processing for the "MORE" pager
  7. Author:
  8. Ramon Juan San Andres (ramonsa) 24-Apr-1990
  9. Notes:
  10. The arguments accepted by the more pager are:
  11. Extended mode switch.- This allows all other options. Without this
  12. switch, no other options are allowed.
  13. Help switch.- Displays usage.
  14. ClearScreen switch.- Clears the screen before displaying each page.
  15. SqueezeBlank switch.- Squeezes consecutive blank lines into a single
  16. line.
  17. ExpandFormFeed switch.- FormFeeds are expanded to fill the rest of
  18. the screen.
  19. Start at line.- Paging starts at the specified line of the
  20. first file.
  21. Tab expansion.- Expand tabs to this number of blanks
  22. File list.- List of files to page.
  23. The more pager obtains its arguments from two sources:
  24. 1.- An environment variable ( "MORE" )
  25. 2.- The command line.
  26. The environment variable may specify any options, except a file
  27. list.
  28. Revision History:
  29. --*/
  30. #include "ulib.hxx"
  31. #include "arg.hxx"
  32. #include "arrayit.hxx"
  33. #include "rtmsg.h"
  34. #include "path.hxx"
  35. #include "smsg.hxx"
  36. #include "system.hxx"
  37. #include "more.hxx"
  38. #define ENABLE_EXTENSIONS_VALUE L"EnableExtensions"
  39. #define COMMAND_PROCESSOR_KEY L"Software\\Microsoft\\Command Processor"
  40. //
  41. // Static variables
  42. //
  43. //
  44. PFLAG_ARGUMENT ExtendedModeArgument;
  45. PFLAG_ARGUMENT ClearScreenArgument;
  46. PFLAG_ARGUMENT ExpandFormFeedArgument;
  47. PFLAG_ARGUMENT SqueezeBlanksArgument;
  48. PFLAG_ARGUMENT Help1Argument;
  49. PFLAG_ARGUMENT Help2Argument;
  50. PLONG_ARGUMENT StartAtLineArgument;
  51. PLONG_ARGUMENT TabExpArgument;
  52. VOID
  53. MORE::SetArguments(
  54. )
  55. /*++
  56. Routine Description:
  57. Obtains the arguments for the "more" pager.
  58. Arguments:
  59. None.
  60. Return Value:
  61. None.
  62. Notes:
  63. --*/
  64. {
  65. FLAG_ARGUMENT LocalExtendedModeArgument;
  66. FLAG_ARGUMENT LocalClearScreenArgument;
  67. FLAG_ARGUMENT LocalExpandFormFeedArgument;
  68. FLAG_ARGUMENT LocalSqueezeBlanksArgument;
  69. FLAG_ARGUMENT LocalHelp1Argument;
  70. FLAG_ARGUMENT LocalHelp2Argument;
  71. LONG_ARGUMENT LocalStartAtLineArgument;
  72. LONG_ARGUMENT LocalTabExpArgument;
  73. ExtendedModeArgument = &LocalExtendedModeArgument;
  74. ClearScreenArgument = &LocalClearScreenArgument;
  75. ExpandFormFeedArgument = &LocalExpandFormFeedArgument;
  76. SqueezeBlanksArgument = &LocalSqueezeBlanksArgument;
  77. Help1Argument = &LocalHelp1Argument;
  78. Help2Argument = &LocalHelp2Argument;
  79. StartAtLineArgument = &LocalStartAtLineArgument;
  80. TabExpArgument = &LocalTabExpArgument;
  81. //
  82. // Get arguments from the environment variable
  83. //
  84. GetArgumentsMore();
  85. //
  86. // Get the arguments from the command line.
  87. //
  88. GetArgumentsCmd();
  89. //
  90. // Determine if there is a need to enable command extension
  91. //
  92. GetRegistryInfo();
  93. //
  94. // Verify the arguments
  95. //
  96. CheckArgumentConsistency();
  97. }
  98. VOID
  99. MORE::GetArgumentsMore(
  100. )
  101. /*++
  102. Routine Description:
  103. Obtains the arguments from the "More" environment variable.
  104. Arguments:
  105. None.
  106. Return Value:
  107. None.
  108. Notes:
  109. --*/
  110. {
  111. ARRAY ArgArray;
  112. PWSTRING MoreVariableName;
  113. PWSTRING MoreVariableValue;
  114. //
  115. // Get the name of the MORE environment variable and the argument
  116. //
  117. if ( (MoreVariableName = QueryMessageString( MORE_ENVIRONMENT_VARIABLE_NAME )) == NULL ) {
  118. Fatal();
  119. }
  120. //
  121. // Get the value of the MORE environment variable.
  122. //
  123. MoreVariableValue = SYSTEM::QueryEnvironmentVariable( MoreVariableName );
  124. if ( MoreVariableValue != NULL ) {
  125. //
  126. // Now prepare for parsing
  127. //
  128. if ( //
  129. // Initialize tha arguments
  130. //
  131. !(ArgArray.Initialize( 7, 7 )) ||
  132. !(ExtendedModeArgument->Initialize( "/E" )) ||
  133. !(ClearScreenArgument->Initialize( "/C" )) ||
  134. !(ExpandFormFeedArgument->Initialize( "/P" )) ||
  135. !(SqueezeBlanksArgument->Initialize( "/S" )) ||
  136. !(Help1Argument->Initialize( "/?" )) ||
  137. !(Help2Argument->Initialize( "/H" )) ||
  138. !(StartAtLineArgument->Initialize( "+*" )) ||
  139. !(TabExpArgument->Initialize( "/t*" )) ||
  140. //
  141. // Put the arguments in the argument array
  142. //
  143. !(ArgArray.Put( ExtendedModeArgument )) ||
  144. !(ArgArray.Put( ClearScreenArgument )) ||
  145. !(ArgArray.Put( ExpandFormFeedArgument )) ||
  146. !(ArgArray.Put( SqueezeBlanksArgument )) ||
  147. !(ArgArray.Put( Help1Argument )) ||
  148. !(ArgArray.Put( Help2Argument )) ||
  149. !(ArgArray.Put( StartAtLineArgument )) ||
  150. !(ArgArray.Put( TabExpArgument ))
  151. ) {
  152. Fatal();
  153. }
  154. //
  155. // Parse the arguments
  156. //
  157. ParseArguments( MoreVariableValue, &ArgArray );
  158. //
  159. // Set the global structures
  160. //
  161. _ExtendedModeSwitch = ExtendedModeArgument->QueryFlag();
  162. _ClearScreenSwitch = ClearScreenArgument->QueryFlag();
  163. _ExpandFormFeedSwitch = ExpandFormFeedArgument->QueryFlag();
  164. _SqueezeBlanksSwitch = SqueezeBlanksArgument->QueryFlag();
  165. _HelpSwitch = (BOOLEAN)(Help1Argument->QueryFlag() || Help2Argument->QueryFlag());
  166. if ( StartAtLineArgument->IsValueSet() ) {
  167. _StartAtLine = StartAtLineArgument->QueryLong();
  168. }
  169. if ( TabExpArgument->IsValueSet() ) {
  170. _TabExp = TabExpArgument->QueryLong();
  171. }
  172. //
  173. // Clean up
  174. //
  175. DELETE( MoreVariableValue );
  176. }
  177. DELETE( MoreVariableName );
  178. }
  179. VOID
  180. MORE::GetArgumentsCmd(
  181. )
  182. /*++
  183. Routine Description:
  184. Obtains the arguments from the Command line
  185. Arguments:
  186. None.
  187. Return Value:
  188. None
  189. Notes:
  190. --*/
  191. {
  192. ARRAY ArgArray;
  193. DSTRING CmdLine;
  194. PATH_ARGUMENT ProgramNameArgument;
  195. //
  196. // Prepare for parsing
  197. //
  198. if (//
  199. // Initialize the arguments
  200. //
  201. !(CmdLine.Initialize( GetCommandLine() )) ||
  202. !(ArgArray.Initialize( 9, 9 )) ||
  203. !(ProgramNameArgument.Initialize( "*" )) ||
  204. !(ExtendedModeArgument->Initialize( "/E" )) ||
  205. !(ClearScreenArgument->Initialize( "/C" )) ||
  206. !(ExpandFormFeedArgument->Initialize( "/P" )) ||
  207. !(SqueezeBlanksArgument->Initialize( "/S" )) ||
  208. !(Help1Argument->Initialize( "/?" )) ||
  209. !(Help2Argument->Initialize( "/H" )) ||
  210. !(StartAtLineArgument->Initialize( "+*" )) ||
  211. !(TabExpArgument->Initialize( "/t*" )) ||
  212. ((_FilesArgument = NEW MULTIPLE_PATH_ARGUMENT) == NULL) ||
  213. !(_FilesArgument->Initialize( "*", TRUE, TRUE )) ||
  214. //
  215. // Put the arguments in the argument array
  216. //
  217. !(ArgArray.Put( &ProgramNameArgument )) ||
  218. !(ArgArray.Put( ExtendedModeArgument )) ||
  219. !(ArgArray.Put( ClearScreenArgument )) ||
  220. !(ArgArray.Put( ExpandFormFeedArgument )) ||
  221. !(ArgArray.Put( SqueezeBlanksArgument )) ||
  222. !(ArgArray.Put( Help1Argument )) ||
  223. !(ArgArray.Put( Help2Argument )) ||
  224. !(ArgArray.Put( StartAtLineArgument )) ||
  225. !(ArgArray.Put( TabExpArgument )) ||
  226. !(ArgArray.Put( _FilesArgument )) ) {
  227. Fatal();
  228. }
  229. //
  230. // Parse the arguments
  231. //
  232. ParseArguments( &CmdLine, &ArgArray );
  233. //
  234. // Set the global structures
  235. //
  236. _ExtendedModeSwitch |= ExtendedModeArgument->QueryFlag();
  237. _ClearScreenSwitch |= ClearScreenArgument->QueryFlag();
  238. _ExpandFormFeedSwitch |= ExpandFormFeedArgument->QueryFlag();
  239. _SqueezeBlanksSwitch |= SqueezeBlanksArgument->QueryFlag();
  240. _HelpSwitch |= Help1Argument->QueryFlag() || Help2Argument->QueryFlag();
  241. if ( StartAtLineArgument->IsValueSet() ) {
  242. _StartAtLine = StartAtLineArgument->QueryLong();
  243. }
  244. if ( TabExpArgument->IsValueSet() ) {
  245. _TabExp = TabExpArgument->QueryLong();
  246. }
  247. }
  248. VOID
  249. MORE::ParseArguments(
  250. IN PWSTRING CmdLine,
  251. OUT PARRAY ArgArray
  252. )
  253. /*++
  254. Routine Description:
  255. Parses a group of arguments
  256. Arguments:
  257. CmdLine - Supplies pointer to a command line to parse
  258. ArgArray - Supplies pointer to array of arguments
  259. Return Value:
  260. none
  261. Notes:
  262. --*/
  263. {
  264. ARGUMENT_LEXEMIZER ArgLex;
  265. ARRAY LexArray;
  266. PWSTRING InvalidParameter;
  267. //
  268. // Initialize lexeme array and the lexemizer.
  269. //
  270. if ( !(LexArray.Initialize( 8, 8 )) ||
  271. !(ArgLex.Initialize( &LexArray )) ) {
  272. Fatal();
  273. }
  274. //
  275. // Set our parsing preferences
  276. //
  277. ArgLex.PutMultipleSwitch( "/ECPSH?" );
  278. ArgLex.PutSwitches( "/" );
  279. ArgLex.PutSeparators( " /\t" );
  280. ArgLex.SetCaseSensitive( FALSE );
  281. ArgLex.PutStartQuotes( "\"" );
  282. ArgLex.PutEndQuotes( "\"" );
  283. //
  284. // Parse the arguments
  285. //
  286. if ( !(ArgLex.PrepareToParse( CmdLine ))) {
  287. Fatal( EXIT_ERROR, MORE_ERROR_GENERAL, "" );
  288. }
  289. if ( !ArgLex.DoParsing( ArgArray ) ) {
  290. _Message.Set(MSG_INVALID_PARAMETER);
  291. _Message.Display("%W", InvalidParameter = ArgLex.QueryInvalidArgument() );
  292. DELETE(InvalidParameter);
  293. ExitProcess( 0 );
  294. }
  295. LexArray.DeleteAllMembers( );
  296. }
  297. VOID
  298. MORE::CheckArgumentConsistency (
  299. )
  300. /*++
  301. Routine Description:
  302. Checks the consistency of the arguments
  303. Arguments:
  304. none
  305. Return Value:
  306. none
  307. Notes:
  308. --*/
  309. {
  310. BOOLEAN ExtendedSwitches;
  311. if ( _HelpSwitch ) {
  312. //
  313. // Help wanted
  314. //
  315. Usage();
  316. }
  317. ExtendedSwitches = (BOOLEAN)( _ClearScreenSwitch ||
  318. _ExpandFormFeedSwitch ||
  319. _SqueezeBlanksSwitch ||
  320. TabExpArgument->IsValueSet() ||
  321. ( _StartAtLine > (LONG)0 ) ||
  322. _FilesArgument->WildCardExpansionFailed() ||
  323. ( _FilesArgument->QueryPathCount() > (ULONG)0));
  324. //
  325. // If the "extended" flag was not specified, then no other argument
  326. // is allowed.
  327. //
  328. if ( !_ExtendedModeSwitch &&
  329. ExtendedSwitches ) {
  330. Fatal( EXIT_ERROR, MORE_ERROR_TOO_MANY_ARGUMENTS, "" );
  331. }
  332. //
  333. // Error out if invalid file specified
  334. //
  335. if ( _FilesArgument->WildCardExpansionFailed() ) {
  336. Fatal( EXIT_ERROR, MORE_ERROR_CANNOT_ACCESS, "%W", _FilesArgument->GetLexemeThatFailed() );
  337. }
  338. }
  339. VOID
  340. MORE::GetRegistryInfo(
  341. )
  342. {
  343. ULONG valueType;
  344. DWORD value;
  345. ULONG valueLength = sizeof(value);
  346. HKEY key;
  347. LONG status;
  348. if (_ExtendedModeSwitch)
  349. return;
  350. status = RegOpenKeyEx(HKEY_CURRENT_USER,
  351. COMMAND_PROCESSOR_KEY,
  352. 0,
  353. KEY_READ,
  354. &key);
  355. if (status != ERROR_SUCCESS) {
  356. return;
  357. }
  358. status = RegQueryValueEx(key,
  359. ENABLE_EXTENSIONS_VALUE,
  360. NULL,
  361. &valueType,
  362. (LPBYTE)&value,
  363. &valueLength);
  364. if (status != ERROR_SUCCESS ||
  365. valueType != REG_DWORD ||
  366. valueLength != sizeof(DWORD)) {
  367. RegCloseKey(key);
  368. return;
  369. }
  370. _ExtendedModeSwitch = (BOOLEAN)value;
  371. RegCloseKey(key);
  372. }