libraries/iosrv/client/command_base.cpp
changeset 0 7f656887cf89
child 6 96d581d2147d
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // command_base.cpp
       
     2 // 
       
     3 // Copyright (c) 2005 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include "iocons.h"
       
    14 #include "ioutils.h"
       
    15 #include "command_base.h"
       
    16 #include <fshell/ltkutils.h>
       
    17 
       
    18 using namespace IoUtils;
       
    19 
       
    20 #define RETURN_IF_ERROR(x) {TInt _err = (x); if (_err<0) return _err;}
       
    21 
       
    22 //
       
    23 // Constants.
       
    24 //
       
    25 
       
    26 _LIT(KHelpName, "help");
       
    27 _LIT(KHelpDescription, "Display help.");
       
    28 _LIT(KOptConsole, "console");
       
    29 _LIT(KOptConsoleTitle, "console-title");
       
    30 _LIT(KOptConsoleSize, "console-size");
       
    31 _LIT(KOptPersistentConsole, "persistent-console");
       
    32 _LIT(KDllExt, ".dll");
       
    33 _LIT(KNewLine, "\r\n");
       
    34 
       
    35 const TUint KValueTypeUninitialized		= 0x0000ffff;
       
    36 const TUint KValueTypeFlagMultiple 		= 0x00010000;
       
    37 const TUint KValueTypeFlagMask     		= 0x0000ffff;
       
    38 const TUint KPublicFlagsMask			= 0x0000ffff;
       
    39 const TUint KPrivateFlagsMask			= 0xffff0000;
       
    40 
       
    41 
       
    42 //
       
    43 // Misc.
       
    44 //
       
    45 
       
    46 void IoUtils::Panic(TCmdBasePanic aReason)
       
    47 	{
       
    48 	_LIT(KCategory, "iocli");
       
    49 	User::Panic(KCategory, aReason);
       
    50 	}
       
    51 
       
    52 // If any of these asserts fail, it constitutes a BC break
       
    53 __ASSERT_COMPILE(sizeof(RChildProcess) == 7*4);
       
    54 __ASSERT_COMPILE(sizeof(RCommandOptionList) == 8*4);
       
    55 __ASSERT_COMPILE(sizeof(RCommandArgumentList) == 8*4);
       
    56 __ASSERT_COMPILE(sizeof(RIoConsoleReadHandle) == 6*4);
       
    57 __ASSERT_COMPILE(sizeof(RIoReadHandle) == 2*4);
       
    58 __ASSERT_COMPILE(sizeof(RIoConsoleWriteHandle) == 2*4);
       
    59 
       
    60 // The member variables of CCommandBase actually sum to 59 words, and from subclasses' point of view it's 59 words,
       
    61 // but EABI rounds the sizeof up to an 8-byte boundary. We can't change CCommandBase to be 60 words so that it's
       
    62 // handled the same on all platforms, because that in itself would be a BC break.
       
    63 #ifdef __EABI__
       
    64 __ASSERT_COMPILE(sizeof(CCommandBase) == 60*4);
       
    65 #else
       
    66 __ASSERT_COMPILE(sizeof(CCommandBase) == 59*4);
       
    67 #endif
       
    68 
       
    69 //
       
    70 // TEnumLex.
       
    71 //
       
    72 	
       
    73 class TEnumLex
       
    74 	{
       
    75 public:
       
    76 	TEnumLex(const TDesC& aCommaSeparatedList);
       
    77 	TBool More();
       
    78 	TPtrC Next();
       
    79 private:
       
    80 	TPtrC iRemainder;
       
    81 	};
       
    82 
       
    83 TEnumLex::TEnumLex(const TDesC& aCommaSeparatedList)
       
    84 	: iRemainder(aCommaSeparatedList)
       
    85 	{
       
    86 	}
       
    87 		
       
    88 
       
    89 TBool TEnumLex::More()
       
    90 	{
       
    91 	return iRemainder.Length() > 0;
       
    92 	}
       
    93 	
       
    94 _LIT(KComma, ",");
       
    95 
       
    96 TPtrC TEnumLex::Next()
       
    97 	{
       
    98 	TInt commaPos = iRemainder.Find(KComma);
       
    99 	if (commaPos<0) commaPos = iRemainder.Length();
       
   100 	TPtrC value(iRemainder.Mid(0, commaPos));
       
   101 	iRemainder.Set(iRemainder.Mid(commaPos));
       
   102 	if (iRemainder.Length()) iRemainder.Set(iRemainder.Mid(1));
       
   103 	return value;
       
   104 	}
       
   105 
       
   106 
       
   107 //
       
   108 // TEnum.
       
   109 //
       
   110 
       
   111 EXPORT_C TEnum::TEnum()
       
   112 	{
       
   113 	}
       
   114 
       
   115 EXPORT_C TEnum::TEnum(const TDesC& aEnumValueList)
       
   116 	: iEnumValueList(aEnumValueList)
       
   117 	{
       
   118 	ValidateValues();
       
   119 	}
       
   120 
       
   121 EXPORT_C TEnum::TEnum(const TDesC& aEnumValueList, const TDesC& aEnumDescriptionList)
       
   122 	: iEnumValueList(aEnumValueList), iEnumDescriptionList(aEnumDescriptionList)
       
   123 	{
       
   124 	ValidateValues();
       
   125 	}
       
   126 	
       
   127 TInt TEnum::GetMatches(const TDesC& aString, RArray<TInt>& aMatches, TInt& aExactMatch)
       
   128 	{
       
   129 	TEnumLex lex(iEnumValueList);
       
   130 	TInt i = 0;
       
   131 	aExactMatch = KErrNotFound;
       
   132 	while ((lex.More()) && (aExactMatch == KErrNotFound))
       
   133 		{
       
   134 		TPtrC value(lex.Next());
       
   135 		if (value.Compare(aString)==0)
       
   136 			{
       
   137 			aExactMatch = i;
       
   138 			}
       
   139 		if (value.Find(aString)==0)
       
   140 			{
       
   141 			TInt err = aMatches.Append(i);
       
   142 			if (err) return err;
       
   143 			}
       
   144 		++i;
       
   145 		}
       
   146 	return KErrNone;
       
   147 	}
       
   148 	
       
   149 EXPORT_C TInt TEnum::Parse(const TDesC& aString, TInt& aValue)
       
   150 	{
       
   151 	RArray<TInt> matches;
       
   152 	TInt exactMatch;
       
   153 	TInt err = GetMatches(aString, matches, exactMatch);
       
   154 	if (err==KErrNone)
       
   155 		{
       
   156 		if (exactMatch != KErrNotFound)
       
   157 			{
       
   158 			aValue = exactMatch;
       
   159 			}
       
   160 		else if (matches.Count()==1)
       
   161 			{
       
   162 			aValue = matches[0];
       
   163 			}
       
   164 		else
       
   165 			{
       
   166 			err = KErrArgument;
       
   167 			}
       
   168 		}
       
   169 	matches.Close();
       
   170 	return err;	
       
   171 	}
       
   172 
       
   173 EXPORT_C TInt TEnum::ParseL(const TDesC& aString)
       
   174 	{
       
   175 	RArray<TInt> matches;
       
   176 	TInt exactMatch;
       
   177 	CleanupClosePushL(matches);
       
   178 	User::LeaveIfError(GetMatches(aString, matches, exactMatch));
       
   179 	
       
   180 	TInt value = 0;
       
   181 	if ((matches.Count()==1) || (exactMatch != KErrNotFound))
       
   182 		{
       
   183 		value = exactMatch != KErrNotFound ? exactMatch : matches[0];
       
   184 		}
       
   185 	else if (matches.Count()==0)
       
   186 		{
       
   187 		if (CCommandBase::HaveStatic())
       
   188 			{
       
   189 			CTextBuffer* buf = CTextBuffer::NewLC(0x20);
       
   190 			buf->AppendL(_L("String '"));
       
   191 			buf->AppendL(aString);
       
   192 			buf->AppendL(_L("' does not match any of "));
       
   193 			AppendValuesL(*buf);
       
   194 			PrintError(KErrArgument, buf->Descriptor());
       
   195 			}
       
   196 		User::Leave(KErrArgument);
       
   197 		}
       
   198 	else
       
   199 		{
       
   200 		if (CCommandBase::HaveStatic())
       
   201 			{
       
   202 			CTextBuffer* buf = CTextBuffer::NewLC(0x20);
       
   203 			buf->AppendL(_L("String '"));
       
   204 			buf->AppendL(aString);
       
   205 			buf->AppendL(_L("' does not match a unique value (matches "));
       
   206 			TInt enumCount = -1;
       
   207 			TEnumLex lex(iEnumValueList);
       
   208 			// here we rely on the fact the matches will be sorted, due to the way the array was populated above.
       
   209 			for (TInt i=0; i<matches.Count(); ++i)
       
   210 				{
       
   211 				TPtrC enumValue;
       
   212 				while (matches[i]>enumCount)
       
   213 					{
       
   214 					++enumCount;
       
   215 					enumValue.Set(lex.Next());
       
   216 					}
       
   217 				buf->AppendL(enumValue);
       
   218 				if (i<matches.Count()-1) buf->AppendL(_L(", "));
       
   219 				}
       
   220 			buf->AppendL(')');
       
   221 			PrintError(KErrArgument, buf->Descriptor());
       
   222 			}
       
   223 		User::Leave(KErrArgument);
       
   224 		}
       
   225 	CleanupStack::PopAndDestroy(); //matches
       
   226 	return value;
       
   227 	}
       
   228 	
       
   229 EXPORT_C const TDesC& TEnum::ValueList() const
       
   230 	{
       
   231 	return iEnumValueList;
       
   232 	}
       
   233 
       
   234 EXPORT_C const TDesC& TEnum::DescriptionList() const
       
   235 	{
       
   236 	return iEnumDescriptionList;
       
   237 	}
       
   238 	
       
   239 void TEnum::ValidateValues() const
       
   240 	{
       
   241 	for (TInt i=0; i<iEnumValueList.Length(); ++i)
       
   242 		{
       
   243 		__ASSERT_ALWAYS(!TChar(iEnumValueList[i]).IsSpace(), IoUtils::Panic(EEnumValueContainsSpace));
       
   244 		}
       
   245 	}
       
   246 
       
   247 EXPORT_C void TEnum::AppendValuesL(CTextBuffer& aBuf) const
       
   248 	{
       
   249 	TEnumLex values(iEnumValueList);
       
   250 	while (values.More())
       
   251 		{
       
   252 		aBuf.AppendL(values.Next());
       
   253 		if (values.More())
       
   254 			{
       
   255 			aBuf.AppendL(_L(", "));
       
   256 			}
       
   257 		}
       
   258 	}
       
   259 	
       
   260 EXPORT_C const TPtrC TEnum::GetString(TInt aIndex) const
       
   261 	{
       
   262 	TEnumLex lex(iEnumValueList);
       
   263 	while (aIndex)
       
   264 		{
       
   265 		lex.Next();
       
   266 		--aIndex;
       
   267 		__ASSERT_ALWAYS(lex.More(), Panic(EEnumValueOutOfRange));
       
   268 		}
       
   269 	return lex.Next();
       
   270 	}
       
   271 
       
   272 EXPORT_C void TEnum::SetValueList(const TDesC& aValueList)
       
   273 	{
       
   274 	__ASSERT_ALWAYS(iEnumValueList.Length() == 0, IoUtils::Panic(EEnumValueListAlreadySet));
       
   275 	iEnumValueList.Set(aValueList);
       
   276 	}
       
   277 
       
   278 EXPORT_C void TEnum::SetDescriptionList(const TDesC& aDescriptionList)
       
   279 	{
       
   280 	__ASSERT_ALWAYS(iEnumDescriptionList.Length() == 0, IoUtils::Panic(EEnumDescriptionListAlreadySet));
       
   281 	iEnumDescriptionList.Set(aDescriptionList);
       
   282 	}
       
   283 
       
   284 EXPORT_C void TEnum::operator=(const TEnum& aEnum)
       
   285 	{
       
   286 	iEnumValueList.Set(aEnum.iEnumValueList);
       
   287 	iEnumDescriptionList.Set(aEnum.iEnumDescriptionList);
       
   288 	}
       
   289 
       
   290 
       
   291 //
       
   292 // TValue.
       
   293 //
       
   294 
       
   295 TValue::TValue(TUint aValueType, void* aValuePointer, const TDesC& aName)
       
   296 	: iValueType(aValueType), iValue(aValuePointer), iIsSet(EFalse), iEnum(KNullDesC, KNullDesC), iName(aName)
       
   297 	{
       
   298 	}
       
   299 
       
   300 TValue::TValue(TUint aValueType, void* aValuePointer, const TDesC& aName, const TDesC& aDescription, const TDesC& aEnvVar)
       
   301 	: iValueType(aValueType), iValue(aValuePointer), iIsSet(EFalse), iEnvVar(aEnvVar), iEnum(KNullDesC, KNullDesC), iName(aName), iDescription(aDescription)
       
   302 	{
       
   303 	__ASSERT_ALWAYS(aValueType != KValueTypeEnum, IoUtils::Panic(EInvalidUseOfEnum));
       
   304 	}
       
   305 	
       
   306 TValue::TValue(TUint aValueType, const TDesC& aEnumValueList, const TDesC& aEnumDescriptionList, void* aValuePointer, const TDesC& aName, const TDesC& aDescription, const TDesC& aEnvVar)
       
   307 	: iValueType(aValueType), iValue(aValuePointer), iIsSet(EFalse), iEnvVar(aEnvVar), iEnum(aEnumValueList, aEnumDescriptionList), iName(aName), iDescription(aDescription)
       
   308 	{
       
   309 	}
       
   310 
       
   311 TUint TValue::ValueType() const
       
   312 	{
       
   313 	return iValueType;
       
   314 	}
       
   315 
       
   316 EXPORT_C TUint TValue::Type() const
       
   317 	{
       
   318 	return iValueType & KPublicFlagsMask;
       
   319 	}
       
   320 
       
   321 void TValue::SetValue()
       
   322 	{
       
   323 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeBool, IoUtils::Panic(EIncorrectCommandOptionType1));
       
   324 	if (iValueType & KValueTypeFlagMultiple)
       
   325 		{
       
   326 		(*(TInt*)iValue)++;
       
   327 		}
       
   328 	else
       
   329 		{
       
   330 		*(TBool*)iValue = ETrue;
       
   331 		}
       
   332 	iIsSet = ETrue;
       
   333 	}
       
   334 
       
   335 void TValue::SetValueL(TInt aInt)
       
   336 	{
       
   337 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeInt, IoUtils::Panic(EIncorrectCommandOptionType2));
       
   338 	if (iValueType & KValueTypeFlagMultiple)
       
   339 		{
       
   340 		User::LeaveIfError(((RArray<TInt>*)iValue)->Append(aInt));
       
   341 		}
       
   342 	else
       
   343 		{
       
   344 		*(TInt*)iValue = aInt;
       
   345 		}
       
   346 	iIsSet = ETrue;
       
   347 	}
       
   348 
       
   349 void TValue::SetValueL(TInt64 aInt)
       
   350 	{
       
   351 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeInt64, IoUtils::Panic(EIncorrectCommandOptionType11));
       
   352 	if (iValueType & KValueTypeFlagMultiple)
       
   353 		{
       
   354 		User::LeaveIfError(((RArray<TInt64>*)iValue)->Append(aInt));
       
   355 		}
       
   356 	else
       
   357 		{
       
   358 		*(TInt64*)iValue = aInt;
       
   359 		}
       
   360 	iIsSet = ETrue;
       
   361 	}
       
   362 
       
   363 void TValue::SetValueL(TUint aUint)
       
   364 	{
       
   365 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeUint, IoUtils::Panic(EIncorrectCommandOptionType3));
       
   366 	if (iValueType & KValueTypeFlagMultiple)
       
   367 		{
       
   368 		User::LeaveIfError(((RArray<TUint>*)iValue)->Append(aUint));
       
   369 		}
       
   370 	else
       
   371 		{
       
   372 		*(TUint*)iValue = aUint;
       
   373 		}
       
   374 	iIsSet = ETrue;
       
   375 	}
       
   376 
       
   377 void TValue::SetValueL(TUint64 aUint)
       
   378 	{
       
   379 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeUint64, IoUtils::Panic(EIncorrectCommandOptionType10));
       
   380 	if (iValueType & KValueTypeFlagMultiple)
       
   381 		{
       
   382 		User::LeaveIfError(((RArray<TUint64>*)iValue)->Append(aUint));
       
   383 		}
       
   384 	else
       
   385 		{
       
   386 		*(TUint64*)iValue = aUint;
       
   387 		}
       
   388 	iIsSet = ETrue;
       
   389 	}
       
   390 
       
   391 void TValue::SetValueL(TReal64 aReal)
       
   392 	{
       
   393 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeReal, IoUtils::Panic(EIncorrectCommandOptionType4));
       
   394 	if (iValueType & KValueTypeFlagMultiple)
       
   395 		{
       
   396 		User::LeaveIfError(((RArray<TReal64>*)iValue)->Append(aReal));
       
   397 		}
       
   398 	else
       
   399 		{
       
   400 		*(TReal64*)iValue = aReal;
       
   401 		}
       
   402 	iIsSet = ETrue;
       
   403 	}
       
   404 
       
   405 void TValue::SetValueL(HBufC* aString)
       
   406 	{
       
   407 	__ASSERT_ALWAYS( ((iValueType & KValueTypeFlagMask) == KValueTypeString) || (iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType5));
       
   408 	if ((iValueType & KValueTypeFlagMask) == KValueTypeEnum)
       
   409 		{
       
   410 		TInt value = iEnum.ParseL(*aString);
       
   411 		if (iValueType & KValueTypeFlagMultiple)
       
   412 			{
       
   413 			User::LeaveIfError(((RArray<TInt>*)iValue)->Append(value));
       
   414 			}
       
   415 		else
       
   416 			{
       
   417 			*(TInt*)iValue = value;
       
   418 			}
       
   419 		iIsSet = ETrue;
       
   420 		}
       
   421 	else // string
       
   422 		{
       
   423 		if (iValueType & KValueTypeFlagMultiple)
       
   424 			{
       
   425 			User::LeaveIfError(((RPointerArray<HBufC>*)iValue)->Append(aString));
       
   426 			}
       
   427 		else
       
   428 			{
       
   429 			*(HBufC**)iValue = aString;
       
   430 			}
       
   431 		iIsSet = ETrue;
       
   432 		}
       
   433 	}
       
   434 
       
   435 void TValue::SetValueL(const TFileName2& aFileName, RFs& aFs)
       
   436 	{
       
   437 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeFileName, IoUtils::Panic(EIncorrectCommandOptionType6));
       
   438 		
       
   439 	if (AcceptsMultiple())
       
   440 		{
       
   441 		if (aFileName.IsWild())
       
   442 			{
       
   443 			CDir* matches;
       
   444 			User::LeaveIfError(aFs.GetDir(aFileName, KEntryAttMaskSupported, ESortByName, matches));
       
   445 			CleanupStack::PushL(matches);
       
   446 			for (TInt i = 0; i < matches->Count(); ++i)
       
   447 				{
       
   448 				TFileName2 expandedFileName((*matches)[i].iName);
       
   449 				expandedFileName.MakeAbsoluteL(aFileName.DriveAndPath());
       
   450 				((RArray<TFileName2>*)iValue)->AppendL(expandedFileName);
       
   451 				}
       
   452 			CleanupStack::PopAndDestroy(matches);
       
   453 			}
       
   454 		else
       
   455 			{
       
   456 			((RArray<TFileName2>*)iValue)->AppendL(aFileName);
       
   457 			}
       
   458 		}
       
   459 	else
       
   460 		{
       
   461 		((TFileName2*)iValue)->SetL(aFileName);
       
   462 		}
       
   463 
       
   464 	iIsSet = ETrue;
       
   465 	}
       
   466 
       
   467 void TValue::SetEnumValues(const TEnum& aEnum)
       
   468 	{
       
   469 	iEnum = aEnum;
       
   470 	}
       
   471 
       
   472 TBool TValue::IsSet() const
       
   473 	{
       
   474 	return iIsSet;
       
   475 	}
       
   476 
       
   477 EXPORT_C TBool TValue::AcceptsMultiple() const
       
   478 	{
       
   479 	return (iValueType & KValueTypeFlagMultiple);
       
   480 	}
       
   481 	
       
   482 EXPORT_C const TDesC& TValue::EnumValueList() const
       
   483 	{
       
   484 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType7));
       
   485 	return iEnum.ValueList();
       
   486 	}
       
   487 
       
   488 const TDesC& TValue::EnumDescriptionList() const
       
   489 	{
       
   490 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType8));
       
   491 	return iEnum.DescriptionList();
       
   492 	}
       
   493 
       
   494 EXPORT_C const TDesC& TValue::EnvVar() const
       
   495 	{
       
   496 	return iEnvVar;
       
   497 	}
       
   498 
       
   499 EXPORT_C const TDesC& TValue::Name() const
       
   500 	{
       
   501 	return iName;
       
   502 	}
       
   503 
       
   504 const TDesC& TValue::Description() const
       
   505 	{
       
   506 	return iDescription;
       
   507 	}
       
   508 
       
   509 EXPORT_C void* TValue::ValuePtr() const
       
   510 	{
       
   511 	return iValue;
       
   512 	}
       
   513 	
       
   514 TPtrC TValue::AsString() const
       
   515 	{
       
   516 	if (!IsSet()) return KNullDesC();
       
   517 	if (AcceptsMultiple()) return KNullDesC();
       
   518 	switch (iValueType)
       
   519 		{
       
   520 	case KValueTypeString:
       
   521 		return *(HBufC*)iValue;
       
   522 	case KValueTypeFileName:
       
   523 		return *(TFileName2*)iValue;
       
   524 	case KValueTypeEnum:
       
   525 		return iEnum.GetString(*(TInt*)iValue);
       
   526 	default:
       
   527 		return KNullDesC();
       
   528 		}
       
   529 	}
       
   530 	
       
   531 void TValue::AppendEnumValuesL(CTextBuffer& aBuf) const
       
   532 	{
       
   533 	__ASSERT_ALWAYS((iValueType & KValueTypeFlagMask) == KValueTypeEnum, IoUtils::Panic(EIncorrectCommandOptionType9));
       
   534 	return iEnum.AppendValuesL(aBuf);
       
   535 	}
       
   536 
       
   537 void TValue::Combine(const TValue& aValue)
       
   538 	{
       
   539 	__ASSERT_ALWAYS(iDescription.Ptr() == NULL, IoUtils::Panic(EValueDescriptionAlreadySet));
       
   540 
       
   541 	iValueType = aValue.iValueType;
       
   542 	iDescription.Set(aValue.iDescription);
       
   543 	if ((iValueType & KValueTypeFlagMask) == KValueTypeEnum)
       
   544 		{
       
   545 		if (aValue.iEnum.ValueList().Length() > 0)
       
   546 			{
       
   547 			iEnum.SetValueList(aValue.iEnum.ValueList());
       
   548 			}
       
   549 		if (aValue.iEnum.DescriptionList().Length() > 0)
       
   550 			{
       
   551 			iEnum.SetDescriptionList(aValue.iEnum.DescriptionList());
       
   552 			}
       
   553 		}
       
   554 	iEnvVar.Set(aValue.EnvVar());
       
   555 	}
       
   556 
       
   557 
       
   558 //
       
   559 // TCommandOption.
       
   560 //
       
   561 
       
   562 TCommandOption::TCommandOption(TUint aValueType, void* aValuePointer, const TDesC& aLongName)
       
   563 	: TValue(aValueType, aValuePointer, aLongName)
       
   564 	{
       
   565 	}
       
   566 
       
   567 TCommandOption::TCommandOption(TUint aValueType, void* aValuePointer, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aEnvVar)
       
   568 	: TValue(aValueType, aValuePointer, aLongName, aDescription, aEnvVar), iShortName(aShortName)
       
   569 	{
       
   570 	}
       
   571 	
       
   572 TCommandOption::TCommandOption(void* aValuePointer, TUint aValueType, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aEnvVar)
       
   573 	: TValue(aValueType, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aValuePointer, aLongName, aDescription, aEnvVar), iShortName(aShortName)
       
   574 	{
       
   575 	}
       
   576 
       
   577 TChar TCommandOption::ShortName() const
       
   578 	{
       
   579 	return iShortName;
       
   580 	}
       
   581 
       
   582 void TCommandOption::Combine(const TCommandOption& aOption)
       
   583 	{
       
   584 	TValue::Combine(aOption);
       
   585 	iShortName = aOption.iShortName;
       
   586 	}
       
   587 
       
   588 
       
   589 //
       
   590 // RCommandOptionList.
       
   591 //
       
   592 
       
   593 void RCommandOptionList::Close()
       
   594 	{
       
   595 	iOptions.Close();
       
   596 	}
       
   597 
       
   598 EXPORT_C void RCommandOptionList::AppendBoolL(TBool& aBool, const TDesC& aLongName)
       
   599 	{
       
   600 	iOptions.AppendL(TCommandOption(KValueTypeBool, &aBool, aLongName));
       
   601 	}
       
   602 
       
   603 EXPORT_C void RCommandOptionList::AppendBoolL(RArray<TBool>& aBools, const TDesC& aLongName)
       
   604 	{
       
   605 	iOptions.AppendL(TCommandOption(KValueTypeBool | KValueTypeFlagMultiple, &aBools, aLongName));
       
   606 	}
       
   607 
       
   608 EXPORT_C void RCommandOptionList::AppendIntL(TInt& aInt, const TDesC& aLongName)
       
   609 	{
       
   610 	iOptions.AppendL(TCommandOption(KValueTypeInt, &aInt, aLongName));
       
   611 	}
       
   612 
       
   613 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt>& aInts, const TDesC& aLongName)
       
   614 	{
       
   615 	iOptions.AppendL(TCommandOption(KValueTypeInt | KValueTypeFlagMultiple, &aInts, aLongName));
       
   616 	}
       
   617 
       
   618 EXPORT_C void RCommandOptionList::AppendIntL(TInt64& aInt, const TDesC& aLongName)
       
   619 	{
       
   620 	iOptions.AppendL(TCommandOption(KValueTypeInt64, &aInt, aLongName));
       
   621 	}
       
   622 
       
   623 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt64>& aInts, const TDesC& aLongName)
       
   624 	{
       
   625 	iOptions.AppendL(TCommandOption(KValueTypeInt64 | KValueTypeFlagMultiple, &aInts, aLongName));
       
   626 	}
       
   627 
       
   628 EXPORT_C void RCommandOptionList::AppendUintL(TUint& aUint, const TDesC& aLongName)
       
   629 	{
       
   630 	iOptions.AppendL(TCommandOption(KValueTypeUint, &aUint, aLongName));
       
   631 	}
       
   632 
       
   633 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint>& aUints, const TDesC& aLongName)
       
   634 	{
       
   635 	iOptions.AppendL(TCommandOption(KValueTypeUint | KValueTypeFlagMultiple, &aUints, aLongName));
       
   636 	}
       
   637 
       
   638 EXPORT_C void RCommandOptionList::AppendUintL(TUint64& aUint, const TDesC& aLongName)
       
   639 	{
       
   640 	iOptions.AppendL(TCommandOption(KValueTypeUint64, &aUint, aLongName));
       
   641 	}
       
   642 
       
   643 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint64>& aUints, const TDesC& aLongName)
       
   644 	{
       
   645 	iOptions.AppendL(TCommandOption(KValueTypeUint64 | KValueTypeFlagMultiple, &aUints, aLongName));
       
   646 	}
       
   647 
       
   648 EXPORT_C void RCommandOptionList::AppendRealL(TReal64& aReal, const TDesC& aLongName)
       
   649 	{
       
   650 	iOptions.AppendL(TCommandOption(KValueTypeReal, &aReal, aLongName));
       
   651 	}
       
   652 
       
   653 EXPORT_C void RCommandOptionList::AppendRealL(RArray<TReal64>& aReals, const TDesC& aLongName)
       
   654 	{
       
   655 	iOptions.AppendL(TCommandOption(KValueTypeReal | KValueTypeFlagMultiple, &aReals, aLongName));
       
   656 	}
       
   657 
       
   658 EXPORT_C void RCommandOptionList::AppendStringL(HBufC*& aBuf, const TDesC& aLongName)
       
   659 	{
       
   660 	iOptions.AppendL(TCommandOption(KValueTypeString, &aBuf, aLongName));
       
   661 	}
       
   662 
       
   663 EXPORT_C void RCommandOptionList::AppendStringL(RPointerArray<HBufC>& aBufs, const TDesC& aLongName)
       
   664 	{
       
   665 	iOptions.AppendL(TCommandOption(KValueTypeString | KValueTypeFlagMultiple, &aBufs, aLongName));
       
   666 	}
       
   667 
       
   668 EXPORT_C void RCommandOptionList::AppendFileNameL(TFileName2& aFileName, const TDesC& aLongName)
       
   669 	{
       
   670 	iOptions.AppendL(TCommandOption(KValueTypeFileName, &aFileName, aLongName));
       
   671 	}
       
   672 
       
   673 EXPORT_C void RCommandOptionList::AppendFileNameL(RArray<TFileName2>& aFileNames, const TDesC& aLongName)
       
   674 	{
       
   675 	iOptions.AppendL(TCommandOption(KValueTypeFileName | KValueTypeFlagMultiple, &aFileNames, aLongName));
       
   676 	}
       
   677 
       
   678 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, const TDesC& aLongName)
       
   679 	{
       
   680 	iOptions.AppendL(TCommandOption(KValueTypeEnum, &aEnum, aLongName));
       
   681 	}
       
   682 
       
   683 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, const TDesC& aLongName, const TDesC& aCommaSeparatedValueList)
       
   684 	{
       
   685 	TCommandOption opt(KValueTypeEnum, &aEnum, aLongName);
       
   686 	opt.SetEnumValues(TEnum(aCommaSeparatedValueList));
       
   687 	iOptions.AppendL(opt);
       
   688 	}
       
   689 
       
   690 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aLongName)
       
   691 	{
       
   692 	iOptions.AppendL(TCommandOption(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aLongName));
       
   693 	}
       
   694 
       
   695 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aLongName, const TDesC& aCommaSeparatedValueList)
       
   696 	{
       
   697 	TCommandOption opt(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aLongName);
       
   698 	opt.SetEnumValues(TEnum(aCommaSeparatedValueList));
       
   699 	iOptions.AppendL(opt);
       
   700 	}
       
   701 
       
   702 EXPORT_C void RCommandOptionList::AppendBoolL(TBool& aBool, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   703 	{
       
   704 	TCommandOption option(KValueTypeBool | aFlags, &aBool, aShortName, aLongName, aDescription, aEnvVar);
       
   705 	Validate(option);
       
   706 	iOptions.AppendL(option);
       
   707 	}
       
   708 
       
   709 EXPORT_C void RCommandOptionList::AppendBoolL(RArray<TBool>& aBools, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   710 	{
       
   711 	TCommandOption option(KValueTypeBool | KValueTypeFlagMultiple | aFlags, &aBools, aShortName, aLongName, aDescription, aEnvVar);
       
   712 	Validate(option);
       
   713 	iOptions.AppendL(option);
       
   714 	}
       
   715 
       
   716 EXPORT_C void RCommandOptionList::AppendIntL(TInt& aInt, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   717 	{
       
   718 	TCommandOption option(KValueTypeInt | aFlags, &aInt, aShortName, aLongName, aDescription, aEnvVar);
       
   719 	Validate(option);
       
   720 	iOptions.AppendL(option);
       
   721 	}
       
   722 
       
   723 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt>& aInts, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   724 	{
       
   725 	TCommandOption option(KValueTypeInt | KValueTypeFlagMultiple | aFlags, &aInts, aShortName, aLongName, aDescription, aEnvVar);
       
   726 	Validate(option);
       
   727 	iOptions.AppendL(option);
       
   728 	}
       
   729 
       
   730 EXPORT_C void RCommandOptionList::AppendIntL(TInt64& aInt, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   731 	{
       
   732 	TCommandOption option(KValueTypeInt64 | aFlags, &aInt, aShortName, aLongName, aDescription, aEnvVar);
       
   733 	Validate(option);
       
   734 	iOptions.AppendL(option);
       
   735 	}
       
   736 
       
   737 EXPORT_C void RCommandOptionList::AppendIntL(RArray<TInt64>& aInts, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   738 	{
       
   739 	TCommandOption option(KValueTypeInt64 | KValueTypeFlagMultiple | aFlags, &aInts, aShortName, aLongName, aDescription, aEnvVar);
       
   740 	Validate(option);
       
   741 	iOptions.AppendL(option);
       
   742 	}
       
   743 
       
   744 EXPORT_C void RCommandOptionList::AppendUintL(TUint& aUint, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   745 	{
       
   746 	TCommandOption option(KValueTypeUint | aFlags, &aUint, aShortName, aLongName, aDescription, aEnvVar);
       
   747 	Validate(option);
       
   748 	iOptions.AppendL(option);
       
   749 	}
       
   750 
       
   751 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint>& aUints, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   752 	{
       
   753 	TCommandOption option(KValueTypeUint | KValueTypeFlagMultiple | aFlags, &aUints, aShortName, aLongName, aDescription, aEnvVar);
       
   754 	Validate(option);
       
   755 	iOptions.AppendL(option);
       
   756 	}
       
   757 
       
   758 EXPORT_C void RCommandOptionList::AppendUintL(TUint64& aUint, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   759 	{
       
   760 	TCommandOption option(KValueTypeUint64 | aFlags, &aUint, aShortName, aLongName, aDescription, aEnvVar);
       
   761 	Validate(option);
       
   762 	iOptions.AppendL(option);
       
   763 	}
       
   764 
       
   765 EXPORT_C void RCommandOptionList::AppendUintL(RArray<TUint64>& aUints, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   766 	{
       
   767 	TCommandOption option(KValueTypeUint64 | KValueTypeFlagMultiple | aFlags, &aUints, aShortName, aLongName, aDescription, aEnvVar);
       
   768 	Validate(option);
       
   769 	iOptions.AppendL(option);
       
   770 	}
       
   771 
       
   772 EXPORT_C void RCommandOptionList::AppendRealL(TReal64& aReal, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   773 	{
       
   774 	TCommandOption option(KValueTypeReal | aFlags, &aReal, aShortName, aLongName, aDescription, aEnvVar);
       
   775 	Validate(option);
       
   776 	iOptions.AppendL(option);
       
   777 	}
       
   778 
       
   779 EXPORT_C void RCommandOptionList::AppendRealL(RArray<TReal64>& aReals, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   780 	{
       
   781 	TCommandOption option(KValueTypeReal | KValueTypeFlagMultiple | aFlags, &aReals, aShortName, aLongName, aDescription, aEnvVar);
       
   782 	Validate(option);
       
   783 	iOptions.AppendL(option);
       
   784 	}
       
   785 
       
   786 EXPORT_C void RCommandOptionList::AppendStringL(HBufC*& aBuf, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   787 	{
       
   788 	TCommandOption option(KValueTypeString | aFlags, &aBuf, aShortName, aLongName, aDescription, aEnvVar);
       
   789 	Validate(option);
       
   790 	iOptions.AppendL(option);
       
   791 	}
       
   792 
       
   793 EXPORT_C void RCommandOptionList::AppendStringL(RPointerArray<HBufC>& aBufs, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   794 	{
       
   795 	TCommandOption option(KValueTypeString | KValueTypeFlagMultiple | aFlags, &aBufs, aShortName, aLongName, aDescription, aEnvVar);
       
   796 	Validate(option);
       
   797 	iOptions.AppendL(option);
       
   798 	}
       
   799 
       
   800 EXPORT_C void RCommandOptionList::AppendFileNameL(TFileName2& aFileName, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   801 	{
       
   802 	TCommandOption option(KValueTypeFileName | aFlags, &aFileName, aShortName, aLongName, aDescription, aEnvVar);
       
   803 	Validate(option);
       
   804 	iOptions.AppendL(option);
       
   805 	}
       
   806 
       
   807 EXPORT_C void RCommandOptionList::AppendFileNameL(RArray<TFileName2>& aFileNames, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
   808 	{
       
   809 	TCommandOption option(KValueTypeFileName | KValueTypeFlagMultiple | aFlags, &aFileNames, aShortName, aLongName, aDescription, aEnvVar);
       
   810 	Validate(option);
       
   811 	iOptions.AppendL(option);
       
   812 	}
       
   813 
       
   814 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar)
       
   815 	{
       
   816 	TCommandOption option(&aEnum, KValueTypeEnum | aFlags, aCommaSeparatedValueList, KNullDesC, aShortName, aLongName, aDescription, aEnvVar);
       
   817 	Validate(option);
       
   818 	iOptions.AppendL(option);
       
   819 	}
       
   820 
       
   821 EXPORT_C void RCommandOptionList::AppendEnumL(TInt& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar)
       
   822 	{
       
   823 	TCommandOption option(&aEnum, KValueTypeEnum | aFlags, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aShortName, aLongName, aDescription, aEnvVar);
       
   824 	Validate(option);
       
   825 	iOptions.AppendL(option);
       
   826 	}
       
   827 
       
   828 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar)
       
   829 	{
       
   830 	TCommandOption option(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aCommaSeparatedValueList, KNullDesC, aShortName, aLongName, aDescription, aEnvVar);
       
   831 	Validate(option);
       
   832 	iOptions.AppendL(option);
       
   833 	}
       
   834 
       
   835 EXPORT_C void RCommandOptionList::AppendEnumL(RArray<TInt>& aEnum, TChar aShortName, const TDesC& aLongName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar)
       
   836 	{
       
   837 	TCommandOption option(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aShortName, aLongName, aDescription, aEnvVar);
       
   838 	Validate(option);
       
   839 	iOptions.AppendL(option);
       
   840 	}
       
   841 
       
   842 void RCommandOptionList::Validate(const TCommandOption& aOption)
       
   843 	{
       
   844 	__ASSERT_ALWAYS(!(aOption.ValueType() & KValueTypeFlagLast), Panic(EOptionTaggedAsLast));
       
   845 	__ASSERT_ALWAYS((aOption.ShortName() == 0) || (FindShort(aOption.ShortName()) == KErrNotFound), Panic(EDuplicateShortOptionName));
       
   846 	TInt pos = Find(aOption.Name());
       
   847 	if (pos >= 0)
       
   848 		{
       
   849 		iOptions.Remove(pos); // Allow a newly added option of the same long name as an existing one to replace it. Primarily of use in .cif files via the "==include" directive to support command class hierarchies.
       
   850 		}
       
   851 	}
       
   852 
       
   853 EXPORT_C TInt RCommandOptionList::Count() const
       
   854 	{
       
   855 	return iOptions.Count();
       
   856 	}
       
   857 
       
   858 EXPORT_C TCommandOption& RCommandOptionList::operator[](TInt aIndex)
       
   859 	{
       
   860 	return iOptions[aIndex];
       
   861 	}
       
   862 
       
   863 EXPORT_C const TCommandOption& RCommandOptionList::operator[](TInt aIndex) const
       
   864 	{
       
   865 	return iOptions[aIndex];
       
   866 	}
       
   867 
       
   868 TInt RCommandOptionList::FindShort(TChar aShortName) const
       
   869 	{
       
   870 	const TInt count = Count();
       
   871 	for (TInt i = 0; i < count; ++i)
       
   872 		{
       
   873 		if (iOptions[i].ShortName() == aShortName)
       
   874 			{
       
   875 			return i;
       
   876 			}
       
   877 		}
       
   878 	return KErrNotFound;
       
   879 	}
       
   880 
       
   881 TInt RCommandOptionList::Find(const TDesC& aLongName) const
       
   882 	{
       
   883 	const TInt count = Count();
       
   884 	for (TInt i = 0; i < count; ++i)
       
   885 		{
       
   886 		if (iOptions[i].Name() == aLongName)
       
   887 			{
       
   888 			return i;
       
   889 			}
       
   890 		}
       
   891 	return KErrNotFound;
       
   892 	}
       
   893 
       
   894 EXPORT_C TBool RCommandOptionList::IsPresent(void* aValuePointer) const
       
   895 	{
       
   896 	const TInt count = Count();
       
   897 	for (TInt i = 0; i < count; ++i)
       
   898 		{
       
   899 		if (iOptions[i].ValuePtr() == aValuePointer)
       
   900 			{
       
   901 			return iOptions[i].IsSet();
       
   902 			}
       
   903 		}
       
   904 	return EFalse;
       
   905 	}
       
   906 	
       
   907 EXPORT_C TPtrC RCommandOptionList::AsString(void* aValuePointer) const
       
   908 	{
       
   909 	const TInt count = Count();
       
   910 	for (TInt i = 0; i < count; ++i)
       
   911 		{
       
   912 		if (iOptions[i].ValuePtr() == aValuePointer)
       
   913 			{
       
   914 			return iOptions[i].AsString();
       
   915 			}
       
   916 		}
       
   917 	return KNullDesC();
       
   918 	}
       
   919 
       
   920 
       
   921 //
       
   922 // TCommandArgument.
       
   923 //
       
   924 
       
   925 TCommandArgument::TCommandArgument(TUint aValueType, void* aValuePointer, const TDesC& aName)
       
   926 	: TValue(aValueType, aValuePointer, aName)
       
   927 	{
       
   928 	}
       
   929 
       
   930 TCommandArgument::TCommandArgument(TUint aValueType, void* aValuePointer, const TDesC& aName, const TDesC& aDescription, const TDesC& aEnvVar)
       
   931 	: TValue(aValueType, aValuePointer, aName, aDescription, aEnvVar)
       
   932 	{
       
   933 	}
       
   934 
       
   935 TCommandArgument::TCommandArgument(void* aValuePointer, TUint aValueType, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, const TDesC& aEnvVar)
       
   936 	: TValue(aValueType, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aValuePointer, aName, aDescription, aEnvVar)
       
   937 	{
       
   938 	}
       
   939 
       
   940 TBool TCommandArgument::IsOptional() const
       
   941 	{
       
   942 	return ValueType() & KValueTypeFlagOptional;
       
   943 	}
       
   944 
       
   945 TBool TCommandArgument::IsLast() const
       
   946 	{
       
   947 	return ValueType() & KValueTypeFlagLast;
       
   948 	}
       
   949 
       
   950 
       
   951 //
       
   952 // RCommandArgumentList.
       
   953 //
       
   954 
       
   955 void RCommandArgumentList::Close()
       
   956 	{
       
   957 	iArguments.Close();
       
   958 	}
       
   959 
       
   960 EXPORT_C void RCommandArgumentList::AppendIntL(TInt& aInt, const TDesC& aName)
       
   961 	{
       
   962 	iArguments.AppendL(TCommandArgument(KValueTypeInt, &aInt, aName));
       
   963 	}
       
   964 
       
   965 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt>& aInts, const TDesC& aName)
       
   966 	{
       
   967 	iArguments.AppendL(TCommandArgument(KValueTypeInt | KValueTypeFlagMultiple, &aInts, aName));
       
   968 	}
       
   969 
       
   970 EXPORT_C void RCommandArgumentList::AppendIntL(TInt64& aInt, const TDesC& aName)
       
   971 	{
       
   972 	iArguments.AppendL(TCommandArgument(KValueTypeInt64, &aInt, aName));
       
   973 	}
       
   974 
       
   975 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt64>& aInts, const TDesC& aName)
       
   976 	{
       
   977 	iArguments.AppendL(TCommandArgument(KValueTypeInt64 | KValueTypeFlagMultiple, &aInts, aName));
       
   978 	}
       
   979 
       
   980 EXPORT_C void RCommandArgumentList::AppendUintL(TUint& aUint, const TDesC& aName)
       
   981 	{
       
   982 	iArguments.AppendL(TCommandArgument(KValueTypeUint, &aUint, aName));
       
   983 	}
       
   984 
       
   985 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint>& aUints, const TDesC& aName)
       
   986 	{
       
   987 	iArguments.AppendL(TCommandArgument(KValueTypeUint | KValueTypeFlagMultiple, &aUints, aName));
       
   988 	}
       
   989 
       
   990 EXPORT_C void RCommandArgumentList::AppendUintL(TUint64& aUint, const TDesC& aName)
       
   991 	{
       
   992 	iArguments.AppendL(TCommandArgument(KValueTypeUint64, &aUint, aName));
       
   993 	}
       
   994 
       
   995 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint64>& aUints, const TDesC& aName)
       
   996 	{
       
   997 	iArguments.AppendL(TCommandArgument(KValueTypeUint64 | KValueTypeFlagMultiple, &aUints, aName));
       
   998 	}
       
   999 
       
  1000 EXPORT_C void RCommandArgumentList::AppendRealL(TReal64& aReal, const TDesC& aName)
       
  1001 	{
       
  1002 	iArguments.AppendL(TCommandArgument(KValueTypeReal, &aReal, aName));
       
  1003 	}
       
  1004 
       
  1005 EXPORT_C void RCommandArgumentList::AppendRealL(RArray<TReal64>& aReals, const TDesC& aName)
       
  1006 	{
       
  1007 	iArguments.AppendL(TCommandArgument(KValueTypeReal | KValueTypeFlagMultiple, &aReals, aName));
       
  1008 	}
       
  1009 
       
  1010 EXPORT_C void RCommandArgumentList::AppendStringL(HBufC*& aBuf, const TDesC& aName)
       
  1011 	{
       
  1012 	iArguments.AppendL(TCommandArgument(KValueTypeString, &aBuf, aName));
       
  1013 	}
       
  1014 
       
  1015 EXPORT_C void RCommandArgumentList::AppendStringL(RPointerArray<HBufC>& aBufs, const TDesC& aName)
       
  1016 	{
       
  1017 	iArguments.AppendL(TCommandArgument(KValueTypeString | KValueTypeFlagMultiple, &aBufs, aName));
       
  1018 	}
       
  1019 
       
  1020 EXPORT_C void RCommandArgumentList::AppendFileNameL(TFileName2& aFileName, const TDesC& aName)
       
  1021 	{
       
  1022 	iArguments.AppendL(TCommandArgument(KValueTypeFileName, &aFileName, aName));
       
  1023 	}
       
  1024 
       
  1025 EXPORT_C void RCommandArgumentList::AppendFileNameL(RArray<TFileName2>& aFileNames, const TDesC& aName)
       
  1026 	{
       
  1027 	iArguments.AppendL(TCommandArgument(KValueTypeFileName | KValueTypeFlagMultiple, &aFileNames, aName));
       
  1028 	}
       
  1029 
       
  1030 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName)
       
  1031 	{
       
  1032 	iArguments.AppendL(TCommandArgument(KValueTypeEnum, &aEnum, aName));
       
  1033 	}
       
  1034 
       
  1035 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName, const TDesC& aCommaSeparatedValueList)
       
  1036 	{
       
  1037 	TCommandArgument arg(KValueTypeEnum, &aEnum, aName);
       
  1038 	arg.SetEnumValues(TEnum(aCommaSeparatedValueList));
       
  1039 	iArguments.AppendL(arg);
       
  1040 	}
       
  1041 
       
  1042 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName)
       
  1043 	{
       
  1044 	iArguments.AppendL(TCommandArgument(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aName));
       
  1045 	}
       
  1046 
       
  1047 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName, const TDesC& aCommaSeparatedValueList)
       
  1048 	{
       
  1049 	TCommandArgument arg(KValueTypeEnum | KValueTypeFlagMultiple, &aEnum, aName);
       
  1050 	arg.SetEnumValues(TEnum(aCommaSeparatedValueList));
       
  1051 	iArguments.AppendL(arg);
       
  1052 	}
       
  1053 
       
  1054 EXPORT_C void RCommandArgumentList::AppendIntL(TInt& aInt, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1055 	{
       
  1056 	TCommandArgument argument(KValueTypeInt | aFlags, &aInt, aName, aDescription, aEnvVar);
       
  1057 	Validate(argument);
       
  1058 	iArguments.AppendL(argument);
       
  1059 	}
       
  1060 
       
  1061 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt>& aInts, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1062 	{
       
  1063 	TCommandArgument argument(KValueTypeInt | KValueTypeFlagMultiple | aFlags, &aInts, aName, aDescription, aEnvVar);
       
  1064 	Validate(argument);
       
  1065 	iArguments.AppendL(argument);
       
  1066 	}
       
  1067 
       
  1068 EXPORT_C void RCommandArgumentList::AppendIntL(TInt64& aInt, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1069 	{
       
  1070 	TCommandArgument argument(KValueTypeInt64 | aFlags, &aInt, aName, aDescription, aEnvVar);
       
  1071 	Validate(argument);
       
  1072 	iArguments.AppendL(argument);
       
  1073 	}
       
  1074 
       
  1075 EXPORT_C void RCommandArgumentList::AppendIntL(RArray<TInt64>& aInts, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1076 	{
       
  1077 	TCommandArgument argument(KValueTypeInt64 | KValueTypeFlagMultiple | aFlags, &aInts, aName, aDescription, aEnvVar);
       
  1078 	Validate(argument);
       
  1079 	iArguments.AppendL(argument);
       
  1080 	}
       
  1081 
       
  1082 EXPORT_C void RCommandArgumentList::AppendUintL(TUint& aUint, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1083 	{
       
  1084 	TCommandArgument argument(KValueTypeUint | aFlags, &aUint, aName, aDescription, aEnvVar);
       
  1085 	Validate(argument);
       
  1086 	iArguments.AppendL(argument);
       
  1087 	}
       
  1088 
       
  1089 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint>& aUints, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1090 	{
       
  1091 	TCommandArgument argument(KValueTypeUint | KValueTypeFlagMultiple | aFlags, &aUints, aName, aDescription, aEnvVar);
       
  1092 	Validate(argument);
       
  1093 	iArguments.AppendL(argument);
       
  1094 	}
       
  1095 
       
  1096 EXPORT_C void RCommandArgumentList::AppendUintL(TUint64& aUint, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1097 	{
       
  1098 	TCommandArgument argument(KValueTypeUint64 | aFlags, &aUint, aName, aDescription, aEnvVar);
       
  1099 	Validate(argument);
       
  1100 	iArguments.AppendL(argument);
       
  1101 	}
       
  1102 
       
  1103 EXPORT_C void RCommandArgumentList::AppendUintL(RArray<TUint64>& aUints, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1104 	{
       
  1105 	TCommandArgument argument(KValueTypeUint64 | KValueTypeFlagMultiple | aFlags, &aUints, aName, aDescription, aEnvVar);
       
  1106 	Validate(argument);
       
  1107 	iArguments.AppendL(argument);
       
  1108 	}
       
  1109 
       
  1110 EXPORT_C void RCommandArgumentList::AppendRealL(TReal64& aReal, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1111 	{
       
  1112 	TCommandArgument argument(KValueTypeReal | aFlags, &aReal, aName, aDescription, aEnvVar);
       
  1113 	Validate(argument);
       
  1114 	iArguments.AppendL(argument);
       
  1115 	}
       
  1116 
       
  1117 EXPORT_C void RCommandArgumentList::AppendRealL(RArray<TReal64>& aReals, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1118 	{
       
  1119 	TCommandArgument argument(KValueTypeReal | KValueTypeFlagMultiple | aFlags, &aReals, aName, aDescription, aEnvVar);
       
  1120 	Validate(argument);
       
  1121 	iArguments.AppendL(argument);
       
  1122 	}
       
  1123 
       
  1124 EXPORT_C void RCommandArgumentList::AppendStringL(HBufC*& aBuf, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1125 	{
       
  1126 	TCommandArgument argument(KValueTypeString | aFlags, &aBuf, aName, aDescription, aEnvVar);
       
  1127 	Validate(argument);
       
  1128 	iArguments.AppendL(argument);
       
  1129 	}
       
  1130 
       
  1131 EXPORT_C void RCommandArgumentList::AppendStringL(RPointerArray<HBufC>& aBufs, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1132 	{
       
  1133 	TCommandArgument argument(KValueTypeString | KValueTypeFlagMultiple | aFlags, &aBufs, aName, aDescription, aEnvVar);
       
  1134 	Validate(argument);
       
  1135 	iArguments.AppendL(argument);
       
  1136 	}
       
  1137 
       
  1138 EXPORT_C void RCommandArgumentList::AppendFileNameL(TFileName2& aFileName, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1139 	{
       
  1140 	TCommandArgument argument(KValueTypeFileName | aFlags, &aFileName, aName, aDescription, aEnvVar);
       
  1141 	Validate(argument);
       
  1142 	iArguments.AppendL(argument);
       
  1143 	}
       
  1144 
       
  1145 EXPORT_C void RCommandArgumentList::AppendFileNameL(RArray<TFileName2>& aFileNames, const TDesC& aName, const TDesC& aDescription, TUint aFlags, const TDesC& aEnvVar)
       
  1146 	{
       
  1147 	TCommandArgument argument(KValueTypeFileName | KValueTypeFlagMultiple | aFlags, &aFileNames, aName, aDescription, aEnvVar);
       
  1148 	Validate(argument);
       
  1149 	iArguments.AppendL(argument);
       
  1150 	}
       
  1151 
       
  1152 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar)
       
  1153 	{
       
  1154 	TCommandArgument argument(&aEnum, KValueTypeEnum | aFlags, aName, aDescription, aCommaSeparatedValueList, KNullDesC, aEnvVar);
       
  1155 	Validate(argument);
       
  1156 	iArguments.AppendL(argument);
       
  1157 	}
       
  1158 
       
  1159 EXPORT_C void RCommandArgumentList::AppendEnumL(TInt& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar)
       
  1160 	{
       
  1161 	TCommandArgument argument(&aEnum, KValueTypeEnum | aFlags, aName, aDescription, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aEnvVar);
       
  1162 	Validate(argument);
       
  1163 	iArguments.AppendL(argument);
       
  1164 	}
       
  1165 
       
  1166 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, TUint aFlags, const TDesC& aEnvVar)
       
  1167 	{
       
  1168 	TCommandArgument argument(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aName, aDescription, aCommaSeparatedValueList, KNullDesC, aEnvVar);
       
  1169 	Validate(argument);
       
  1170 	iArguments.AppendL(argument);
       
  1171 	}
       
  1172 
       
  1173 EXPORT_C void RCommandArgumentList::AppendEnumL(RArray<TInt>& aEnum, const TDesC& aName, const TDesC& aDescription, const TDesC& aCommaSeparatedValueList, const TDesC& aCommaSeparatedDescriptionList, TUint aFlags, const TDesC& aEnvVar)
       
  1174 	{
       
  1175 	TCommandArgument argument(&aEnum, KValueTypeEnum | KValueTypeFlagMultiple | aFlags, aName, aDescription, aCommaSeparatedValueList, aCommaSeparatedDescriptionList, aEnvVar);
       
  1176 	Validate(argument);
       
  1177 	iArguments.AppendL(argument);
       
  1178 	}
       
  1179 
       
  1180 EXPORT_C TBool RCommandArgumentList::IsPresent(TInt aIndex) const
       
  1181 	{
       
  1182 	__ASSERT_ALWAYS((aIndex >= 0) && (aIndex < Count()), Panic(EInvalidArgumentIndex));	
       
  1183 	return iArguments[aIndex].IsSet();
       
  1184 	}
       
  1185 
       
  1186 EXPORT_C TBool RCommandArgumentList::IsPresent(void* aValuePointer) const
       
  1187 	{
       
  1188 	const TInt count = Count();
       
  1189 	for (TInt i = 0; i < count; ++i)
       
  1190 		{
       
  1191 		if (iArguments[i].ValuePtr() == aValuePointer)
       
  1192 			{
       
  1193 			return iArguments[i].IsSet();
       
  1194 			}
       
  1195 		}
       
  1196 	return EFalse;
       
  1197 	}
       
  1198 
       
  1199 void RCommandArgumentList::Validate(const TCommandArgument& aArgument)
       
  1200 	{
       
  1201 	TUint valueType = aArgument.ValueType();
       
  1202 	__ASSERT_ALWAYS(!(valueType & KValueTypeFlagLast) || (valueType & KValueTypeString), Panic(ELastArgNotStringType));
       
  1203 	__ASSERT_ALWAYS(!(valueType & KValueTypeFlagLast) || !(valueType & KValueTypeFlagMultiple), Panic(ELastArgMultiple));
       
  1204 	if (iArguments.Count() > 0)
       
  1205 		{
       
  1206 		__ASSERT_ALWAYS(!iArguments[iArguments.Count() - 1].AcceptsMultiple(), Panic(EArgumentFollowsMultipleArgument));
       
  1207 		__ASSERT_ALWAYS(valueType & KValueTypeFlagOptional || !iArguments[iArguments.Count() - 1].IsOptional(), Panic(ENonOptionalArgumentFollowsOptionalArgument));
       
  1208 		}
       
  1209 	TInt pos = Find(aArgument.Name());
       
  1210 	if (pos >= 0)
       
  1211 		{
       
  1212 		iArguments.Remove(pos); // Allow a newly added argument of the same long name as an existing one to replace it. Primarily of use in .cif files via the "==include" directive to support command class hierarchies.
       
  1213 		}
       
  1214 	}
       
  1215 
       
  1216 EXPORT_C TInt RCommandArgumentList::Count() const
       
  1217 	{
       
  1218 	return iArguments.Count();
       
  1219 	}
       
  1220 
       
  1221 TCommandArgument& RCommandArgumentList::operator[](TInt aIndex)
       
  1222 	{
       
  1223 	return iArguments[aIndex];
       
  1224 	}
       
  1225 
       
  1226 EXPORT_C const TCommandArgument& RCommandArgumentList::operator[](TInt aIndex) const
       
  1227 	{
       
  1228 	return iArguments[aIndex];
       
  1229 	}
       
  1230 
       
  1231 EXPORT_C TBool RCommandArgumentList::AllSet() const
       
  1232 	{
       
  1233 	TBool allSet(ETrue);
       
  1234 	const TInt count = Count();
       
  1235 	for (TInt i = 0; i < count; ++i)
       
  1236 		{
       
  1237 		const TCommandArgument& thisArgument = iArguments[i];
       
  1238 		if (!thisArgument.IsOptional() && !thisArgument.IsSet() && !(thisArgument.ValueType() == (KValueTypeFileName | KValueTypeFlagMultiple))) // Note, allow multiple file names because "dir\*" might not produces any matches, but we don't want to report that as a syntax error. Instead expect commands to cope with zero file names.
       
  1239 			{
       
  1240 			allSet = EFalse;
       
  1241 			break;
       
  1242 			}
       
  1243 		}
       
  1244 	return allSet;
       
  1245 	}
       
  1246 
       
  1247 TInt RCommandArgumentList::Find(const TDesC& aName) const
       
  1248 	{
       
  1249 	const TInt count = Count();
       
  1250 	for (TInt i = 0; i < count; ++i)
       
  1251 		{
       
  1252 		if (iArguments[i].Name() == aName)
       
  1253 			{
       
  1254 			return i;
       
  1255 			}
       
  1256 		}
       
  1257 	return KErrNotFound;
       
  1258 	}
       
  1259 
       
  1260 EXPORT_C TPtrC RCommandArgumentList::AsString(void* aValuePointer) const
       
  1261 	{
       
  1262 	for (TInt i=0; i<Count(); ++i)
       
  1263 		{
       
  1264 		if (iArguments[i].ValuePtr() == aValuePointer)
       
  1265 			{
       
  1266 			return iArguments[i].AsString();
       
  1267 			}
       
  1268 		}
       
  1269 	return KNullDesC();
       
  1270 	}
       
  1271 
       
  1272 
       
  1273 //
       
  1274 // CCommandBase.
       
  1275 //
       
  1276 
       
  1277 EXPORT_C TInt CCommandBase::RunCommand()
       
  1278 	{
       
  1279 	TRAPD(err, RunCommandL());
       
  1280 	return err;
       
  1281 	}
       
  1282 
       
  1283 EXPORT_C void CCommandBase::RunCommandL()
       
  1284 	{
       
  1285 	RunCommandL(NULL, NULL);
       
  1286 	}
       
  1287 
       
  1288 EXPORT_C TInt CCommandBase::RunCommand(const TDesC* aCommandLine, CEnvironment* aEnv)
       
  1289 	{
       
  1290 	TRAPD(err, RunCommandL(aCommandLine, aEnv));
       
  1291 	return err;
       
  1292 	}
       
  1293 
       
  1294 NONSHARABLE_CLASS(TExitController) : public MCommandBaseObserver
       
  1295 	{
       
  1296 public:
       
  1297 	TExitController();
       
  1298 	TBool IsComplete() const;
       
  1299 	TInt CompletionError() const;
       
  1300 	void WaitForCompletion();
       
  1301 private:
       
  1302 	virtual void HandleCommandComplete(CCommandBase& aCommand, TInt aError);
       
  1303 private:
       
  1304 	TBool iSchedulerStarted;
       
  1305 	TBool iComplete;
       
  1306 	TInt iCompletionError;
       
  1307 	};
       
  1308 
       
  1309 TExitController::TExitController()
       
  1310 	: iSchedulerStarted(EFalse), iComplete(EFalse), iCompletionError(KErrNone)
       
  1311 	{
       
  1312 	}
       
  1313 
       
  1314 TBool TExitController::IsComplete() const
       
  1315 	{
       
  1316 	return iComplete;
       
  1317 	}
       
  1318 
       
  1319 TInt TExitController::CompletionError() const
       
  1320 	{
       
  1321 	return iCompletionError;
       
  1322 	}
       
  1323 
       
  1324 void TExitController::WaitForCompletion()
       
  1325 	{
       
  1326 	iSchedulerStarted = ETrue;
       
  1327 	CActiveScheduler::Start();
       
  1328 	}
       
  1329 
       
  1330 void TExitController::HandleCommandComplete(CCommandBase&, TInt aError)
       
  1331 	{
       
  1332 	iComplete = ETrue;
       
  1333 	iCompletionError = aError;
       
  1334 	if (iSchedulerStarted)
       
  1335 		{
       
  1336 		CActiveScheduler::Stop();
       
  1337 		iSchedulerStarted = EFalse;
       
  1338 		}
       
  1339 	}
       
  1340 
       
  1341 void CCommandBase::CreateHandlesL()
       
  1342 	{
       
  1343 	// This function is called *before* the command line is parsed, so things like iConsoleImplementation and iConsoleSize are not available.
       
  1344 	// UpdateHandlesL is called *after* the command line is parsed to change the handles if necessary.
       
  1345 
       
  1346 	TFullName name;
       
  1347 	LtkUtils::GetFriendlyThreadName(RThread(), name);
       
  1348 	RIoConsole console;
       
  1349 	CleanupClosePushL(console);
       
  1350 
       
  1351 	TInt err = iStdin.Open(iIoSession);
       
  1352 	if (err == KErrNone)
       
  1353 		{
       
  1354 		User::LeaveIfError(iStdout.Open(iIoSession));
       
  1355 		User::LeaveIfError(iStderr.Open(iIoSession));
       
  1356 		}
       
  1357 	else
       
  1358 		{
       
  1359 		console.CreateL(iIoSession, name, TSize(KConsFullScreen, KConsFullScreen), RIoConsole::ELazyCreate);
       
  1360 		DoCreateHandlesL(console, iStdin, iStdout, iStderr);
       
  1361 		}
       
  1362 
       
  1363 	CleanupStack::PopAndDestroy(&console); // Console (if used) will be held open by the read and write handles.
       
  1364 
       
  1365 	if (iFlags & ENotifyStdinChanges)
       
  1366 		{
       
  1367 		iReadChangeNotifier = new(ELeave)CReaderChangeNotifier(*this, iStdin);
       
  1368 		iReadChangeNotifier->Notify();
       
  1369 		}	
       
  1370 	}
       
  1371 
       
  1372 void CCommandBase::UpdateHandlesL()
       
  1373 	{
       
  1374 	TFullName name;
       
  1375 	LtkUtils::GetFriendlyThreadName(RThread(), name);
       
  1376 	RIoConsole console;
       
  1377 	CleanupClosePushL(console);
       
  1378 
       
  1379 	if (iPersistentConsoleName)
       
  1380 		{
       
  1381 		((RIoPersistentConsole&)console).CreateL(iIoSession, *iPersistentConsoleName, (iConsoleTitle == NULL) ? name : *iConsoleTitle);
       
  1382 		}
       
  1383 	else
       
  1384 		{
       
  1385 		TSize size(KConsFullScreen, KConsFullScreen);
       
  1386 		if (iConsoleSize.Count() > 0)
       
  1387 			{
       
  1388 			size.iWidth = iConsoleSize[0];
       
  1389 			}
       
  1390 		if (iConsoleSize.Count() > 1)
       
  1391 			{
       
  1392 			size.iHeight = iConsoleSize[1];
       
  1393 			}
       
  1394 		RIoConsole underlyingConsole;
       
  1395 		underlyingConsole.OpenL(iIoSession, iStdout);
       
  1396 		CleanupClosePushL(underlyingConsole);
       
  1397 		console.CreateL(iIoSession, *iConsoleImplementation, underlyingConsole, (iConsoleTitle == NULL) ? name : *iConsoleTitle, size);
       
  1398 		CleanupStack::PopAndDestroy(&underlyingConsole);
       
  1399 		RIoConsoleReadHandle stdin;
       
  1400 		CleanupClosePushL(stdin);
       
  1401 		RIoConsoleWriteHandle stdout;
       
  1402 		CleanupClosePushL(stdout);
       
  1403 		RIoConsoleWriteHandle stderr;
       
  1404 		CleanupClosePushL(stderr);
       
  1405 		DoCreateHandlesL(console, stdin, stdout, stderr);
       
  1406 		if (iFlags & ENotifyStdinChanges)
       
  1407 			{
       
  1408 			CReaderChangeNotifier* readChangeNotifier = new(ELeave)CReaderChangeNotifier(*this, iStdin);
       
  1409 			delete iReadChangeNotifier;
       
  1410 			iReadChangeNotifier = readChangeNotifier;
       
  1411 			}	
       
  1412 		iStdin.Close();
       
  1413 		iStdin = stdin;
       
  1414 		iStdout.Close();
       
  1415 		iStdout = stdout;
       
  1416 		iStderr.Close();
       
  1417 		iStderr = stderr;
       
  1418 		CleanupStack::Pop(3, &stdin);
       
  1419 		if (iFlags & ENotifyStdinChanges)
       
  1420 			{
       
  1421 			iReadChangeNotifier->Notify();
       
  1422 			}
       
  1423 		}
       
  1424 
       
  1425 	CleanupStack::PopAndDestroy(&console); // Console (if used) will be held open by the read and write handles.
       
  1426 	}
       
  1427 
       
  1428 void CCommandBase::DoCreateHandlesL(RIoConsole& aConsole, RIoConsoleReadHandle& aStdin, RIoConsoleWriteHandle& aStdout, RIoConsoleWriteHandle& aStderr)
       
  1429 	{
       
  1430 	TFullName name;
       
  1431 	LtkUtils::GetFriendlyThreadName(RThread(), name);
       
  1432 
       
  1433 	TName consImpl;
       
  1434 	TInt err = aConsole.Implementation(consImpl);
       
  1435 	if (err != KErrOverflow)
       
  1436 		{
       
  1437 		User::LeaveIfError(err);
       
  1438 		}
       
  1439 	if (consImpl.Right(KDllExt().Length()).CompareF(KDllExt)==0)
       
  1440 		{
       
  1441 		consImpl.SetLength(consImpl.Length() - KDllExt().Length());
       
  1442 		}
       
  1443 	if (name.Length() + consImpl.Length() + 1 > name.MaxLength())
       
  1444 		{
       
  1445 		name.SetLength(name.MaxLength() - (name.Length() + consImpl.Length() + 1));
       
  1446 		}
       
  1447 	name.Insert(0, _L("_"));
       
  1448 	name.Insert(0, consImpl);
       
  1449 
       
  1450 	iIoSession.SetObjectNameL(aConsole.SubSessionHandle(), name);
       
  1451 	
       
  1452 	aStdin.CreateL(iIoSession);
       
  1453 	_LIT(KStdin, "_stdin");
       
  1454 	name.Append(KStdin);
       
  1455 	iIoSession.SetObjectNameL(aStdin.SubSessionHandle(), name);
       
  1456 
       
  1457 	aStdout.CreateL(iIoSession);
       
  1458 	name.Delete(name.Length() - KStdin().Length(), KStdin().Length());
       
  1459 	_LIT(KStdout, "_stdout");
       
  1460 	name.Append(KStdout);
       
  1461 	iIoSession.SetObjectNameL(aStdout.SubSessionHandle(), name);
       
  1462 
       
  1463 	aStderr.CreateL(iIoSession);
       
  1464 	User::LeaveIfError(aStderr.SetIsStdErr(ETrue));
       
  1465 	name.Delete(name.Length() - KStdout().Length(), KStdout().Length());
       
  1466 	_LIT(KStderr, "_stderr");
       
  1467 	name.Append(KStderr);
       
  1468 	iIoSession.SetObjectNameL(aStderr.SubSessionHandle(), name);
       
  1469 
       
  1470 	aConsole.AttachL(aStdin, RIoEndPoint::EForeground);
       
  1471 	aConsole.AttachL(aStdout);
       
  1472 	aConsole.AttachL(aStderr);
       
  1473 
       
  1474 	aStdin.SetUnderlyingConsoleL(aConsole);
       
  1475 	aStdout.SetUnderlyingConsoleL(aConsole);
       
  1476 	aStderr.SetUnderlyingConsoleL(aConsole);
       
  1477 	}
       
  1478 
       
  1479 EXPORT_C void CCommandBase::RunCommandL(const TDesC* aCommandLine, CEnvironment* aEnv)
       
  1480 	{
       
  1481 	iFlags |= EOwnsHandles;
       
  1482 
       
  1483 	User::LeaveIfError(iIoSession.Connect());
       
  1484 	if (iFlags & ESharableIoSession)
       
  1485 		{
       
  1486 		User::LeaveIfError(iIoSession.ShareAuto());
       
  1487 		}
       
  1488 
       
  1489 	TBool commandLineOnStack(EFalse);
       
  1490 	const TDesC* commandLine = aCommandLine;
       
  1491 	if (aCommandLine == NULL)
       
  1492 		{
       
  1493 		commandLine = ReadCommandLineLC();
       
  1494 		commandLineOnStack = ETrue;
       
  1495 		}
       
  1496 
       
  1497 	CreateEnvironmentL(aEnv);
       
  1498 	CreateHandlesL();
       
  1499 
       
  1500 	TExitController exitController;
       
  1501 	RunCommand(iIoSession, iStdin, iStdout, iStderr, commandLine, iEnv, &exitController);
       
  1502 	if (!exitController.IsComplete())
       
  1503 		{
       
  1504 		exitController.WaitForCompletion();
       
  1505 		}
       
  1506 
       
  1507 	TInt completionError = exitController.CompletionError();
       
  1508 	if (completionError != KErrNone)
       
  1509 		{
       
  1510 		User::Leave(completionError);
       
  1511 		}
       
  1512 
       
  1513 	if (commandLineOnStack)
       
  1514 		{
       
  1515 		CleanupStack::PopAndDestroy((TAny*)commandLine);
       
  1516 		}
       
  1517 	}
       
  1518 
       
  1519 EXPORT_C TInt CCommandBase::RunCommand(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv)
       
  1520 	{
       
  1521 	TExitController exitController;
       
  1522 	RunCommand(aIoSession, aStdin, aStdout, aStderr, aCommandLine, aEnv, &exitController);
       
  1523 	if (exitController.IsComplete())
       
  1524 		{
       
  1525 		return exitController.CompletionError();
       
  1526 		}
       
  1527 	else
       
  1528 		{
       
  1529 		exitController.WaitForCompletion();
       
  1530 		return exitController.CompletionError();
       
  1531 		}
       
  1532 	}
       
  1533 
       
  1534 EXPORT_C void CCommandBase::RunCommandL(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv)
       
  1535 	{
       
  1536 	User::LeaveIfError(RunCommand(aIoSession, aStdin, aStdout, aStderr, aCommandLine, aEnv));
       
  1537 	}
       
  1538 
       
  1539 EXPORT_C void CCommandBase::RunCommand(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv, MCommandBaseObserver* aObserver)
       
  1540 	{
       
  1541 	TRAPD(err, RunCommandL(aIoSession, aStdin, aStdout, aStderr, aCommandLine, aEnv, aObserver));
       
  1542 	if (err)
       
  1543 		{
       
  1544 		Complete(err);
       
  1545 		}
       
  1546 	}
       
  1547 
       
  1548 EXPORT_C TUint CCommandBase::Flags() const
       
  1549 	{
       
  1550 	return (iFlags & KPublicFlagsMask);
       
  1551 	}
       
  1552 
       
  1553 EXPORT_C void CCommandBase::SetFlags(TUint aFlags)
       
  1554 	{
       
  1555 	TUint privateFlags = (iFlags & KPrivateFlagsMask);
       
  1556 	iFlags = (aFlags & KPublicFlagsMask);
       
  1557 	iFlags |= privateFlags;
       
  1558 	if (iFlags & ECompleteOnRunL)
       
  1559 		{
       
  1560 		iFlags |= EManualComplete;
       
  1561 		}
       
  1562 	}
       
  1563 
       
  1564 EXPORT_C void CCommandBase::SetCif(const CCommandInfoFile& aCif)
       
  1565 	{
       
  1566 	ASSERT((iCif == NULL) && !(iFlags & EOwnsCif));
       
  1567 	iCif = &const_cast<CCommandInfoFile&>(aCif);
       
  1568 	}
       
  1569 
       
  1570 EXPORT_C const CCommandInfoFile* CCommandBase::Cif() const
       
  1571 	{
       
  1572 	return iCif;
       
  1573 	}
       
  1574 
       
  1575 void CCommandBase::RunCommandL(RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const TDesC* aCommandLine, CEnvironment* aEnv, MCommandBaseObserver* aObserver)
       
  1576 	{
       
  1577 	iIoSession = aIoSession;
       
  1578 	iStdin = aStdin;
       
  1579 	iStdout = aStdout;
       
  1580 	iStderr = aStderr;
       
  1581 	iObserver = aObserver;
       
  1582 
       
  1583 	CreateEnvironmentL(aEnv);
       
  1584 
       
  1585 	if (aCommandLine)
       
  1586 		{
       
  1587 		RunL(*aCommandLine);
       
  1588 		}
       
  1589 	else
       
  1590 		{
       
  1591 		const TDesC* commandLine = ReadCommandLineLC();
       
  1592 		RunL(*commandLine);
       
  1593 		CleanupStack::PopAndDestroy((TAny*)commandLine);
       
  1594 		}
       
  1595 	}
       
  1596 
       
  1597 void CCommandBase::RunL(const TDesC& aCommandLine)
       
  1598 	{
       
  1599 	TInt err = ParseCommandLine(aCommandLine);
       
  1600 	if (iFlags & ECifReadFailed)
       
  1601 		{
       
  1602 		// No point in trying to display help.
       
  1603 		Complete(err);
       
  1604 		}
       
  1605 	else if (err || iDisplayHelp)
       
  1606 		{
       
  1607 		if (err && !iDisplayHelp)
       
  1608 			{
       
  1609 			DisplayHelpAndComplete(err, _L("Couldn't parse command line"));
       
  1610 			}
       
  1611 		else
       
  1612 			{
       
  1613 			DisplayHelpAndComplete();
       
  1614 			}
       
  1615 		}
       
  1616 	else
       
  1617 		{
       
  1618 		if (iConsoleImplementation || iPersistentConsoleName)
       
  1619 			{
       
  1620 			UpdateHandlesL();
       
  1621 			}
       
  1622 
       
  1623 		TBool deleted(EFalse);
       
  1624 		iDeleted = &deleted;	
       
  1625 		// Note, commands that manually complete may call CCommandBase::Complete from their DoRunL, which in the case 
       
  1626 		// of "local" fshell commands (i.e. ones that run in the context of fshell's thread) will result in the object
       
  1627 		// being deleted. This flag detects this to avoid code later in this function blowing up.
       
  1628 		TRAP(err, DoRunL());
       
  1629 		if (err)
       
  1630 			{
       
  1631 			HandleLeave(err);
       
  1632 			}
       
  1633 		else if (!deleted && !(iFlags & EManualComplete) && !IsActive() && !(iFlags & ECompleted))
       
  1634 			{
       
  1635 			Complete();
       
  1636 			}
       
  1637 		if (!deleted)
       
  1638 			{
       
  1639 			iDeleted = NULL;
       
  1640 			}
       
  1641 		}
       
  1642 	}
       
  1643 
       
  1644 EXPORT_C CCommandBase::CCommandBase()
       
  1645 	: CActive(CActive::EPriorityStandard)
       
  1646 	{
       
  1647 	// These are protected so could be accessed directly, hence can't move
       
  1648 	// The asserts have to be scoped inside a CCommandBase function because the member vars are protected. They don't generate any code.
       
  1649 	__ASSERT_COMPILE(_FOFF(CCommandBase, iOptions) == 7*4);
       
  1650 	__ASSERT_COMPILE(_FOFF(CCommandBase, iArguments) == 15*4);
       
  1651 
       
  1652 	CActiveScheduler::Add(this);
       
  1653 	if (Dll::Tls() == NULL)
       
  1654 		{
       
  1655 		Dll::SetTls(this);
       
  1656 		iFlags |= ETlsSet;
       
  1657 		}
       
  1658 	}
       
  1659 
       
  1660 EXPORT_C CCommandBase::CCommandBase(TUint aFlags)
       
  1661 	: CActive(CActive::EPriorityStandard), iFlags(aFlags)
       
  1662 	{
       
  1663 	CActiveScheduler::Add(this);
       
  1664 	if (Dll::Tls() == NULL)
       
  1665 		{
       
  1666 		Dll::SetTls(this);
       
  1667 		iFlags |= ETlsSet;
       
  1668 		}
       
  1669 
       
  1670 	// Ensure EManualComplete is set if ECompleteOnRunL is.
       
  1671 	SetFlags(Flags());
       
  1672 	}
       
  1673 
       
  1674 EXPORT_C CCommandBase::~CCommandBase()
       
  1675 	{
       
  1676 	delete iReadChangeNotifier;
       
  1677 	delete iCompleter;
       
  1678 	iFs.Close();
       
  1679 	if (iFlags & EOwnsHandles)
       
  1680 		{
       
  1681 		iStderr.Close();
       
  1682 		iStdout.Close();
       
  1683 		iStdin.Close();
       
  1684 		iIoSession.Close();
       
  1685 		}
       
  1686 
       
  1687 	if (iFlags & EOwnsEnv)
       
  1688 		{
       
  1689 		delete iEnv;
       
  1690 		}
       
  1691 	delete iConsoleImplementation;
       
  1692 	delete iConsoleTitle;
       
  1693 	delete iPersistentConsoleName;
       
  1694 	iConsoleSize.Close();
       
  1695 	iOptions.Close();
       
  1696 	iArguments.Close();
       
  1697 	if (iFlags & EOwnsCif)
       
  1698 		{
       
  1699 		delete iCif;
       
  1700 		}
       
  1701 	if (iDeleted)
       
  1702 		{
       
  1703 		*iDeleted = ETrue;
       
  1704 		}
       
  1705 	if (iFlags & ETlsSet)
       
  1706 		{
       
  1707 		Dll::SetTls(NULL);
       
  1708 		}
       
  1709 	}
       
  1710 
       
  1711 EXPORT_C void CCommandBase::BaseConstructL()
       
  1712 	{
       
  1713 	iCompleter = new(ELeave)CCommandCompleter(*this);
       
  1714 	}
       
  1715 
       
  1716 EXPORT_C CEnvironment& CCommandBase::Env()
       
  1717 	{
       
  1718 	__ASSERT_ALWAYS(iEnv, Panic(ENoEnvironment));
       
  1719 	return *iEnv;
       
  1720 	}
       
  1721 
       
  1722 EXPORT_C const CEnvironment& CCommandBase::Env() const
       
  1723 	{
       
  1724 	__ASSERT_ALWAYS(iEnv, Panic(ENoEnvironment));
       
  1725 	return *iEnv;
       
  1726 	}
       
  1727 
       
  1728 void CCommandBase::CompleteCallback(TInt aError)
       
  1729 	{
       
  1730 	Complete(aError);
       
  1731 	}
       
  1732 
       
  1733 EXPORT_C void CCommandBase::Complete()
       
  1734 	{
       
  1735 	Complete(KErrNone);
       
  1736 	}
       
  1737 
       
  1738 EXPORT_C void CCommandBase::Complete(TInt aError)
       
  1739 	{
       
  1740 	__ASSERT_ALWAYS(!(iFlags & ECompleted), Panic(EAlreadyCompleted));
       
  1741 	iFlags |= ECompleted;
       
  1742 	iCompletionReason = aError;
       
  1743 	if (aError < 0)
       
  1744 		{
       
  1745 		RProcess::Rendezvous(aError);
       
  1746 		const TDesC& name = Name();
       
  1747 		PrintError(aError, _L("Unable to run \"%S\""), &name);
       
  1748 		}
       
  1749 	if (iObserver)
       
  1750 		{
       
  1751 		iObserver->HandleCommandComplete(*this, aError);
       
  1752 		}
       
  1753 	}
       
  1754 
       
  1755 EXPORT_C void CCommandBase::Complete(TRefByValue<const TDesC> aFmt, ...)
       
  1756 	{
       
  1757 	VA_LIST list;
       
  1758 	VA_START(list, aFmt);
       
  1759 	TBuf<0x100> buf;
       
  1760 	TOverflowTruncate overflow;
       
  1761 	buf.AppendFormatList(aFmt, list, &overflow);
       
  1762 	VA_END(list);
       
  1763 	iStdout.Write(buf);
       
  1764 	Complete();
       
  1765 	}
       
  1766 
       
  1767 EXPORT_C void CCommandBase::Complete(TInt aError, TRefByValue<const TDesC> aFmt, ...)
       
  1768 	{
       
  1769 	if (iFlags & EErrorReported)
       
  1770 		{
       
  1771 		Complete(aError);
       
  1772 		}
       
  1773 	else
       
  1774 		{
       
  1775 		RProcess::Rendezvous(aError); // This isn't right for thread commands - not sure how to distinguish. Probably won't cause a problem though. (We also rendezvous in Complete(TInt), but to avoid deadlocks in server commands we need to rendezvous before writing anything (in the error case)
       
  1776 		VA_LIST list;
       
  1777 		VA_START(list, aFmt);
       
  1778 		PrintErrorList(aError, aFmt, list);
       
  1779 		Complete(aError);
       
  1780 		VA_END(list);
       
  1781 		}
       
  1782 	}
       
  1783 
       
  1784 EXPORT_C void CCommandBase::CompleteAsync(TInt aError)
       
  1785 	{
       
  1786 	iCompleter->Complete(aError);
       
  1787 	}
       
  1788 
       
  1789 EXPORT_C void CCommandBase::CompleteAsync(TInt aError, TRefByValue<const TDesC> aFmt, ...)
       
  1790 	{
       
  1791 	if (iFlags & EErrorReported)
       
  1792 		{
       
  1793 		iCompleter->Complete(aError);
       
  1794 		}
       
  1795 	else
       
  1796 		{
       
  1797 		VA_LIST list;
       
  1798 		VA_START(list, aFmt);
       
  1799 		TBuf<0x100> buf;
       
  1800 		FormatErrorText(buf, aError, aFmt, list);
       
  1801 		VA_END(list);
       
  1802 		iCompleter->Complete(aError, buf, iStderr);
       
  1803 		}
       
  1804 	}
       
  1805 
       
  1806 EXPORT_C void CCommandBase::ReadL(TDes& aData)
       
  1807 	{
       
  1808 	User::LeaveIfError(iStdin.Read(aData));
       
  1809 	}
       
  1810 
       
  1811 EXPORT_C void CCommandBase::Write(const TDesC& aData)
       
  1812 	{
       
  1813 	iStdout.Write(aData); // Ignore error.
       
  1814 	}
       
  1815 
       
  1816 EXPORT_C void CCommandBase::Printf(TRefByValue<const TDesC> aFmt, ...)
       
  1817 	{
       
  1818 	VA_LIST list;
       
  1819 	VA_START(list, aFmt);
       
  1820 	PrintList(aFmt, list);
       
  1821 	VA_END(list);
       
  1822 	}
       
  1823 
       
  1824 EXPORT_C void CCommandBase::Printf(TRefByValue<const TDesC8> aFmt, ...)
       
  1825 	{
       
  1826 	VA_LIST list;
       
  1827 	VA_START(list, aFmt);
       
  1828 	PrintList(aFmt, list);
       
  1829 	VA_END(list);
       
  1830 	}
       
  1831 
       
  1832 EXPORT_C void CCommandBase::PrintError(TInt aError, TRefByValue<const TDesC> aFmt, ...)
       
  1833 	{
       
  1834 	VA_LIST list;
       
  1835 	VA_START(list, aFmt);
       
  1836 	PrintErrorList(aError, aFmt, list);
       
  1837 	VA_END(list);
       
  1838 	}
       
  1839 
       
  1840 EXPORT_C void CCommandBase::PrintWarning(TRefByValue<const TDesC> aFmt, ...)
       
  1841 	{
       
  1842 	VA_LIST list;
       
  1843 	VA_START(list, aFmt);
       
  1844 	PrintWarningList(aFmt, list);
       
  1845 	VA_END(list);
       
  1846 	}
       
  1847 
       
  1848 EXPORT_C void CCommandBase::PrintList(TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
  1849 	{
       
  1850 	TOverflowTruncate overflow;
       
  1851 	TBuf<0x100> buf;
       
  1852 	buf.AppendFormatList(aFmt, aList, &overflow);
       
  1853 	iStdout.Write(buf);
       
  1854 	}
       
  1855 
       
  1856 EXPORT_C void CCommandBase::PrintList(TRefByValue<const TDesC8> aFmt, VA_LIST& aList)
       
  1857 	{
       
  1858 	TOverflowTruncate8 overflow;
       
  1859 	TBuf8<0x200> buf;
       
  1860 	buf.AppendFormatList(aFmt, aList, &overflow);
       
  1861 	if (buf.Length() > 0x100) buf.SetLength(0x100); // Truncate to half the buffer size so that the call to Expand doesn't panic
       
  1862 	TPtrC wideBuf = buf.Expand();
       
  1863 	iStdout.Write(wideBuf);
       
  1864 	}
       
  1865 
       
  1866 EXPORT_C void CCommandBase::PrintErrorList(TInt aError, TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
  1867 	{
       
  1868 	if (!Stderr().SubSessionHandle())
       
  1869 		{
       
  1870 		// Only can happen if we error during say command line parsing, which occurs before the handles are set up.
       
  1871 		return;
       
  1872 		}
       
  1873 
       
  1874 	if (iSupressingErrors > 0 || ((iFlags & EErrorReported) && !(iFlags & EReportAllErrors)))
       
  1875 		{
       
  1876 		return;
       
  1877 		}
       
  1878 
       
  1879 	CheckNewLine();
       
  1880 	TBuf<0x100> buf;
       
  1881 	FormatErrorText(buf, aError, aFmt, aList);
       
  1882 	iStderr.Write(buf);
       
  1883 	iFlags |= EErrorReported;
       
  1884 	}
       
  1885 
       
  1886 EXPORT_C void CCommandBase::PrintWarningList(TRefByValue<const TDesC> aFmt, VA_LIST& aList)
       
  1887 	{
       
  1888 	if (!Stderr().SubSessionHandle())
       
  1889 		{
       
  1890 		// Only can happen if we error during say command line parsing, which occurs before the handles are set up.
       
  1891 		return;
       
  1892 		}
       
  1893 	CheckNewLine();
       
  1894 	TBuf<0x100> buf;
       
  1895 	FormatWarningText(buf, aFmt, aList);
       
  1896 	iStderr.Write(buf);
       
  1897 	}
       
  1898 
       
  1899 EXPORT_C void CCommandBase::LeaveIfFileExists(const TDesC& aFileName)
       
  1900 	{
       
  1901 	TFileName2 fileName(aFileName);
       
  1902 	if (fileName.Exists(FsL()))
       
  1903 		{
       
  1904 		PrintError(KErrAlreadyExists, _L("\"%S\" already exists"), &aFileName);
       
  1905 		User::Leave(KErrAlreadyExists);
       
  1906 		}
       
  1907 	}
       
  1908 
       
  1909 EXPORT_C void CCommandBase::LeaveIfFileNotFound(const TDesC& aFileName)
       
  1910 	{
       
  1911 	TEntry e;
       
  1912 	TInt err = FsL().Entry(aFileName, e);
       
  1913 	if (err == KErrNotFound)
       
  1914 		{
       
  1915 		PrintError(err, _L("\"%S\" not found"), &aFileName);
       
  1916 		}
       
  1917 	else if (err)
       
  1918 		{
       
  1919 		PrintError(err, _L("Couldn't read \"%S\""), &aFileName);
       
  1920 		}
       
  1921 	User::LeaveIfError(err);
       
  1922 	}
       
  1923 
       
  1924 EXPORT_C RFs& CCommandBase::Fs()
       
  1925 	{
       
  1926 	__ASSERT_ALWAYS(iFs.Handle(), Panic(ERFsNotConnected));
       
  1927 	return iFs;
       
  1928 	}
       
  1929 
       
  1930 EXPORT_C const RFs& CCommandBase::Fs() const
       
  1931 	{
       
  1932 	__ASSERT_ALWAYS(iFs.Handle(), Panic(ERFsNotConnected));
       
  1933 	return iFs;
       
  1934 	}
       
  1935 
       
  1936 EXPORT_C RFs& CCommandBase::FsL()
       
  1937 	{
       
  1938 	if (iFs.Handle() == 0)
       
  1939 		{
       
  1940 		User::LeaveIfError(iFs.Connect());
       
  1941 		const TDesC& pwd = Env().Pwd();
       
  1942 		TInt err = iFs.SetSessionPath(pwd);
       
  1943 		if (err)
       
  1944 			{
       
  1945 			// Could fail if, for eg, we have no capabilities and the fshell we were launched from had \sys\bin as its cwd. In such a case shouldn't be considered an error, only a warning.
       
  1946 			PrintWarning(_L("Couldn't set session path for %S to '%S'. (err = %d)\r\n"), &Name(), &pwd, err);
       
  1947 			}
       
  1948 		}
       
  1949 	return iFs;
       
  1950 	}
       
  1951 
       
  1952 EXPORT_C const RFs& CCommandBase::FsL() const
       
  1953 	{
       
  1954 	return const_cast<CCommandBase*>(this)->FsL();
       
  1955 	}
       
  1956 
       
  1957 EXPORT_C RIoSession& CCommandBase::IoSession()
       
  1958 	{
       
  1959 	return iIoSession;
       
  1960 	}
       
  1961 
       
  1962 EXPORT_C RIoConsoleReadHandle& CCommandBase::Stdin()
       
  1963 	{
       
  1964 	return iStdin;
       
  1965 	}
       
  1966 
       
  1967 EXPORT_C RIoConsoleWriteHandle& CCommandBase::Stdout()
       
  1968 	{
       
  1969 	return iStdout;
       
  1970 	}
       
  1971 
       
  1972 EXPORT_C RIoConsoleWriteHandle& CCommandBase::Stderr()
       
  1973 	{
       
  1974 	return iStderr;
       
  1975 	}
       
  1976 
       
  1977 EXPORT_C void CCommandBase::OptionsL(RCommandOptionList&)
       
  1978 	{
       
  1979 	}
       
  1980 
       
  1981 EXPORT_C void CCommandBase::ArgumentsL(RCommandArgumentList&)
       
  1982 	{
       
  1983 	}
       
  1984 
       
  1985 EXPORT_C TInt CCommandBase::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
       
  1986 	{
       
  1987 	return CActive::Extension_(aExtensionId, a0, a1);
       
  1988 	}
       
  1989 
       
  1990 EXPORT_C void CCommandBase::HandleLeave(TInt aError)
       
  1991 	{
       
  1992 	const TDesC& name = Name();
       
  1993 	Complete(aError, _L("Command \"%S\" failed"), &name);
       
  1994 	}
       
  1995 
       
  1996 void HandleEscapeL(TLex& aLex, CTextBuffer& aBuf)
       
  1997 	{
       
  1998 	_LIT(KBell, "\a");
       
  1999 	_LIT(KBackspace, "\b");
       
  2000 	_LIT(KFormFeed, "\f");
       
  2001 	_LIT(KHorizontalTab, "\t");
       
  2002 	_LIT(KVerticalTab, "\v");
       
  2003 	_LIT(KNewLine, "\n");
       
  2004 	_LIT(KCarriageReturn, "\r");
       
  2005 	if (!aLex.Eos())
       
  2006 		{
       
  2007 		TChar c2 = aLex.Get();
       
  2008 		switch (c2)
       
  2009 			{
       
  2010 			case 'a':
       
  2011 				aBuf.AppendL(KBell);
       
  2012 				break;
       
  2013 			case 'b':
       
  2014 				aBuf.AppendL(KBackspace);
       
  2015 				break;
       
  2016 			case 'f':
       
  2017 				aBuf.AppendL(KFormFeed);
       
  2018 				break;
       
  2019 			case 't':
       
  2020 				aBuf.AppendL(KHorizontalTab);
       
  2021 				break;
       
  2022 			case 'v':
       
  2023 				aBuf.AppendL(KVerticalTab);
       
  2024 				break;
       
  2025 			case 'n':
       
  2026 				aBuf.AppendL(KNewLine);
       
  2027 				break;
       
  2028 			case 'r':
       
  2029 				aBuf.AppendL(KCarriageReturn);
       
  2030 				break;
       
  2031 			case 'x':
       
  2032 			case 'X':
       
  2033 				if (aLex.Remainder().Length() >= 2)
       
  2034 					{
       
  2035 					TLex lex(aLex.Remainder().Mid(0, 2)); // Note, can't use aLex directly because there could be hex characters following the 2 that relate to this escape sequence.
       
  2036 					TUint16 val;
       
  2037 					User::LeaveIfError(lex.Val(val, EHex));
       
  2038 					aBuf.AppendL(TPtrC(&val, 1));
       
  2039 					aLex.Inc(2);
       
  2040 					}
       
  2041 				break;
       
  2042 			case 'u':
       
  2043 				if (aLex.Remainder().Length() >= 4)
       
  2044 					{
       
  2045 					TLex lex(aLex.Remainder().Mid(0, 4)); // Note, can't use aLex directly because there could be hex characters following the 4 that relate to this escape sequence.
       
  2046 					TUint16 val;
       
  2047 					User::LeaveIfError(lex.Val(val, EHex));
       
  2048 					aBuf.AppendL(TChar(val));
       
  2049 					aLex.Inc(4);
       
  2050 					}
       
  2051 				break;
       
  2052 			case 'U':
       
  2053 				if (aLex.Remainder().Length() >= 8)
       
  2054 					{
       
  2055 					TLex lex(aLex.Remainder().Mid(0, 8)); // Note, can't use aLex directly because there could be hex characters following the 8 that relate to this escape sequence.
       
  2056 					TUint32 val;
       
  2057 					User::LeaveIfError(lex.Val(val, EHex));
       
  2058 					aBuf.AppendL(TChar(val));
       
  2059 					aLex.Inc(8);
       
  2060 					}
       
  2061 				break;
       
  2062 			default:
       
  2063 				aBuf.AppendL(TPtrC((TUint16*)&c2, 1));
       
  2064 				break;
       
  2065 			}
       
  2066 		}
       
  2067 	}
       
  2068 
       
  2069 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar)
       
  2070 	{
       
  2071 	return ReadLC(aLex, aEscapeChar, NULL, 0);
       
  2072 	}
       
  2073 
       
  2074 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, CCommandBase& aErrorContext)
       
  2075 	{
       
  2076 	return ReadLC(aLex, aEscapeChar, &aErrorContext, 0);
       
  2077 	}
       
  2078 
       
  2079 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, TUint aReadMode)
       
  2080 	{
       
  2081 	return ReadLC(aLex, aEscapeChar, NULL, aReadMode);
       
  2082 	}
       
  2083 
       
  2084 EXPORT_C HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, CCommandBase& aErrorContext, TUint aReadMode)
       
  2085 	{
       
  2086 	return ReadLC(aLex, aEscapeChar, &aErrorContext, aReadMode);
       
  2087 	}
       
  2088 	
       
  2089 #define ReadLCLeaveIfErr(_command, _error, _errorFmtString...) do {if (_command) {CommandLeaveIfErr(*_command, _error, _errorFmtString);} else User::LeaveIfError(_error); } while(0)
       
  2090 	
       
  2091 HBufC* Stringify::ReadLC(TLex& aLex, const TChar& aEscapeChar, CCommandBase* aErrorContext, TUint aReadMode)
       
  2092 	{
       
  2093 	CTextBuffer* buf = CTextBuffer::NewLC(20);
       
  2094 	while (!aLex.Eos())
       
  2095 		{
       
  2096 		TChar c = aLex.Get();
       
  2097 		if (c == aEscapeChar)
       
  2098 			{
       
  2099 			HandleEscapeL(aLex, *buf);
       
  2100 			}
       
  2101 		else if (c == '\'')
       
  2102 			{
       
  2103 			TBool foundClose = EFalse;
       
  2104 			while (!aLex.Eos())
       
  2105 				{
       
  2106 				c = aLex.Get();
       
  2107 				if ((c == aEscapeChar) && !aLex.Eos() && (aLex.Peek() == '\''))
       
  2108 					{
       
  2109 					// Allow quoted single quote characters. Note, the is a departure from Bash behaviour, but is in line with Perl and is generally helpful.
       
  2110 					buf->AppendL('\'');
       
  2111 					aLex.Get();
       
  2112 					}
       
  2113 				else if (c == '\'')
       
  2114 					{
       
  2115 					foundClose = ETrue;
       
  2116 					break;
       
  2117 					}
       
  2118 				else
       
  2119 					{
       
  2120 					buf->AppendL(c);
       
  2121 					}
       
  2122 				}
       
  2123 			if (!foundClose)
       
  2124 				{
       
  2125 				ReadLCLeaveIfErr(aErrorContext, KErrArgument, _L("Unmatched single quote"));
       
  2126 				}
       
  2127 			}
       
  2128 		else if (c == '"')
       
  2129 			{
       
  2130 			TBool foundClose = EFalse;
       
  2131 			while (!aLex.Eos())
       
  2132 				{
       
  2133 				c = aLex.Get();
       
  2134 				if (c == aEscapeChar)
       
  2135 					{
       
  2136 					HandleEscapeL(aLex, *buf);
       
  2137 					}
       
  2138 				else if (c == '"')
       
  2139 					{
       
  2140 					foundClose = ETrue;
       
  2141 					break;
       
  2142 					}
       
  2143 				else
       
  2144 					{
       
  2145 					buf->AppendL(c);
       
  2146 					}
       
  2147 				}
       
  2148 			if (!foundClose)
       
  2149 				{
       
  2150 				ReadLCLeaveIfErr(aErrorContext, KErrArgument, _L("Unmatched double quote"));
       
  2151 				}
       
  2152 			}
       
  2153 		else if (c.IsSpace() || ((c == ',') && (aReadMode & EBreakOnComma)))
       
  2154 			{
       
  2155 			aLex.UnGet();
       
  2156 			break;
       
  2157 			}
       
  2158 		else
       
  2159 			{
       
  2160 			buf->AppendL(c);
       
  2161 			}
       
  2162 		}
       
  2163 
       
  2164 	HBufC* hbuf = buf->Descriptor().AllocL();
       
  2165 	CleanupStack::PopAndDestroy(buf);
       
  2166 	CleanupStack::PushL(hbuf);
       
  2167 	return hbuf;
       
  2168 	}
       
  2169 
       
  2170 EXPORT_C HBufC* Stringify::WidenLC(const TDesC8& aDes)
       
  2171 	{
       
  2172 	HBufC* buf = HBufC::NewLC(aDes.Length());
       
  2173 	buf->Des().Copy(aDes);
       
  2174 	return buf;
       
  2175 	}
       
  2176 
       
  2177 EXPORT_C HBufC8* Stringify::NarrowLC(const TDesC& aDes)
       
  2178 	{
       
  2179 	HBufC8* buf = HBufC8::NewLC(aDes.Length());
       
  2180 	buf->Des().Copy(aDes);
       
  2181 	return buf;
       
  2182 	}
       
  2183 
       
  2184 EXPORT_C HBufC* Stringify::EscapeLC(const TDesC& aDes, const TChar& aEscapeChar)
       
  2185 	{
       
  2186 	const TInt origLength = aDes.Length();
       
  2187 	TInt newLength = origLength;
       
  2188 	for (TInt i = 0; i < origLength; ++i)
       
  2189 		{
       
  2190 		if (!TChar(aDes[i]).IsPrint())
       
  2191 			{
       
  2192 			// Hmmm, is this going to go horribly wrong with surrogate pairs?
       
  2193 			newLength += 5; // 5 because <unprintable-char> -> '^unnnn'
       
  2194 			}
       
  2195 		}
       
  2196 	HBufC* buf = HBufC::NewLC(newLength);
       
  2197 	TPtr bufPtr(buf->Des());
       
  2198 	for (TInt i = 0; i < origLength; ++i)
       
  2199 		{
       
  2200 		if (TChar(aDes[i]).IsPrint())
       
  2201 			{
       
  2202 			bufPtr.Append(aDes[i]);
       
  2203 			}
       
  2204 		else
       
  2205 			{
       
  2206 			bufPtr.Append(aEscapeChar);
       
  2207 			bufPtr.Append('u');
       
  2208 			bufPtr.AppendNumFixedWidthUC(aDes[i], EHex, 4);
       
  2209 			}
       
  2210 		}
       
  2211 	return buf;
       
  2212 	}
       
  2213 
       
  2214 EXPORT_C HBufC8* Stringify::EscapeLC(const TDesC8& aDes, const TChar& aEscapeChar)
       
  2215 	{
       
  2216 	const TInt origLength = aDes.Length();
       
  2217 	TInt newLength = origLength;
       
  2218 	for (TInt i = 0; i < origLength; ++i)
       
  2219 		{
       
  2220 		if (!TChar(aDes[i]).IsPrint())
       
  2221 			{
       
  2222 			newLength += 3; // 3 because <unprintable-char> -> '^xnn'
       
  2223 			}
       
  2224 		}
       
  2225 	HBufC8* buf = HBufC8::NewLC(newLength);
       
  2226 	TPtr8 bufPtr(buf->Des());
       
  2227 	for (TInt i = 0; i < origLength; ++i)
       
  2228 		{
       
  2229 		if (TChar(aDes[i]).IsPrint())
       
  2230 			{
       
  2231 			bufPtr.Append(aDes[i]);
       
  2232 			}
       
  2233 		else
       
  2234 			{
       
  2235 			bufPtr.Append(aEscapeChar);
       
  2236 			bufPtr.Append('x');
       
  2237 			bufPtr.AppendNumFixedWidthUC(aDes[i], EHex, 2);
       
  2238 			}
       
  2239 		}
       
  2240 	return buf;
       
  2241 	}
       
  2242 
       
  2243 TRadix Radix(TLex& aLex)
       
  2244 	{
       
  2245 	_LIT(KBinPrefix, "0b");
       
  2246 	_LIT(KOctPrefix, "0.");
       
  2247 	_LIT(KHexPrefix, "0x");
       
  2248 	
       
  2249 	TRadix radix(EDecimal);
       
  2250 
       
  2251 	if (aLex.Remainder().Length() > 2)
       
  2252 		{
       
  2253 		TLexMark mark;
       
  2254 		aLex.Mark(mark);
       
  2255 		aLex.Inc(2);
       
  2256 		TPtrC prefix(aLex.MarkedToken(mark));
       
  2257 		if (prefix == KBinPrefix)
       
  2258 			{
       
  2259 			radix = EBinary;
       
  2260 			}
       
  2261 		else if (prefix == KOctPrefix)
       
  2262 			{
       
  2263 			radix = EOctal;
       
  2264 			}
       
  2265 		else if (prefix == KHexPrefix)
       
  2266 			{
       
  2267 			radix = EHex;
       
  2268 			}
       
  2269 		
       
  2270 		if (radix == EDecimal)
       
  2271 			{
       
  2272 			aLex.UnGetToMark(mark);
       
  2273 			}
       
  2274 		}
       
  2275 
       
  2276 	return radix;
       
  2277 	}
       
  2278 
       
  2279 void CCommandBase::SetValueL(TLex& aLex, TValue& aValue)
       
  2280 	{
       
  2281 	TBool more((aValue.ValueType() & KValueTypeFlagMultiple) && !(aValue.ValueType() & KValueTypeFlagLast));
       
  2282 	if (aValue.IsSet() && !(aValue.ValueType() & KValueTypeFlagMultiple)) User::Leave(KErrArgument); // Can't set the same parameter repeatedly unless it has the multiple attribute
       
  2283 	do
       
  2284 		{
       
  2285 		switch (aValue.ValueType() & KValueTypeFlagMask)
       
  2286 			{
       
  2287 			case KValueTypeBool:
       
  2288 				{
       
  2289 				aValue.SetValue();
       
  2290 				break;
       
  2291 				}
       
  2292 			case KValueTypeInt:
       
  2293 				{
       
  2294 				aLex.SkipSpace();
       
  2295 				TInt val;
       
  2296 				if (aLex.Val(val) < 0)
       
  2297 					{
       
  2298 					User::Leave(KErrArgument);
       
  2299 					}
       
  2300 				aValue.SetValueL(val);
       
  2301 				break;
       
  2302 				}
       
  2303 			case KValueTypeInt64:
       
  2304 				{
       
  2305 				aLex.SkipSpace();
       
  2306 				TInt64 val;
       
  2307 				if (aLex.Val(val) < 0)
       
  2308 					{
       
  2309 					User::Leave(KErrArgument);
       
  2310 					}
       
  2311 				aValue.SetValueL(val);
       
  2312 				break;
       
  2313 				}
       
  2314 			case KValueTypeUint:
       
  2315 				{
       
  2316 				aLex.SkipSpace();
       
  2317 				TUint val;
       
  2318 				if (aLex.Val(val, Radix(aLex)) < 0)
       
  2319 					{
       
  2320 					User::Leave(KErrArgument);
       
  2321 					}
       
  2322 				aValue.SetValueL(val);
       
  2323 				break;
       
  2324 				}
       
  2325 			case KValueTypeUint64:
       
  2326 				{
       
  2327 				aLex.SkipSpace();
       
  2328 				TInt64 val; // There's no implementation of TLex16::Val(TUint64&, TRadix), so we'll have to use the TInt64 version instead.
       
  2329 				if (aLex.Val(val, Radix(aLex)) < 0)
       
  2330 					{
       
  2331 					User::Leave(KErrArgument);
       
  2332 					}
       
  2333 				aValue.SetValueL((TUint64)val);
       
  2334 				break;
       
  2335 				}
       
  2336 			case KValueTypeReal:
       
  2337 				{
       
  2338 				aLex.SkipSpace();
       
  2339 				TReal64 val;
       
  2340 				if (aLex.Val(val) < 0)
       
  2341 					{
       
  2342 					User::Leave(KErrArgument);
       
  2343 					}
       
  2344 				aValue.SetValueL(val);
       
  2345 				break;
       
  2346 				}
       
  2347 			case KValueTypeString:
       
  2348 				{
       
  2349 				if (aValue.ValueType() & KValueTypeFlagLast)
       
  2350 					{
       
  2351 					TLexMark mark;
       
  2352 					aLex.Mark(mark);
       
  2353 					HBufC* string = ReadStringLC(aLex, 0);
       
  2354 					if ((aLex.Remainder().Length() == 0) || (aLex.Remainder() == KNewLine))
       
  2355 						{
       
  2356 						// ReadStringLC consumed the whole of the remainder of the command line. This means the
       
  2357 						// user must have either provided a just single word, or explicitly quoted / escaped the whitespace
       
  2358 						// between multiple words.
       
  2359 						// Either way, we've got a single argument to satisfy 'last' so we'll use what ReadStringLC
       
  2360 						// returned.
       
  2361 						aValue.SetValueL(string);
       
  2362 						CleanupStack::Pop(string);
       
  2363 						}
       
  2364 					else
       
  2365 						{
       
  2366 						// ReadStringLC didn't consume the remainder of the command line. This means the user must have
       
  2367 						// provided multiple words, but didn't quote or escape the whitespace. In this case take the
       
  2368 						// string they provided unaltered (which is equivalent to adding quotes around the whole string
       
  2369 						// and passing it back through ReadStringLC).
       
  2370 						CleanupStack::PopAndDestroy(string);
       
  2371 						aLex.UnGetToMark(mark);
       
  2372 						aValue.SetValueL(aLex.Remainder().AllocLC());
       
  2373 						CleanupStack::Pop();
       
  2374 						aLex.Inc(aLex.Remainder().Length());
       
  2375 						}
       
  2376 					}
       
  2377 				else
       
  2378 					{
       
  2379 					HBufC* string = ReadStringLC(aLex, (aValue.ValueType() & KValueTypeFlagLast) ? 0 : EDisallowLeadingHyphen);
       
  2380 					aValue.SetValueL(string);
       
  2381 					CleanupStack::Pop(string);
       
  2382 					}
       
  2383 				break;
       
  2384 				}		
       
  2385 			case KValueTypeFileName:
       
  2386 				{
       
  2387 				HBufC* string = ReadStringLC(aLex, EDisallowLeadingHyphen);
       
  2388 				TFileName2 fileName(*string);
       
  2389 				CleanupStack::PopAndDestroy(string);
       
  2390 				if (fileName.Length() == 0)
       
  2391 					{
       
  2392 					User::Leave(KErrArgument);
       
  2393 					}
       
  2394 				fileName.MakeAbsoluteL(iEnv->Pwd());
       
  2395 				aValue.SetValueL(fileName, FsL());
       
  2396 				break;
       
  2397 				}
       
  2398 			case KValueTypeEnum:
       
  2399 				{
       
  2400 				HBufC* string = ReadStringLC(aLex, EDisallowLeadingHyphen);
       
  2401 				aValue.SetValueL(string);	
       
  2402 				CleanupStack::PopAndDestroy(string);
       
  2403 				break;
       
  2404 				}
       
  2405 			default:
       
  2406 				{
       
  2407 				__ASSERT_ALWAYS(EFalse, Panic(EInvalidCommandOptionType));
       
  2408 				break;
       
  2409 				}
       
  2410 			}
       
  2411 
       
  2412 		if (more)
       
  2413 			{
       
  2414 			TLexMark mark;
       
  2415 			aLex.Mark(mark);
       
  2416 			aLex.SkipSpace();
       
  2417 			if (aLex.Peek() == ',')
       
  2418 				{
       
  2419 				aLex.Get();
       
  2420 				aLex.SkipSpace();
       
  2421 				// Loop again to process the next value in the set.
       
  2422 				}
       
  2423 			else
       
  2424 				{
       
  2425 				aLex.UnGetToMark(mark);
       
  2426 				more = EFalse;
       
  2427 				}
       
  2428 			}
       
  2429 		}
       
  2430 		while (more);
       
  2431 	}
       
  2432 
       
  2433 void CCommandBase::SetValueFromEnvL(TValue& aValue)
       
  2434 	{
       
  2435 	if (!aValue.IsSet() && (aValue.EnvVar().Length() > 0) && iEnv->IsDefined(aValue.EnvVar()))
       
  2436 		{
       
  2437 		TUint type = aValue.ValueType() & KValueTypeFlagMask;
       
  2438 		if ((type == KValueTypeString) || (type == KValueTypeEnum))
       
  2439 			{
       
  2440 			HBufC* value = iEnv->GetAsDesL(aValue.EnvVar()).AllocLC();
       
  2441 			aValue.SetValueL(value);
       
  2442 			CleanupStack::Pop(value);
       
  2443 			}
       
  2444 		else if (type == KValueTypeFileName)
       
  2445 			{
       
  2446 			TFileName2 fileName(iEnv->GetAsDesL(aValue.EnvVar()));
       
  2447 			fileName.MakeAbsoluteL(iEnv->Pwd());
       
  2448 			aValue.SetValueL(fileName, FsL());
       
  2449 			}
       
  2450 		else
       
  2451 			{
       
  2452 			TLex lex(iEnv->GetAsDesL(aValue.EnvVar()));
       
  2453 			SetValueL(lex, aValue);
       
  2454 			}
       
  2455 		}
       
  2456 	}
       
  2457 
       
  2458 
       
  2459 
       
  2460 template <class T> TBool ValueTypesConsistent(const T& aList)
       
  2461 	{
       
  2462 	// class T is expected to be either RCommandArgumentList or RCommandOptionList.
       
  2463 	// Returns true if either all the list values have an uninitialized value type, or all have an initialized value type.
       
  2464 	// Returns false if there is a mixture of unitialized and uninitialized value types.
       
  2465 
       
  2466 	TBool unitialized(EFalse);
       
  2467 	const TInt count = aList.Count();
       
  2468 	if (count > 0)
       
  2469 		{
       
  2470 		for (TInt i = 0; i < count; ++i)
       
  2471 			{
       
  2472 			if (i == 0)
       
  2473 				{
       
  2474 				unitialized = (aList[i].ValueType() == KValueTypeUninitialized);
       
  2475 				}
       
  2476 			else if (!unitialized != !(aList[i].ValueType() == KValueTypeUninitialized))
       
  2477 				{
       
  2478 				return EFalse;
       
  2479 				}
       
  2480 			}
       
  2481 		}
       
  2482 	return ETrue;
       
  2483 	}
       
  2484 
       
  2485 template <class T> TBool ValueTypesInitialized(const T& aList)
       
  2486 	{
       
  2487 	return !(aList[0].ValueType() == KValueTypeUninitialized);
       
  2488 	}
       
  2489 
       
  2490 
       
  2491 TBool ValueTypesInitializedL(const RCommandArgumentList& aArguments, const RCommandOptionList& aOptions)
       
  2492 	{
       
  2493 	if (!ValueTypesConsistent(aArguments))
       
  2494 		{
       
  2495 		StaticLeaveIfErr(KErrArgument, _L("Arguments inconsistently or incompletely initialized."));
       
  2496 		}
       
  2497 	if (!ValueTypesConsistent(aOptions))
       
  2498 		{
       
  2499 		StaticLeaveIfErr(KErrArgument, _L("Options inconsistently or incompletely initialized."));
       
  2500 		}
       
  2501 	if (aArguments.Count() && aOptions.Count())
       
  2502 		{
       
  2503 		TBool argumentsInitialized(ValueTypesInitialized(aArguments));
       
  2504 		TBool optionsInitialized(ValueTypesInitialized(aOptions));
       
  2505 		if (!argumentsInitialized != !optionsInitialized)
       
  2506 			{
       
  2507 			StaticLeaveIfErr(KErrArgument, _L("Arguments and options inconsistently or incompletely initialized."));
       
  2508 			}
       
  2509 		}
       
  2510 	if (aArguments.Count())
       
  2511 		{
       
  2512 		return ValueTypesInitialized(aArguments);
       
  2513 		}
       
  2514 	else if (aOptions.Count())
       
  2515 		{
       
  2516 		return ValueTypesInitialized(aOptions);
       
  2517 		}
       
  2518 	else
       
  2519 		{
       
  2520 		return ETrue;
       
  2521 		}
       
  2522 	}
       
  2523 
       
  2524 EXPORT_C TInt CCommandBase::ParseCommandLine(const TDesC& aCommandLine)
       
  2525 	{
       
  2526 	TRAPD(err, DoParseCommandLineL(aCommandLine));
       
  2527 	return err;
       
  2528 	}
       
  2529 
       
  2530 void CCommandBase::DoParseCommandLineL(const TDesC& aCommandLine)
       
  2531 	{
       
  2532 	// Read the CIF if required.
       
  2533 	if (CifReadRequired())
       
  2534 		{
       
  2535 		ReadCifL();
       
  2536 		}
       
  2537 
       
  2538 	// Add command specific arguments and options.
       
  2539 	ArgumentsL(iArguments);
       
  2540 	OptionsL(iOptions);
       
  2541 
       
  2542 	if (iCif)
       
  2543 		{
       
  2544 		TRAPD(err, iCif->AssignL(iArguments, iOptions));
       
  2545 		if (err)
       
  2546 			{
       
  2547 			iFlags |= ECifReadFailed;
       
  2548 			User::Leave(err);
       
  2549 			}
       
  2550 		__ASSERT_ALWAYS(ValueTypesInitializedL(iArguments, iOptions), Panic(EIncompleteArgumentOrOptionInitialization));
       
  2551 		}
       
  2552 
       
  2553 	// Add global options.
       
  2554 	iOptions.AppendBoolL(iDisplayHelp, TChar('h'), KHelpName, KHelpDescription);
       
  2555 	iOptions.AppendStringL(iConsoleImplementation, TChar(0), KOptConsole, KNullDesC);
       
  2556 	iOptions.AppendStringL(iConsoleTitle, TChar(0), KOptConsoleTitle, KNullDesC);
       
  2557 	iOptions.AppendUintL(iConsoleSize, TChar(0), KOptConsoleSize, KNullDesC);
       
  2558 	iOptions.AppendStringL(iPersistentConsoleName, TChar(0), KOptPersistentConsole, KNullDesC);
       
  2559 
       
  2560 	// Parse the command line.
       
  2561 	ParseCommandLineL(aCommandLine);
       
  2562 
       
  2563 	// Set optional arguments that haven't been set explicitly from environment variables if applicable.
       
  2564 	const TInt numArgs = iArguments.Count();
       
  2565 	for (TInt i = 0; i < numArgs; ++i)
       
  2566 		{
       
  2567 		SetValueFromEnvL(iArguments[i]);
       
  2568 		}
       
  2569 
       
  2570 	// Set options that haven't been set explicitly from environment variables if applicable.
       
  2571 	const TInt numOpts = iOptions.Count();
       
  2572 	for (TInt i = 0; i < numOpts; ++i)
       
  2573 		{
       
  2574 		SetValueFromEnvL(iOptions[i]);
       
  2575 		}
       
  2576 		
       
  2577 	if (!iArguments.AllSet())
       
  2578 		{
       
  2579 		User::Leave(KErrArgument);
       
  2580 		}
       
  2581 	}
       
  2582 
       
  2583 TBool CCommandBase::CifReadRequired() const
       
  2584 	{
       
  2585 	if (iCif)
       
  2586 		{
       
  2587 		return EFalse;
       
  2588 		}
       
  2589 
       
  2590 	// Call the virtual Description function to see if the sub-class has implemented it.
       
  2591 	// If not, it is assumed that it expects a CIF file to be read.
       
  2592 	Description();
       
  2593 	return (iFlags & EReadCif);
       
  2594 	}
       
  2595 
       
  2596 void CCommandBase::ReadCifL()
       
  2597 	{
       
  2598 	TRAPD(err, DoReadCifL());
       
  2599 	if (err)
       
  2600 		{
       
  2601 		iFlags |= ECifReadFailed;
       
  2602 		}
       
  2603 	}
       
  2604 
       
  2605 void CCommandBase::DoReadCifL()
       
  2606 	{
       
  2607 	iCif = CCommandInfoFile::NewL(FsL(), Env(), Name());
       
  2608 	iFlags |= EOwnsCif;
       
  2609 	}
       
  2610 
       
  2611 EXPORT_C TBool CCommandBase::UsingCif() const
       
  2612 	{
       
  2613 	if (iCif)
       
  2614 		{
       
  2615 		return ETrue;
       
  2616 		}
       
  2617 	return (CifReadRequired());
       
  2618 	}
       
  2619 
       
  2620 EXPORT_C void CCommandBase::ParseCommandLineL(const TDesC& aCommandLine)
       
  2621 	{
       
  2622 	TInt argumentIndex = 0;
       
  2623 	TLex lex(aCommandLine);
       
  2624 	lex.SkipSpace();
       
  2625 	TBool lastArgSeen(EFalse);
       
  2626 	while (!lex.Eos())
       
  2627 		{
       
  2628 		TBool isOption = EFalse;
       
  2629 		if (!lastArgSeen && (lex.Peek() == TChar('-')))
       
  2630 			{	// Start of an option.
       
  2631 			isOption = ETrue;
       
  2632 			lex.Get();
       
  2633 			TChar peek = lex.Peek();
       
  2634 			if (peek == TChar('-'))
       
  2635 				{	// Start of a long named option.
       
  2636 				lex.Get();
       
  2637 				lex.Mark();
       
  2638 				lex.SkipCharacters();
       
  2639 				TInt optionIndex = iOptions.Find(lex.MarkedToken());
       
  2640 				if (optionIndex < 0)
       
  2641 					{
       
  2642 					User::Leave(KErrArgument);
       
  2643 					}
       
  2644 				SetValueL(lex, iOptions[optionIndex]);
       
  2645 				}
       
  2646 			else if (peek.IsDigit())
       
  2647 				{
       
  2648 				// It could be a negative integer argument, providing there aren't any numeric short options.
       
  2649 				// If there are, they take precedence, so don't use a digit as a short option unless you don't care about negative arguments
       
  2650 				TInt optionIndex = iOptions.FindShort(peek);
       
  2651 				if (optionIndex < 0)
       
  2652 					{
       
  2653 					isOption = EFalse; // get to the argument clause below
       
  2654 					lex.UnGet(); // So the minus sign is picked up
       
  2655 					}
       
  2656 				}
       
  2657 			
       
  2658 			if (isOption)
       
  2659 				{	// Start of a short option (or block of short options).
       
  2660 				while (!lex.Eos() && !lex.Peek().IsSpace() && (lex.Peek() != TChar('-')))
       
  2661 					{
       
  2662 					TInt optionIndex = iOptions.FindShort(lex.Get());
       
  2663 					if (optionIndex < 0)
       
  2664 						{
       
  2665 						User::Leave(KErrArgument);
       
  2666 						}
       
  2667 					SetValueL(lex, iOptions[optionIndex]);
       
  2668 					}
       
  2669 				}
       
  2670 			}
       
  2671 
       
  2672 		if (!isOption)
       
  2673 			{	// Start of an argument.
       
  2674 			if (argumentIndex < iArguments.Count())
       
  2675 				{
       
  2676 				TCommandArgument& argument = iArguments[argumentIndex];
       
  2677 				SetValueL(lex, argument);
       
  2678 				if (!(argument.ValueType() & KValueTypeFlagMultiple))
       
  2679 					{
       
  2680 					++argumentIndex;
       
  2681 					}
       
  2682 				lastArgSeen = (argument.ValueType() & KValueTypeFlagLast);
       
  2683 				// Look ahead to see if the next argument is the last, and if so set lastArgSeen early. This allows the next argument to be an option, but be treated as part of the 'last' string not an option for this command.
       
  2684 				if (!lastArgSeen && (argumentIndex < iArguments.Count()))
       
  2685 					{
       
  2686 					lastArgSeen = (iArguments[argumentIndex].ValueType() & KValueTypeFlagLast);
       
  2687 					}
       
  2688 				}
       
  2689 			else
       
  2690 				{
       
  2691 				User::Leave(KErrArgument);
       
  2692 				}
       
  2693 			}
       
  2694 
       
  2695 		lex.SkipSpace();
       
  2696 		}
       
  2697 	}
       
  2698 
       
  2699 const TDesC* CCommandBase::ReadCommandLineLC()
       
  2700 	{
       
  2701 #ifdef EKA2
       
  2702 	HBufC* commandLine = HBufC::NewLC(User::CommandLineLength());
       
  2703 	TPtr commandLinePtr(commandLine->Des());
       
  2704 	User::CommandLine(commandLinePtr);
       
  2705 #else
       
  2706 	RProcess process;
       
  2707 	HBufC* commandLine = HBufC::NewLC(process.CommandLineLength());
       
  2708 	TPtr commandLinePtr(commandLine->Des());
       
  2709 	process.CommandLine(commandLinePtr);
       
  2710 #endif
       
  2711 	return commandLine;
       
  2712 	}
       
  2713 
       
  2714 void AppendHeadingL(const TDesC& aHeading, CTextBuffer& aBuffer)
       
  2715 	{
       
  2716 	_LIT(KFormat, "\r\n=head1 %S\r\n\r\n");
       
  2717 	aBuffer.AppendFormatL(KFormat, &aHeading);
       
  2718 	}
       
  2719 
       
  2720 void AppendSubCommandL(TInt aIndent, CTextBuffer& aBuffer, const CCommandInfoFile& aCif)
       
  2721 	{
       
  2722 	aBuffer.AppendSpacesL(aIndent);
       
  2723 	aBuffer.AppendL(aCif.Name());
       
  2724 	aBuffer.AppendL(KNewLine);
       
  2725 
       
  2726 	TInt numSubCommands = aCif.NumSubCommands();
       
  2727 	for (TInt i = 0; i < numSubCommands; ++i)
       
  2728 		{
       
  2729 		AppendSubCommandL(aIndent + 2, aBuffer, aCif.SubCommand(i));
       
  2730 		}
       
  2731 	}
       
  2732 
       
  2733 EXPORT_C const CTextBuffer* CCommandBase::GetHelpTextL()
       
  2734 	{
       
  2735 	CTextBuffer* buffer = CTextBuffer::NewLC(0x100);
       
  2736 
       
  2737 	AppendHeadingL(_L("SYNTAX"), *buffer);
       
  2738 	buffer->AppendFormatL(_L("    %S"), &Name());
       
  2739 
       
  2740 	const TInt numOptions = iOptions.Count();
       
  2741 	if (numOptions > 0)
       
  2742 		{
       
  2743 		buffer->AppendL(_L(" [options]"));
       
  2744 		}
       
  2745 
       
  2746 	const TInt numArguments = iArguments.Count();
       
  2747 	if (numArguments > 0)
       
  2748 		{
       
  2749 		for (TInt i = 0; i < numArguments; ++i)
       
  2750 			{
       
  2751 			const TCommandArgument& thisArgument = iArguments[i];
       
  2752 			TBool isOptional = thisArgument.IsOptional();
       
  2753 			if (isOptional)
       
  2754 				{
       
  2755 				buffer->AppendL(_L(" [<"));
       
  2756 				}
       
  2757 			else
       
  2758 				{
       
  2759 				buffer->AppendL(_L(" <"));
       
  2760 				}
       
  2761 			buffer->AppendL(thisArgument.Name());
       
  2762 			if (isOptional)
       
  2763 				{
       
  2764 				buffer->AppendL(_L(">]"));
       
  2765 				}
       
  2766 			else
       
  2767 				{
       
  2768 				buffer->AppendL(_L(">"));
       
  2769 				}
       
  2770 
       
  2771 			if (thisArgument.AcceptsMultiple())
       
  2772 				{
       
  2773 				buffer->AppendL(_L(" ..."));
       
  2774 				}
       
  2775 			}
       
  2776 		}
       
  2777 	buffer->AppendL(_L("\r\n"));
       
  2778 
       
  2779 	if (numOptions > 0)
       
  2780 		{
       
  2781 		AppendHeadingL(_L("OPTIONS"), *buffer);
       
  2782 		buffer->AppendL(_L("=over 5\r\n\r\n"));
       
  2783 		for (TInt i = 0; i < numOptions; ++i)
       
  2784 			{
       
  2785 			const TCommandOption& thisOption = iOptions[i];
       
  2786 			TChar shortName(thisOption.ShortName());
       
  2787 			if (shortName)
       
  2788 				{
       
  2789 				buffer->AppendFormatL(_L("=item -%c (--%S)"), (TUint)shortName, &thisOption.Name());
       
  2790 				switch (thisOption.ValueType() & KValueTypeFlagMask)
       
  2791 					{
       
  2792 					case KValueTypeBool:
       
  2793 						{
       
  2794 						// Do nothing.
       
  2795 						break;
       
  2796 						}
       
  2797 					case KValueTypeInt:
       
  2798 						{
       
  2799 						buffer->AppendL(_L(" <int>"));
       
  2800 						break;
       
  2801 						}
       
  2802 					case KValueTypeInt64:
       
  2803 						{
       
  2804 						buffer->AppendL(_L(" <int64>"));
       
  2805 						break;
       
  2806 						}
       
  2807 					case KValueTypeUint:
       
  2808 						{
       
  2809 						buffer->AppendL(_L(" <uint>"));
       
  2810 						break;
       
  2811 						}
       
  2812 					case KValueTypeUint64:
       
  2813 						{
       
  2814 						buffer->AppendL(_L(" <uint64>"));
       
  2815 						break;
       
  2816 						}
       
  2817 					case KValueTypeString:
       
  2818 						{
       
  2819 						buffer->AppendL(_L(" <string>"));
       
  2820 						break;
       
  2821 						}
       
  2822 					case KValueTypeFileName:
       
  2823 						{
       
  2824 						buffer->AppendL(_L(" <filename>"));
       
  2825 						break;
       
  2826 						}
       
  2827 					case KValueTypeEnum:
       
  2828 						{
       
  2829 						buffer->AppendL(_L(" <enum>"));
       
  2830 						break;
       
  2831 						}
       
  2832 					case KValueTypeReal:
       
  2833 						{
       
  2834 						buffer->AppendL(_L(" <real>"));
       
  2835 						break;
       
  2836 						}
       
  2837 					default:
       
  2838 						{
       
  2839 						__ASSERT_ALWAYS(EFalse, Panic(EInvalidCommandOptionType));
       
  2840 						break;
       
  2841 						}
       
  2842 					}
       
  2843 				buffer->AppendFormatL(_L("\r\n\r\n%S"), &thisOption.Description());
       
  2844 				if ((thisOption.ValueType() & KValueTypeFlagMask) == KValueTypeEnum)
       
  2845 					{
       
  2846 					if (thisOption.EnumDescriptionList().Length() > 0)
       
  2847 						{
       
  2848 						FormatEnumL(thisOption, *buffer);
       
  2849 						}
       
  2850 					else
       
  2851 						{
       
  2852 						buffer->AppendL(_L(" ["));
       
  2853 						thisOption.AppendEnumValuesL(*buffer);
       
  2854 						buffer->AppendL(']');
       
  2855 						}
       
  2856 					}
       
  2857 				if (thisOption.ValueType() & KValueTypeFlagMultiple)
       
  2858 					{
       
  2859 					buffer->AppendL(_L(" Can be specified more than once."));
       
  2860 					}
       
  2861 				if (thisOption.EnvVar().Length() > 0)
       
  2862 					{
       
  2863 					const TDesC& envVar = thisOption.EnvVar();
       
  2864 					buffer->AppendFormatL(_L(" Can also be specified by defining the environment variable \"%S\"."), &envVar);
       
  2865 					}
       
  2866 				buffer->AppendL(_L("\r\n\r\n"));
       
  2867 				}
       
  2868 			}
       
  2869 		buffer->AppendL(_L("=back\r\n"));
       
  2870 		}
       
  2871 
       
  2872 	if (numArguments > 0)
       
  2873 		{
       
  2874 		AppendHeadingL(_L("ARGUMENTS"), *buffer);
       
  2875 		buffer->AppendL(_L("=over 5\r\n\r\n"));
       
  2876 		for (TInt i = 0; i < numArguments; ++i)
       
  2877 			{
       
  2878 			buffer->AppendL(_L("=item "));
       
  2879 			const TCommandArgument& thisArgument = iArguments[i];
       
  2880 			TBool isOptional = thisArgument.IsOptional();
       
  2881 			if (isOptional)
       
  2882 				{
       
  2883 				buffer->AppendL(_L("[<"));
       
  2884 				}
       
  2885 			else
       
  2886 				{
       
  2887 				buffer->AppendL(_L("<"));
       
  2888 				}
       
  2889 			buffer->AppendL(thisArgument.Name());
       
  2890 			if (isOptional)
       
  2891 				{
       
  2892 				buffer->AppendL(_L(">]\r\n\r\n"));
       
  2893 				}
       
  2894 			else
       
  2895 				{
       
  2896 				buffer->AppendL(_L(">\r\n\r\n"));
       
  2897 				}
       
  2898 
       
  2899 			buffer->AppendL(thisArgument.Description());
       
  2900 
       
  2901 			if (thisArgument.ValueType() & KValueTypeFlagMultiple)
       
  2902 				{
       
  2903 				buffer->AppendL(_L(" Can be specified more than once."));
       
  2904 				}
       
  2905 
       
  2906 			if (thisArgument.EnvVar().Length() > 0)
       
  2907 				{
       
  2908 				const TDesC& envVar = thisArgument.EnvVar();
       
  2909 				buffer->AppendFormatL(_L(" Can also be specified by defining the environment variable \"%S\"."), &envVar);
       
  2910 				}
       
  2911 
       
  2912 			if (thisArgument.IsLast())
       
  2913 				{
       
  2914 				buffer->AppendFormatL(_L(" Any further arguments or options will be coalesced into this one."));
       
  2915 				}
       
  2916 
       
  2917 			TBool noClosingSquareBracket(EFalse);
       
  2918 
       
  2919 			switch (thisArgument.ValueType() & KValueTypeFlagMask)
       
  2920 				{
       
  2921 				case KValueTypeInt:
       
  2922 					{
       
  2923 					buffer->AppendL(_L(" [int"));
       
  2924 					break;
       
  2925 					}
       
  2926 				case KValueTypeInt64:
       
  2927 					{
       
  2928 					buffer->AppendL(_L(" [int64"));
       
  2929 					break;
       
  2930 					}
       
  2931 				case KValueTypeUint:
       
  2932 					{
       
  2933 					buffer->AppendL(_L(" [uint"));
       
  2934 					break;
       
  2935 					}
       
  2936 				case KValueTypeUint64:
       
  2937 					{
       
  2938 					buffer->AppendL(_L(" [uint64"));
       
  2939 					break;
       
  2940 					}
       
  2941 				case KValueTypeString:
       
  2942 					{
       
  2943 					buffer->AppendL(_L(" [string"));
       
  2944 					break;
       
  2945 					}
       
  2946 				case KValueTypeFileName:
       
  2947 					{
       
  2948 					buffer->AppendL(_L(" [filename"));
       
  2949 					break;
       
  2950 					}
       
  2951 				case KValueTypeEnum:
       
  2952 					{
       
  2953 					if (thisArgument.EnumDescriptionList().Length() > 0)
       
  2954 						{
       
  2955 						FormatEnumL(thisArgument, *buffer);
       
  2956 						noClosingSquareBracket = ETrue;
       
  2957 						}
       
  2958 					else
       
  2959 						{
       
  2960 						buffer->AppendL(_L(" ["));
       
  2961 						thisArgument.AppendEnumValuesL(*buffer);
       
  2962 						}
       
  2963 					break;
       
  2964 					}
       
  2965 				case KValueTypeReal:
       
  2966 					{
       
  2967 					buffer->AppendL(_L(" [real"));
       
  2968 					break;
       
  2969 					}
       
  2970 				default:
       
  2971 					{
       
  2972 					__ASSERT_ALWAYS(EFalse, Panic(EInvalidCommandArgumentType));
       
  2973 					break;
       
  2974 					}
       
  2975 				}
       
  2976 
       
  2977 			if (!noClosingSquareBracket)
       
  2978 				{
       
  2979 				if (thisArgument.ValueType() & KValueTypeFlagMultiple)
       
  2980 					{
       
  2981 					buffer->AppendL(_L("(s)]\r\n\r\n"));
       
  2982 					}
       
  2983 				else
       
  2984 					{
       
  2985 					buffer->AppendL(_L("]\r\n\r\n"));
       
  2986 					}
       
  2987 				}
       
  2988 			}
       
  2989 		buffer->AppendL(_L("=back\r\n"));
       
  2990 		}
       
  2991 
       
  2992 	AppendHeadingL(_L("DESCRIPTION"), *buffer);
       
  2993 	buffer->AppendL(Description());
       
  2994 	buffer->AppendL(_L("\r\n\r\n"));
       
  2995 	if (iCif && iCif->LongDescription().Length())
       
  2996 		{
       
  2997 		buffer->AppendL(iCif->LongDescription());
       
  2998 		buffer->AppendL(_L("\r\n\r\n"));
       
  2999 		}
       
  3000 
       
  3001 	if (iCif && iCif->SeeAlso().Length())
       
  3002 		{
       
  3003 		AppendHeadingL(_L("SEE ALSO"), *buffer);
       
  3004 		buffer->AppendL(iCif->SeeAlso());
       
  3005 		buffer->AppendL(_L("\r\n\r\n"));
       
  3006 		}
       
  3007 
       
  3008 	if (iCif && (iCif->NumSubCommands() > 0))
       
  3009 		{
       
  3010 		AppendHeadingL(_L("SUB-COMMANDS"), *buffer);
       
  3011 		TInt numSubCommands = iCif->NumSubCommands();
       
  3012 		for (TInt i = 0; i < numSubCommands; ++i)
       
  3013 			{
       
  3014 			AppendSubCommandL(2, *buffer, iCif->SubCommand(i));
       
  3015 			}
       
  3016 		}
       
  3017 
       
  3018 	if (iCif && iCif->Copyright().Length())
       
  3019 		{
       
  3020 		AppendHeadingL(_L("COPYRIGHT"), *buffer);
       
  3021 		buffer->AppendL(iCif->Copyright());
       
  3022 		buffer->AppendL(_L("\r\n\r\n"));
       
  3023 		}
       
  3024 	
       
  3025 	CTextFormatter* textFormatter = CTextFormatter::NewLC(Stdout());
       
  3026 	textFormatter->AppendPodL(buffer->Descriptor());
       
  3027 	CleanupStack::Pop(textFormatter);
       
  3028 	CleanupStack::PopAndDestroy(buffer);
       
  3029 	return textFormatter;
       
  3030 	}
       
  3031 
       
  3032 void CCommandBase::DisplayHelpAndComplete()
       
  3033 	{
       
  3034 	const CTextBuffer* helpText = NULL;
       
  3035 	TRAPD(err, helpText = GetHelpTextL());
       
  3036 	if (err)
       
  3037 		{
       
  3038 		Complete(err, _L("Error displaying help"));
       
  3039 		}
       
  3040 	else
       
  3041 		{
       
  3042 		CleanupStack::PushL(const_cast<CTextBuffer*>(helpText));
       
  3043 		CheckNewLine();
       
  3044 		PageL(*helpText);
       
  3045 		Complete();
       
  3046 		CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText));
       
  3047 		}
       
  3048 	}
       
  3049 
       
  3050 void CCommandBase::DisplayHelpAndComplete(TInt aError, const TDesC& aText)
       
  3051 	{
       
  3052 	CheckNewLine();
       
  3053 	PrintError(aError, aText);
       
  3054 	const CTextBuffer* helpText = NULL;
       
  3055 	TRAPD(err, helpText = GetHelpTextL());
       
  3056 	if (err == KErrNone)
       
  3057 		{
       
  3058 		CleanupStack::PushL(const_cast<CTextBuffer*>(helpText));
       
  3059 		PageL(*helpText);
       
  3060 		CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText));
       
  3061 		}
       
  3062 	Complete(aError);
       
  3063 	}
       
  3064 
       
  3065 void CCommandBase::FormatErrorText(TDes& aDes, TInt aError, TRefByValue<const TDesC> aFmt, VA_LIST& aList) const
       
  3066 	{
       
  3067 	TOverflowTruncate overflow;
       
  3068 	aDes = _L("Error: ");
       
  3069 	aDes.AppendFormatList(aFmt, aList, &overflow);
       
  3070 	aDes.AppendFormat(_L(" : %S (%d)\r\n"), &overflow, Stringify::Error(aError), aError);
       
  3071 	}
       
  3072 
       
  3073 void CCommandBase::FormatWarningText(TDes& aDes, TRefByValue<const TDesC> aFmt, VA_LIST& aList) const
       
  3074 	{
       
  3075 	TOverflowTruncate overflow;
       
  3076 	aDes = _L("Warning: ");
       
  3077 	aDes.AppendFormatList(aFmt, aList, &overflow);
       
  3078 	if ((aDes.Length() < KNewLine().Length()) || ((aDes.Right(KNewLine().Length()) != KNewLine)))
       
  3079 		{
       
  3080 		aDes.AppendFormat(KNewLine, &overflow);
       
  3081 		}
       
  3082 	}
       
  3083 
       
  3084 void CCommandBase::CheckNewLine()
       
  3085 	{
       
  3086 	if (iStderr.AttachedToConsole())
       
  3087 		{
       
  3088 		TPoint cursorPos(0, 0);
       
  3089 		iStderr.GetCursorPos(cursorPos);
       
  3090 		if (cursorPos.iX != 0)
       
  3091 			{
       
  3092 			iStderr.Write(_L("\r\n"));
       
  3093 			}
       
  3094 		}
       
  3095 	}
       
  3096 
       
  3097 void CCommandBase::FormatEnumL(const TValue& aValue, CTextBuffer& aBuffer) const
       
  3098 	{
       
  3099 	aBuffer.AppendL(_L(" Supported values are:\r\n\r\n=over 5\r\n\r\n"));
       
  3100 	TLex descLex(aValue.EnumDescriptionList());
       
  3101 	TLex valLex(aValue.EnumValueList());
       
  3102 	while (!valLex.Eos())
       
  3103 		{
       
  3104 		HBufC* value = ReadStringLC(valLex, EBreakOnComma);
       
  3105 		__ASSERT_ALWAYS(!descLex.Eos(), IoUtils::Panic(EEnumDescriptionMissing));
       
  3106 		HBufC* description = ReadStringLC(descLex, EBreakOnComma);
       
  3107 		aBuffer.AppendFormatL(_L("=item %S\r\n\r\n%S\r\n\r\n"), value, description);
       
  3108 		CleanupStack::PopAndDestroy(2, value);
       
  3109 		}
       
  3110 	aBuffer.AppendL(_L("=back\r\n\r\n"));
       
  3111 	}
       
  3112 
       
  3113 EXPORT_C void CCommandBase::CreateEnvironmentL(CEnvironment* aEnv)
       
  3114 	{
       
  3115 	if (aEnv)
       
  3116 		{
       
  3117 		iEnv = aEnv;
       
  3118 		}
       
  3119 	else
       
  3120 		{
       
  3121 		iEnv = CEnvironment::NewL();
       
  3122 		iFlags |= EOwnsEnv;
       
  3123 #ifdef EKA2
       
  3124 		const TInt length = User::ParameterLength(KEnvironmentProcessSlot);
       
  3125 		if (length > 0)
       
  3126 			{
       
  3127 			HBufC8* buf = HBufC8::NewLC(length);
       
  3128 			TPtr8 bufPtr(buf->Des());
       
  3129 			User::LeaveIfError(User::GetDesParameter(KEnvironmentProcessSlot, bufPtr));
       
  3130 			iEnv->InternalizeL(bufPtr);
       
  3131 			CleanupStack::PopAndDestroy(buf);
       
  3132 			}
       
  3133 #endif
       
  3134 		}
       
  3135 	}
       
  3136 
       
  3137 EXPORT_C void CCommandBase::RunL()
       
  3138 	{
       
  3139 	if (iFlags & ECompleteOnRunL)
       
  3140 		{
       
  3141 		Complete(iStatus.Int());
       
  3142 		}
       
  3143 	else
       
  3144 		{
       
  3145 		// if a derived class ever makes this Active Object active, it must also override this unless ECompleteOnRunL is specified.
       
  3146 		Panic(EActiveObjectRunLNotOverridden);
       
  3147 		}
       
  3148 	}
       
  3149 
       
  3150 EXPORT_C void CCommandBase::DoCancel()
       
  3151 	{
       
  3152 	// if a derived class ever makes this Active Object active, it must also override this.
       
  3153 	Panic(EActiveObjectRunLNotOverridden);
       
  3154 	}
       
  3155 
       
  3156 EXPORT_C TInt CCommandBase::RunError(TInt aError)
       
  3157 	{
       
  3158 	HandleLeave(aError);
       
  3159 	return KErrNone;
       
  3160 	}
       
  3161 
       
  3162 EXPORT_C CConsoleBase* CCommandBase::GetConsoleBaseL()
       
  3163 	{
       
  3164 	CIoConsole* console = new(ELeave) CIoConsole(Stdin(), Stdout());
       
  3165 	return console;
       
  3166 	}
       
  3167 
       
  3168 EXPORT_C CColorConsoleBase* CCommandBase::GetColorConsoleBaseL()
       
  3169 	{
       
  3170 	// CIoConsole now derives from CColorConsoleBase so implementation is the same as GetConsoleBaseL
       
  3171 	CIoConsole* console = new(ELeave) CIoConsole(Stdin(), Stdout());
       
  3172 	return console;
       
  3173 	}
       
  3174 
       
  3175 EXPORT_C CCommandBase& CCommandBase::Static()
       
  3176 	{
       
  3177 	CCommandBase* self = static_cast<CCommandBase*>(Dll::Tls());
       
  3178 	__ASSERT_ALWAYS(self, Panic(ENoStaticCommand));
       
  3179 	return *self;
       
  3180 	}
       
  3181 	
       
  3182 EXPORT_C TBool CCommandBase::HaveStatic()
       
  3183 	{
       
  3184 	CCommandBase* self = static_cast<CCommandBase*>(Dll::Tls());
       
  3185 	return (self != NULL);
       
  3186 	}
       
  3187 	
       
  3188 EXPORT_C void CCommandBase::StdinChange(TUint /*aChange*/)
       
  3189 	{
       
  3190 	}
       
  3191 
       
  3192 EXPORT_C void CCommandBase::DisplayHelp()
       
  3193 	{
       
  3194 	const CTextBuffer* helpText = NULL;
       
  3195 	TRAPD(err, helpText = GetHelpTextL());
       
  3196 	if (err)
       
  3197 		{
       
  3198 		PrintError(err, _L("Error displaying help"));
       
  3199 		}
       
  3200 	else
       
  3201 		{
       
  3202 		CleanupStack::PushL(const_cast<CTextBuffer*>(helpText));
       
  3203 		CheckNewLine();
       
  3204 		PageL(*helpText);
       
  3205 		CleanupStack::PopAndDestroy(const_cast<CTextBuffer*>(helpText));
       
  3206 		}
       
  3207 	}
       
  3208 
       
  3209 namespace IoUtils
       
  3210 	{
       
  3211 	class MLineReader
       
  3212 		{
       
  3213 	public:
       
  3214 		virtual TInt GetNextLine(CTextBuffer& aText) = 0;
       
  3215 		virtual void InitializeL() {}
       
  3216 		};
       
  3217 
       
  3218 	NONSHARABLE_CLASS(TTextBufferLineReader) : public MLineReader
       
  3219 		{
       
  3220 	public:
       
  3221 		TTextBufferLineReader(const CTextBuffer& aBuffer);
       
  3222 	public: // From MLineReader.
       
  3223 		virtual TInt GetNextLine(CTextBuffer& aText);
       
  3224 	private:
       
  3225 		const CTextBuffer& iBuffer;
       
  3226 		TInt iPos;
       
  3227 		};
       
  3228 
       
  3229 	NONSHARABLE_CLASS(TReadHandleLineReader) : public MLineReader
       
  3230 		{
       
  3231 	public:
       
  3232 		TReadHandleLineReader(RIoReadHandle& aHandle);
       
  3233 	public: // From MLineReader.
       
  3234 		virtual void InitializeL();
       
  3235 		virtual TInt GetNextLine(CTextBuffer& aText);
       
  3236 	private:
       
  3237 		RIoReadHandle& iHandle;
       
  3238 		TBuf<512> iLineBuf; // Note, the code in CCommandBase::PageL(MLineReader&) doesn't properly handle the situation where a given line of input is longer than this buffer.
       
  3239 		};
       
  3240 	}
       
  3241 
       
  3242 TTextBufferLineReader::TTextBufferLineReader(const CTextBuffer& aBuffer)
       
  3243 	: iBuffer(aBuffer), iPos(0)
       
  3244 	{
       
  3245 	}
       
  3246 
       
  3247 TInt TTextBufferLineReader::GetNextLine(CTextBuffer& aText)
       
  3248 	{
       
  3249 	aText.Zero();
       
  3250 	TInt newLinePos = iBuffer.Descriptor().Mid(iPos).Find(KNewLine);
       
  3251 	if (newLinePos < 0)
       
  3252 		{
       
  3253 		if (iPos < iBuffer.Length())
       
  3254 			{
       
  3255 			aText.AppendL(iBuffer, iPos);
       
  3256 			return KErrNone;
       
  3257 			}
       
  3258 		return KErrNotFound;
       
  3259 		}
       
  3260 	else
       
  3261 		{
       
  3262 		const TInt lineLength = newLinePos + KNewLine().Length();
       
  3263 		aText.AppendL(iBuffer, iPos, lineLength);
       
  3264 		iPos += lineLength;
       
  3265 		return KErrNone;
       
  3266 		}
       
  3267 	}
       
  3268 
       
  3269 TReadHandleLineReader::TReadHandleLineReader(RIoReadHandle& aHandle)
       
  3270 	: iHandle(aHandle)
       
  3271 	{
       
  3272 	}
       
  3273 
       
  3274 void TReadHandleLineReader::InitializeL()
       
  3275 	{
       
  3276 	iHandle.SetReadModeL(RIoReadHandle::ELine);
       
  3277 	}
       
  3278 
       
  3279 TInt TReadHandleLineReader::GetNextLine(CTextBuffer& aText)
       
  3280 	{
       
  3281 	aText.Zero();
       
  3282 	TInt err = iHandle.Read(iLineBuf);
       
  3283 	if (err == KErrNone)
       
  3284 		{
       
  3285 		aText.AppendL(iLineBuf);
       
  3286 		}
       
  3287 	else if (err == KErrEof)
       
  3288 		{
       
  3289 		err = KErrNotFound;
       
  3290 		}
       
  3291 	return err;
       
  3292 	}
       
  3293 
       
  3294 
       
  3295 EXPORT_C void CCommandBase::PageL(const CTextBuffer& aText)
       
  3296 	{
       
  3297 	TTextBufferLineReader lineReader(aText);
       
  3298 	lineReader.InitializeL();
       
  3299 	PageL(lineReader);
       
  3300 	}
       
  3301 
       
  3302 EXPORT_C void CCommandBase::PageL(RIoReadHandle& aInput)
       
  3303 	{
       
  3304 	TReadHandleLineReader lineReader(aInput);
       
  3305 	lineReader.InitializeL();
       
  3306 	PageL(lineReader);
       
  3307 	}
       
  3308 
       
  3309 void CCommandBase::PageL(MLineReader& aLineReader)
       
  3310 	{
       
  3311 	_LIT(KPrompt, "--More--");
       
  3312 	_LIT(KRemovePrompt, "\x08\x08\x08\x08\x08\x08\x08\x08        \x08\x08\x08\x08\x08\x08\x08\x08");
       
  3313 
       
  3314 	if (iStdout.AttachedToConsole())
       
  3315 		{
       
  3316 		RIoConsole console;
       
  3317 		console.OpenL(IoSession(), iStdout);
       
  3318 		CleanupClosePushL(console);
       
  3319 		RIoConsoleReadHandle consReader;
       
  3320 		consReader.CreateL(IoSession());
       
  3321 		CleanupClosePushL(consReader);
       
  3322 		console.AttachL(consReader, RIoEndPoint::EForeground);
       
  3323 		consReader.CaptureAllKeysL();
       
  3324 		TSize consoleSize = iStdout.GetScreenSizeL();
       
  3325 		CTextBuffer* lineBuf = CTextBuffer::NewLC(0x100);
       
  3326 		TInt linesPrinted = 0;
       
  3327 		TBool finished(EFalse);
       
  3328 		while (!finished)
       
  3329 			{
       
  3330 			if (linesPrinted < (consoleSize.iHeight - 1))
       
  3331 				{
       
  3332 				if (lineBuf->Length() == 0)
       
  3333 					{
       
  3334 					TInt err = aLineReader.GetNextLine(*lineBuf);
       
  3335 					if (err == KErrNotFound)
       
  3336 						{
       
  3337 						finished = ETrue;
       
  3338 						}
       
  3339 					else if (err)
       
  3340 						{
       
  3341 						User::Leave(err);
       
  3342 						}
       
  3343 					}
       
  3344 
       
  3345 				if (!finished && lineBuf->Length())
       
  3346 					{
       
  3347 					const TInt lineLength = lineBuf->Length();
       
  3348 					const TInt numConsoleLines = ((lineLength / consoleSize.iWidth) + ((lineLength % consoleSize.iWidth) ? 1 : 0));
       
  3349 					const TInt numFreeLines = consoleSize.iHeight - linesPrinted - 1;
       
  3350 					TInt lengthToWrite;
       
  3351 					if (numConsoleLines < numFreeLines)
       
  3352 						{
       
  3353 						lengthToWrite = lineLength;
       
  3354 						}
       
  3355 					else
       
  3356 						{
       
  3357 						lengthToWrite = Min(lineLength, numFreeLines * consoleSize.iWidth);
       
  3358 						}
       
  3359 
       
  3360 					lineBuf->Write(iStdout, 0, lengthToWrite);
       
  3361 					linesPrinted += ((lengthToWrite / consoleSize.iWidth) + ((lengthToWrite % consoleSize.iWidth) ? 1 : 0));
       
  3362 					lineBuf->Delete(0, lengthToWrite);
       
  3363 
       
  3364 					if (lineBuf->Length() == 0)
       
  3365 						{
       
  3366 						TInt err = aLineReader.GetNextLine(*lineBuf);
       
  3367 						if (err == KErrNotFound)
       
  3368 							{
       
  3369 							finished = ETrue;
       
  3370 							}
       
  3371 						else if (err)
       
  3372 							{
       
  3373 							User::Leave(err);
       
  3374 							}
       
  3375 						}
       
  3376 					}
       
  3377 				}
       
  3378 			else
       
  3379 				{
       
  3380 				iStdout.Write(KPrompt);
       
  3381 				switch ((TInt)consReader.ReadKey())
       
  3382 					{
       
  3383 					case 'q':
       
  3384 					case 'Q':
       
  3385 					case EKeyNull:
       
  3386 						{
       
  3387 						finished = ETrue;
       
  3388 						break;
       
  3389 						}
       
  3390 					case EKeyEnter:
       
  3391 						{
       
  3392 						--linesPrinted;
       
  3393 						break;
       
  3394 						}
       
  3395 					default:
       
  3396 						{
       
  3397 						linesPrinted = 0;
       
  3398 						break;
       
  3399 						}
       
  3400 					}
       
  3401 				iStdout.Write(KRemovePrompt);
       
  3402 				}
       
  3403 			}
       
  3404 		CleanupStack::PopAndDestroy(3, &console);
       
  3405 		}
       
  3406 	else
       
  3407 		{
       
  3408 		// Not attached to a console, so just copy stdin to stdout.
       
  3409 		CTextBuffer* lineBuf = CTextBuffer::NewLC(0x100);
       
  3410 		while (aLineReader.GetNextLine(*lineBuf) == KErrNone)
       
  3411 			{
       
  3412 			iStdout.Write(lineBuf->Descriptor());
       
  3413 			}
       
  3414 		CleanupStack::PopAndDestroy(lineBuf);
       
  3415 		}
       
  3416 	}
       
  3417 
       
  3418 EXPORT_C const TDesC& CCommandBase::Description() const
       
  3419 	{
       
  3420 	if (iCif == NULL)
       
  3421 		{
       
  3422 		const_cast<CCommandBase*>(this)->iFlags |= EReadCif;
       
  3423 		return KNullDesC; // Dummy return value.
       
  3424 		}
       
  3425 	return iCif->ShortDescription();
       
  3426 	}
       
  3427 	
       
  3428 EXPORT_C const TDesC* CCommandBase::ConsoleImplementation()
       
  3429 	{
       
  3430 	return iConsoleImplementation;
       
  3431 	}
       
  3432 
       
  3433 EXPORT_C void CCommandBase::SetErrorReported(TBool aReported)
       
  3434 	{
       
  3435 	if (aReported)
       
  3436 		{
       
  3437 		iFlags |= EErrorReported;
       
  3438 		}
       
  3439 	else
       
  3440 		{
       
  3441 		iFlags &= ~EErrorReported;
       
  3442 		}
       
  3443 	}
       
  3444 
       
  3445 EXPORT_C void CCommandBase::StartSupressingErrors()
       
  3446 	{
       
  3447 	iSupressingErrors++;
       
  3448 	}
       
  3449 
       
  3450 EXPORT_C void CCommandBase::StopSupressingErrors()
       
  3451 	{
       
  3452 	iSupressingErrors--;
       
  3453 	}
       
  3454 
       
  3455 EXPORT_C TBool CCommandBase::IsComplete() const
       
  3456 	{
       
  3457 	return (iFlags & ECompleted);
       
  3458 	}
       
  3459 
       
  3460 EXPORT_C TInt CCommandBase::CompletionReason() const
       
  3461 	{
       
  3462 	__ASSERT_ALWAYS(IsComplete(), Panic(ENotYetComplete));
       
  3463 	return iCompletionReason;
       
  3464 	}
       
  3465 
       
  3466 HBufC* CCommandBase::ReadStringLC(TLex& aLex, TUint aOptions) const
       
  3467 	{
       
  3468 	while (!aLex.Eos() && (aLex.Peek().IsSpace() || ((aOptions & EBreakOnComma) && (aLex.Peek() == ','))))
       
  3469 		{
       
  3470 		aLex.Inc();
       
  3471 		}
       
  3472 
       
  3473 	if (aLex.Eos())
       
  3474 		{
       
  3475 		// There aren't any characters at all. This can be considered a syntax error because if an empty string was intended
       
  3476 		// it should have been written as "" or ''.
       
  3477 		CommandLeaveIfErr(*const_cast<CCommandBase*>(this), KErrArgument, _L("Missing argument"));
       
  3478 		}
       
  3479 
       
  3480 	TChar c = aLex.Peek();
       
  3481 	TBool quoted = ((c == '\'') || (c == '"') || (c == iEnv->EscapeChar()));
       
  3482 	TUint readMode = 0;
       
  3483 	if (aOptions & EBreakOnComma)
       
  3484 		{
       
  3485 		readMode |= Stringify::EBreakOnComma;
       
  3486 		}
       
  3487 	HBufC* string = Stringify::ReadLC(aLex, iEnv->EscapeChar(), *const_cast<CCommandBase*>(this), readMode);
       
  3488 	if ((aOptions & EDisallowLeadingHyphen) && (string->Length() > 0) && ((*string)[0] == '-') && !quoted)
       
  3489 		{
       
  3490 		CommandLeaveIfErr(*const_cast<CCommandBase*>(this), KErrArgument, _L("Argument \"%S\" appears to be an option - probable missing argument"), string);
       
  3491 		}
       
  3492 	return string;
       
  3493 	}
       
  3494 
       
  3495 EXPORT_C void RChildProcess::Close()
       
  3496 	{
       
  3497 	iStderr.Close();
       
  3498 	iStdout.Close();
       
  3499 	iStdin.Close();
       
  3500 	iProcess.Close();
       
  3501 	}
       
  3502 
       
  3503 void SetIoObjectName(RIoSession& aIoSession, TInt aObjHandle, TRefByValue<const TDesC> aFmt, ...)
       
  3504 	{
       
  3505 	TOverflowTruncate overflow;
       
  3506 	VA_LIST list;
       
  3507 	VA_START(list, aFmt);
       
  3508 	TFullName name;
       
  3509 	name.AppendFormatList(aFmt, list, &overflow);
       
  3510 	VA_END(list);
       
  3511 	aIoSession.SetObjectName(aObjHandle, name);
       
  3512 	}
       
  3513 
       
  3514 EXPORT_C void RChildProcess::CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr)
       
  3515 	{
       
  3516 	DoCreateL(aExecutableName, aCommandLine, aIoSession, aStdin, aStdout, aStderr, NULL);
       
  3517 	}
       
  3518 
       
  3519 EXPORT_C void RChildProcess::CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const CEnvironment& aEnv)
       
  3520 	{
       
  3521 	DoCreateL(aExecutableName, aCommandLine, aIoSession, aStdin, aStdout, aStderr, &aEnv);
       
  3522 	}
       
  3523 	
       
  3524 EXPORT_C void RChildProcess::CreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoConsole& aConsole, const CEnvironment* aEnv)
       
  3525 	{
       
  3526 	CleanupClosePushL(*this);
       
  3527 	iStdin.CreateL(aIoSession);
       
  3528 	iStdout.CreateL(aIoSession);
       
  3529 	iStderr.CreateL(aIoSession);
       
  3530 	
       
  3531 	NameHandles(aExecutableName, aIoSession);
       
  3532 	
       
  3533 	aConsole.AttachL(iStdin, RIoEndPoint::EForeground);
       
  3534 	iStdin.SetUnderlyingConsoleL(aConsole);
       
  3535 	aConsole.AttachL(iStdout);
       
  3536 	iStdout.SetUnderlyingConsoleL(aConsole);
       
  3537 	aConsole.AttachL(iStderr);
       
  3538 	iStderr.SetUnderlyingConsoleL(aConsole);
       
  3539 	
       
  3540 	ProcessCreateL(aExecutableName, aCommandLine, aEnv);
       
  3541 	
       
  3542 	CleanupStack::Pop();
       
  3543 	}
       
  3544 
       
  3545 void RChildProcess::NameHandles(const TDesC& aExecutableName, RIoSession& aIoSession)
       
  3546 	{
       
  3547 	// Give the handles a name to aid debugging (makes the iosvr logs easier to understand).
       
  3548 	SetIoObjectName(aIoSession, iStdin.SubSessionHandle(), _L("%S_stdin"), &aExecutableName);
       
  3549 	SetIoObjectName(aIoSession, iStdout.SubSessionHandle(), _L("%S_stdout"), &aExecutableName);
       
  3550 	SetIoObjectName(aIoSession, iStderr.SubSessionHandle(), _L("%S_stderr"), &aExecutableName);
       
  3551 	}
       
  3552 
       
  3553 void RChildProcess::DoCreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, RIoSession& aIoSession, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr, const CEnvironment* aEnv)
       
  3554 	{
       
  3555 	CleanupClosePushL(*this);
       
  3556 
       
  3557 	// Create a set of I/O handles for the new process.
       
  3558 	User::LeaveIfError(iStdin.Create(aIoSession));
       
  3559 	User::LeaveIfError(iStdout.Create(aIoSession));
       
  3560 	User::LeaveIfError(iStderr.Create(aIoSession));
       
  3561 	
       
  3562 	NameHandles(aExecutableName, aIoSession);
       
  3563 
       
  3564 	// Make the newly created handles duplicates of the ones that were passed in.
       
  3565 	// This makes them attached to the same I/O end-points (consoles, files, etc)
       
  3566 	// as the passed in handles.
       
  3567 	User::LeaveIfError(iStdin.Duplicate(aStdin));
       
  3568 	User::LeaveIfError(iStdin.SetToForeground());
       
  3569 	User::LeaveIfError(iStdout.Duplicate(aStdout));
       
  3570 	User::LeaveIfError(iStderr.Duplicate(aStderr));
       
  3571 
       
  3572 	// Create the process.
       
  3573 	ProcessCreateL(aExecutableName, aCommandLine, aEnv);
       
  3574 	
       
  3575 	CleanupStack::Pop(this);	
       
  3576 	}
       
  3577 	
       
  3578 void RChildProcess::ProcessCreateL(const TDesC& aExecutableName, const TDesC& aCommandLine, const CEnvironment* aEnv)
       
  3579 	{
       
  3580 	User::LeaveIfError(iProcess.Create(aExecutableName, aCommandLine));
       
  3581 
       
  3582 #ifdef EKA2
       
  3583 	if (aEnv)
       
  3584 		{
       
  3585 		// Attach a copy of aEnv as a parameter.
       
  3586 		HBufC8* envBuf = aEnv->ExternalizeLC();
       
  3587 		User::LeaveIfError(iProcess.SetParameter(IoUtils::KEnvironmentProcessSlot, *envBuf));
       
  3588 		CleanupStack::PopAndDestroy(envBuf);
       
  3589 		}
       
  3590 #endif
       
  3591 
       
  3592 	// Make the main thread of the new process the owner of the I/O handles.
       
  3593 	// This makes it possible for the new process to subsequently open them and
       
  3594 	// avoid having to create a new set (which would prevent end-point sharing).
       
  3595 	TFullName fullName(iProcess.Name());
       
  3596 	_LIT(KThreadName,"::Main");
       
  3597 	fullName.Append(KThreadName);
       
  3598 	RThread thread;
       
  3599 	User::LeaveIfError(thread.Open(fullName));
       
  3600 	TThreadId threadId(thread.Id());
       
  3601 	thread.Close();
       
  3602 	User::LeaveIfError(iStdin.SetOwner(threadId));
       
  3603 	User::LeaveIfError(iStdout.SetOwner(threadId));
       
  3604 	User::LeaveIfError(iStderr.SetOwner(threadId));
       
  3605 	}
       
  3606 
       
  3607 EXPORT_C void RChildProcess::Run(TRequestStatus& aStatus)
       
  3608 	{
       
  3609 	iProcess.Logon(aStatus);
       
  3610 	if (aStatus != KRequestPending)
       
  3611 		{
       
  3612 		iProcess.Kill(KErrAbort);
       
  3613 		}
       
  3614 	else
       
  3615 		{
       
  3616 		iProcess.Resume();
       
  3617 		}
       
  3618 	}
       
  3619 	
       
  3620 EXPORT_C void RChildProcess::Detach()
       
  3621 	{
       
  3622 	iProcess.Resume();
       
  3623 	}
       
  3624 
       
  3625 EXPORT_C RProcess& RChildProcess::Process()
       
  3626 	{
       
  3627 	return iProcess;
       
  3628 	}
       
  3629 
       
  3630 EXPORT_C const RProcess& RChildProcess::Process() const
       
  3631 	{
       
  3632 	return iProcess;
       
  3633 	}
       
  3634 
       
  3635 #define CASE_RETURN_LIT(XXX) case XXX: { _LIT(_KLit, #XXX); return &_KLit; }
       
  3636 #define CASE_RETURN_LIT2(XXX, YYY) case XXX: { _LIT(_KLit, YYY); return &_KLit; }
       
  3637 #define DEFAULT_RETURN_LIT(XXX) default: { _LIT(_KLit, XXX); return &_KLit; }
       
  3638 	
       
  3639 EXPORT_C const TDesC* Stringify::Error(TInt aError)
       
  3640 	{
       
  3641 	enum TThingsNotAvailableEverywhere
       
  3642 		{
       
  3643 		KErrNoSecureTime = -49,
       
  3644 		KErrCorruptSurrogateFound = -50,
       
  3645 		};
       
  3646 
       
  3647 	switch (aError)
       
  3648 		{
       
  3649 		CASE_RETURN_LIT(KErrNone);
       
  3650 		CASE_RETURN_LIT(KErrNotFound);
       
  3651 		CASE_RETURN_LIT(KErrGeneral);
       
  3652 		CASE_RETURN_LIT(KErrCancel);
       
  3653 		CASE_RETURN_LIT(KErrNoMemory);
       
  3654 		CASE_RETURN_LIT(KErrNotSupported);
       
  3655 		CASE_RETURN_LIT(KErrArgument);
       
  3656 		CASE_RETURN_LIT(KErrTotalLossOfPrecision);
       
  3657 		CASE_RETURN_LIT(KErrBadHandle);
       
  3658 		CASE_RETURN_LIT(KErrOverflow);
       
  3659 		CASE_RETURN_LIT(KErrUnderflow);
       
  3660 		CASE_RETURN_LIT(KErrAlreadyExists);
       
  3661 		CASE_RETURN_LIT(KErrPathNotFound);
       
  3662 		CASE_RETURN_LIT(KErrDied);
       
  3663 		CASE_RETURN_LIT(KErrInUse);
       
  3664 		CASE_RETURN_LIT(KErrServerTerminated);
       
  3665 		CASE_RETURN_LIT(KErrServerBusy);
       
  3666 		CASE_RETURN_LIT(KErrCompletion);
       
  3667 		CASE_RETURN_LIT(KErrNotReady);
       
  3668 		CASE_RETURN_LIT(KErrUnknown);
       
  3669 		CASE_RETURN_LIT(KErrCorrupt);
       
  3670 		CASE_RETURN_LIT(KErrAccessDenied);
       
  3671 		CASE_RETURN_LIT(KErrLocked);
       
  3672 		CASE_RETURN_LIT(KErrWrite);
       
  3673 		CASE_RETURN_LIT(KErrDisMounted);
       
  3674 		CASE_RETURN_LIT(KErrEof);
       
  3675 		CASE_RETURN_LIT(KErrDiskFull);
       
  3676 		CASE_RETURN_LIT(KErrBadDriver);
       
  3677 		CASE_RETURN_LIT(KErrBadName);
       
  3678 		CASE_RETURN_LIT(KErrCommsLineFail);
       
  3679 		CASE_RETURN_LIT(KErrCommsFrame);
       
  3680 		CASE_RETURN_LIT(KErrCommsOverrun);
       
  3681 		CASE_RETURN_LIT(KErrCommsParity);
       
  3682 		CASE_RETURN_LIT(KErrTimedOut);
       
  3683 		CASE_RETURN_LIT(KErrCouldNotConnect);
       
  3684 		CASE_RETURN_LIT(KErrCouldNotDisconnect);
       
  3685 		CASE_RETURN_LIT(KErrDisconnected);
       
  3686 		CASE_RETURN_LIT(KErrBadLibraryEntryPoint);
       
  3687 		CASE_RETURN_LIT(KErrBadDescriptor);
       
  3688 		CASE_RETURN_LIT(KErrAbort);
       
  3689 		CASE_RETURN_LIT(KErrTooBig);
       
  3690 		CASE_RETURN_LIT(KErrDivideByZero);
       
  3691 		CASE_RETURN_LIT(KErrBadPower);
       
  3692 		CASE_RETURN_LIT(KErrDirFull);
       
  3693 		CASE_RETURN_LIT(KErrHardwareNotAvailable);
       
  3694 #ifdef EKA2
       
  3695 		CASE_RETURN_LIT(KErrSessionClosed);
       
  3696 		CASE_RETURN_LIT(KErrPermissionDenied);
       
  3697 		CASE_RETURN_LIT(KErrExtensionNotSupported);
       
  3698 		CASE_RETURN_LIT(KErrCommsBreak);
       
  3699 		CASE_RETURN_LIT(KErrNoSecureTime);
       
  3700 		CASE_RETURN_LIT(KErrCorruptSurrogateFound);
       
  3701 #endif
       
  3702 		DEFAULT_RETURN_LIT("*** ERROR UNKNOWN ***");
       
  3703 		}
       
  3704 	}
       
  3705 
       
  3706 EXPORT_C void IoUtils::ReadL(TDes& aData)
       
  3707 	{
       
  3708 	CCommandBase::Static().ReadL(aData);
       
  3709 	}
       
  3710 
       
  3711 EXPORT_C void IoUtils::Write(const TDesC& aData)
       
  3712 	{
       
  3713 	CCommandBase::Static().Write(aData);
       
  3714 	}
       
  3715 
       
  3716 EXPORT_C void IoUtils::Printf(TRefByValue<const TDesC> aFmt, ...)
       
  3717 	{
       
  3718 	VA_LIST list;
       
  3719 	VA_START(list, aFmt);
       
  3720 	CCommandBase::Static().PrintList(aFmt, list);
       
  3721 	VA_END(list);
       
  3722 	}
       
  3723 
       
  3724 EXPORT_C void IoUtils::Printf(TRefByValue<const TDesC8> aFmt, ...)
       
  3725 	{
       
  3726 	VA_LIST list;
       
  3727 	VA_START(list, aFmt);
       
  3728 	CCommandBase::Static().PrintList(aFmt, list);
       
  3729 	VA_END(list);
       
  3730 	}
       
  3731 
       
  3732 EXPORT_C void IoUtils::PrintError(TInt aError, TRefByValue<const TDesC> aFmt, ...)
       
  3733 	{
       
  3734 	VA_LIST list;
       
  3735 	VA_START(list, aFmt);
       
  3736 	CCommandBase::Static().PrintErrorList(aError, aFmt, list);
       
  3737 	VA_END(list);
       
  3738 	}
       
  3739 
       
  3740 EXPORT_C void IoUtils::PrintWarning(TRefByValue<const TDesC> aFmt, ...)
       
  3741 	{
       
  3742 	VA_LIST list;
       
  3743 	VA_START(list, aFmt);
       
  3744 	CCommandBase::Static().PrintWarningList(aFmt, list);
       
  3745 	VA_END(list);
       
  3746 	}
       
  3747 
       
  3748 
       
  3749 //
       
  3750 // CCommandCompleter.
       
  3751 //
       
  3752 
       
  3753 CCommandCompleter::CCommandCompleter(IoUtils::CCommandBase& aCmd)
       
  3754 	: CActive(CActive::EPriorityStandard), iCmd(aCmd)
       
  3755 	{
       
  3756 	CActiveScheduler::Add(this);
       
  3757 	}
       
  3758 
       
  3759 CCommandCompleter::~CCommandCompleter()
       
  3760 	{
       
  3761 	Cancel();
       
  3762 	delete iTextBuffer;
       
  3763 	}
       
  3764 
       
  3765 void CCommandCompleter::Complete(TInt aError)
       
  3766 	{
       
  3767 	TRequestStatus* status = &iStatus;
       
  3768 	User::RequestComplete(status, aError);
       
  3769 	SetActive();
       
  3770 	}
       
  3771 
       
  3772 void CCommandCompleter::Complete(TInt aError, const TDesC& aText, RIoWriteHandle& aWhere)
       
  3773 	{
       
  3774 	TOverflowTruncate overflow;
       
  3775 	iBuf.AppendFormat(aText, &overflow);
       
  3776 	iError = aError;
       
  3777 	aWhere.Write(iBuf, iStatus);
       
  3778 	SetActive();
       
  3779 	}
       
  3780 	
       
  3781 void CCommandCompleter::Complete(TInt aError, const CTextBuffer* aTextBuffer, RIoWriteHandle& aWhere)
       
  3782 	{
       
  3783 	ASSERT(iTextBuffer == NULL);
       
  3784 	iTextBuffer = aTextBuffer;
       
  3785 	iError = aError;
       
  3786 	iTextBuffer->Write(aWhere, iStatus);
       
  3787 	SetActive();
       
  3788 	}
       
  3789 
       
  3790 void CCommandCompleter::RunL()
       
  3791 	{
       
  3792 	iCmd.CompleteCallback(iError ? iError : iStatus.Int());
       
  3793 	}
       
  3794 
       
  3795 void CCommandCompleter::DoCancel()
       
  3796 	{
       
  3797 	}
       
  3798 	
       
  3799 
       
  3800 //
       
  3801 // CReaderChangeNotifier.
       
  3802 //
       
  3803 
       
  3804 CReaderChangeNotifier::CReaderChangeNotifier(IoUtils::CCommandBase& aCmd, RIoReadHandle& aReadHandle)
       
  3805 	: CActive(CActive::EPriorityStandard)
       
  3806 	, iCmd(aCmd)
       
  3807 	, iReadHandle(aReadHandle)
       
  3808 	{
       
  3809 	CActiveScheduler::Add(this);
       
  3810 	}
       
  3811 
       
  3812 CReaderChangeNotifier::~CReaderChangeNotifier()
       
  3813 	{
       
  3814 	Cancel();
       
  3815 	}
       
  3816 
       
  3817 void CReaderChangeNotifier::Notify()
       
  3818 	{
       
  3819 	iReadHandle.NotifyChange(iChangeType, iStatus);
       
  3820 	SetActive();
       
  3821 	}
       
  3822 
       
  3823 void CReaderChangeNotifier::RunL()
       
  3824 	{
       
  3825 	if (iStatus.Int()==KErrNone)
       
  3826 		{
       
  3827 		TUint change = iChangeType();
       
  3828 		Notify();
       
  3829 		iCmd.StdinChange(change);
       
  3830 		}
       
  3831 	}
       
  3832 
       
  3833 void CReaderChangeNotifier::DoCancel()
       
  3834 	{
       
  3835 	iReadHandle.CancelNotifyChange();
       
  3836 	}
       
  3837 
       
  3838