core/src/commands.cpp
changeset 0 7f656887cf89
child 7 184a1eb85cf2
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // commands.cpp
       
     2 // 
       
     3 // Copyright (c) 2006 - 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 <e32debug.h>
       
    14 #include <e32rom.h>
       
    15 #include <f32dbg.h>
       
    16 #include <f32image.h>
       
    17 #include <hal.h>
       
    18 #include <fshell/common.mmh>
       
    19 #include <fshell/ltkutils.h>
       
    20 #include <fshell/descriptorutils.h>
       
    21 #include <fshell/heaputils.h>
       
    22 using LtkUtils::RAllocatorHelper;
       
    23 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
    24 #include <fshell/memoryaccess.h>
       
    25 #endif
       
    26 #include "fshell.h"
       
    27 #include "commands.h"
       
    28 #include "command_factory.h"
       
    29 #include "string_utils.h"
       
    30 
       
    31 
       
    32 //
       
    33 // Constants.
       
    34 //
       
    35 
       
    36 _LIT(KOptVerbose, "verbose");
       
    37 _LIT(KOptHuman, "human");
       
    38 
       
    39 _LIT(KNewLine, "\r\n");
       
    40 _LIT(KTab, "\t");
       
    41 _LIT(KRepeatCount, "REPEAT_COUNT");
       
    42 const TInt KBlockSize = 512;
       
    43 
       
    44 _LIT(KMatchAll, "*");
       
    45 
       
    46 
       
    47 //
       
    48 // CCmdHelp.
       
    49 //
       
    50 
       
    51 CCommandBase* CCmdHelp::NewLC()
       
    52 	{
       
    53 	CCmdHelp* self = new(ELeave) CCmdHelp();
       
    54 	CleanupStack::PushL(self);
       
    55 	self->BaseConstructL();
       
    56 	return self;
       
    57 	}
       
    58 
       
    59 CCmdHelp::~CCmdHelp()
       
    60 	{
       
    61 	delete iFormatter;
       
    62 	}
       
    63 
       
    64 CCmdHelp::CCmdHelp() : CCommandBase(ECompleteOnRunL)
       
    65 	{
       
    66 	}
       
    67 
       
    68 const TDesC& CCmdHelp::Name() const
       
    69 	{
       
    70 	_LIT(KCmdHelpName, "help");
       
    71 	return KCmdHelpName;
       
    72 	}
       
    73 
       
    74 void CCmdHelp::DoRunL()
       
    75 	{
       
    76 	if (iOptions.IsPresent(&iCount))
       
    77 		{
       
    78 		const TInt count = gShell->CommandFactory().CountUniqueCommandsL();
       
    79 		Complete(_L("%d\r\n"), count);
       
    80 		}
       
    81 	else
       
    82 		{
       
    83 		RArray<TPtrC> commands;
       
    84 		CleanupClosePushL(commands);
       
    85 		gShell->CommandFactory().ListCommandsL(commands);
       
    86 		iFormatter = CTextFormatter::NewL(Stdout());
       
    87 		iFormatter->ColumnizeL(0, 2, commands.Array());
       
    88 		CleanupStack::PopAndDestroy(&commands);
       
    89 		Stdout().Write(iFormatter->Descriptor(), iStatus);
       
    90 		SetActive();
       
    91 		}
       
    92 	}
       
    93 
       
    94 void CCmdHelp::OptionsL(RCommandOptionList& aOptions)
       
    95 	{
       
    96 	_LIT(KOptCount, "count");
       
    97 	aOptions.AppendBoolL(iCount, KOptCount);
       
    98 	}
       
    99 
       
   100 
       
   101 //
       
   102 // CCmdExit.
       
   103 //
       
   104 
       
   105 CCommandBase* CCmdExit::NewLC()
       
   106 	{
       
   107 	CCmdExit* self = new(ELeave) CCmdExit();
       
   108 	CleanupStack::PushL(self);
       
   109 	self->BaseConstructL();
       
   110 	return self;
       
   111 	}
       
   112 
       
   113 CCmdExit::~CCmdExit()
       
   114 	{
       
   115 	}
       
   116 
       
   117 CCmdExit::CCmdExit()
       
   118 	{
       
   119 	}
       
   120 
       
   121 const TDesC& CCmdExit::Name() const
       
   122 	{
       
   123 	_LIT(KCmdExitName, "exit");
       
   124 	return KCmdExitName;
       
   125 	}
       
   126 
       
   127 void CCmdExit::DoRunL()
       
   128 	{
       
   129 	// Note, this command should never execute as 'exit' has handled explicitly by CParser.
       
   130 	// It exists so that 'exit' appears in fshell's help list and also to support 'exit --help'.
       
   131 	LeaveIfErr(KErrGeneral, _L("Invalid context for 'exit' command (must be run as a bare command, not in a pipe-line)"));
       
   132 	}
       
   133 
       
   134 
       
   135 //
       
   136 // CCmdLs.
       
   137 //
       
   138 
       
   139 CCommandBase* CCmdLs::NewLC()
       
   140 	{
       
   141 	CCmdLs* self = new(ELeave) CCmdLs();
       
   142 	CleanupStack::PushL(self);
       
   143 	self->ConstructL();
       
   144 	return self;
       
   145 	}
       
   146 
       
   147 CCmdLs::~CCmdLs()
       
   148 	{
       
   149 	delete iFormatter;
       
   150 	}
       
   151 
       
   152 CCmdLs::CCmdLs()
       
   153 	{
       
   154 	}
       
   155 
       
   156 void CCmdLs::ConstructL()
       
   157 	{
       
   158 	BaseConstructL();
       
   159 	}
       
   160 
       
   161 void CCmdLs::PrintDirContentL(RDir& aDir)
       
   162 	{
       
   163 	TInt err = KErrNone;
       
   164 	TEntry entry;
       
   165 	while (err == KErrNone)
       
   166 		{
       
   167 		err = aDir.Read(entry);
       
   168 		if (err == KErrNone)
       
   169 			{
       
   170 			FormatEntryL(entry);
       
   171 			Write(iFormatter->Descriptor());
       
   172 			iFormatter->Zero();
       
   173 
       
   174 			if (iOptRecurse && entry.IsDir())
       
   175 				{
       
   176 				RecursiveScanDirL(entry.iName);
       
   177 				}
       
   178 			}
       
   179 		}
       
   180 	if (err == KErrEof)
       
   181 		{
       
   182 		err = KErrNone;
       
   183 		}
       
   184 	User::LeaveIfError(err);
       
   185 	}
       
   186 
       
   187 void CCmdLs::PrintDirContentL(const CDir& aDir)
       
   188 	{
       
   189 	IoUtils::CTextBuffer* buf = IoUtils::CTextBuffer::NewLC(0x100);
       
   190 
       
   191 	const TInt numEntries = aDir.Count();
       
   192 	for (TInt i = 0; i < numEntries; ++i)
       
   193 		{
       
   194 		const TEntry& entry = aDir[i];
       
   195 		buf->AppendL(entry.iName);
       
   196 		buf->AppendL(_L("\t"));
       
   197 		}
       
   198 
       
   199 	iFormatter->ColumnizeL(0, 2, buf->Descriptor());
       
   200 	Write(iFormatter->Descriptor());
       
   201 	CleanupStack::PopAndDestroy(buf);
       
   202 	}
       
   203 
       
   204 void CCmdLs::FormatEntryL(const TEntry& aEntry)
       
   205 	{
       
   206 	if (iOptLong)
       
   207 		{
       
   208 		iFormatter->AppendFormatL(_L("%c%c%c%c%c  "), aEntry.IsDir() ? 'd' : '-', aEntry.IsReadOnly() ? 'r' : '-', aEntry.IsHidden() ? 'h' : '-', aEntry.IsSystem() ? 's' : '-', aEntry.IsArchive() ? 'a' : '-');
       
   209 		if (iOptHuman)
       
   210 			{
       
   211 			iFormatter->AppendHumanReadableSizeL(aEntry.iSize);
       
   212 			iFormatter->AppendL(_L("  "));
       
   213 			}
       
   214 		else
       
   215 			{
       
   216 			iFormatter->AppendFormatL(_L("%+ 10d  "), aEntry.iSize);
       
   217 			}
       
   218 		aEntry.iModified.FormatL(iTempBuf, _L("%1%/1%2%/2%3 %H%:1%T%:2%S "));
       
   219 		TPtrC pathRelativeToBaseDir = iFileName.Mid(iBaseDir.Length());
       
   220 		iFormatter->AppendFormatL(_L("%S%S%S\r\n"), &iTempBuf, &pathRelativeToBaseDir, &aEntry.iName);
       
   221 		}
       
   222 	else
       
   223 		{
       
   224 		TPtrC pathRelativeToBaseDir = iFileName.Mid(iBaseDir.Length());
       
   225 		iFormatter->AppendFormatL(_L("%S%S\r\n"), &pathRelativeToBaseDir, &aEntry.iName);
       
   226 		}
       
   227 	}
       
   228 
       
   229 const TDesC& CCmdLs::Name() const
       
   230 	{
       
   231 	_LIT(KCmdLsName, "ls");
       
   232 	return KCmdLsName;
       
   233 	}
       
   234 
       
   235 void CCmdLs::DoRunL()
       
   236 	{
       
   237 	if (iFileName.Length() == 0)
       
   238 		{
       
   239 		iFileName = Env().Pwd();
       
   240 		}
       
   241 
       
   242 	if (!iFileName.IsWild() && !iFileName.IsDriveRoot())
       
   243 		{
       
   244 		LeaveIfFileNotFound(iFileName);
       
   245 		if (iFileName.IsDirL(FsL()))
       
   246 			{
       
   247 			iFileName.SetIsDirectoryL();
       
   248 			}
       
   249 		}
       
   250 
       
   251 	if (iOptRecurse || iOptLong || !Stdout().AttachedToConsole())
       
   252 		{
       
   253 		iOptOnePerLine = ETrue;
       
   254 		}
       
   255 
       
   256 	iFormatter = CTextFormatter::NewL(Stdout());
       
   257 	iBaseDir.Set(TParsePtrC(iFileName).DriveAndPath());
       
   258 
       
   259 	if (iOptOnePerLine)
       
   260 		{
       
   261 		DoScanDirL();
       
   262 		}
       
   263 	else
       
   264 		{
       
   265 		CDir* files;
       
   266 		LeaveIfErr(FsL().GetDir(iFileName, iOptAll ? KEntryAttMaskSupported : KEntryAttNormal | KEntryAttDir, ESortByName, files), _L("Couldn't read whole directory into memory - try using -1"));
       
   267 		CleanupStack::PushL(files);
       
   268 		PrintDirContentL(*files);
       
   269 		CleanupStack::PopAndDestroy(files);
       
   270 		}
       
   271 	}
       
   272 
       
   273 void CCmdLs::OptionsL(RCommandOptionList& aOptions)
       
   274 	{
       
   275 	_LIT(KCmdLsOptAll, "all");
       
   276 	_LIT(KCmdLsOptLong, "long");
       
   277 	_LIT(KCmdLsOptHuman, "human");
       
   278 	_LIT(KCmdLsOptOnePerLine, "one");
       
   279 	_LIT(KCmdLsOpRecurse, "recurse");
       
   280 
       
   281 	aOptions.AppendBoolL(iOptAll, KCmdLsOptAll);
       
   282 	aOptions.AppendBoolL(iOptLong, KCmdLsOptLong);
       
   283 	aOptions.AppendBoolL(iOptHuman, KCmdLsOptHuman);
       
   284 	aOptions.AppendBoolL(iOptOnePerLine, KCmdLsOptOnePerLine);
       
   285 	aOptions.AppendBoolL(iOptRecurse, KCmdLsOpRecurse);
       
   286 	}
       
   287 
       
   288 void CCmdLs::ArgumentsL(RCommandArgumentList& aArguments)
       
   289 	{
       
   290 	_LIT(KCmdLsArg, "dir_name");
       
   291 	aArguments.AppendFileNameL(iFileName, KCmdLsArg);
       
   292 	}
       
   293 
       
   294 void CCmdLs::RecursiveScanDirL(const TDesC& aName)
       
   295 	{
       
   296 	TInt currentDirectoryLen = iFileName.Length();
       
   297 	iFileName.AppendComponentL(aName, TFileName2::EDirectory);
       
   298 	DoScanDirL();
       
   299 	iFileName.SetLength(currentDirectoryLen); // Since this is called recursively, restore iTempName to what it was previously
       
   300 	}
       
   301 
       
   302 void CCmdLs::DoScanDirL()
       
   303 	{
       
   304 	RDir dir;
       
   305 	User::LeaveIfError(dir.Open(FsL(), iFileName, iOptAll ? KEntryAttMaskSupported : KEntryAttNormal | KEntryAttDir));
       
   306 	CleanupClosePushL(dir);
       
   307 	iFileName.SetLength(TParsePtrC(iFileName).DriveAndPath().Length()); // Remove any possible wildcard or name from the end of iFileName before recursing
       
   308 	PrintDirContentL(dir);
       
   309 	CleanupStack::PopAndDestroy(&dir);
       
   310 	}
       
   311 
       
   312 //
       
   313 // CCmdCd.
       
   314 //
       
   315 
       
   316 CCommandBase* CCmdCd::NewLC()
       
   317 	{
       
   318 	CCmdCd* self = new(ELeave) CCmdCd();
       
   319 	CleanupStack::PushL(self);
       
   320 	self->BaseConstructL();
       
   321 	return self;
       
   322 	}
       
   323 
       
   324 CCmdCd::~CCmdCd()
       
   325 	{
       
   326 	}
       
   327 
       
   328 CCmdCd::CCmdCd()
       
   329 	: iDir(TFileName2::EDirectory)
       
   330 	{
       
   331 	}
       
   332 
       
   333 const TDesC& CCmdCd::Name() const
       
   334 	{
       
   335 	_LIT(KCmdCdName, "cd");
       
   336 	return KCmdCdName;
       
   337 	}
       
   338 
       
   339 void CCmdCd::DoRunL()
       
   340 	{
       
   341 	if (iDir.IsDriveRoot()) // For some reason best known to the designers of F32, it's not possible to retrieve a TEntry object for the root of a drive (fails with KErrBadName).
       
   342 		{
       
   343 		TDriveList driveList;
       
   344 		LeaveIfErr(FsL().DriveList(driveList), _L("Couldn't get drive list"));
       
   345 		TInt driveNum = TChar(iDir[0]).GetUpperCase() - 'A';
       
   346 		if (driveNum >= KMaxDrives)
       
   347 			{
       
   348 			Complete(KErrArgument, _L("Invalid drive letter"));
       
   349 			return;
       
   350 			}
       
   351 		if (!driveList[driveNum])
       
   352 			{
       
   353 			Complete(KErrNotReady, _L("Drive not present"));
       
   354 			return;
       
   355 			}
       
   356 		}
       
   357 	else
       
   358 		{
       
   359 		LeaveIfFileNotFound(iDir);
       
   360 		if (!iDir.IsDirL(FsL()))
       
   361 			{
       
   362 			Complete(KErrBadName, _L("%S is not a directory"), &iDir);
       
   363 			return;
       
   364 			}
       
   365 		}
       
   366 
       
   367 	Env().SetPwdL(iDir);
       
   368 	}
       
   369 
       
   370 void CCmdCd::ArgumentsL(RCommandArgumentList& aArguments)
       
   371 	{
       
   372 	_LIT(KCmdCdArg, "directory");
       
   373 	aArguments.AppendFileNameL(iDir, KCmdCdArg);
       
   374 	}
       
   375 
       
   376 
       
   377 //
       
   378 // CCmdClear.
       
   379 //
       
   380 
       
   381 CCommandBase* CCmdClear::NewLC()
       
   382 	{
       
   383 	CCmdClear* self = new(ELeave) CCmdClear();
       
   384 	CleanupStack::PushL(self);
       
   385 	self->BaseConstructL();
       
   386 	return self;
       
   387 	}
       
   388 
       
   389 CCmdClear::~CCmdClear()
       
   390 	{
       
   391 	}
       
   392 
       
   393 CCmdClear::CCmdClear()
       
   394 	{
       
   395 	}
       
   396 
       
   397 const TDesC& CCmdClear::Name() const
       
   398 	{
       
   399 	_LIT(KCmdClearName, "clear");
       
   400 	return KCmdClearName;
       
   401 	}
       
   402 
       
   403 void CCmdClear::DoRunL()
       
   404 	{
       
   405 	if (iFormFeed)
       
   406 		{
       
   407 		TInt consoleHeight = Stdout().GetScreenSizeL().iHeight;
       
   408 		Stdout().SetCursorPosAbsL(TPoint(0, consoleHeight-1));
       
   409 		RBuf buf;
       
   410 		buf.CreateL(consoleHeight * 2);
       
   411 		while (consoleHeight--) buf.Append(KNewLine);
       
   412 		Stdout().Write(buf);
       
   413 		buf.Close();
       
   414 		Stdout().SetCursorPosAbsL(TPoint(0,0));
       
   415 		}
       
   416 	else
       
   417 		{
       
   418 		Stdout().ClearScreenL();
       
   419 		Stdin().SetMode(RIoReadWriteHandle::EText);
       
   420 		Stdout().SetMode(RIoReadWriteHandle::EText);
       
   421 		Stderr().SetMode(RIoReadWriteHandle::EText);
       
   422 		}
       
   423 	}
       
   424 
       
   425 void CCmdClear::OptionsL(RCommandOptionList& aOptions)
       
   426 	{
       
   427 	_LIT(KOptFormFeed, "formfeed");
       
   428 	aOptions.AppendBoolL(iFormFeed, KOptFormFeed);
       
   429 	}
       
   430 
       
   431 //
       
   432 // CForegroundAdjuster
       
   433 //
       
   434 
       
   435 class CForegroundAdjuster : public CActive
       
   436 	{
       
   437 public:
       
   438 	static CForegroundAdjuster* NewL(CCommandBase& aCommand, TInt aJobId, TBool aToForeground);
       
   439 	~CForegroundAdjuster();
       
   440 private: // From CActive.
       
   441 	virtual void RunL();
       
   442 	virtual void DoCancel();
       
   443 	virtual TInt RunError(TInt aError);
       
   444 private:
       
   445 	CForegroundAdjuster(CCommandBase& aCommand, TInt aJobId, TBool aToForeground);
       
   446 private:
       
   447 	CCommandBase& iCommand;
       
   448 	TInt iJobId;
       
   449 	TBool iToForeground;
       
   450 	};
       
   451 
       
   452 CForegroundAdjuster* CForegroundAdjuster::NewL(CCommandBase& aCommand, TInt aJobId, TBool aToForeground)
       
   453 	{
       
   454 	return new(ELeave) CForegroundAdjuster(aCommand, aJobId, aToForeground);
       
   455 	}
       
   456 
       
   457 void CForegroundAdjuster::RunL()
       
   458 	{
       
   459 	gShell->ClaimJobsLockLC();
       
   460 
       
   461 	if (iToForeground)
       
   462 		{
       
   463 		gShell->BringJobToForeground(iJobId);
       
   464 		}
       
   465 	else
       
   466 		{
       
   467 		gShell->SendJobToBackground(iJobId);
       
   468 		}
       
   469 
       
   470 	CleanupStack::PopAndDestroy(); // jobs lock.
       
   471 	iCommand.Complete();
       
   472 	}
       
   473 
       
   474 void CForegroundAdjuster::DoCancel()
       
   475 	{
       
   476 	}
       
   477 
       
   478 TInt CForegroundAdjuster::RunError(TInt aError)
       
   479 	{
       
   480 	iCommand.Complete(aError);
       
   481 	return KErrNone;
       
   482 	}
       
   483 
       
   484 CForegroundAdjuster::CForegroundAdjuster(CCommandBase& aCommand, TInt aJobId, TBool aToForeground)
       
   485 	: CActive(CActive::EPriorityStandard), iCommand(aCommand), iJobId(aJobId), iToForeground(aToForeground)
       
   486 	{
       
   487 	CActiveScheduler::Add(this);
       
   488 	TRequestStatus* status = &iStatus;
       
   489 	User::RequestComplete(status, KErrNone);
       
   490 	SetActive();
       
   491 	}
       
   492 
       
   493 CForegroundAdjuster::~CForegroundAdjuster()
       
   494 	{
       
   495 	}
       
   496 
       
   497 
       
   498 //
       
   499 // CCmdFg.
       
   500 //
       
   501 
       
   502 void ParseJobSpecL(const TDesC& aString, TInt& aJobId)
       
   503 	{
       
   504 	TLex lex(aString);
       
   505 	lex.SkipSpace();
       
   506 	if (lex.Peek() == '%')
       
   507 		{
       
   508 		lex.Get();
       
   509 		}
       
   510 	User::LeaveIfError(lex.Val(aJobId));
       
   511 	}
       
   512 
       
   513 CCommandBase* CCmdFg::NewLC()
       
   514 	{
       
   515 	CCmdFg* self = new(ELeave) CCmdFg();
       
   516 	CleanupStack::PushL(self);
       
   517 	self->BaseConstructL();
       
   518 	return self;
       
   519 	}
       
   520 
       
   521 CCmdFg::~CCmdFg()
       
   522 	{
       
   523 	delete iJobSpec;
       
   524 	delete iForegroundAdjuster;
       
   525 	}
       
   526 
       
   527 CCmdFg::CCmdFg() : CCommandBase(EManualComplete)
       
   528 	{
       
   529 	}
       
   530 
       
   531 const TDesC& CCmdFg::Name() const
       
   532 	{
       
   533 	_LIT(KCmdFgName, "fg");
       
   534 	return KCmdFgName;
       
   535 	}
       
   536 
       
   537 void CCmdFg::DoRunL()
       
   538 	{
       
   539 	TInt jobId = -1;
       
   540 	if (iJobSpec)
       
   541 		{
       
   542 		ParseJobSpecL(*iJobSpec, jobId);
       
   543 		}
       
   544 	else
       
   545 		{
       
   546 		gShell->ClaimJobsLockLC();
       
   547 		const RPointerArray<CJob>& jobs = gShell->Jobs();
       
   548 		const TInt numJobs = jobs.Count();
       
   549 		if (numJobs >= 2)
       
   550 			{
       
   551 			jobId = jobs[numJobs - 2]->Id(); // Note, the most recent job (jobs[numJobs - 1]) will be this command.
       
   552 			}
       
   553 		CleanupStack::PopAndDestroy(); // jobs lock.
       
   554 		}
       
   555 	if (jobId >= 0)
       
   556 		{
       
   557 		iForegroundAdjuster = CForegroundAdjuster::NewL(*this, jobId, ETrue);
       
   558 		}
       
   559 	else
       
   560 		{
       
   561 		Complete();
       
   562 		}
       
   563 	}
       
   564 
       
   565 void CCmdFg::ArgumentsL(RCommandArgumentList& aArguments)
       
   566 	{
       
   567 	_LIT(KCmdFgArg, "job_spec");
       
   568 	aArguments.AppendStringL(iJobSpec, KCmdFgArg);
       
   569 	}
       
   570 
       
   571 
       
   572 //
       
   573 // CCmdBg.
       
   574 //
       
   575 
       
   576 CCommandBase* CCmdBg::NewLC()
       
   577 	{
       
   578 	CCmdBg* self = new(ELeave) CCmdBg();
       
   579 	CleanupStack::PushL(self);
       
   580 	self->BaseConstructL();
       
   581 	return self;
       
   582 	}
       
   583 
       
   584 CCmdBg::~CCmdBg()
       
   585 	{
       
   586 	delete iJobSpec;
       
   587 	delete iForegroundAdjuster;
       
   588 	}
       
   589 
       
   590 CCmdBg::CCmdBg() : CCommandBase(EManualComplete)
       
   591 	{
       
   592 	}
       
   593 
       
   594 const TDesC& CCmdBg::Name() const
       
   595 	{
       
   596 	_LIT(KCmdBgName, "bg");
       
   597 	return KCmdBgName;
       
   598 	}
       
   599 
       
   600 void CCmdBg::DoRunL()
       
   601 	{
       
   602 	TInt jobId = -1;
       
   603 	if (iJobSpec)
       
   604 		{
       
   605 		ParseJobSpecL(*iJobSpec, jobId);
       
   606 		}
       
   607 	else
       
   608 		{
       
   609 		gShell->ClaimJobsLockLC();
       
   610 		const RPointerArray<CJob>& jobs = gShell->Jobs();
       
   611 		const TInt numJobs = jobs.Count();
       
   612 		if (numJobs >= 2)
       
   613 			{
       
   614 			jobId = jobs[numJobs - 2]->Id(); // Note, the most recent job (jobs[numJobs - 1]) will be this command.
       
   615 			}
       
   616 		CleanupStack::PopAndDestroy(); // jobs lock.
       
   617 		}
       
   618 	if (jobId >= 0)
       
   619 		{
       
   620 		iForegroundAdjuster = CForegroundAdjuster::NewL(*this, jobId, EFalse);
       
   621 		}
       
   622 	}
       
   623 
       
   624 void CCmdBg::ArgumentsL(RCommandArgumentList& aArguments)
       
   625 	{
       
   626 	_LIT(KCmdBgArg, "job_spec");
       
   627 	aArguments.AppendStringL(iJobSpec, KCmdBgArg);
       
   628 	}
       
   629 
       
   630 
       
   631 //
       
   632 // CCmdJobs.
       
   633 //
       
   634 
       
   635 CCommandBase* CCmdJobs::NewLC()
       
   636 	{
       
   637 	CCmdJobs* self = new(ELeave) CCmdJobs();
       
   638 	CleanupStack::PushL(self);
       
   639 	self->BaseConstructL();
       
   640 	return self;
       
   641 	}
       
   642 
       
   643 CCmdJobs::~CCmdJobs()
       
   644 	{
       
   645 	delete iFormatter;
       
   646 	}
       
   647 
       
   648 CCmdJobs::CCmdJobs() : CCommandBase(ECompleteOnRunL)
       
   649 	{
       
   650 	}
       
   651 
       
   652 const TDesC& CCmdJobs::Name() const
       
   653 	{
       
   654 	_LIT(KCmgJobsName, "jobs");
       
   655 	return KCmgJobsName;
       
   656 	}
       
   657 
       
   658 void CCmdJobs::DoRunL()
       
   659 	{
       
   660 	iFormatter = CTextFormatter::NewL(Stdout());
       
   661 	gShell->ClaimJobsLockLC();
       
   662 	const RPointerArray<CJob>& jobs = gShell->Jobs();
       
   663 	const TInt numJobs = (jobs.Count() - 1);
       
   664 	if (numJobs > 0)
       
   665 		{
       
   666 		IoUtils::CTextBuffer* buf = IoUtils::CTextBuffer::NewLC(0x100);
       
   667 		for (TInt i = 0; i < numJobs; ++i)
       
   668 			{
       
   669 			const CJob& job = *(jobs[i]);
       
   670 			buf->AppendFormatL(_L("[%d]\t%S\t%S\r\n"), job.Id(), ShStringify::JobStatus(job.Status()), job.Name());
       
   671 			}
       
   672 		iFormatter->TabulateL(0, 2, buf->Descriptor());
       
   673 		CleanupStack::PopAndDestroy(2); // buf, jobs lock.
       
   674 		Stdout().Write(iFormatter->Descriptor(), iStatus);
       
   675 		SetActive();
       
   676 		}
       
   677 	else
       
   678 		{
       
   679 		CleanupStack::PopAndDestroy(); // jobs lock.
       
   680 		Complete();
       
   681 		}
       
   682 	}
       
   683 
       
   684 
       
   685 //
       
   686 // CCmdRm.
       
   687 //
       
   688 
       
   689 CCommandBase* CCmdRm::NewLC()
       
   690 	{
       
   691 	CCmdRm* self = new(ELeave) CCmdRm();
       
   692 	CleanupStack::PushL(self);
       
   693 	self->BaseConstructL();
       
   694 	return self;
       
   695 	}
       
   696 
       
   697 CCmdRm::~CCmdRm()
       
   698 	{
       
   699 	delete iFileMan;
       
   700 	iFileNames.Close();
       
   701 	}
       
   702 
       
   703 CCmdRm::CCmdRm()
       
   704 	{
       
   705 	}
       
   706 
       
   707 const TDesC& CCmdRm::Name() const
       
   708 	{
       
   709 	_LIT(KCmdRmName, "rm");
       
   710 	return KCmdRmName;
       
   711 	}
       
   712 
       
   713 void CCmdRm::DoRunL()
       
   714 	{
       
   715 	iFileMan = CFileMan::NewL(FsL());
       
   716 
       
   717 	const TInt numFiles = iFileNames.Count();
       
   718 	for (TInt i = 0; i < numFiles; ++i)
       
   719 		{
       
   720 		TFileName2& fileName = iFileNames[i];
       
   721 		LeaveIfFileNotFound(fileName);
       
   722 		if (iRecurse)
       
   723 			{
       
   724 			if (fileName.IsDirL(FsL()))
       
   725 				{
       
   726 				fileName.SetTypeL(TFileName2::EDirectory);
       
   727 				}
       
   728 			else
       
   729 				{
       
   730 				PrintError(KErrArgument, _L("Invalid use of \"-r\" option - \"%S\" is not a directory."), &fileName);
       
   731 				User::Leave(KErrArgument);
       
   732 				}
       
   733 			}
       
   734 		else if (fileName.IsDirL(FsL()))
       
   735 			{
       
   736 			PrintError(KErrArgument, _L("Couldn't remove \"%S\" because it is a directory - use \"rm -r\" or \"rmdir\" instead."), &fileName);
       
   737 			User::Leave(KErrArgument);
       
   738 			}
       
   739 
       
   740 		TInt err = DoDelete(fileName);
       
   741 		if (err == KErrAccessDenied && iForce)
       
   742 			{
       
   743 			// Try removing read-only attribute from file and try again
       
   744 			err = Fs().SetAtt(fileName, 0, KEntryAttReadOnly);
       
   745 			if (!err)
       
   746 				{
       
   747 				iForce = EFalse; // Otherwise we'll end up here again (could happen if iFileName is a directory and cannot be deleted because it contains read-only files
       
   748 				err = DoDelete(fileName);
       
   749 				}
       
   750 			}
       
   751 		User::LeaveIfError(err);
       
   752 		}
       
   753 	}
       
   754 
       
   755 TInt CCmdRm::DoDelete(const TDesC& aFileName)
       
   756 	{
       
   757 	TInt err;
       
   758 	if (iRecurse)
       
   759 		{
       
   760 		err = iFileMan->RmDir(aFileName);
       
   761 		}
       
   762 	else
       
   763 		{
       
   764 		err = iFileMan->Delete(aFileName);
       
   765 		}
       
   766 	return err;
       
   767 	}
       
   768 
       
   769 void CCmdRm::OptionsL(RCommandOptionList& aOptions)
       
   770 	{
       
   771 	_LIT(KCmdRmOptRecurse, "recurse");
       
   772 	_LIT(KCmdRmOptForce, "force");
       
   773 	aOptions.AppendBoolL(iRecurse, KCmdRmOptRecurse);
       
   774 	aOptions.AppendBoolL(iForce, KCmdRmOptForce);
       
   775 	}
       
   776 
       
   777 void CCmdRm::ArgumentsL(RCommandArgumentList& aArguments)
       
   778 	{
       
   779 	_LIT(KCmdRmArg, "file_name");
       
   780 	aArguments.AppendFileNameL(iFileNames, KCmdRmArg);
       
   781 	}
       
   782 
       
   783 
       
   784 //
       
   785 // CCmdCp.
       
   786 //
       
   787 
       
   788 CCommandBase* CCmdCp::NewLC()
       
   789 	{
       
   790 	CCmdCp* self = new(ELeave) CCmdCp();
       
   791 	CleanupStack::PushL(self);
       
   792 	self->BaseConstructL();
       
   793 	return self;
       
   794 	}
       
   795 
       
   796 CCmdCp::~CCmdCp()
       
   797 	{
       
   798 	delete iFileMan;
       
   799 	}
       
   800 
       
   801 CCmdCp::CCmdCp()
       
   802 	{
       
   803 	}
       
   804 
       
   805 const TDesC& CCmdCp::Name() const
       
   806 	{
       
   807 	_LIT(KCmdCpName, "cp");
       
   808 	return KCmdCpName;
       
   809 	}
       
   810 
       
   811 void CCmdCp::ForciblyCopyFileL(const TDesC& aSourceFileName, const TDesC& aDestFileName)
       
   812 	{
       
   813 	RFs& fs = FsL();
       
   814 	TInt err = fs.MkDirAll(aDestFileName);
       
   815 	if (err != KErrNone && err != KErrAlreadyExists)
       
   816 		{
       
   817 		User::Leave(err);
       
   818 		}
       
   819 	TInt numRetries = 3;
       
   820 retry:
       
   821 	TEntry startEntry;
       
   822 	User::LeaveIfError(fs.Entry(aSourceFileName, startEntry));
       
   823 	RFile destFile;
       
   824 	if (iOverwrite)
       
   825 		{
       
   826 		User::LeaveIfError(destFile.Replace(fs, aDestFileName, EFileShareExclusive | EFileStream | EFileWrite));
       
   827 		}
       
   828 	else
       
   829 		{
       
   830 		User::LeaveIfError(destFile.Create(fs, aDestFileName, EFileShareExclusive | EFileStream | EFileWrite));
       
   831 		}
       
   832 	CleanupClosePushL(destFile);
       
   833 
       
   834 	HBufC8* blockBuf = HBufC8::NewLC(KBlockSize);
       
   835 	TPtr8 blockPtr(blockBuf->Des());
       
   836 	TInt pos = 0;
       
   837 	while (pos < startEntry.iSize)
       
   838 		{
       
   839 		User::LeaveIfError(fs.ReadFileSection(aSourceFileName, pos, blockPtr, KBlockSize));
       
   840 		if (blockPtr.Length() == 0)
       
   841 			{
       
   842 			Printf(_L("\r\nReadFileSection returned zero length descriptor, aborting\r\n"));
       
   843 			pos = startEntry.iSize;
       
   844 			}
       
   845 		else
       
   846 			{
       
   847 			pos += blockPtr.Length();
       
   848 			User::LeaveIfError(destFile.Write(*blockBuf));
       
   849 			}
       
   850 		}
       
   851 	Printf(KNewLine);
       
   852 
       
   853 	CleanupStack::PopAndDestroy(2, &destFile); // blockBuf, destFile.
       
   854 
       
   855 	TEntry endEntry;
       
   856 	User::LeaveIfError(fs.Entry(aSourceFileName, endEntry));
       
   857 	if (startEntry.iModified != endEntry.iModified)
       
   858 		{
       
   859 		--numRetries;
       
   860 		if (numRetries > 0)
       
   861 			{
       
   862 			Printf(_L("Modification while copying - retrying...\r\n"));
       
   863 			fs.Delete(aDestFileName);	// Ignore error.
       
   864 			goto retry;
       
   865 			}
       
   866 		else
       
   867 			{
       
   868 			Printf(_L("Modification while copying - failed 3 times, aborting...\r\n"));
       
   869 			}
       
   870 		}
       
   871 	}
       
   872 
       
   873 void CCmdCp::DoRunL()
       
   874 	{
       
   875 	if (iRecurse && iForce)
       
   876 		{
       
   877 		PrintWarning(_L("--recurse and --force options can't be used together"));
       
   878 		User::Leave(KErrArgument);
       
   879 		}
       
   880 
       
   881 	if (iForce)
       
   882 		{
       
   883 		ForciblyCopyFileL(iFrom, iTo);
       
   884 		}
       
   885 	else
       
   886 		{
       
   887 		iFileMan = CFileMan::NewL(FsL());
       
   888 		TUint flags = 0;
       
   889 		if (iRecurse) flags |= CFileMan::ERecurse;
       
   890 		if (iOverwrite) flags |= CFileMan::EOverWrite;
       
   891 
       
   892 		if (iRecurse && iFrom.Exists(FsL()) && iFrom.IsDirL(FsL()))
       
   893 			{
       
   894 			// CFileMan behaves markedly differently to standard posix cp, in the case of copying a directory.
       
   895 			// POSIX cp does different things depending on whether the destination exists or not:
       
   896 			// 1) "cp -r dirname existingdir" will produce the tree "./existingdir/dirname/<files>"
       
   897 			// 2) "cp -r dirname nonexistingdir" will produce the tree "./nonexistingdir/<files>"
       
   898 			//
       
   899 			// CFileMan differs in case (1) and puts the contents of dirname straight into the destination dir.
       
   900 			// Therefore to behave sensibly like posix cp in case (1) we add the source name to the destination
       
   901 			if (iTo.Exists(FsL()))
       
   902 				{
       
   903 				iTo.AppendComponentL(iFrom.Name(), TFileName2::EDirectory);
       
   904 				}
       
   905 			}
       
   906 		User::LeaveIfError(iFileMan->Copy(iFrom, iTo, flags));
       
   907 		}
       
   908 	}
       
   909 
       
   910 void CCmdCp::OptionsL(RCommandOptionList& aOptions)
       
   911 	{
       
   912 	_LIT(KCmdCpOptRecurse, "recurse");
       
   913 	_LIT(KCmdCpOptOverwrite, "overwrite");
       
   914 	_LIT(KCmdCpOptForce, "force");
       
   915 	aOptions.AppendBoolL(iRecurse, KCmdCpOptRecurse);
       
   916 	aOptions.AppendBoolL(iOverwrite, KCmdCpOptOverwrite);
       
   917 	aOptions.AppendBoolL(iForce, KCmdCpOptForce);
       
   918 	}
       
   919 
       
   920 void CCmdCp::ArgumentsL(RCommandArgumentList& aArguments)
       
   921 	{
       
   922 	_LIT(KCmdCpArg1, "source");
       
   923 	_LIT(KCmdCpArg2, "destination");
       
   924 	aArguments.AppendFileNameL(iFrom, KCmdCpArg1);
       
   925 	aArguments.AppendFileNameL(iTo, KCmdCpArg2);
       
   926 	}
       
   927 
       
   928 
       
   929 //
       
   930 // CCmdMv.
       
   931 //
       
   932 
       
   933 CCommandBase* CCmdMv::NewLC()
       
   934 	{
       
   935 	CCmdMv* self = new(ELeave) CCmdMv();
       
   936 	CleanupStack::PushL(self);
       
   937 	self->BaseConstructL();
       
   938 	return self;
       
   939 	}
       
   940 
       
   941 CCmdMv::~CCmdMv()
       
   942 	{
       
   943 	delete iFileMan;
       
   944 	}
       
   945 
       
   946 CCmdMv::CCmdMv()
       
   947 	{
       
   948 	}
       
   949 
       
   950 const TDesC& CCmdMv::Name() const
       
   951 	{
       
   952 	_LIT(KCmdMvName, "mv");
       
   953 	return KCmdMvName;
       
   954 	}
       
   955 
       
   956 void CCmdMv::DoRunL()
       
   957 	{
       
   958 	if (iTo.Exists(FsL()) && iTo.IsDirL(FsL()))
       
   959 		{
       
   960 		iTo.SetTypeL(TFileName2::EDirectory);
       
   961 		}
       
   962 	iFileMan = CFileMan::NewL(FsL());
       
   963 	User::LeaveIfError(iFileMan->Move(iFrom, iTo, 0));
       
   964 	}
       
   965 
       
   966 void CCmdMv::ArgumentsL(RCommandArgumentList& aArguments)
       
   967 	{
       
   968 	_LIT(KCmdMvArg1, "source_file");
       
   969 	_LIT(KCmdMvArg2, "destination_file");
       
   970 	aArguments.AppendFileNameL(iFrom, KCmdMvArg1);
       
   971 	aArguments.AppendFileNameL(iTo, KCmdMvArg2);
       
   972 	}
       
   973 
       
   974 
       
   975 //
       
   976 // CCmdMkDir.
       
   977 //
       
   978 
       
   979 CCommandBase* CCmdMkDir::NewLC()
       
   980 	{
       
   981 	CCmdMkDir* self = new(ELeave) CCmdMkDir();
       
   982 	CleanupStack::PushL(self);
       
   983 	self->BaseConstructL();
       
   984 	return self;
       
   985 	}
       
   986 
       
   987 CCmdMkDir::~CCmdMkDir()
       
   988 	{
       
   989 	}
       
   990 
       
   991 CCmdMkDir::CCmdMkDir()
       
   992 	: iDir(TFileName2::EDirectory)
       
   993 	{
       
   994 	}
       
   995 
       
   996 const TDesC& CCmdMkDir::Name() const
       
   997 	{
       
   998 	_LIT(KCmdMkDirName, "mkdir");
       
   999 	return KCmdMkDirName;
       
  1000 	}
       
  1001 
       
  1002 void CCmdMkDir::DoRunL()
       
  1003 	{
       
  1004 	TInt err = FsL().MkDirAll(iDir);
       
  1005 	if (iAllowExists && (err == KErrAlreadyExists))
       
  1006 		{
       
  1007 		err = KErrNone;
       
  1008 		}
       
  1009 	User::LeaveIfError(err);
       
  1010 	}
       
  1011 
       
  1012 void CCmdMkDir::OptionsL(RCommandOptionList& aOptions)
       
  1013 	{
       
  1014 	_LIT(KCmdMkDirOptAllowExists, "allow_exists");
       
  1015 	aOptions.AppendBoolL(iAllowExists, KCmdMkDirOptAllowExists);
       
  1016 	}
       
  1017 
       
  1018 void CCmdMkDir::ArgumentsL(RCommandArgumentList& aArguments)
       
  1019 	{
       
  1020 	_LIT(KCmdMkDirArg, "dir_name");
       
  1021 	aArguments.AppendFileNameL(iDir, KCmdMkDirArg);
       
  1022 	}
       
  1023 
       
  1024 
       
  1025 //
       
  1026 // CCmdRmDir.
       
  1027 //
       
  1028 
       
  1029 CCommandBase* CCmdRmDir::NewLC()
       
  1030 	{
       
  1031 	CCmdRmDir* self = new(ELeave) CCmdRmDir();
       
  1032 	CleanupStack::PushL(self);
       
  1033 	self->BaseConstructL();
       
  1034 	return self;
       
  1035 	}
       
  1036 
       
  1037 CCmdRmDir::~CCmdRmDir()
       
  1038 	{
       
  1039 	delete iFileMan;
       
  1040 	iDirs.Close();
       
  1041 	}
       
  1042 
       
  1043 CCmdRmDir::CCmdRmDir()
       
  1044 	{
       
  1045 	}
       
  1046 
       
  1047 const TDesC& CCmdRmDir::Name() const
       
  1048 	{
       
  1049 	_LIT(KCmdRmDirName, "rmdir");
       
  1050 	return KCmdRmDirName;
       
  1051 	}
       
  1052 
       
  1053 void CCmdRmDir::DoRunL()
       
  1054 	{
       
  1055 	const TInt numDirs = iDirs.Count();
       
  1056 	for (TInt i = 0; i < numDirs; ++i)
       
  1057 		{
       
  1058 		TFileName2& dir = iDirs[i];
       
  1059 		if (dir.IsDirL(FsL()))
       
  1060 			{
       
  1061 			dir.SetTypeL(TFileName2::EDirectory);
       
  1062 			}
       
  1063 		else
       
  1064 			{
       
  1065 			PrintError(KErrArgument, _L("\"%S\" is not a directory."), &dir);
       
  1066 			User::Leave(KErrArgument);
       
  1067 			}
       
  1068 
       
  1069 		LeaveIfFileNotFound(dir);
       
  1070 	
       
  1071 		if (iRecurse)
       
  1072 			{
       
  1073 			if (iFileMan == NULL)
       
  1074 				{
       
  1075 				iFileMan = CFileMan::NewL(FsL());
       
  1076 				}
       
  1077 			User::LeaveIfError(iFileMan->RmDir(dir));
       
  1078 			}
       
  1079 		else
       
  1080 			{
       
  1081 			User::LeaveIfError(FsL().RmDir(dir));
       
  1082 			}
       
  1083 		}
       
  1084 	}
       
  1085 
       
  1086 void CCmdRmDir::OptionsL(RCommandOptionList& aOptions)
       
  1087 	{
       
  1088 	_LIT(KCmdRmDirOptRecurse, "recurse");
       
  1089 	aOptions.AppendBoolL(iRecurse, KCmdRmDirOptRecurse);
       
  1090 	}
       
  1091 
       
  1092 void CCmdRmDir::ArgumentsL(RCommandArgumentList& aArguments)
       
  1093 	{
       
  1094 	_LIT(KCmdRmDirArg, "dir_name");
       
  1095 	aArguments.AppendFileNameL(iDirs, KCmdRmDirArg);
       
  1096 	}
       
  1097 
       
  1098 
       
  1099 //
       
  1100 // CCmdMatch.
       
  1101 //
       
  1102 
       
  1103 CCommandBase* CCmdMatch::NewLC()
       
  1104 	{
       
  1105 	CCmdMatch* self = new(ELeave) CCmdMatch();
       
  1106 	CleanupStack::PushL(self);
       
  1107 	self->BaseConstructL();
       
  1108 	return self;
       
  1109 	}
       
  1110 
       
  1111 CCmdMatch::~CCmdMatch()
       
  1112 	{
       
  1113 	delete iToMatch;
       
  1114 	}
       
  1115 
       
  1116 CCmdMatch::CCmdMatch()
       
  1117 	{
       
  1118 	}
       
  1119 
       
  1120 const TDesC& CCmdMatch::Name() const
       
  1121 	{
       
  1122 	_LIT(KCmdMatchName, "match");
       
  1123 	return KCmdMatchName;
       
  1124 	}
       
  1125 
       
  1126 void CCmdMatch::DoRunL()
       
  1127 	{
       
  1128 	Stdin().SetReadMode(RIoReadHandle::ELine);
       
  1129 	TBuf<0x100> line;
       
  1130 	TInt count = 0;
       
  1131 	while (Stdin().Read(line) == KErrNone)
       
  1132 		{
       
  1133 		TBool matches;
       
  1134 		if (iIgnoreCase)
       
  1135 			{
       
  1136 			matches = (line.MatchF(*iToMatch) != KErrNotFound);
       
  1137 			}
       
  1138 		else
       
  1139 			{
       
  1140 			matches = (line.Match(*iToMatch) != KErrNotFound);
       
  1141 			}
       
  1142 		if (iInvertMatch)
       
  1143 			{
       
  1144 			matches = !matches;
       
  1145 			}
       
  1146 		if (matches)
       
  1147 			{
       
  1148 			if (iCount)
       
  1149 				{
       
  1150 				count++;
       
  1151 				}
       
  1152 			else
       
  1153 				{
       
  1154 				Write(line);
       
  1155 				}
       
  1156 			}
       
  1157 		}
       
  1158 
       
  1159 	if (iCount)
       
  1160 		{
       
  1161 		Printf(_L("Count = %d"), count);
       
  1162 		}
       
  1163 	}
       
  1164 
       
  1165 void CCmdMatch::OptionsL(RCommandOptionList& aOptions)
       
  1166 	{
       
  1167 	_LIT(KCmdMatchOptIgnoreCase, "ignore-case");
       
  1168 	_LIT(KCmdMatchOptInvertMatch, "invert-match");
       
  1169 	_LIT(KCmdMatchOptCount, "count");
       
  1170 	aOptions.AppendBoolL(iIgnoreCase, KCmdMatchOptIgnoreCase);
       
  1171 	aOptions.AppendBoolL(iInvertMatch, KCmdMatchOptInvertMatch);
       
  1172 	aOptions.AppendBoolL(iCount, KCmdMatchOptCount);
       
  1173 	}
       
  1174 
       
  1175 void CCmdMatch::ArgumentsL(RCommandArgumentList& aArguments)
       
  1176 	{
       
  1177 	_LIT(KCmdMatchArg1, "pattern");
       
  1178 	aArguments.AppendStringL(iToMatch, KCmdMatchArg1);
       
  1179 	}
       
  1180 
       
  1181 
       
  1182 //
       
  1183 // CCmdEcho.
       
  1184 //
       
  1185 
       
  1186 CCommandBase* CCmdEcho::NewLC()
       
  1187 	{
       
  1188 	CCmdEcho* self = new(ELeave) CCmdEcho();
       
  1189 	CleanupStack::PushL(self);
       
  1190 	self->BaseConstructL();
       
  1191 	return self;
       
  1192 	}
       
  1193 
       
  1194 CCmdEcho::~CCmdEcho()
       
  1195 	{
       
  1196 	delete iToEcho;
       
  1197 	iAttributes.Close();
       
  1198 	}
       
  1199 
       
  1200 CCmdEcho::CCmdEcho()
       
  1201 	: iForegroundColor(ConsoleAttributes::EUnchanged), iBackgroundColor(ConsoleAttributes::EUnchanged)
       
  1202 	{
       
  1203 	}
       
  1204 
       
  1205 void CCmdEcho::DoWriteL(const TDesC& aDes)
       
  1206 	{
       
  1207 	if (iToStderr)
       
  1208 		{
       
  1209 		Stderr().Write(aDes);
       
  1210 		}
       
  1211 	else
       
  1212 		{
       
  1213 		Stdout().Write(aDes);
       
  1214 		}
       
  1215 	}
       
  1216 
       
  1217 const TDesC& CCmdEcho::Name() const
       
  1218 	{
       
  1219 	_LIT(KCmdEchoName, "echo");
       
  1220 	return KCmdEchoName;
       
  1221 	}
       
  1222 
       
  1223 void CCmdEcho::DoRunL()
       
  1224 	{
       
  1225 	RIoConsoleWriteHandle& out = iToStderr ? Stderr() : Stdout();
       
  1226 
       
  1227 	if (iBinaryMode)
       
  1228 		{
       
  1229 		LeaveIfErr(out.SetMode(RIoReadWriteHandle::EBinary), _L("Unable to set write handle to binary mode"));
       
  1230 		}
       
  1231 	
       
  1232 	CTextFormatter* formatter = CTextFormatter::NewLC(out);
       
  1233 
       
  1234 	TUint attributes = 0;
       
  1235 	const TInt numAttributes = iAttributes.Count();
       
  1236 	for (TInt i = 0; i < numAttributes; ++i)
       
  1237 		{
       
  1238 		switch ((TAttr)iAttributes[i])
       
  1239 			{
       
  1240 			case EBold:
       
  1241 				attributes |= ConsoleAttributes::EBold;
       
  1242 				break;
       
  1243 			case EUnderscore:
       
  1244 				attributes |= ConsoleAttributes::EUnderscore;
       
  1245 				break;
       
  1246 			case EBlink:
       
  1247 				attributes |= ConsoleAttributes::EBlink;
       
  1248 				break;
       
  1249 			case EInverse:
       
  1250 				attributes |= ConsoleAttributes::EInverse;
       
  1251 				break;
       
  1252 			case EConceal:
       
  1253 				attributes |= ConsoleAttributes::EConceal;
       
  1254 				break;
       
  1255 			}
       
  1256 		}
       
  1257 
       
  1258 	formatter->SetAttributesL(attributes, iForegroundColor, iBackgroundColor);
       
  1259 
       
  1260 	if (iToEcho)
       
  1261 		{
       
  1262 		if (iWrap) 
       
  1263 			{
       
  1264 			formatter->WrapL(iIndent, *iToEcho);
       
  1265 			}
       
  1266 		else
       
  1267 			{
       
  1268 			formatter->AppendL(*iToEcho);
       
  1269 			}
       
  1270 		// Add a newline if it doesn't already end in one (and --no-newline isn't specified)
       
  1271 		if (!iNoNewline && iToEcho->Right(KNewLine().Length()) != KNewLine)
       
  1272 			{
       
  1273 			formatter->AppendL(KNewLine);
       
  1274 			}
       
  1275 		}
       
  1276 	else
       
  1277 		{
       
  1278 		TBuf<0x100> buf;
       
  1279 		TInt err = KErrNone;
       
  1280 		do
       
  1281 			{
       
  1282 			err = Stdin().Read(buf);
       
  1283 			if (err == KErrNone)
       
  1284 				{
       
  1285 				if (iWrap) 
       
  1286 					{
       
  1287 					formatter->WrapL(iIndent, buf);
       
  1288 					}
       
  1289 				else
       
  1290 					{
       
  1291 					formatter->AppendL(buf);
       
  1292 					}
       
  1293 				}
       
  1294 			}
       
  1295 			while (err == KErrNone);
       
  1296 		}
       
  1297 
       
  1298 	formatter->Write();
       
  1299 	CleanupStack::PopAndDestroy(formatter);
       
  1300 	}
       
  1301 
       
  1302 void CCmdEcho::OptionsL(RCommandOptionList& aOptions)
       
  1303 	{
       
  1304 	_LIT(KCmdEchoOptToStderr, "stderr");
       
  1305 	_LIT(KCmdEchoOptWrap, "wrap");
       
  1306 	_LIT(KCmdEchoOptIndent, "indent");
       
  1307 	_LIT(KCmdEchoOptAttributes, "attributes");
       
  1308 	_LIT(KCmdEchoOptForground, "foreground-color");
       
  1309 	_LIT(KCmdEchoOptBackground, "background-color");
       
  1310 	_LIT(KCmdEchoOptBinaryMode, "binary");
       
  1311 	_LIT(KCmdEchoOptNoNewline, "no-newline");
       
  1312 
       
  1313 	aOptions.AppendBoolL(iToStderr, KCmdEchoOptToStderr);
       
  1314 	aOptions.AppendBoolL(iWrap, KCmdEchoOptWrap);
       
  1315 	aOptions.AppendUintL(iIndent, KCmdEchoOptIndent);
       
  1316 	aOptions.AppendEnumL(iAttributes, KCmdEchoOptAttributes);
       
  1317 	aOptions.AppendEnumL((TInt&)iForegroundColor, KCmdEchoOptForground);
       
  1318 	aOptions.AppendEnumL((TInt&)iBackgroundColor, KCmdEchoOptBackground);
       
  1319 	aOptions.AppendBoolL(iBinaryMode, KCmdEchoOptBinaryMode);
       
  1320 	aOptions.AppendBoolL(iNoNewline, KCmdEchoOptNoNewline);
       
  1321 	}
       
  1322 
       
  1323 void CCmdEcho::ArgumentsL(RCommandArgumentList& aArguments)
       
  1324 	{
       
  1325 	_LIT(KCmdEchoArg1, "string");
       
  1326 	aArguments.AppendStringL(iToEcho, KCmdEchoArg1);
       
  1327 	}
       
  1328 
       
  1329 
       
  1330 //
       
  1331 // CCmdMore.
       
  1332 //
       
  1333 
       
  1334 CCommandBase* CCmdMore::NewLC()
       
  1335 	{
       
  1336 	CCmdMore* self = new(ELeave) CCmdMore();
       
  1337 	CleanupStack::PushL(self);
       
  1338 	self->BaseConstructL();
       
  1339 	return self;
       
  1340 	}
       
  1341 
       
  1342 CCmdMore::~CCmdMore()
       
  1343 	{
       
  1344 	}
       
  1345 
       
  1346 CCmdMore::CCmdMore()
       
  1347 	{
       
  1348 	}
       
  1349 
       
  1350 const TDesC& CCmdMore::Name() const
       
  1351 	{
       
  1352 	_LIT(KCmdMoreName, "more");
       
  1353 	return KCmdMoreName;
       
  1354 	}
       
  1355 	
       
  1356 void CCmdMore::ArgumentsL(RCommandArgumentList& aArguments)
       
  1357 	{
       
  1358 	_LIT(KMoreArg1, "file_name");
       
  1359 	aArguments.AppendFileNameL(iFile, KMoreArg1);
       
  1360 	}
       
  1361 
       
  1362 void CCmdMore::DoRunL()
       
  1363 	{
       
  1364 	RIoReadHandle input;
       
  1365 	input.CreateL(IoSession());
       
  1366 	CleanupClosePushL(input);
       
  1367 
       
  1368 	RIoFile file;
       
  1369 	CleanupClosePushL(file);
       
  1370 
       
  1371 	if (iArguments.IsPresent(0))
       
  1372 		{
       
  1373 		file.CreateL(IoSession(), iFile, RIoFile::ERead);
       
  1374 		IoSession().SetObjectNameL(file.SubSessionHandle(), iFile);
       
  1375 		_LIT(KReaderSuffix, "_more_reader");
       
  1376 		iFile.SetLength(Min(iFile.Length(), iFile.MaxLength() - KReaderSuffix().Length()));
       
  1377 		iFile.Append(KReaderSuffix);
       
  1378 		IoSession().SetObjectNameL(input.SubSessionHandle(), iFile);
       
  1379 		file.AttachL(input, RIoEndPoint::EForeground);
       
  1380 		}
       
  1381 	else
       
  1382 		{
       
  1383 		input.DuplicateL(Stdin());
       
  1384 		input.SetToForegroundL();
       
  1385 		}
       
  1386 
       
  1387 	PageL(input);
       
  1388 	
       
  1389 	CleanupStack::PopAndDestroy(2, &input);
       
  1390 	}
       
  1391 
       
  1392 
       
  1393 //
       
  1394 // CCmdTrace.
       
  1395 //
       
  1396 
       
  1397 CCommandBase* CCmdTrace::NewLC()
       
  1398 	{
       
  1399 	CCmdTrace* self = new(ELeave) CCmdTrace();
       
  1400 	CleanupStack::PushL(self);
       
  1401 	self->BaseConstructL();
       
  1402 	return self;
       
  1403 	}
       
  1404 
       
  1405 CCmdTrace::~CCmdTrace()
       
  1406 	{
       
  1407 	iEnable.ResetAndDestroy();
       
  1408 	iDisable.ResetAndDestroy();
       
  1409 	}
       
  1410 
       
  1411 CCmdTrace::CCmdTrace()
       
  1412 	{
       
  1413 	}
       
  1414 
       
  1415 const TDesC& CCmdTrace::Name() const
       
  1416 	{
       
  1417 	_LIT(KCmdTraceName, "trace");
       
  1418 	return KCmdTraceName;
       
  1419 	}
       
  1420 
       
  1421 const LtkUtils::SLitC8 KTraceBitNames[] =
       
  1422 	{
       
  1423 	DESC8("khardware"),
       
  1424 	DESC8("kboot"),
       
  1425 	DESC8("kserver"),
       
  1426 	DESC8("kmmu"),
       
  1427 	DESC8("ksemaphore"),
       
  1428 	DESC8("ksched"),
       
  1429 	DESC8("kproc"),
       
  1430 	DESC8("kexec"),
       
  1431 	DESC8("kdebugger"),
       
  1432 	DESC8("kthread"),
       
  1433 	DESC8("kdll"),
       
  1434 	DESC8("kipc"),
       
  1435 	DESC8("kpbus1"),
       
  1436 	DESC8("kpbus"),
       
  1437 	DESC8("kpbusdrv"),
       
  1438 	DESC8("kpower"),
       
  1439 	DESC8("ktiming"),
       
  1440 	DESC8("kevent"),
       
  1441 	DESC8("kobject"),
       
  1442 	DESC8("kdfc"),
       
  1443 	DESC8("kextension"),
       
  1444 	DESC8("ksched2"),
       
  1445 	DESC8("klocdrv"),
       
  1446 	DESC8("kfail"),
       
  1447 	DESC8("kthread2"),
       
  1448 	DESC8("kdevice"),
       
  1449 	DESC8("kmemtrace"),
       
  1450 	DESC8("kdma"),
       
  1451 	DESC8("kmmu2"),
       
  1452 	DESC8("knkern"),
       
  1453 	DESC8("kscratch"),
       
  1454 	DESC8("kpanic"),
       
  1455 	// Word 1
       
  1456 	DESC8("kusb"),
       
  1457 	DESC8("kusbpsl"),
       
  1458 	DESC8("knetwork1"),
       
  1459 	DESC8("knetwork2"),
       
  1460 	DESC8("ksound1"),
       
  1461 	DESC8("kusbhost"),
       
  1462 	DESC8("kusbotg"),
       
  1463 	DESC8("kusbjournal"),
       
  1464 	DESC8("kusbho"),
       
  1465 	DESC8("kresmanager"),
       
  1466 	DESC8("kiic"),
       
  1467 	DESC8("khcr"),
       
  1468 	DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""),
       
  1469 	DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""),
       
  1470 	DESC8("kpipe"),
       
  1471 	DESC8("kpci"),
       
  1472 	DESC8("kdatapagewarn"),
       
  1473 	DESC8("klocdpaging"),
       
  1474 	DESC8("kpaging"),
       
  1475 	DESC8("krealtime"),
       
  1476 	// Word 2
       
  1477 	DESC8("kallthreadssystem"),
       
  1478 	DESC8("ktestfast"),
       
  1479 	DESC8("ktestlatency"),
       
  1480 	DESC8("kdebugmonitordisable"),
       
  1481 	DESC8("kcrashmonitordisable"),
       
  1482 	DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""),
       
  1483 	DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""),
       
  1484 	DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""), DESC8(""),
       
  1485 	DESC8(""), DESC8(""), DESC8(""),
       
  1486 	// Word 3
       
  1487 	DESC8("kuserheaptrace"),
       
  1488 	};
       
  1489 const TInt KTraceBitCount = sizeof(KTraceBitNames) / sizeof(LtkUtils::SLitC);
       
  1490 
       
  1491 #ifndef KCOMPFS // Not defined on 9.1
       
  1492 #define	KCOMPFS		0x0400
       
  1493 #endif
       
  1494 
       
  1495 void CCmdTrace::DoRunL()
       
  1496 	{
       
  1497 	TInt debugVal = 0;
       
  1498 	if (iOptF32)
       
  1499 		debugVal|=KFSERV;
       
  1500 	if (iOptLoader)
       
  1501 		debugVal|=KFLDR;
       
  1502 	if (iOptFat)
       
  1503 		debugVal|=KFSYS;
       
  1504 	if (iOptLffs)
       
  1505 		debugVal|=KLFFS;
       
  1506 #ifdef EKA2
       
  1507 	if (iOptIso9660)
       
  1508 		debugVal|=KISO9660;
       
  1509 	if (iOptNtfs)
       
  1510 		debugVal|=KNTFS;
       
  1511 	if (iOptMultiThread)
       
  1512 		debugVal|=KTHRD;
       
  1513 	if (iOptRofs)
       
  1514 		debugVal|=KROFS;
       
  1515 	if (iOptCompfs)
       
  1516 		debugVal|=KCOMPFS;
       
  1517 #endif
       
  1518 	TInt err = FsL().SetDebugRegister(debugVal);
       
  1519 	if (err && debugVal != 0)
       
  1520 		{
       
  1521 		// Don't bother printing a warning if none of the FS-related options were actually specified
       
  1522 		PrintWarning(_L("Unable to configure file server traces: %d"), err);
       
  1523 		}
       
  1524 	
       
  1525 	if (iArguments.IsPresent(0))
       
  1526 		{
       
  1527 #ifdef EKA2
       
  1528 		User::SetDebugMask(iMask, iIndex);
       
  1529 #else
       
  1530 		User::SetDebugMask(iMask);
       
  1531 #endif
       
  1532 		}
       
  1533 	else if (debugVal == 0)
       
  1534 		{
       
  1535 		if (iEnable.Count() || iDisable.Count())
       
  1536 			{
       
  1537 			for (TInt i = 0; i < iEnable.Count(); i++)
       
  1538 				{
       
  1539 				TInt err = SetFlag(*iEnable[i], ETrue);
       
  1540 				if (err) PrintWarning(_L("Flag '%S' not understood"), iEnable[i]);
       
  1541 				}
       
  1542 			for (TInt i = 0; i < iDisable.Count(); i++)
       
  1543 				{
       
  1544 				TInt err = SetFlag(*iDisable[i], EFalse);
       
  1545 				if (err) PrintWarning(_L("Flag '%S' not understood"), iEnable[i]);
       
  1546 				}
       
  1547 			}
       
  1548 		else
       
  1549 			{
       
  1550 			PrintConfig();
       
  1551 			}
       
  1552 		}
       
  1553 	}
       
  1554 
       
  1555 void CCmdTrace::PrintConfig()
       
  1556 	{
       
  1557 #ifdef EKA2
       
  1558 	for (TInt i = 0; i < 8; ++i)
       
  1559 		{
       
  1560 		TBool seen = EFalse;
       
  1561 		TUint32 mask = UserSvr::DebugMask(i);
       
  1562 		Printf(_L("DebugMask(%d) = 0x%08X"), i, mask);
       
  1563 		for (TInt bit = 0; bit < 32; bit++)
       
  1564 			{
       
  1565 			if (mask & (1 << bit))
       
  1566 				{
       
  1567 				if (seen)
       
  1568 					{
       
  1569 					Write(_L("|"));
       
  1570 					}
       
  1571 				else
       
  1572 					{
       
  1573 					Write(_L(" ("));
       
  1574 					}
       
  1575 				seen = ETrue;
       
  1576 				TInt idx = i*32 + bit;
       
  1577 				if (idx < KTraceBitCount && KTraceBitNames[idx]().Length())
       
  1578 					{
       
  1579 					Printf(KTraceBitNames[idx]());
       
  1580 					}
       
  1581 				else
       
  1582 					{
       
  1583 					Write(_L("?"));
       
  1584 					}
       
  1585 				}
       
  1586 			}
       
  1587 		if (seen) Write(_L(")"));
       
  1588 		Write(KNewLine);
       
  1589 		}
       
  1590 #else
       
  1591 	Printf(_L("DebugMask = 0x%08X\r\n"), UserSvr::DebugMask());
       
  1592 #endif
       
  1593 	}
       
  1594 
       
  1595 TInt CCmdTrace::SetFlag(const TDesC& aFlagName, TBool aSet)
       
  1596 	{
       
  1597 	// Find aFlagName in KTraceBitNames
       
  1598 	TBuf8<64> flagname;
       
  1599 	for (TInt i = 0; i < KTraceBitCount; i++)
       
  1600 		{
       
  1601 		flagname.Copy(aFlagName);
       
  1602 		flagname.LowerCase();
       
  1603 		if (flagname.Compare(KTraceBitNames[i]) == 0)
       
  1604 			{
       
  1605 			TInt word = i / 32;
       
  1606 			TInt idx = i % 32;
       
  1607 			TUint32 mask = UserSvr::DebugMask(word);
       
  1608 			if (aSet)
       
  1609 				{
       
  1610 				mask |= 1 << idx;
       
  1611 				}
       
  1612 			else
       
  1613 				{
       
  1614 				mask &= ~(1 << idx);
       
  1615 				}
       
  1616 			User::SetDebugMask(mask, word);
       
  1617 			return KErrNone;
       
  1618 			}
       
  1619 		}
       
  1620 	return KErrNotFound;
       
  1621 	}
       
  1622 
       
  1623 void CCmdTrace::OptionsL(RCommandOptionList& aOptions)
       
  1624 	{
       
  1625 	_LIT(KCmdTraceOptS, "f32");
       
  1626 	_LIT(KCmdTraceOptM, "multi-thread");
       
  1627 	_LIT(KCmdTraceOptL, "loader");
       
  1628 	_LIT(KCmdTraceOptF, "fat");
       
  1629 	_LIT(KCmdTraceOptT, "lffs");
       
  1630 	_LIT(KCmdTraceOptI, "iso9660");
       
  1631 	_LIT(KCmdTraceOptN, "ntfs");
       
  1632 	_LIT(KCmdTraceOptO, "rofs");
       
  1633 	_LIT(KCmdTraceOptC, "compfs");
       
  1634 
       
  1635 	aOptions.AppendBoolL(iOptF32, KCmdTraceOptS);
       
  1636 	aOptions.AppendBoolL(iOptMultiThread, KCmdTraceOptM);
       
  1637 	aOptions.AppendBoolL(iOptLoader, KCmdTraceOptL);
       
  1638 	aOptions.AppendBoolL(iOptFat, KCmdTraceOptF);
       
  1639 	aOptions.AppendBoolL(iOptLffs, KCmdTraceOptT);
       
  1640 #ifdef EKA2
       
  1641 	aOptions.AppendBoolL(iOptIso9660, KCmdTraceOptI);
       
  1642 	aOptions.AppendBoolL(iOptNtfs, KCmdTraceOptN);
       
  1643 	aOptions.AppendBoolL(iOptRofs, KCmdTraceOptO);
       
  1644 	aOptions.AppendBoolL(iOptCompfs, KCmdTraceOptC);
       
  1645 #endif
       
  1646 
       
  1647 	_LIT(KEnable, "enable");
       
  1648 	aOptions.AppendStringL(iEnable, KEnable);
       
  1649 	_LIT(KDisable, "disable");
       
  1650 	aOptions.AppendStringL(iDisable, KDisable);
       
  1651 	}
       
  1652 
       
  1653 void CCmdTrace::ArgumentsL(RCommandArgumentList& aArguments)
       
  1654 	{
       
  1655 	_LIT(KCmdTraceArg1, "debug_mask");
       
  1656 	aArguments.AppendUintL(iMask, KCmdTraceArg1);
       
  1657 #ifdef EKA2
       
  1658 	_LIT(KCmdTraceArg2, "index");
       
  1659 	aArguments.AppendUintL(iIndex, KCmdTraceArg2);
       
  1660 #endif
       
  1661 	}
       
  1662 
       
  1663 
       
  1664 //
       
  1665 // CCmdMemInfo.
       
  1666 //
       
  1667 
       
  1668 CCommandBase* CCmdMemInfo::NewLC()
       
  1669 	{
       
  1670 	CCmdMemInfo* self = new(ELeave) CCmdMemInfo();
       
  1671 	CleanupStack::PushL(self);
       
  1672 	self->BaseConstructL();
       
  1673 	return self;
       
  1674 	}
       
  1675 
       
  1676 CCmdMemInfo::~CCmdMemInfo()
       
  1677 	{
       
  1678 	}
       
  1679 
       
  1680 CCmdMemInfo::CCmdMemInfo()
       
  1681 	{
       
  1682 	}
       
  1683 
       
  1684 const TDesC& CCmdMemInfo::Name() const
       
  1685 	{
       
  1686 	_LIT(KCmdMemInfoName, "meminfo");
       
  1687 	return KCmdMemInfoName;
       
  1688 	}
       
  1689 
       
  1690 void CCmdMemInfo::AppendLineL(CTextFormatter& aFormatter, const TDesC& aCaption, HALData::TAttribute aHalAttribute, TBool aNewLine)
       
  1691 	{
       
  1692 	TInt value;
       
  1693 	TInt err = HAL::Get(aHalAttribute, value);
       
  1694 	if (err)
       
  1695 		{
       
  1696 		PrintWarning(_L("Unable to read %S%d"), &aCaption, err);
       
  1697 		}
       
  1698 	else
       
  1699 		{
       
  1700 		if ((aHalAttribute != HALData::EMemoryRAMFree) || ((aHalAttribute == HALData::EMemoryRAMFree) && (value != iLastTotalRamUsage)))
       
  1701 			{
       
  1702 			aFormatter.AppendL(aCaption);
       
  1703 			if (iHumanReadable)
       
  1704 				{
       
  1705 				aFormatter.AppendHumanReadableSizeL(value, EColumnAlignedRight);
       
  1706 				}
       
  1707 			else
       
  1708 				{
       
  1709 				aFormatter.AppendFormatL(_L("%d"), value);
       
  1710 				}
       
  1711 			if (aNewLine)
       
  1712 				{
       
  1713 				aFormatter.AppendL(KNewLine);
       
  1714 				}
       
  1715 			}
       
  1716 		if (aHalAttribute == HALData::EMemoryRAMFree)
       
  1717 			{
       
  1718 			iLastTotalRamUsage = value;
       
  1719 			}
       
  1720 		}
       
  1721 	}
       
  1722 
       
  1723 void CCmdMemInfo::DoRunL()
       
  1724 	{
       
  1725 	if (iOnlyFreeRam && iOnlyTotalRam)
       
  1726 		{
       
  1727 		LeaveIfErr(KErrArgument, _L("Mutually exclusive options"));
       
  1728 		}
       
  1729 	CTextFormatter* formatter = CTextFormatter::NewLC(Stdout());
       
  1730 	if (iOnlyFreeRam)
       
  1731 		{
       
  1732 		AppendLineL(*formatter, KNullDesC, HALData::EMemoryRAMFree, EFalse);
       
  1733 		}
       
  1734 	else if (iOnlyTotalRam)
       
  1735 		{
       
  1736 		AppendLineL(*formatter, KNullDesC, HALData::EMemoryRAM, EFalse);
       
  1737 		}
       
  1738 	else
       
  1739 		{
       
  1740 		AppendLineL(*formatter, _L("Total ROM: "), HALData::EMemoryROM, ETrue);
       
  1741 		AppendLineL(*formatter, _L("Total RAM: "), HALData::EMemoryRAM, ETrue);
       
  1742 		AppendLineL(*formatter, _L("Page size: "), HALData::EMemoryPageSize, ETrue);
       
  1743 		AppendLineL(*formatter, _L("Free RAM:  "), HALData::EMemoryRAMFree, EFalse);
       
  1744 		}
       
  1745 
       
  1746 	Write(formatter->Descriptor());
       
  1747 	if (iUpdateRate)
       
  1748 		{
       
  1749 		if (Stdout().AttachedToConsole())
       
  1750 			{
       
  1751 			RIoConsoleWriteHandle stdout = Stdout();
       
  1752 			stdout.SetCursorHeight(0);
       
  1753 			}
       
  1754 		FOREVER
       
  1755 			{
       
  1756 			User::After(iUpdateRate * 1000);
       
  1757 			formatter->Zero();
       
  1758 			AppendLineL(*formatter, _L("\rFree RAM:  "), HALData::EMemoryRAMFree, EFalse);
       
  1759 			Write(formatter->Descriptor());
       
  1760 			}
       
  1761 		}
       
  1762 	CleanupStack::PopAndDestroy(formatter);
       
  1763 	}
       
  1764 
       
  1765 void CCmdMemInfo::OptionsL(RCommandOptionList& aOptions)
       
  1766 	{
       
  1767 	_LIT(KCmdMemInfoOptUpdateRate, "rate");
       
  1768 	_LIT(KCmdMemInfoOptHuman, "human");
       
  1769 	_LIT(KCmdMemInfoOptOnlyFreeRam, "free");
       
  1770 	_LIT(KCmdMemInfoOptOnlyTotalRam, "total");
       
  1771 
       
  1772 	aOptions.AppendBoolL(iHumanReadable, KCmdMemInfoOptHuman);
       
  1773 	aOptions.AppendUintL(iUpdateRate, KCmdMemInfoOptUpdateRate);
       
  1774 	aOptions.AppendBoolL(iOnlyFreeRam, KCmdMemInfoOptOnlyFreeRam);
       
  1775 	aOptions.AppendBoolL(iOnlyTotalRam, KCmdMemInfoOptOnlyTotalRam);
       
  1776 	}
       
  1777 
       
  1778 
       
  1779 //
       
  1780 // CCmdDump.
       
  1781 //
       
  1782 
       
  1783 void Dump(const TDesC8& aData, CCommandBase& aCommand, TInt& aPos)
       
  1784 	{
       
  1785 	TBuf<80> out;
       
  1786 	TBuf<16> ascii;
       
  1787 	TInt dataIndex = 0;
       
  1788 	do
       
  1789 		{
       
  1790 		out.Zero();
       
  1791 		ascii.Zero();
       
  1792 		out.AppendNumFixedWidthUC(aPos, EHex, 8);
       
  1793 		out.Append(_L(": "));
       
  1794 		for (TInt i = 0; i < 16; ++i)
       
  1795 			{
       
  1796 			if (dataIndex < aData.Length())
       
  1797 				{
       
  1798 				TUint8 byte = aData[dataIndex++];
       
  1799 				out.AppendNumFixedWidthUC(byte, EHex, 2);
       
  1800 				out.Append(_L(" "));
       
  1801 				if ((byte < 0x20) || (byte >= 0x7f) || byte == '%')
       
  1802 					{
       
  1803 					byte = '.';
       
  1804 					}
       
  1805 				ascii.Append(TChar(byte));
       
  1806 				++aPos;
       
  1807 				}
       
  1808 			else
       
  1809 				{
       
  1810 				out.Append(_L("   "));
       
  1811 				aPos = 0;
       
  1812 				}
       
  1813 			}
       
  1814 		out.Append(ascii);
       
  1815 		out.Append(KNewLine);
       
  1816 		aCommand.Write(out);
       
  1817 		}
       
  1818 		while (dataIndex < aData.Length());
       
  1819 	}
       
  1820 
       
  1821 CCommandBase* CCmdDump::NewLC()
       
  1822 	{
       
  1823 	CCmdDump* self = new(ELeave) CCmdDump();
       
  1824 	CleanupStack::PushL(self);
       
  1825 	self->BaseConstructL();
       
  1826 	return self;
       
  1827 	}
       
  1828 
       
  1829 CCmdDump::~CCmdDump()
       
  1830 	{
       
  1831 	iFileNames.Close();
       
  1832 	}
       
  1833 
       
  1834 CCmdDump::CCmdDump()
       
  1835 	{
       
  1836 	}
       
  1837 
       
  1838 const TDesC& CCmdDump::Name() const
       
  1839 	{
       
  1840 	_LIT(KCmdDumpName, "dump");
       
  1841 	return KCmdDumpName;
       
  1842 	}
       
  1843 
       
  1844 void CCmdDump::DoRunL()
       
  1845 	{
       
  1846 	if (iFileNames.Count())
       
  1847 		{
       
  1848 		for (TInt i = 0; i < iFileNames.Count(); i++)
       
  1849 			{
       
  1850 			TInt pos = 0;
       
  1851 			const TFileName& fn = iFileNames[i];
       
  1852 			LeaveIfFileNotFound(fn);
       
  1853 			RFile file;
       
  1854 			User::LeaveIfError(file.Open(FsL(), fn, EFileRead));
       
  1855 			TBuf8<KBlockSize> buf;
       
  1856 			TInt err = KErrNone;
       
  1857 			if (iFileNames.Count() > 1) Printf(_L("%S:\r\n"), &fn); // For compatability don't print the file name if there's only one file
       
  1858 			FOREVER
       
  1859 				{
       
  1860 				err = file.Read(buf);
       
  1861 				if ((err == KErrNone) && (buf.Length() > 0))
       
  1862 					{
       
  1863 					Dump(buf, *this, pos);
       
  1864 					buf.Zero();
       
  1865 					}
       
  1866 				else
       
  1867 					{
       
  1868 					break;
       
  1869 					}
       
  1870 				}
       
  1871 			file.Close();
       
  1872 			}
       
  1873 		}
       
  1874 	else
       
  1875 		{
       
  1876 		TInt pos = 0;
       
  1877 		RIoConsoleReadHandle& stdin = Stdin();
       
  1878 		if (iBinaryMode)
       
  1879 			{
       
  1880 			stdin.SetModeL(RIoReadWriteHandle::EBinary);
       
  1881 			}
       
  1882 		stdin.SetReadModeL(RIoReadHandle::EOneOrMore);
       
  1883 		TBuf<KBlockSize> buf;
       
  1884 		TInt err = KErrNone;
       
  1885 		while (err == KErrNone)
       
  1886 			{
       
  1887 			err = stdin.Read(buf);
       
  1888 			if (err == KErrNone)
       
  1889 				{
       
  1890 				Dump(TPtrC8((TUint8*)buf.Ptr(), buf.Length() * 2), *this, pos);
       
  1891 				}
       
  1892 			}
       
  1893 		}
       
  1894 	}
       
  1895 
       
  1896 void CCmdDump::OptionsL(RCommandOptionList& aOptions)
       
  1897 	{
       
  1898 	_LIT(KCmdDumpOptBinaryMode, "binary");
       
  1899 	aOptions.AppendBoolL(iBinaryMode, KCmdDumpOptBinaryMode);
       
  1900 	}
       
  1901 
       
  1902 void CCmdDump::ArgumentsL(RCommandArgumentList& aArguments)
       
  1903 	{
       
  1904 	_LIT(KCmdDumpArg1, "file_name");
       
  1905 	aArguments.AppendFileNameL(iFileNames, KCmdDumpArg1);
       
  1906 	}
       
  1907 
       
  1908 
       
  1909 //
       
  1910 // CCmdSleep.
       
  1911 //
       
  1912 
       
  1913 CCommandBase* CCmdSleep::NewLC()
       
  1914 	{
       
  1915 	CCmdSleep* self = new(ELeave) CCmdSleep();
       
  1916 	CleanupStack::PushL(self);
       
  1917 	self->BaseConstructL();
       
  1918 	return self;
       
  1919 	}
       
  1920 
       
  1921 CCmdSleep::~CCmdSleep()
       
  1922 	{
       
  1923 	}
       
  1924 
       
  1925 CCmdSleep::CCmdSleep() : CCommandBase(EManualComplete)
       
  1926 	{
       
  1927 	}
       
  1928 
       
  1929 const TDesC& CCmdSleep::Name() const
       
  1930 	{
       
  1931 	_LIT(KCmdSleepName, "sleep");
       
  1932 	return KCmdSleepName;
       
  1933 	}
       
  1934 
       
  1935 void CCmdSleep::DoRunL()
       
  1936 	{
       
  1937 	if (iDuration > (KMaxTUint / 1000000))
       
  1938 		{
       
  1939 		LeaveIfErr(KErrArgument, _L("Duration too large"));
       
  1940 		}
       
  1941 
       
  1942 	if (iDuration > 0)
       
  1943 		{
       
  1944 		User::After(iDuration * 1000000);
       
  1945 		Complete();
       
  1946 		}
       
  1947 	}
       
  1948 
       
  1949 void CCmdSleep::ArgumentsL(RCommandArgumentList& aArguments)
       
  1950 	{
       
  1951 	_LIT(KCmdSleepArg1, "duration");
       
  1952 	aArguments.AppendUintL(iDuration, KCmdSleepArg1);
       
  1953 	}
       
  1954 
       
  1955 
       
  1956 //
       
  1957 // CCmdEnv.
       
  1958 //
       
  1959 
       
  1960 CCommandBase* CCmdEnv::NewLC()
       
  1961 	{
       
  1962 	CCmdEnv* self = new(ELeave) CCmdEnv();
       
  1963 	CleanupStack::PushL(self);
       
  1964 	self->BaseConstructL();
       
  1965 	return self;
       
  1966 	}
       
  1967 
       
  1968 CCmdEnv::~CCmdEnv()
       
  1969 	{
       
  1970 	}
       
  1971 
       
  1972 CCmdEnv::CCmdEnv()
       
  1973 	{
       
  1974 	}
       
  1975 
       
  1976 const TDesC& CCmdEnv::Name() const
       
  1977 	{
       
  1978 	_LIT(KCmdEnvName, "env");
       
  1979 	return KCmdEnvName;
       
  1980 	}
       
  1981 
       
  1982 void CCmdEnv::DoRunL()
       
  1983 	{
       
  1984 	const IoUtils::CEnvironment& env = Env();
       
  1985 
       
  1986 	RPointerArray<HBufC> keys;
       
  1987 	LtkUtils::CleanupResetAndDestroyPushL(keys);
       
  1988 	env.GetKeysL(keys);
       
  1989 
       
  1990 	const TInt numVars = keys.Count();
       
  1991 	for (TInt i = 0; i < numVars; ++i)
       
  1992 		{
       
  1993 		const TDesC& key = *keys[i];
       
  1994 		if (env.IsInt(key))
       
  1995 			{
       
  1996 			Printf(_L("%S=%d\r\n"), &key, env.GetAsIntL(key));
       
  1997 			}
       
  1998 		else if (env.IsDes(key))
       
  1999 			{
       
  2000 			const TDesC& des = env.GetAsDesL(key);
       
  2001 			Printf(_L("%S=%S\r\n"), &key, &des);
       
  2002 			}
       
  2003 		}
       
  2004 	CleanupStack::PopAndDestroy(&keys);
       
  2005 	}
       
  2006 
       
  2007 
       
  2008 //
       
  2009 // CCmdExport.
       
  2010 //
       
  2011 
       
  2012 CCommandBase* CCmdExport::NewLC()
       
  2013 	{
       
  2014 	CCmdExport* self = new(ELeave) CCmdExport();
       
  2015 	CleanupStack::PushL(self);
       
  2016 	self->BaseConstructL();
       
  2017 	return self;
       
  2018 	}
       
  2019 
       
  2020 CCmdExport::~CCmdExport()
       
  2021 	{
       
  2022 	delete iKey;
       
  2023 	delete iVal;
       
  2024 	}
       
  2025 
       
  2026 CCmdExport::CCmdExport()
       
  2027 	{
       
  2028 	}
       
  2029 
       
  2030 const TDesC& CCmdExport::Name() const
       
  2031 	{
       
  2032 	_LIT(KCmdExportName, "export");
       
  2033 	return KCmdExportName;
       
  2034 	}
       
  2035 
       
  2036 void CCmdExport::DoRunL()
       
  2037 	{
       
  2038 	if (iStdin)
       
  2039 		{
       
  2040 		if (iVal)
       
  2041 			{
       
  2042 			Complete(KErrArgument, _L("You can only specify one of --stdin or <value>"));
       
  2043 			return;
       
  2044 			}
       
  2045 
       
  2046 		Stdin().SetReadModeL(RIoReadHandle::EFull);
       
  2047 		TInt err = Stdin().Read(iBuf);
       
  2048 		if (err == KErrEof)
       
  2049 			{
       
  2050 			Env().SetL(*iKey, KNullDesC);
       
  2051 			}
       
  2052 		else
       
  2053 			{
       
  2054 			LeaveIfErr(err, _L("Couldn't read from stdin"));
       
  2055 			Env().SetL(*iKey, iBuf);
       
  2056 			}
       
  2057 		}
       
  2058 	else if (iVal)
       
  2059 		{
       
  2060 		Env().SetL(*iKey, *iVal);
       
  2061 		}
       
  2062 	else
       
  2063 		{
       
  2064 		Env().RemoveL(*iKey);
       
  2065 		}
       
  2066 	}
       
  2067 
       
  2068 void CCmdExport::OptionsL(RCommandOptionList& aOptions)
       
  2069 	{
       
  2070 	_LIT(KCmdExportOptStdin, "stdin");
       
  2071 	aOptions.AppendBoolL(iStdin, KCmdExportOptStdin);
       
  2072 	}
       
  2073 
       
  2074 void CCmdExport::ArgumentsL(RCommandArgumentList& aArguments)
       
  2075 	{
       
  2076 	_LIT(KCmdExportArg1, "variable");
       
  2077 	_LIT(KCmdExportArg2, "value");
       
  2078 	aArguments.AppendStringL(iKey, KCmdExportArg1);
       
  2079 	aArguments.AppendStringL(iVal, KCmdExportArg2);
       
  2080 	}
       
  2081 
       
  2082 
       
  2083 //
       
  2084 // CCmdSort.
       
  2085 //
       
  2086 
       
  2087 CCommandBase* CCmdSort::NewLC()
       
  2088 	{
       
  2089 	CCmdSort* self = new(ELeave) CCmdSort();
       
  2090 	CleanupStack::PushL(self);
       
  2091 	self->BaseConstructL();
       
  2092 	return self;
       
  2093 	}
       
  2094 
       
  2095 CCmdSort::~CCmdSort()
       
  2096 	{
       
  2097 	}
       
  2098 
       
  2099 CCmdSort::CCmdSort()
       
  2100 	{
       
  2101 	}
       
  2102 
       
  2103 const TDesC& CCmdSort::Name() const
       
  2104 	{
       
  2105 	_LIT(KCmdSortName, "sort");
       
  2106 	return KCmdSortName;
       
  2107 	}
       
  2108 
       
  2109 TInt ComparePtrs(const TPtrC& aPtr1, const TPtrC& aPtr2)
       
  2110 	{
       
  2111 	return aPtr1.Compare(aPtr2);
       
  2112 	}
       
  2113 
       
  2114 void CCmdSort::DoRunL()
       
  2115 	{
       
  2116 	// Read all input into a buffer.
       
  2117 	CTextBuffer* buffer = CTextBuffer::NewLC(0x100);
       
  2118 	Stdin().SetReadMode(RIoReadHandle::EOneOrMore);
       
  2119 	TBuf<0x100> buf;
       
  2120 	while (Stdin().Read(buf) == KErrNone)
       
  2121 		{
       
  2122 		buffer->AppendL(buf);
       
  2123 		}
       
  2124 
       
  2125 	// Populate an ordered list of lines.
       
  2126 	RArray<TPtrC> sortedLines;
       
  2127 	CleanupClosePushL(sortedLines);
       
  2128 	TPtrC ptr(buffer->Descriptor());
       
  2129 	FOREVER
       
  2130 		{
       
  2131 		TInt pos = ptr.Find(KNewLine);
       
  2132 		if (pos >= 0)
       
  2133 			{
       
  2134 			pos += KNewLine().Length();
       
  2135 			TPtrC line(ptr.Left(pos));
       
  2136 			User::LeaveIfError(sortedLines.InsertInOrderAllowRepeats(line, TLinearOrder<TPtrC>(ComparePtrs)));
       
  2137 			if (pos < (ptr.Length() - 1))
       
  2138 				{
       
  2139 				ptr.Set(ptr.Mid(pos));
       
  2140 				}
       
  2141 			else
       
  2142 				{
       
  2143 				break;
       
  2144 				}
       
  2145 			}
       
  2146 		else
       
  2147 			{
       
  2148 			User::LeaveIfError(sortedLines.InsertInOrderAllowRepeats(ptr, TLinearOrder<TPtrC>(ComparePtrs)));
       
  2149 			break;
       
  2150 			}
       
  2151 		}
       
  2152 
       
  2153 	// Output the ordered list of lines.
       
  2154 	const TInt numLines = sortedLines.Count();
       
  2155 	if (iReverse)
       
  2156 		{
       
  2157 		for (TInt i = (numLines - 1); i >= 0; --i)
       
  2158 			{
       
  2159 			Write(sortedLines[i]);
       
  2160 			}
       
  2161 		}
       
  2162 	else
       
  2163 		{
       
  2164 		for (TInt i = 0; i < numLines; ++i)
       
  2165 			{
       
  2166 			Write(sortedLines[i]);
       
  2167 			}
       
  2168 		}
       
  2169 
       
  2170 	CleanupStack::PopAndDestroy(2, buffer);
       
  2171 	}
       
  2172 
       
  2173 void CCmdSort::OptionsL(RCommandOptionList& aOptions)
       
  2174 	{
       
  2175 	_LIT(KCmdSortOptReverse, "reverse");
       
  2176 	aOptions.AppendBoolL(iReverse, KCmdSortOptReverse);
       
  2177 	}
       
  2178 
       
  2179 
       
  2180 //
       
  2181 // CCmdExists.
       
  2182 //
       
  2183 
       
  2184 CCommandBase* CCmdExists::NewLC()
       
  2185 	{
       
  2186 	CCmdExists* self = new(ELeave) CCmdExists();
       
  2187 	CleanupStack::PushL(self);
       
  2188 	self->BaseConstructL();
       
  2189 	return self;
       
  2190 	}
       
  2191 
       
  2192 CCmdExists::~CCmdExists()
       
  2193 	{
       
  2194 	}
       
  2195 
       
  2196 CCmdExists::CCmdExists()
       
  2197 	{
       
  2198 	}
       
  2199 
       
  2200 const TDesC& CCmdExists::Name() const
       
  2201 	{
       
  2202 	_LIT(KCmdExistsName, "exists");
       
  2203 	return KCmdExistsName;
       
  2204 	}
       
  2205 
       
  2206 void CCmdExists::DoRunL()
       
  2207 	{
       
  2208 	TUint att;
       
  2209 	Complete(!(FsL().Att(iFileName, att) == KErrNone));
       
  2210 	}
       
  2211 
       
  2212 void CCmdExists::ArgumentsL(RCommandArgumentList& aArguments)
       
  2213 	{
       
  2214 	_LIT(KCmdExistsArg, "file_name");
       
  2215 	aArguments.AppendFileNameL(iFileName, KCmdExistsArg);
       
  2216 	}
       
  2217 
       
  2218 
       
  2219 //
       
  2220 // CCmdInfoPrint.
       
  2221 //
       
  2222 
       
  2223 CCommandBase* CCmdInfoPrint::NewLC()
       
  2224 	{
       
  2225 	CCmdInfoPrint* self = new(ELeave) CCmdInfoPrint();
       
  2226 	CleanupStack::PushL(self);
       
  2227 	self->BaseConstructL();
       
  2228 	return self;
       
  2229 	}
       
  2230 
       
  2231 CCmdInfoPrint::~CCmdInfoPrint()
       
  2232 	{
       
  2233 	delete iToPrint;
       
  2234 	}
       
  2235 
       
  2236 CCmdInfoPrint::CCmdInfoPrint()
       
  2237 	{
       
  2238 	}
       
  2239 
       
  2240 const TDesC& CCmdInfoPrint::Name() const
       
  2241 	{
       
  2242 	_LIT(KCmdInfoPrintName, "infoprint");
       
  2243 	return KCmdInfoPrintName;
       
  2244 	}
       
  2245 
       
  2246 void CCmdInfoPrint::DoRunL()
       
  2247 	{
       
  2248 	if (!iToPrint)
       
  2249 		{
       
  2250 		TBuf<0x100> toPrint;
       
  2251 		Stdin().SetReadModeL(RIoReadHandle::EFull);
       
  2252 		Stdin().Read(toPrint);
       
  2253 		// remove a newline from the end, if one exists
       
  2254 		if ((toPrint.Length() > 0) && (toPrint[toPrint.Length()-1] == '\n'))
       
  2255 			{
       
  2256 			toPrint.SetLength(toPrint.Length()-1);
       
  2257 			if ((toPrint.Length() > 0) && (toPrint[toPrint.Length()-1] == '\r'))
       
  2258 				{
       
  2259 				toPrint.SetLength(toPrint.Length()-1);
       
  2260 				}
       
  2261 			}
       
  2262 		User::InfoPrint(toPrint);
       
  2263 		}
       
  2264 	else
       
  2265 		{
       
  2266 		User::InfoPrint(*iToPrint);
       
  2267 		}
       
  2268 	}
       
  2269 
       
  2270 void CCmdInfoPrint::ArgumentsL(RCommandArgumentList& aArguments)
       
  2271 	{
       
  2272 	_LIT(KCmdInfoPrintArg, "message");
       
  2273 	aArguments.AppendStringL(iToPrint, KCmdInfoPrintArg);
       
  2274 	}
       
  2275 
       
  2276 
       
  2277 //
       
  2278 // CCmdRDebug.
       
  2279 //
       
  2280 
       
  2281 CCommandBase* CCmdRDebug::NewLC()
       
  2282 	{
       
  2283 	CCmdRDebug* self = new(ELeave) CCmdRDebug();
       
  2284 	CleanupStack::PushL(self);
       
  2285 	self->BaseConstructL();
       
  2286 	return self;
       
  2287 	}
       
  2288 
       
  2289 CCmdRDebug::~CCmdRDebug()
       
  2290 	{
       
  2291 	delete iToPrint;
       
  2292 	}
       
  2293 
       
  2294 CCmdRDebug::CCmdRDebug()
       
  2295 	{
       
  2296 	}
       
  2297 
       
  2298 const TDesC& CCmdRDebug::Name() const
       
  2299 	{
       
  2300 	_LIT(KCmdRDebugName, "rdebug");
       
  2301 	return KCmdRDebugName;
       
  2302 	}
       
  2303 
       
  2304 void CCmdRDebug::DoRunL()
       
  2305 	{
       
  2306 	if (iToPrint)
       
  2307 		{
       
  2308 		RDebug::Print(*iToPrint);
       
  2309 		}
       
  2310 	else
       
  2311 		{
       
  2312 		RIoConsoleReadHandle& stdin = Stdin();
       
  2313 		stdin.SetReadModeL(RIoReadHandle::ELine);
       
  2314 		TBuf<512> buf;
       
  2315 		TInt err = KErrNone;
       
  2316 		while (err == KErrNone)
       
  2317 			{
       
  2318 			err = stdin.Read(buf);
       
  2319 			if (err == KErrNone)
       
  2320 				{
       
  2321 				RDebug::Print(buf);
       
  2322 				}
       
  2323 			}
       
  2324 		}
       
  2325 	}
       
  2326 
       
  2327 void CCmdRDebug::ArgumentsL(RCommandArgumentList& aArguments)
       
  2328 	{
       
  2329 	_LIT(KCmdRDebugArg, "message");
       
  2330 	aArguments.AppendStringL(iToPrint, KCmdRDebugArg);
       
  2331 	}
       
  2332 
       
  2333 
       
  2334 //
       
  2335 // CCmdDate.
       
  2336 //
       
  2337 
       
  2338 CCommandBase* CCmdDate::NewLC()
       
  2339 	{
       
  2340 	CCmdDate* self = new(ELeave) CCmdDate();
       
  2341 	CleanupStack::PushL(self);
       
  2342 	self->BaseConstructL();
       
  2343 	return self;
       
  2344 	}
       
  2345 
       
  2346 CCmdDate::~CCmdDate()
       
  2347 	{
       
  2348 	delete iDateToSet;
       
  2349 	}
       
  2350 
       
  2351 CCmdDate::CCmdDate()
       
  2352 	{
       
  2353 	}
       
  2354 
       
  2355 void CCmdDate::Display(const TTime& aTime)
       
  2356 	{
       
  2357 	if (iRaw)
       
  2358 		{
       
  2359 		Printf(_L("%Ld\r\n"), aTime.Int64());
       
  2360 		}
       
  2361 	else if (iUseTimestampFormat)
       
  2362 		{
       
  2363 		TDateTime dateTime(aTime.DateTime());
       
  2364 		Printf(_L("%04d%02d%02d-%02d%02d.%02d"), dateTime.Year(), dateTime.Month() + 1, dateTime.Day() + 1, dateTime.Hour(), dateTime.Minute(), dateTime.Second());
       
  2365 		}
       
  2366 	else
       
  2367 		{
       
  2368 		TDateTime dateTime(aTime.DateTime());
       
  2369 		Printf(_L("%+02d/%+02d/%+04d %+02d:%+02d:%+02d.%+06d\r\n"), dateTime.Day() + 1, dateTime.Month() + 1, dateTime.Year(), dateTime.Hour(), dateTime.Minute(), dateTime.Second(), dateTime.MicroSecond());
       
  2370 		}
       
  2371 	}
       
  2372 
       
  2373 const TDesC& CCmdDate::Name() const
       
  2374 	{
       
  2375 	_LIT(KCmdDateName, "date");
       
  2376 	return KCmdDateName;
       
  2377 	}
       
  2378 
       
  2379 void CCmdDate::DoRunL()
       
  2380 	{
       
  2381 	if (!iDateToSet && !iOptions.IsPresent(&iRawTimeToSet))
       
  2382 		{
       
  2383 		TTime time;
       
  2384 		if (iUniversalTime)
       
  2385 			{
       
  2386 #ifdef FSHELL_CORE_SUPPORT_SECURE_TIME
       
  2387 			if (iSecure)
       
  2388 				{
       
  2389 				LeaveIfErr(time.UniversalTimeSecure(), _L("Unable to get secure universal time"));
       
  2390 				}
       
  2391 			else
       
  2392 #endif
       
  2393 				{
       
  2394 				time.UniversalTime();
       
  2395 				}
       
  2396 			}
       
  2397 		else
       
  2398 			{
       
  2399 #ifdef FSHELL_CORE_SUPPORT_SECURE_TIME
       
  2400 			if (iSecure)
       
  2401 				{
       
  2402 				LeaveIfErr(time.HomeTimeSecure(), _L("Unable to get secure home time"));
       
  2403 				}
       
  2404 			else
       
  2405 #endif
       
  2406 				{
       
  2407 				time.HomeTime();
       
  2408 				}
       
  2409 			}
       
  2410 		Display(time);
       
  2411 		}
       
  2412 	else
       
  2413 		{
       
  2414 		_LIT(KSettingError, "Cannot set the time");
       
  2415 		TTime time(iRawTimeToSet);
       
  2416 		if (iDateToSet)
       
  2417 			{
       
  2418 			_LIT(KParsingTime, "Cannot parse time string");
       
  2419 			LeaveIfErr(time.Parse(*iDateToSet), KParsingTime);
       
  2420 			}
       
  2421 		if (iJustDisplay)
       
  2422 			{
       
  2423 			Display(time);
       
  2424 			}
       
  2425 		else
       
  2426 			{
       
  2427 			if (iUniversalTime)
       
  2428 				{
       
  2429 #ifdef FSHELL_CORE_SUPPORT_SECURE_TIME
       
  2430 				if (iSecure)
       
  2431 					{
       
  2432 					LeaveIfErr(User::SetUTCTimeSecure(time), KSettingError);
       
  2433 					}
       
  2434 				else
       
  2435 #endif
       
  2436 					{
       
  2437 					LeaveIfErr(User::SetUTCTime(time), KSettingError);
       
  2438 					}
       
  2439 				}
       
  2440 			else
       
  2441 				{
       
  2442 #ifdef FSHELL_CORE_SUPPORT_SECURE_TIME
       
  2443 				if (iSecure)
       
  2444 					{
       
  2445 					LeaveIfErr(User::SetHomeTimeSecure(time), KSettingError);
       
  2446 					}
       
  2447 				else
       
  2448 #endif
       
  2449 					{
       
  2450 					LeaveIfErr(User::SetHomeTime(time), KSettingError);
       
  2451 					}
       
  2452 				}
       
  2453 			if (iOptions.IsPresent(&iUtcOffset))
       
  2454 				{
       
  2455 				User::SetUTCOffset(TTimeIntervalSeconds(iUtcOffset));
       
  2456 				}
       
  2457 			}
       
  2458 		}
       
  2459 	}
       
  2460 
       
  2461 void CCmdDate::OptionsL(RCommandOptionList& aOptions)
       
  2462 	{
       
  2463 	_LIT(KCmdDateOptUniversal, "universal");
       
  2464 	_LIT(KCmdDateOptSet, "set");
       
  2465 	_LIT(KCmdDateOptUtcOffset, "utc-offset");
       
  2466 #ifdef FSHELL_CORE_SUPPORT_SECURE_TIME
       
  2467 	_LIT(KCmdDateOptSecure, "secure");
       
  2468 #endif
       
  2469 	_LIT(KCmdDateOptRaw, "raw");
       
  2470 	_LIT(KCmdDateOptJustDisplay, "just-display");
       
  2471 	_LIT(KCmdDateOptSetRaw, "raw-set");
       
  2472 	_LIT(KCmdDataOptTimestamp, "timestamp");
       
  2473 
       
  2474 	aOptions.AppendBoolL(iUniversalTime, KCmdDateOptUniversal);
       
  2475 	aOptions.AppendStringL(iDateToSet, KCmdDateOptSet);
       
  2476 	aOptions.AppendIntL(iUtcOffset, KCmdDateOptUtcOffset);
       
  2477 #ifdef FSHELL_CORE_SUPPORT_SECURE_TIME
       
  2478 	aOptions.AppendBoolL(iSecure, KCmdDateOptSecure);
       
  2479 #endif
       
  2480 	aOptions.AppendBoolL(iRaw, KCmdDateOptRaw);
       
  2481 	aOptions.AppendBoolL(iJustDisplay, KCmdDateOptJustDisplay);
       
  2482 	aOptions.AppendIntL(iRawTimeToSet, KCmdDateOptSetRaw);
       
  2483 	aOptions.AppendBoolL(iUseTimestampFormat, KCmdDataOptTimestamp);
       
  2484 	}
       
  2485 
       
  2486 
       
  2487 //
       
  2488 // CCmdFsck.
       
  2489 //
       
  2490 
       
  2491 CCommandBase* CCmdFsck::NewLC()
       
  2492 	{
       
  2493 	CCmdFsck* self = new(ELeave) CCmdFsck();
       
  2494 	CleanupStack::PushL(self);
       
  2495 	self->BaseConstructL();
       
  2496 	return self;
       
  2497 	}
       
  2498 
       
  2499 CCmdFsck::~CCmdFsck()
       
  2500 	{
       
  2501 	delete iDriveLetter;
       
  2502 	}
       
  2503 
       
  2504 CCmdFsck::CCmdFsck()
       
  2505 	{
       
  2506 	}
       
  2507 
       
  2508 const TDesC& CCmdFsck::Name() const
       
  2509 	{
       
  2510 	_LIT(KCmdFsckName, "fsck");
       
  2511 	return KCmdFsckName;
       
  2512 	}
       
  2513 
       
  2514 void CCmdFsck::DoRunL()
       
  2515 	{
       
  2516 	TInt ret = FsL().CheckDisk(*iDriveLetter);
       
  2517 
       
  2518 	switch (ret)
       
  2519 		{
       
  2520 		case KErrNotSupported:
       
  2521 			Printf(_L("Not supported\r\n"));
       
  2522 			break;
       
  2523 		case 0:
       
  2524 			Printf(_L("No errors\r\n"));
       
  2525 			break;
       
  2526 		case 1:
       
  2527 			Printf(_L("Error: File cluster chain contains a bad value (<2 or >maxCluster)\r\n"));
       
  2528 			break;
       
  2529 		case 2:
       
  2530 			Printf(_L("Error: Two files are linked to the same cluster\r\n"));
       
  2531 			break;
       
  2532 		case 3:
       
  2533 			Printf(_L("Error: Unallocated cluster contains a value != 0\r\n"));
       
  2534 			break;
       
  2535 		case 4:
       
  2536 			Printf(_L("Error: Size of file != number of clusters in chain\r\n"));
       
  2537 			break;
       
  2538 		default:
       
  2539 			Printf(_L("Error: %d\r\n"), ret);
       
  2540 		}
       
  2541 
       
  2542 	User::LeaveIfError(ret);
       
  2543 	}
       
  2544 
       
  2545 void CCmdFsck::ArgumentsL(RCommandArgumentList& aArguments)
       
  2546 	{
       
  2547 	_LIT(KCmdFsckArg, "drive_letter");
       
  2548 	aArguments.AppendStringL(iDriveLetter, KCmdFsckArg);
       
  2549 	}
       
  2550 
       
  2551 
       
  2552 //
       
  2553 // CCmdDriver.
       
  2554 //
       
  2555 
       
  2556 CCommandBase* CCmdDriver::NewLC()
       
  2557 	{
       
  2558 	CCmdDriver* self = new(ELeave) CCmdDriver();
       
  2559 	CleanupStack::PushL(self);
       
  2560 	self->BaseConstructL();
       
  2561 	return self;
       
  2562 	}
       
  2563 
       
  2564 CCmdDriver::~CCmdDriver()
       
  2565 	{
       
  2566 	delete iDriverName;
       
  2567 	}
       
  2568 
       
  2569 CCmdDriver::CCmdDriver()
       
  2570 	{
       
  2571 	}
       
  2572 
       
  2573 const TDesC& CCmdDriver::Name() const
       
  2574 	{
       
  2575 	_LIT(KCmdDriverName, "driver");
       
  2576 	return KCmdDriverName;
       
  2577 	}
       
  2578 
       
  2579 void CCmdDriver::DoRunL()
       
  2580 	{
       
  2581 	TInt err = KErrNone;
       
  2582 	switch (iOperation)
       
  2583 		{
       
  2584 		case ELoad:
       
  2585 			{
       
  2586 			if (iType == ELogical)
       
  2587 				{
       
  2588 				err = User::LoadLogicalDevice(*iDriverName);
       
  2589 				}
       
  2590 			else
       
  2591 				{
       
  2592 				err = User::LoadPhysicalDevice(*iDriverName);
       
  2593 				}
       
  2594 			break;
       
  2595 			}
       
  2596 		case EFree:
       
  2597 			{
       
  2598 			if (iType == ELogical)
       
  2599 				{
       
  2600 				err = User::FreeLogicalDevice(*iDriverName);
       
  2601 				}
       
  2602 			else
       
  2603 				{
       
  2604 				err = User::FreePhysicalDevice(*iDriverName);
       
  2605 				}
       
  2606 			break;
       
  2607 			}
       
  2608 		case EFind:
       
  2609 			{
       
  2610 			if (iType == ELogical)
       
  2611 				{
       
  2612 				TFindLogicalDevice findLogicalDevice;
       
  2613 				TFullName name;
       
  2614 				while (findLogicalDevice.Next(name) == KErrNone)
       
  2615 					{
       
  2616 					Printf(_L("%S\r\n"), &name);
       
  2617 					}
       
  2618 				}
       
  2619 			else
       
  2620 				{
       
  2621 				TFindPhysicalDevice findPhysicalDevice;
       
  2622 				TFullName name;
       
  2623 				while (findPhysicalDevice.Next(name) == KErrNone)
       
  2624 					{
       
  2625 					Printf(_L("%S\r\n"), &name);
       
  2626 					}
       
  2627 				}
       
  2628 			break;
       
  2629 			}
       
  2630 		default:
       
  2631 			{
       
  2632 			ASSERT(EFalse);
       
  2633 			break;
       
  2634 			}
       
  2635 		}
       
  2636 
       
  2637 	if (err)
       
  2638 		{
       
  2639 		TPtrC operation(iArguments.AsString(&iOperation));
       
  2640 		TPtrC type(iArguments.AsString(&iType));
       
  2641 		PrintError(err, _L("Unable to %S %S device"), &operation, &type);
       
  2642 		User::Leave(err);
       
  2643 		}
       
  2644 	}
       
  2645 
       
  2646 void CCmdDriver::ArgumentsL(RCommandArgumentList& aArguments)
       
  2647 	{
       
  2648 	_LIT(KCmdDriverArg1, "operation");
       
  2649 	_LIT(KCmdDriverArg2, "type");
       
  2650 	_LIT(KCmdDriverArg3, "name");
       
  2651 
       
  2652 	aArguments.AppendEnumL((TInt&)iOperation, KCmdDriverArg1);
       
  2653 	aArguments.AppendEnumL((TInt&)iType, KCmdDriverArg2);
       
  2654 	aArguments.AppendStringL(iDriverName, KCmdDriverArg3);
       
  2655 	}
       
  2656 
       
  2657 
       
  2658 //
       
  2659 // CCmdChunkInfo.
       
  2660 //
       
  2661 
       
  2662 CCommandBase* CCmdChunkInfo::NewLC()
       
  2663 	{
       
  2664 	CCmdChunkInfo* self = new(ELeave) CCmdChunkInfo();
       
  2665 	CleanupStack::PushL(self);
       
  2666 	self->BaseConstructL();
       
  2667 	return self;
       
  2668 	}
       
  2669 
       
  2670 CCmdChunkInfo::~CCmdChunkInfo()
       
  2671 	{
       
  2672 	delete iOwningProcess;
       
  2673 	delete iBuf;
       
  2674 	delete iFormatter;
       
  2675 	}
       
  2676 
       
  2677 CCmdChunkInfo::CCmdChunkInfo()
       
  2678 	{
       
  2679 	}
       
  2680 
       
  2681 void CCmdChunkInfo::ListChunksL()
       
  2682 	{
       
  2683 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  2684 	TInt bufSize = 1024;
       
  2685 	TInt err = KErrNone;
       
  2686 	HBufC8* addressesBuf;
       
  2687 	do
       
  2688 		{
       
  2689 		addressesBuf = HBufC8::NewLC(bufSize);
       
  2690 		TPtr8 addressesPtr(addressesBuf->Des());
       
  2691 		if (iControllingProcess != 0)
       
  2692 			{
       
  2693 			err = iMemAccess.GetChunkAddresses(iControllingProcess, addressesPtr);
       
  2694 			}
       
  2695 		else
       
  2696 			{
       
  2697 			err = iMemAccess.GetObjectAddresses(EChunk, iOwningProcess ? *iOwningProcess : KNullDesC(), addressesPtr);
       
  2698 			}
       
  2699 		if (err == KErrOverflow)
       
  2700 			{
       
  2701 			CleanupStack::PopAndDestroy(addressesBuf);
       
  2702 			bufSize *= 2;
       
  2703 			}
       
  2704 		}
       
  2705 		while (err == KErrOverflow);
       
  2706 
       
  2707 	if (err)
       
  2708 		{
       
  2709 		PrintError(err, _L("Unable to read chunk addresses."));
       
  2710 		User::Leave(err);
       
  2711 		}
       
  2712 
       
  2713 	const TInt numAddresses = addressesBuf->Length() / sizeof(TUint32*);
       
  2714 	if (numAddresses == 0)
       
  2715 		{
       
  2716 		Write(_L("No chunks found.\r\n"));
       
  2717 		}
       
  2718 	else
       
  2719 		{
       
  2720 		TUint32* p = (TUint32*)addressesBuf->Ptr();
       
  2721 		TInt offset = 0;
       
  2722 		while (offset < numAddresses)
       
  2723 			{
       
  2724 			TChunkKernelInfo chunkInfo;
       
  2725 			TPckg<TChunkKernelInfo> chunkInfoPckg(chunkInfo);
       
  2726 			TUint32* ptr = p + offset++;
       
  2727 			err = iMemAccess.GetObjectInfo(EChunk, (TUint8*)(*ptr), chunkInfoPckg);
       
  2728 			if (err == KErrNone)
       
  2729 				{
       
  2730 				iFullName.Copy(chunkInfo.iFullName);
       
  2731 				if (iIncludeSize)
       
  2732 					{
       
  2733 					iBuf->AppendFormatL(_L("0x%08x\t"), *ptr);
       
  2734 					if (iHumanReadable)
       
  2735 						{
       
  2736 						iBuf->AppendHumanReadableSizeL(chunkInfo.iSize, EUnaligned);
       
  2737 						iBuf->AppendFormatL(KTab);
       
  2738 						}
       
  2739 					else
       
  2740 						{
       
  2741 						iBuf->AppendFormatL(_L("%d\t"), chunkInfo.iSize);
       
  2742 						}
       
  2743 					iBuf->AppendFormatL(_L("\'%S\'\r\n"), &iFullName);
       
  2744 					}
       
  2745 				else
       
  2746 					{
       
  2747 					iBuf->AppendFormatL(_L("0x%08x\t\'%S\'\r\n"), *ptr, &iFullName);
       
  2748 					}
       
  2749 				}
       
  2750 			else if (err != KErrNotFound)
       
  2751 				{
       
  2752 				// Only abort on something other than KErrNotFound. KErrNotFound could legitimately
       
  2753 				// happen if the chunk in question has been deleted since we called RMemoryAccess::GetObjectAddresses.
       
  2754 				PrintError(err, _L("Unable to read chunk at 0x%08x, aborting."), ptr);
       
  2755 				User::Leave(err);
       
  2756 				}
       
  2757 			}
       
  2758 		}
       
  2759 
       
  2760 	CleanupStack::PopAndDestroy(addressesBuf);
       
  2761 #endif
       
  2762 	}
       
  2763 
       
  2764 void CCmdChunkInfo::PrintChunkInfoL()
       
  2765 	{
       
  2766 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  2767 	TChunkKernelInfo chunkInfo;
       
  2768 	TPckg<TChunkKernelInfo> chunkInfoPckg(chunkInfo);
       
  2769 	TInt err = iMemAccess.GetObjectInfo(EChunk, (TUint8*)iAddress, chunkInfoPckg);
       
  2770 	if (err)
       
  2771 		{
       
  2772 		PrintError(err, _L("Unable to get info for chunk 0x%08x"), iAddress);
       
  2773 		User::Leave(err);
       
  2774 		}
       
  2775 	else
       
  2776 		{
       
  2777 		iFullName.Copy(chunkInfo.iFullName);
       
  2778 		iBuf->AppendFormatL(_L("Name:\t\'%S\'\r\n"), &iFullName);
       
  2779 		iBuf->AppendFormatL(_L("Base:\t0x%08x\r\n"), chunkInfo.iBase);
       
  2780 		PrintSizeL(_L("Max size:\t"), chunkInfo.iMaxSize);
       
  2781 		PrintSizeL(_L("Current size:\t"), chunkInfo.iSize);
       
  2782 		iBuf->AppendFormatL(_L("Attributes:\t0x%08x\r\n"), chunkInfo.iAttributes);
       
  2783 		iBuf->AppendFormatL(_L("Type:\t0x%08x\r\n"), chunkInfo.iChunkType);
       
  2784 		iBuf->AppendFormatL(_L("Restrictions:\t0x%08x\r\n"), chunkInfo.iRestrictions);
       
  2785 
       
  2786 		RProcess process;
       
  2787 		TInt err = process.Open(chunkInfo.iControllingOwnerProcessId);
       
  2788 		if (err == KErrNone)
       
  2789 			{
       
  2790 			iName = process.Name();
       
  2791 			process.Close();
       
  2792 			iBuf->AppendFormatL(_L("Controlling process:\t\'%S\' (%u)\r\n"), &iName, chunkInfo.iControllingOwnerProcessId);
       
  2793 			LtkUtils::RProxyAllocatorHelper allocHelper;
       
  2794 			CleanupClosePushL(allocHelper);
       
  2795 			err = allocHelper.OpenChunkHeap(iMemAccess, (TAny*)iAddress);
       
  2796 			if (err == KErrNone)
       
  2797 				{
       
  2798 				iBuf->AppendFormatL(_L("Allocator type:\t%S\r\n"), &allocHelper.Description());
       
  2799 				PrintSizeL(_L("Heap size:\t"), allocHelper.CommittedSize());
       
  2800 				PrintSizeL(_L("Heap max size:\t"), allocHelper.MaxCommittedSize());
       
  2801 				iBuf->AppendFormatL(_L("Alloc count:\t%d\r\n"), allocHelper.AllocationCount());
       
  2802 				PrintSizeL(_L("Total alloc size:\t"), allocHelper.AllocatedSize());
       
  2803 				TReal overheadRatio = ((allocHelper.CommittedSize() - allocHelper.AllocatedSize() - allocHelper.CommittedFreeSpace()) * 100) / (TReal)allocHelper.CommittedSize();
       
  2804 				iBuf->AppendFormatL(_L("Metadata overhead:\t%00.2f%%\r\n"), overheadRatio);
       
  2805 				TInt val = allocHelper.SizeForCellType(RAllocatorHelper::EDlaAllocation);
       
  2806 				if (val >= 0)
       
  2807 					{
       
  2808 					PrintSizeL(_L("DL alloc size:\t"), val);
       
  2809 					iBuf->AppendFormatL(_L("DL alloc count:\t%d\r\n"), allocHelper.CountForCellType(RAllocatorHelper::EDlaAllocation));
       
  2810 					PrintSizeL(_L("DL free size:\t"), allocHelper.SizeForCellType(RAllocatorHelper::EDlaFreeCell));
       
  2811 					iBuf->AppendFormatL(_L("DL free cell count:\t%d\r\n"), allocHelper.CountForCellType(RAllocatorHelper::EDlaFreeCell));
       
  2812 					PrintSizeL(_L("Paged alloc size:\t"), allocHelper.SizeForCellType(RAllocatorHelper::EPageAllocation));
       
  2813 					iBuf->AppendFormatL(_L("Paged alloc count:\t%d\r\n"), allocHelper.CountForCellType(RAllocatorHelper::EPageAllocation));
       
  2814 					PrintSizeL(_L("Slab alloc size:\t"), allocHelper.SizeForCellType(RAllocatorHelper::ESlabAllocation));
       
  2815 					iBuf->AppendFormatL(_L("Slab alloc count:\t%d\r\n"), allocHelper.CountForCellType(RAllocatorHelper::ESlabAllocation));
       
  2816 					PrintSizeL(_L("Slab free size:\t"), allocHelper.SizeForCellType(RAllocatorHelper::ESlabFreeCell));
       
  2817 					iBuf->AppendFormatL(_L("Slab free cell count:\t%d\r\n"), allocHelper.CountForCellType(RAllocatorHelper::ESlabFreeCell));
       
  2818 					PrintSizeL(_L("Unused slabs size:\t"), allocHelper.SizeForCellType(RAllocatorHelper::ESlabFreeSlab));
       
  2819 					iBuf->AppendFormatL(_L("Unused slabs count:\t%d\r\n"), allocHelper.CountForCellType(RAllocatorHelper::ESlabFreeSlab));
       
  2820 					}
       
  2821 				else if (val != KErrNotSupported)
       
  2822 					{
       
  2823 					iBuf->AppendFormatL(_L("\t[Error %d returned from heap stats]\r\n"), val);
       
  2824 					}
       
  2825 				}
       
  2826 			else
       
  2827 				{
       
  2828 				iBuf->AppendL(_L("\t[RHeap allocator not found]\r\n"));
       
  2829 				}
       
  2830 			CleanupStack::PopAndDestroy(&allocHelper);
       
  2831 			}
       
  2832 		if (err)
       
  2833 			{
       
  2834 			PrintWarning(_L("Unable to read RHeap info: %d"), err);
       
  2835 			}
       
  2836 		}
       
  2837 #endif
       
  2838 	}
       
  2839 
       
  2840 void CCmdChunkInfo::PrintSizeL(const TDesC& aCaption, TInt aSize)
       
  2841 	{
       
  2842 	if (iHumanReadable)
       
  2843 		{
       
  2844 		iBuf->AppendL(aCaption);
       
  2845 		iBuf->AppendHumanReadableSizeL(aSize, EUnaligned);
       
  2846 		iBuf->AppendL(KNewLine);
       
  2847 		}
       
  2848 	else
       
  2849 		{
       
  2850 		_LIT(KFormat, "%S%d\r\n");
       
  2851 		iBuf->AppendFormatL(KFormat, &aCaption, aSize);
       
  2852 		}
       
  2853 	}
       
  2854 
       
  2855 const TDesC& CCmdChunkInfo::Name() const
       
  2856 	{
       
  2857 	_LIT(KCmdChunkInfoName, "chunkinfo");
       
  2858 	return KCmdChunkInfoName;
       
  2859 	}
       
  2860 
       
  2861 void CCmdChunkInfo::DoPrintL()
       
  2862 	{
       
  2863 	iBuf->Zero();
       
  2864 	iFormatter->Zero();
       
  2865 
       
  2866 	if (iAddress == 0)
       
  2867 		{
       
  2868 		ListChunksL();
       
  2869 		}
       
  2870 	else
       
  2871 		{
       
  2872 		PrintChunkInfoL();
       
  2873 		}
       
  2874 
       
  2875 	iFormatter->TabulateL(0, 2, iBuf->Descriptor(), ETruncateLongestColumn);
       
  2876 	Write(iFormatter->Descriptor());
       
  2877 	}
       
  2878 
       
  2879 void CCmdChunkInfo::DoRunL()
       
  2880 	{
       
  2881 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  2882 	iFormatter = CTextFormatter::NewL(Stdout());
       
  2883 	iBuf = IoUtils::CTextBuffer::NewL(0x100);
       
  2884 	LoadMemoryAccessL();
       
  2885 
       
  2886 	RIoConsoleWriteHandle stdout = Stdout();
       
  2887 	TBool attachedToConsole(stdout.AttachedToConsole());
       
  2888 	if (attachedToConsole && iUpdateRate && iAddress)
       
  2889 		{
       
  2890 		stdout.SetCursorHeight(0);
       
  2891 		stdout.ClearScreen();
       
  2892 		}
       
  2893 
       
  2894 	DoPrintL();
       
  2895 
       
  2896 	if (iUpdateRate && iAddress)
       
  2897 		{
       
  2898 		FOREVER
       
  2899 			{
       
  2900 			User::After(iUpdateRate * 1000);
       
  2901 			if (attachedToConsole)
       
  2902 				{
       
  2903 				stdout.ClearScreen();
       
  2904 				}
       
  2905 			DoPrintL();
       
  2906 			}
       
  2907 		}
       
  2908 #else
       
  2909 	PrintError(KErrNotSupported, _L("Unable to fetch chunk information because fshell was not built with FSHELL_MEMORY_ACCESS_SUPPORT defined. That probably means this plaform doesn't support the MemoryAccess device driver."));
       
  2910 	User::Leave(KErrNotSupported);
       
  2911 #endif
       
  2912 	}
       
  2913 
       
  2914 void CCmdChunkInfo::OptionsL(RCommandOptionList& aOptions)
       
  2915 	{
       
  2916 	_LIT(KCmdChunkInfoOptRate, "rate");
       
  2917 	_LIT(KCmdChunkInfoOptHuman, "human");
       
  2918 	_LIT(KCmdChunkInfoOptOwningProcess, "owning-process");
       
  2919 	_LIT(KCmdChunkInfoOptControllingProcess, "controlling-process");
       
  2920 	_LIT(KCmdChunkInfoOptSize, "size");
       
  2921 
       
  2922 	aOptions.AppendUintL(iUpdateRate, KCmdChunkInfoOptRate);
       
  2923 	aOptions.AppendBoolL(iHumanReadable, KCmdChunkInfoOptHuman);
       
  2924 	aOptions.AppendStringL(iOwningProcess, KCmdChunkInfoOptOwningProcess);
       
  2925 	aOptions.AppendUintL(iControllingProcess, KCmdChunkInfoOptControllingProcess);
       
  2926 	aOptions.AppendBoolL(iIncludeSize, KCmdChunkInfoOptSize);
       
  2927 
       
  2928 	}
       
  2929 
       
  2930 void CCmdChunkInfo::ArgumentsL(RCommandArgumentList& aArguments)
       
  2931 	{
       
  2932 	_LIT(KCmdChunkInfoArg, "chunk_address");
       
  2933 	aArguments.AppendUintL(iAddress, KCmdChunkInfoArg);
       
  2934 	}
       
  2935 
       
  2936 
       
  2937 //
       
  2938 // CCmdSvrInfo.
       
  2939 //
       
  2940 
       
  2941 CCommandBase* CCmdSvrInfo::NewLC()
       
  2942 	{
       
  2943 	CCmdSvrInfo* self = new(ELeave) CCmdSvrInfo();
       
  2944 	CleanupStack::PushL(self);
       
  2945 	self->BaseConstructL();
       
  2946 	return self;
       
  2947 	}
       
  2948 
       
  2949 CCmdSvrInfo::~CCmdSvrInfo()
       
  2950 	{
       
  2951 	delete iBuf;
       
  2952 	delete iFormatter;
       
  2953 	}
       
  2954 
       
  2955 CCmdSvrInfo::CCmdSvrInfo()
       
  2956 	{
       
  2957 	}
       
  2958 
       
  2959 void CCmdSvrInfo::ListServersL()
       
  2960 	{
       
  2961 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  2962 	TInt bufSize = 1024;
       
  2963 	TInt err = KErrNone;
       
  2964 	HBufC8* addressesBuf;
       
  2965 	do
       
  2966 		{
       
  2967 		addressesBuf = HBufC8::NewLC(bufSize);
       
  2968 		TPtr8 addressesPtr(addressesBuf->Des());
       
  2969 		err = iMemAccess.GetObjectAddresses(EServer, KNullDesC(), addressesPtr);
       
  2970 		if (err == KErrOverflow)
       
  2971 			{
       
  2972 			CleanupStack::PopAndDestroy(addressesBuf);
       
  2973 			bufSize *= 2;
       
  2974 			}
       
  2975 		}
       
  2976 		while (err == KErrOverflow);
       
  2977 
       
  2978 	if (err)
       
  2979 		{
       
  2980 		PrintError(err, _L("Unable to read server addresses."));
       
  2981 		User::Leave(err);
       
  2982 		}
       
  2983 
       
  2984 	const TInt numAddresses = addressesBuf->Length() / sizeof(TUint32*);
       
  2985 	if (numAddresses == 0)
       
  2986 		{
       
  2987 		Write(_L("No servers found.\r\n"));
       
  2988 		}
       
  2989 	else
       
  2990 		{
       
  2991 		TUint32* p = (TUint32*)addressesBuf->Ptr();
       
  2992 		TInt offset = 0;
       
  2993 		while (offset < numAddresses)
       
  2994 			{
       
  2995 			TPckg<TServerKernelInfo> serverInfoPckg(iServerInfo);
       
  2996 			TUint32* ptr = p + offset++;
       
  2997 			err = iMemAccess.GetObjectInfo(EServer, (TUint8*)(*ptr), serverInfoPckg);
       
  2998 			if (err == KErrNone)
       
  2999 				{
       
  3000 				iFullName.Copy(iServerInfo.iFullName);
       
  3001 				iBuf->AppendFormatL(_L("0x%08x\t\'%S\'\r\n"), *ptr, &iFullName);
       
  3002 				}
       
  3003 			else if (err != KErrNotFound)
       
  3004 				{
       
  3005 				// Only warn on something other than KErrNotFound. KErrNotFound could legitimately
       
  3006 				// happen if the chunk in question has been deleted since we called RMemoryAccess::GetObjectAddresses.
       
  3007 				PrintWarning(_L("Unable to read server at 0x%08x (%d)"), ptr, err);
       
  3008 				}
       
  3009 			}
       
  3010 		}
       
  3011 
       
  3012 	CleanupStack::PopAndDestroy(addressesBuf);
       
  3013 
       
  3014 #endif
       
  3015 	}
       
  3016 
       
  3017 void CCmdSvrInfo::ListSessionsL()
       
  3018 	{
       
  3019 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  3020 	TPckg<TServerKernelInfo> serverInfoPckg(iServerInfo);
       
  3021 	TInt err = iMemAccess.GetObjectInfo(EServer, (TUint8*)iAddress, serverInfoPckg);
       
  3022 	if (err)
       
  3023 		{
       
  3024 		PrintError(err, _L("Unable to get info for server 0x%08x"), iAddress);
       
  3025 		User::Leave(err);
       
  3026 		}
       
  3027 	
       
  3028 	TPckg<TThreadKernelInfo> threadInfoPckg(iThreadInfo);
       
  3029 	err = iMemAccess.GetObjectInfo(EThread, iServerInfo.iAddressOfOwningThread, threadInfoPckg);
       
  3030 	if (err)
       
  3031 		{
       
  3032 		PrintError(err, _L("Unable to get info for thread 0x%08x"), iServerInfo.iAddressOfOwningThread);
       
  3033 		User::Leave(err);
       
  3034 		}
       
  3035 
       
  3036 	iFullName.Copy(iThreadInfo.iFullName);
       
  3037 	iBuf->AppendFormatL(_L("Owning thread id:\t%u\r\n"), iThreadInfo.iThreadId);
       
  3038 	iBuf->AppendFormatL(_L("Owning thread name:\t\'%S\'\r\n"), &iFullName);
       
  3039 	TUint type = iServerInfo.iSessionType;
       
  3040 	iBuf->AppendFormatL(_L("Session type:\t%u\r\n"), type);
       
  3041 
       
  3042 	for (TUint i = iServerInfo.iSessionQ.iStartFrom; i < iServerInfo.iSessionQ.iCount; ++i)
       
  3043 		{
       
  3044 		TPckg<TSessionKernelInfo> sessionInfoPckg(iSessionInfo);
       
  3045 		err = iMemAccess.GetObjectInfo(ESession, iServerInfo.iSessionQ.iBuffer[i], sessionInfoPckg);
       
  3046 		if (err)
       
  3047 			{
       
  3048 			PrintWarning(_L("Unable to get info for session 0x%08x (%d)"), iServerInfo.iSessionQ.iBuffer[i], err);
       
  3049 			}
       
  3050 		else
       
  3051 			{
       
  3052 			iFullName.Copy(iSessionInfo.iFullName);
       
  3053 			iBuf->AppendFormatL(_L("Session:\t\'%S\'\r\n"), &iFullName);
       
  3054 
       
  3055 			TPckg<TProcessKernelInfo> processInfoPckg(iProcessInfo);
       
  3056 			err = iMemAccess.GetObjectInfo(EProcess, iSessionInfo.iAddressOfKernelOwner, processInfoPckg);
       
  3057 			if (err == KErrNone)
       
  3058 				{
       
  3059 				iFullName.Copy(iProcessInfo.iFullName);
       
  3060 				iBuf->AppendFormatL(_L("Session owner:\t\'%S\'\r\n"), &iFullName);
       
  3061 				}
       
  3062 			else
       
  3063 				{
       
  3064 				err = iMemAccess.GetObjectInfo(EThread, iSessionInfo.iAddressOfKernelOwner, threadInfoPckg);
       
  3065 				if (err == KErrNone)
       
  3066 					{
       
  3067 					iFullName.Copy(iThreadInfo.iFullName);
       
  3068 					iBuf->AppendFormatL(_L("Session owner:\t\'%S\'\r\n"), &iFullName);
       
  3069 					}
       
  3070 				else
       
  3071 					{
       
  3072 					PrintWarning(_L("Unable to get info for session owner 0x%08x (%d)"), iSessionInfo.iAddressOfKernelOwner, err);
       
  3073 					}
       
  3074 				}
       
  3075 			}
       
  3076 		}
       
  3077 #endif
       
  3078 	}
       
  3079 
       
  3080 const TDesC& CCmdSvrInfo::Name() const
       
  3081 	{
       
  3082 	_LIT(KCmdSvrInfoName, "svrinfo");
       
  3083 	return KCmdSvrInfoName;
       
  3084 	}
       
  3085 
       
  3086 void CCmdSvrInfo::DoRunL()
       
  3087 	{
       
  3088 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  3089 	iFormatter = CTextFormatter::NewL(Stdout());
       
  3090 	iBuf = IoUtils::CTextBuffer::NewL(0x100);
       
  3091 	LoadMemoryAccessL();
       
  3092 
       
  3093 	if (iAddress == 0)
       
  3094 		{
       
  3095 		ListServersL();
       
  3096 		}
       
  3097 	else
       
  3098 		{
       
  3099 		ListSessionsL();
       
  3100 		}
       
  3101 
       
  3102 	iFormatter->TabulateL(0, 2, iBuf->Descriptor(), ETruncateLongestColumn);
       
  3103 	Write(iFormatter->Descriptor());
       
  3104 #else
       
  3105 	PrintError(KErrNotSupported, _L("Unable to fetch server information because fshell was not built with FSHELL_MEMORY_ACCESS_SUPPORT defined. That probably means this plaform doesn't support the MemoryAccess device driver."));
       
  3106 	User::Leave(KErrNotSupported);
       
  3107 #endif
       
  3108 	}
       
  3109 
       
  3110 void CCmdSvrInfo::ArgumentsL(RCommandArgumentList& aArguments)
       
  3111 	{
       
  3112 	_LIT(KCmdSvrInfoArg, "server_address");
       
  3113 	aArguments.AppendUintL(iAddress, KCmdSvrInfoArg);
       
  3114 	}
       
  3115 
       
  3116 
       
  3117 //
       
  3118 // CCmdTickle.
       
  3119 //
       
  3120 	
       
  3121 CCommandBase* CCmdTickle::NewLC()
       
  3122 	{
       
  3123 	CCmdTickle* self = new (ELeave) CCmdTickle();
       
  3124 	CleanupStack::PushL(self);
       
  3125 	self->BaseConstructL();
       
  3126 	return self;
       
  3127 	}
       
  3128 
       
  3129 CCmdTickle::~CCmdTickle()
       
  3130 	{
       
  3131 	}
       
  3132 
       
  3133 CCmdTickle::CCmdTickle()
       
  3134 	{
       
  3135 	}
       
  3136 
       
  3137 void CCmdTickle::DoRunL()
       
  3138 	{
       
  3139 	User::ResetInactivityTime();
       
  3140 	const TInt KGiveSystemTimeToFocus = 500000; // microseconds
       
  3141 	User::After(KGiveSystemTimeToFocus);
       
  3142 	}
       
  3143 	
       
  3144 const TDesC& CCmdTickle::Name() const
       
  3145 	{
       
  3146 	_LIT(KName, "tickle");
       
  3147 	return KName;
       
  3148 	}
       
  3149 
       
  3150 
       
  3151 //
       
  3152 // CCmdTicks.
       
  3153 //
       
  3154 	
       
  3155 CCommandBase* CCmdTicks::NewLC()
       
  3156 	{
       
  3157 	CCmdTicks* self = new (ELeave) CCmdTicks();
       
  3158 	CleanupStack::PushL(self);
       
  3159 	self->BaseConstructL();
       
  3160 	return self;
       
  3161 	}
       
  3162 
       
  3163 CCmdTicks::~CCmdTicks()
       
  3164 	{
       
  3165 	}
       
  3166 
       
  3167 CCmdTicks::CCmdTicks()
       
  3168 	{
       
  3169 	}
       
  3170 
       
  3171 TInt NanoTickPeriod()
       
  3172 	{
       
  3173 	TInt nanoTickPeriod;
       
  3174 	if (HAL::Get(HAL::ENanoTickPeriod, nanoTickPeriod) != KErrNone)
       
  3175 		{
       
  3176 		nanoTickPeriod = 1000;
       
  3177 		}
       
  3178 	return nanoTickPeriod;
       
  3179 	}
       
  3180 
       
  3181 TInt FastCounterFrequency()
       
  3182 	{
       
  3183 	TInt fastCounterFrequency;
       
  3184 	if (HAL::Get(HAL::EFastCounterFrequency, fastCounterFrequency) != KErrNone)
       
  3185 		{
       
  3186 		fastCounterFrequency = 1000;
       
  3187 		}
       
  3188 	return fastCounterFrequency;
       
  3189 	}
       
  3190 
       
  3191 TBool FastCounterCountsUp()
       
  3192 	{
       
  3193 	TBool countsUp;
       
  3194 	if (HAL::Get(HAL::EFastCounterCountsUp, countsUp) != KErrNone)
       
  3195 		{
       
  3196 		countsUp = EFalse;
       
  3197 		}
       
  3198 	return countsUp;
       
  3199 	}
       
  3200 
       
  3201 void CCmdTicks::DoRunL()
       
  3202 	{
       
  3203 	TUint nticks = User::NTickCount();
       
  3204 	TUint fast = User::FastCounter();
       
  3205 
       
  3206 	Printf(_L("NKern ticks: %u\r\n"), nticks);
       
  3207 	Printf(_L("Fast ticks: %u\r\n"), fast);
       
  3208 
       
  3209 	if (iVerbose)
       
  3210 		{
       
  3211 		Printf(_L("\r\nNKern tick period: %d\r\n"), NanoTickPeriod());
       
  3212 		Printf(_L("Fast counter frequency: %d\r\n"), FastCounterFrequency());
       
  3213 		Printf(_L("Fast counter counts up: %d\r\n"), FastCounterCountsUp());
       
  3214 		}
       
  3215 	}
       
  3216 	
       
  3217 const TDesC& CCmdTicks::Name() const
       
  3218 	{
       
  3219 	_LIT(KName, "ticks");
       
  3220 	return KName;
       
  3221 	}
       
  3222 
       
  3223 void CCmdTicks::OptionsL(RCommandOptionList& aOptions)
       
  3224 	{
       
  3225 	aOptions.AppendBoolL(iVerbose, KOptVerbose);
       
  3226 	}
       
  3227 
       
  3228 
       
  3229 //
       
  3230 // CCmdUpTime.
       
  3231 //
       
  3232 	
       
  3233 CCommandBase* CCmdUpTime::NewLC()
       
  3234 	{
       
  3235 	CCmdUpTime* self = new (ELeave) CCmdUpTime();
       
  3236 	CleanupStack::PushL(self);
       
  3237 	self->BaseConstructL();
       
  3238 	return self;
       
  3239 	}
       
  3240 
       
  3241 CCmdUpTime::~CCmdUpTime()
       
  3242 	{
       
  3243 	}
       
  3244 
       
  3245 CCmdUpTime::CCmdUpTime()
       
  3246 	{
       
  3247 	}
       
  3248 
       
  3249 void AppendTimeUnit(TInt aValue, const TDesC& aUnit, TDes& aBuf)
       
  3250 	{
       
  3251 	if (aValue == 1)
       
  3252 		{
       
  3253 		aBuf.AppendFormat(_L("1 %S "), &aUnit);
       
  3254 		}
       
  3255 	else
       
  3256 		{
       
  3257 		aBuf.AppendFormat(_L("%d %Ss "), aValue, &aUnit);
       
  3258 		}
       
  3259 	}
       
  3260 
       
  3261 void FormatTime(const TUint64& aInterval, TDes& aBuf)
       
  3262 	{
       
  3263 	const TInt ms = 1000;
       
  3264 	const TInt s = ms * ms;
       
  3265 	const TInt64 m = s * 60;
       
  3266 	const TInt64 h = m * 60;
       
  3267 	const TInt64 d = h * 24;
       
  3268 
       
  3269 	TInt64 interval = aInterval;
       
  3270 	const TInt numDays = interval / d;
       
  3271 	if (numDays > 0)
       
  3272 		{
       
  3273 		AppendTimeUnit(numDays, _L("day"), aBuf);
       
  3274 		interval = interval % d;
       
  3275 		}
       
  3276 
       
  3277 	const TInt numHours = interval / h;
       
  3278 	if (numHours > 0)
       
  3279 		{
       
  3280 		AppendTimeUnit(numHours, _L("hour"), aBuf);
       
  3281 		interval = interval % h;
       
  3282 		}
       
  3283 
       
  3284 	const TInt numMinutes = interval / m;
       
  3285 	if (numMinutes > 0)
       
  3286 		{
       
  3287 		AppendTimeUnit(numMinutes, _L("minute"), aBuf);
       
  3288 		interval = interval % m;
       
  3289 		}
       
  3290 
       
  3291 	TBuf<16> format(_L("%.2f "));
       
  3292 	TReal realInterval = interval;
       
  3293 	if (realInterval >= s)
       
  3294 		{
       
  3295 		realInterval /= s;
       
  3296 		format.Append(_L("s"));
       
  3297 		}
       
  3298 	else if (realInterval >= ms)
       
  3299 		{
       
  3300 		realInterval /= ms;
       
  3301 		format.Append(_L("ms"));
       
  3302 		}
       
  3303 	else
       
  3304 		{
       
  3305 		format.Append(_L("us"));
       
  3306 		}
       
  3307 	aBuf.AppendFormat(format, realInterval); 
       
  3308 	}
       
  3309 
       
  3310 void CCmdUpTime::DoRunL()
       
  3311 	{
       
  3312 	TUint64 n = User::NTickCount();
       
  3313 	n *= NanoTickPeriod();
       
  3314 
       
  3315 	if (iHuman)
       
  3316 		{
       
  3317 		TBuf<256> timeBuf;
       
  3318 		FormatTime(n, timeBuf);
       
  3319 		Printf(_L("%S"), &timeBuf);
       
  3320 		}
       
  3321 	else
       
  3322 		{
       
  3323 		Printf(_L("%Lu"), n);
       
  3324 		}
       
  3325 	}
       
  3326 	
       
  3327 const TDesC& CCmdUpTime::Name() const
       
  3328 	{
       
  3329 	_LIT(KName, "uptime");
       
  3330 	return KName;
       
  3331 	}
       
  3332 
       
  3333 void CCmdUpTime::OptionsL(RCommandOptionList& aOptions)
       
  3334 	{
       
  3335 	aOptions.AppendBoolL(iHuman, KOptHuman);
       
  3336 	}
       
  3337 
       
  3338 
       
  3339 //
       
  3340 // CCmdVar.
       
  3341 //
       
  3342 	
       
  3343 CCommandBase* CCmdVar::NewLC()
       
  3344 	{
       
  3345 	CCmdVar* self = new (ELeave) CCmdVar();
       
  3346 	CleanupStack::PushL(self);
       
  3347 	self->BaseConstructL();
       
  3348 	return self;
       
  3349 	}
       
  3350 
       
  3351 CCmdVar::~CCmdVar()
       
  3352 	{
       
  3353 	delete iVar1;
       
  3354 	delete iArg;
       
  3355 	}
       
  3356 
       
  3357 CCmdVar::CCmdVar()
       
  3358 	{
       
  3359 	}
       
  3360 
       
  3361 void CCmdVar::DoRunL()
       
  3362 	{
       
  3363 	IoUtils::CEnvironment& env = Env();
       
  3364 	switch (iOperation)
       
  3365 		{
       
  3366 		case EDefined:
       
  3367 			if (iArg)
       
  3368 				{
       
  3369 				Complete(KErrArgument, _L("Argument should not be specified for \"defined\" operation"));
       
  3370 				}
       
  3371 			else
       
  3372 				{
       
  3373 				SetErrorReported(ETrue); // To silence leaves.
       
  3374 				Complete(!env.IsDefined(*iVar1));
       
  3375 				}
       
  3376 			break;
       
  3377 		case ENotDefined:
       
  3378 			if (iArg)
       
  3379 				{
       
  3380 				Complete(KErrArgument, _L("Argument should not be specified for \"not-defined\" operation"));
       
  3381 				}
       
  3382 			else
       
  3383 				{
       
  3384 				SetErrorReported(ETrue); // To silence leaves.
       
  3385 				Complete(env.IsDefined(*iVar1));
       
  3386 				}
       
  3387 			break;
       
  3388 		case EEqual:
       
  3389 			if (iArg == NULL)
       
  3390 				{
       
  3391 				Complete(KErrArgument, _L("Argument must be specified for == operation"));
       
  3392 				}
       
  3393 			else
       
  3394 				{
       
  3395 				SetErrorReported(ETrue); // To silence leaves.
       
  3396 				Complete(!(env.GetAsDesL(*iVar1) == *iArg));
       
  3397 				}
       
  3398 			break;
       
  3399 		case ENotEqual:
       
  3400 			if (iArg == NULL)
       
  3401 				{
       
  3402 				Complete(KErrArgument, _L("Argument must be specified for != operation"));
       
  3403 				}
       
  3404 			else
       
  3405 				{
       
  3406 				SetErrorReported(ETrue); // To silence leaves.
       
  3407 				Complete(env.GetAsDesL(*iVar1) == *iArg);
       
  3408 				}
       
  3409 			break;
       
  3410 		case EAdd:
       
  3411 		case ESubtract:
       
  3412 			{
       
  3413 			if (iArg == NULL) LeaveIfErr(KErrArgument, _L("Argument must be specified for add and subtract operations"));
       
  3414 			TLex lex(*iArg);
       
  3415 			TInt operand;
       
  3416 			TInt err = lex.Val(operand);
       
  3417 			LeaveIfErr(err, _L("Couldn't parse an integer from argument '%S'"), iArg);
       
  3418 			if (iOperation == ESubtract) operand = -operand;
       
  3419 			TInt current = 0;
       
  3420 			TRAP_IGNORE(current = env.GetAsIntL(*iVar1)); // If it doesn't yet exist or isn't an int, we'll treat it as if it was zero
       
  3421 			env.SetL(*iVar1, current + operand);
       
  3422 			break;
       
  3423 			}
       
  3424 		default:
       
  3425 			User::Leave(KErrNotSupported);
       
  3426 		}
       
  3427 	}
       
  3428 	
       
  3429 const TDesC& CCmdVar::Name() const
       
  3430 	{
       
  3431 	_LIT(KName, "var");
       
  3432 	return KName;
       
  3433 	}
       
  3434 
       
  3435 void CCmdVar::ArgumentsL(RCommandArgumentList& aArguments)
       
  3436 	{
       
  3437 	_LIT(KArgVariable, "variable");
       
  3438 	_LIT(KArgOperation, "operation");
       
  3439 	_LIT(KArgArgument, "argument");
       
  3440 
       
  3441 	aArguments.AppendStringL(iVar1, KArgVariable);
       
  3442 	aArguments.AppendEnumL((TInt&)iOperation, KArgOperation);
       
  3443 	aArguments.AppendStringL(iArg, KArgArgument);
       
  3444 	}
       
  3445 
       
  3446 
       
  3447 //
       
  3448 // CCmdSource.
       
  3449 //
       
  3450 
       
  3451 CCommandBase* CCmdSource::NewLC()
       
  3452 	{
       
  3453 	CCmdSource* self = new (ELeave) CCmdSource();
       
  3454 	CleanupStack::PushL(self);
       
  3455 	self->BaseConstructL();
       
  3456 	return self;
       
  3457 	}
       
  3458 
       
  3459 CCmdSource::~CCmdSource()
       
  3460 	{
       
  3461 	delete iArgs;
       
  3462 	delete iScriptData;
       
  3463 	delete iParser;
       
  3464 	}
       
  3465 
       
  3466 CCmdSource::CCmdSource() : CCommandBase(EManualComplete)
       
  3467 	{
       
  3468 	}
       
  3469 
       
  3470 void CCmdSource::DoRunL()
       
  3471 	{
       
  3472 	TIoHandleSet ioHandles(IoSession(), Stdin(), Stdout(), Stderr());
       
  3473 	TBool helpPrinted;
       
  3474 	iScriptData = CShell::ReadScriptL(iFileName, iArgs, Env(), FsL(), ioHandles, helpPrinted);
       
  3475 
       
  3476 	if (helpPrinted)
       
  3477 		{
       
  3478 		Complete();
       
  3479 		}
       
  3480 	else
       
  3481 		{
       
  3482 		TUint mode = CParser::EExportLineNumbers;
       
  3483 		if (iKeepGoing)
       
  3484 			{
       
  3485 			mode |= CParser::EKeepGoing;
       
  3486 			}
       
  3487 		iParser = CParser::NewL(mode, *iScriptData, IoSession(), Stdin(), Stdout(), Stderr(), Env(), gShell->CommandFactory(), this);
       
  3488 		iParser->Start();
       
  3489 		}
       
  3490 	}
       
  3491 	
       
  3492 const TDesC& CCmdSource::Name() const
       
  3493 	{
       
  3494 	_LIT(KName, "source");
       
  3495 	return KName;
       
  3496 	}
       
  3497 
       
  3498 void CCmdSource::ArgumentsL(RCommandArgumentList& aArguments)
       
  3499 	{
       
  3500 	_LIT(KArgFileName, "script_file_name");
       
  3501 	aArguments.AppendFileNameL(iFileName, KArgFileName);
       
  3502 
       
  3503 	_LIT(KArgArgs, "script_args");
       
  3504 	aArguments.AppendStringL(iArgs, KArgArgs);
       
  3505 	}
       
  3506 
       
  3507 void CCmdSource::OptionsL(RCommandOptionList& aOptions)
       
  3508 	{
       
  3509 	_LIT(KOptKeepGoing, "keep-going");
       
  3510 	aOptions.AppendBoolL(iKeepGoing, KOptKeepGoing);
       
  3511 	}
       
  3512 
       
  3513 void CCmdSource::HandleParserComplete(CParser&, const TError& aError)
       
  3514 	{
       
  3515 	TInt err = aError.Error();
       
  3516 	if (err < 0)
       
  3517 		{
       
  3518 		aError.Report();
       
  3519 		const TDesC& scriptPath = Env().GetAsDes(KScriptPath);
       
  3520 		const TDesC& scriptName = Env().GetAsDes(KScriptName);
       
  3521 		PrintError(err, _L("Aborted \"%S\" at line %d"), &aError.ScriptFileName(), aError.ScriptLineNumber());
       
  3522 		}
       
  3523 	Complete(err);
       
  3524 	}
       
  3525 
       
  3526 //
       
  3527 // CCmdStart.
       
  3528 //
       
  3529 	
       
  3530 CCommandBase* CCmdStart::NewLC()
       
  3531 	{
       
  3532 	CCmdStart* self = new (ELeave) CCmdStart();
       
  3533 	CleanupStack::PushL(self);
       
  3534 	self->BaseConstructL();
       
  3535 	return self;
       
  3536 	}
       
  3537 
       
  3538 CCmdStart::~CCmdStart()
       
  3539 	{
       
  3540 	delete iExe;
       
  3541 	delete iCommandLine;
       
  3542 	}
       
  3543 
       
  3544 CCmdStart::CCmdStart()
       
  3545 	{
       
  3546 	}
       
  3547 
       
  3548 void CCmdStart::DoRunL()
       
  3549 	{
       
  3550 	if (iRendezvous && iWait)
       
  3551 		{
       
  3552 		LeaveIfErr(KErrArgument, _L("--rendezvous cannot be used with --wait"));
       
  3553 		}
       
  3554 	if (iTimeout && !(iRendezvous || iWait))
       
  3555 		{
       
  3556 		LeaveIfErr(KErrArgument, _L("--timeout must be used with either --rendezvous or --wait"));
       
  3557 		}
       
  3558 	if (iMeasure && !(iRendezvous || iWait))
       
  3559 		{
       
  3560 		LeaveIfErr(KErrArgument, _L("--measure must be used with either --rendezvous or --wait"));
       
  3561 		}
       
  3562 
       
  3563 	TRequestStatus waitStatus;
       
  3564 	RProcess process;
       
  3565 	LeaveIfErr(process.Create(*iExe, iCommandLine ? *iCommandLine : KNullDesC(), EOwnerThread), _L("Couldn't create \"%S\" process"), iExe);
       
  3566 	CleanupClosePushL(process);
       
  3567 
       
  3568 	if (iRendezvous)
       
  3569 		{
       
  3570 		process.Rendezvous(waitStatus);
       
  3571 		if (waitStatus != KRequestPending)
       
  3572 			{
       
  3573 			User::WaitForRequest(waitStatus);
       
  3574 			process.Kill(0);
       
  3575 			LeaveIfErr(waitStatus.Int(), _L("Failed to log on to process"));
       
  3576 			}
       
  3577 		}
       
  3578 	else if (iWait)
       
  3579 		{
       
  3580 		process.Logon(waitStatus);
       
  3581 		if (waitStatus != KRequestPending)
       
  3582 			{
       
  3583 			User::WaitForRequest(waitStatus);
       
  3584 			process.Kill(0);
       
  3585 			LeaveIfErr(waitStatus.Int(), _L("Failed to log on to process"));
       
  3586 			}
       
  3587 		}
       
  3588 
       
  3589 	TRequestStatus timerStat;
       
  3590 	RTimer timer;
       
  3591 	if (iTimeout)
       
  3592 		{
       
  3593 		User::LeaveIfError(timer.CreateLocal());
       
  3594 		CleanupClosePushL(timer);
       
  3595 		timer.After(timerStat, iTimeout * 1000 * 1000);
       
  3596 		}
       
  3597 
       
  3598 	TUint32 startTime = 0, endTime = 0;
       
  3599 	if (iMeasure) startTime = User::NTickCount();
       
  3600 
       
  3601 	process.Resume();
       
  3602 
       
  3603 	if (iTimeout)
       
  3604 		{
       
  3605 		timer.After(timerStat, iTimeout * 1000 * 1000);
       
  3606 		User::WaitForRequest(waitStatus, timerStat);
       
  3607 		if (iMeasure) endTime = User::NTickCount();
       
  3608 
       
  3609 		if (waitStatus == KRequestPending)
       
  3610 			{
       
  3611 			// Then the timer expired
       
  3612 			if (iRendezvous)
       
  3613 				{
       
  3614 				process.RendezvousCancel(waitStatus);
       
  3615 				}
       
  3616 			else if (iWait)
       
  3617 				{
       
  3618 				process.LogonCancel(waitStatus);
       
  3619 				}
       
  3620 			User::WaitForRequest(waitStatus);
       
  3621 			LeaveIfErr(KErrTimedOut, _L("Timed out waiting for \"%S\""), iExe);
       
  3622 			}
       
  3623 		else
       
  3624 			{
       
  3625 			timer.Cancel();
       
  3626 			User::WaitForRequest(timerStat);
       
  3627 			}
       
  3628 
       
  3629 		CleanupStack::PopAndDestroy(&timer);
       
  3630 		}
       
  3631 	else if (iRendezvous || iWait)
       
  3632 		{
       
  3633 		User::WaitForRequest(waitStatus);
       
  3634 		if (iMeasure) endTime = User::NTickCount();
       
  3635 		}
       
  3636 
       
  3637 	CleanupStack::PopAndDestroy(&process);
       
  3638 
       
  3639 	if (iMeasure)
       
  3640 		{
       
  3641 		TUint32 elapsed = endTime - startTime;
       
  3642 		elapsed *= NanoTickPeriod();
       
  3643 		TBuf<50> timeBuf;
       
  3644 		FormatTime(elapsed, timeBuf);
       
  3645 		Write(timeBuf);
       
  3646 		Write(_L("\r\n"));
       
  3647 		}
       
  3648 
       
  3649 	if (iRendezvous)
       
  3650 		{
       
  3651 		LeaveIfErr(waitStatus.Int(), _L("Error returned from rendezvous"));
       
  3652 		}
       
  3653 	if (iWait)
       
  3654 		{
       
  3655 		LeaveIfErr(waitStatus.Int(), _L("Error returned from logon"));
       
  3656 		}
       
  3657 	}
       
  3658 	
       
  3659 const TDesC& CCmdStart::Name() const
       
  3660 	{
       
  3661 	_LIT(KName, "start");
       
  3662 	return KName;
       
  3663 	}
       
  3664 
       
  3665 void CCmdStart::ArgumentsL(RCommandArgumentList& aArguments)
       
  3666 	{
       
  3667 	_LIT(KExeName, "exe-name");
       
  3668 	_LIT(KArgs, "arguments");
       
  3669 
       
  3670 	aArguments.AppendStringL(iExe, KExeName);
       
  3671 	aArguments.AppendStringL(iCommandLine, KArgs);
       
  3672 	}
       
  3673 
       
  3674 void CCmdStart::OptionsL(RCommandOptionList& aOptions)
       
  3675 	{
       
  3676 	_LIT(KOptRendezvous, "rendezvous");
       
  3677 	_LIT(KOptWait, "wait");
       
  3678 	_LIT(KOptTimeout, "timeout");
       
  3679 	_LIT(KOptMeasure, "measure");
       
  3680 
       
  3681 	aOptions.AppendBoolL(iRendezvous, KOptRendezvous);
       
  3682 	aOptions.AppendBoolL(iWait, KOptWait);
       
  3683 	aOptions.AppendIntL(iTimeout, KOptTimeout);
       
  3684 	aOptions.AppendBoolL(iMeasure, KOptMeasure);
       
  3685 	}
       
  3686 
       
  3687 
       
  3688 //
       
  3689 // CCmdCompare.
       
  3690 //
       
  3691 	
       
  3692 CCommandBase* CCmdCompare::NewLC()
       
  3693 	{
       
  3694 	CCmdCompare* self = new (ELeave) CCmdCompare();
       
  3695 	CleanupStack::PushL(self);
       
  3696 	self->BaseConstructL();
       
  3697 	return self;
       
  3698 	}
       
  3699 
       
  3700 CCmdCompare::~CCmdCompare()
       
  3701 	{
       
  3702 	}
       
  3703 
       
  3704 CCmdCompare::CCmdCompare()
       
  3705 	{
       
  3706 	}
       
  3707 
       
  3708 void CCmdCompare::DoRunL()
       
  3709 	{
       
  3710 	RFile file1;
       
  3711 	LeaveIfErr(file1.Open(FsL(), iFileName1, EFileRead), _L("Couldn't open \"%S\" for reading"), &iFileName1);
       
  3712 	CleanupClosePushL(file1);
       
  3713 	RFile file2;
       
  3714 	LeaveIfErr(file2.Open(FsL(), iFileName2, EFileRead), _L("Couldn't open \"%S\" for reading"), &iFileName2);
       
  3715 	CleanupClosePushL(file2);
       
  3716 
       
  3717 	TBool same(ETrue);
       
  3718 	FOREVER
       
  3719 		{
       
  3720 		TBuf8<KBlockSize> buf1;
       
  3721 		TBuf8<KBlockSize> buf2;
       
  3722 		LeaveIfErr(file1.Read(buf1), _L("Couldn't read \"%S\""), &iFileName1);
       
  3723 		LeaveIfErr(file2.Read(buf2), _L("Couldn't read \"%S\""), &iFileName2);
       
  3724 		if (buf1 != buf2)
       
  3725 			{
       
  3726 			same = EFalse;
       
  3727 			break;
       
  3728 			}
       
  3729 		if (buf1.Length() == 0)
       
  3730 			{
       
  3731 			break;
       
  3732 			}
       
  3733 		}
       
  3734 
       
  3735 	CleanupStack::PopAndDestroy(2, &file1);
       
  3736 	if (iVerbose)
       
  3737 		{
       
  3738 		if (same)
       
  3739 			{
       
  3740 			Write(_L("Identical\r\n"));
       
  3741 			}
       
  3742 		else
       
  3743 			{
       
  3744 			Write(_L("Different\r\n"));
       
  3745 			}
       
  3746 		}
       
  3747 	Complete(!same);
       
  3748 	}
       
  3749 	
       
  3750 const TDesC& CCmdCompare::Name() const
       
  3751 	{
       
  3752 	_LIT(KName, "compare");
       
  3753 	return KName;
       
  3754 	}
       
  3755 
       
  3756 void CCmdCompare::ArgumentsL(RCommandArgumentList& aArguments)
       
  3757 	{
       
  3758 	_LIT(KFileName1, "file_name_1");
       
  3759 	_LIT(KFileName2, "file_name_2");
       
  3760 	aArguments.AppendFileNameL(iFileName1, KFileName1);
       
  3761 	aArguments.AppendFileNameL(iFileName2, KFileName2);
       
  3762 	}
       
  3763 
       
  3764 void CCmdCompare::OptionsL(RCommandOptionList& aOptions)
       
  3765 	{
       
  3766 	aOptions.AppendBoolL(iVerbose, KOptVerbose);
       
  3767 	}
       
  3768 
       
  3769 
       
  3770 //
       
  3771 // CCmdTime.
       
  3772 //
       
  3773 	
       
  3774 CCommandBase* CCmdTime::NewLC()
       
  3775 	{
       
  3776 	CCmdTime* self = new (ELeave) CCmdTime();
       
  3777 	CleanupStack::PushL(self);
       
  3778 	self->BaseConstructL();
       
  3779 	return self;
       
  3780 	}
       
  3781 
       
  3782 CCmdTime::~CCmdTime()
       
  3783 	{
       
  3784 	delete iParser;
       
  3785 	delete iCommandLine;
       
  3786 	}
       
  3787 
       
  3788 CCmdTime::CCmdTime() : CCommandBase(EManualComplete), iRepeatCount(1)
       
  3789 	{
       
  3790 	}
       
  3791 
       
  3792 void CCmdTime::DoRunL()
       
  3793 	{
       
  3794 	NextIterationL();
       
  3795 	}
       
  3796 
       
  3797 void CCmdTime::NextIterationL()
       
  3798 	{
       
  3799 	delete iParser;
       
  3800 	iParser = NULL;
       
  3801 	iParser = CParser::NewL(CParser::ENormal, *iCommandLine, IoSession(), Stdin(), Stdout(), Stderr(), Env(), gShell->CommandFactory(), this);
       
  3802 	iCountBefore = iFastCounter ? User::FastCounter() : User::NTickCount();
       
  3803 	iParser->Start();
       
  3804 	}
       
  3805 	
       
  3806 const TDesC& CCmdTime::Name() const
       
  3807 	{
       
  3808 	_LIT(KName, "time");
       
  3809 	return KName;
       
  3810 	}
       
  3811 
       
  3812 void CCmdTime::ArgumentsL(RCommandArgumentList& aArguments)
       
  3813 	{
       
  3814 	_LIT(KArgs, "command");
       
  3815 	aArguments.AppendStringL(iCommandLine, KArgs);
       
  3816 	}
       
  3817 
       
  3818 void CCmdTime::OptionsL(RCommandOptionList& aOptions)
       
  3819 	{
       
  3820 	_LIT(KOptFastCounter, "fast-counter");
       
  3821 	_LIT(KOptRepeatCount, "repeat");
       
  3822 	aOptions.AppendBoolL(iHuman, KOptHuman);
       
  3823 	aOptions.AppendBoolL(iFastCounter, KOptFastCounter);
       
  3824 	aOptions.AppendIntL(iRepeatCount, KOptRepeatCount);
       
  3825 	}
       
  3826 
       
  3827 void CCmdTime::HandleParserComplete(CParser&, const TError& aError)
       
  3828 	{
       
  3829 	if (aError.Error() < 0)
       
  3830 		{
       
  3831 		aError.Report();
       
  3832 		}
       
  3833 
       
  3834 	TUint32 countAfter = iFastCounter ? User::FastCounter() : User::NTickCount();
       
  3835 	
       
  3836 	TUint64 difference;
       
  3837 	if (iFastCounter)
       
  3838 		{
       
  3839 		difference = FastCounterCountsUp() ? (countAfter - iCountBefore) : (iCountBefore - countAfter);
       
  3840 		difference *= 1000000;
       
  3841 		difference /= FastCounterFrequency();
       
  3842 		}
       
  3843 	else
       
  3844 		{
       
  3845 		difference = countAfter - iCountBefore;
       
  3846 		difference *= NanoTickPeriod();
       
  3847 		}
       
  3848 
       
  3849 	if (Stdout().AttachedToConsole())
       
  3850 		{
       
  3851 		TPoint cursorPos;
       
  3852 		Stdout().GetCursorPos(cursorPos);
       
  3853 		if (cursorPos.iX != 0)
       
  3854 			{
       
  3855 			Write(KNewLine);
       
  3856 			}
       
  3857 		}
       
  3858 
       
  3859 	if (iHuman)
       
  3860 		{
       
  3861 		TBuf<256> timeBuf;
       
  3862 		FormatTime(difference, timeBuf);
       
  3863 		timeBuf.Append(KNewLine);
       
  3864 		Write(timeBuf);
       
  3865 		}
       
  3866 	else if (iRepeatCount == 1)
       
  3867 		{
       
  3868 		// Don't print individual times if we asked for non-human readable output. (If you want that behaviour, use "repeat n time xyz...")
       
  3869 		Printf(_L("%Lu\r\n"), difference);
       
  3870 		}
       
  3871 	
       
  3872 	iTotalTime += difference;
       
  3873 	iIteration++;
       
  3874 	if (iRepeatCount > 1 && iIteration == iRepeatCount)
       
  3875 		{
       
  3876 		// Need to print the average
       
  3877 		difference = iTotalTime / iRepeatCount;
       
  3878 		if (iHuman)
       
  3879 			{
       
  3880 			TBuf<256> timeBuf;
       
  3881 			timeBuf.Append(_L("Average: "));
       
  3882 			FormatTime(difference, timeBuf);
       
  3883 			timeBuf.Append(KNewLine);
       
  3884 			Write(timeBuf);
       
  3885 			}
       
  3886 		else
       
  3887 			{
       
  3888 			Printf(_L("%Lu\r\n"), difference);
       
  3889 			}
       
  3890 		}
       
  3891 	if (aError.Error() < 0 || iIteration == iRepeatCount)
       
  3892 		{
       
  3893 		Complete(aError.Error());
       
  3894 		}
       
  3895 	else
       
  3896 		{
       
  3897 		// Rerun the fun
       
  3898 		TRAPD(err, NextIterationL());
       
  3899 		if (err) Complete(err);
       
  3900 		}
       
  3901 	}
       
  3902 
       
  3903 
       
  3904 //
       
  3905 // CCmdRepeat.
       
  3906 //
       
  3907 	
       
  3908 CCommandBase* CCmdRepeat::NewLC()
       
  3909 	{
       
  3910 	CCmdRepeat* self = new (ELeave) CCmdRepeat();
       
  3911 	CleanupStack::PushL(self);
       
  3912 	self->BaseConstructL();
       
  3913 	return self;
       
  3914 	}
       
  3915 
       
  3916 CCmdRepeat::~CCmdRepeat()
       
  3917 	{
       
  3918 	delete iParser;
       
  3919 	delete iCommandLine;
       
  3920 	}
       
  3921 
       
  3922 CCmdRepeat::CCmdRepeat() : CCommandBase(EManualComplete)
       
  3923 	{
       
  3924 	}
       
  3925 
       
  3926 void CCmdRepeat::DoRunL()
       
  3927 	{
       
  3928 	if (iNumRepeats == 0)
       
  3929 		{
       
  3930 		iForever = ETrue;
       
  3931 		}
       
  3932 
       
  3933 	CreateParserL();
       
  3934 	}
       
  3935 	
       
  3936 const TDesC& CCmdRepeat::Name() const
       
  3937 	{
       
  3938 	_LIT(KName, "repeat");
       
  3939 	return KName;
       
  3940 	}
       
  3941 
       
  3942 void CCmdRepeat::ArgumentsL(RCommandArgumentList& aArguments)
       
  3943 	{
       
  3944 	_LIT(KCount, "count");
       
  3945 	_LIT(KArgs, "command");
       
  3946 
       
  3947 	aArguments.AppendUintL(iNumRepeats, KCount);
       
  3948 	aArguments.AppendStringL(iCommandLine, KArgs);
       
  3949 	}
       
  3950 
       
  3951 void CCmdRepeat::OptionsL(RCommandOptionList& aOptions)
       
  3952 	{
       
  3953 	_LIT(KOptKeepGoing, "keep-going");
       
  3954 	_LIT(KOptWait, "wait");
       
  3955 
       
  3956 	aOptions.AppendBoolL(iKeepGoing, KOptKeepGoing);
       
  3957 	aOptions.AppendIntL(iWaitTime, KOptWait);
       
  3958 	}
       
  3959 
       
  3960 void CCmdRepeat::HandleParserComplete(CParser&, const TError& aError)
       
  3961 	{
       
  3962 	TRAPD(err, HandleParserCompleteL(aError));
       
  3963 	if (err)
       
  3964 		{
       
  3965 		Complete(err);
       
  3966 		}
       
  3967 	}
       
  3968 
       
  3969 void CCmdRepeat::HandleParserCompleteL(const TError& aError)
       
  3970 	{
       
  3971 	if (aError.Error() < 0)
       
  3972 		{
       
  3973 		aError.Report();
       
  3974 		}
       
  3975 
       
  3976 	if (((aError.Error() == KErrNone) || iKeepGoing) && ((++iCount < iNumRepeats) || iForever))
       
  3977 		{
       
  3978 		delete iParser;
       
  3979 		iParser = NULL;
       
  3980 		if (iWaitTime) User::After(iWaitTime * 1000);
       
  3981 		CreateParserL();
       
  3982 		}
       
  3983 	else
       
  3984 		{
       
  3985 		Complete(aError.Error());
       
  3986 		}
       
  3987 	}
       
  3988 
       
  3989 void CCmdRepeat::CreateParserL()
       
  3990 	{
       
  3991 	TBuf<32> buf;
       
  3992 	buf.AppendNum(iCount);
       
  3993 	Env().SetL(KRepeatCount, buf);
       
  3994 	iParser = CParser::NewL(iKeepGoing ? CParser::EKeepGoing : CParser::ENormal, *iCommandLine, IoSession(), Stdin(), Stdout(), Stderr(), Env(), gShell->CommandFactory(), this);
       
  3995 	iParser->Start();
       
  3996 	}
       
  3997 
       
  3998 
       
  3999 //
       
  4000 // CCmdDebug.
       
  4001 //
       
  4002 	
       
  4003 CCommandBase* CCmdDebug::NewLC()
       
  4004 	{
       
  4005 	CCmdDebug* self = new (ELeave) CCmdDebug();
       
  4006 	CleanupStack::PushL(self);
       
  4007 	self->BaseConstructL();
       
  4008 	return self;
       
  4009 	}
       
  4010 
       
  4011 CCmdDebug::~CCmdDebug()
       
  4012 	{
       
  4013 	delete iScriptData;
       
  4014 	delete iParser;
       
  4015 	delete iArgs;
       
  4016 	}
       
  4017 
       
  4018 CCmdDebug::CCmdDebug() : CCommandBase(EManualComplete)
       
  4019 	{
       
  4020 	}
       
  4021 
       
  4022 void CCmdDebug::DoRunL()
       
  4023 	{
       
  4024 	TIoHandleSet ioHandles(IoSession(), Stdin(), Stdout(), Stderr());
       
  4025 	TBool helpPrinted;
       
  4026 	iScriptData = CShell::ReadScriptL(iFileName, iArgs, Env(), FsL(), ioHandles, helpPrinted);
       
  4027 	if (helpPrinted)
       
  4028 		{
       
  4029 		Complete();
       
  4030 		}
       
  4031 	else
       
  4032 		{
       
  4033 		TUint mode = CParser::EDebug | CParser::EExportLineNumbers;
       
  4034 		if (iKeepGoing)
       
  4035 			{
       
  4036 			mode |= CParser::EKeepGoing;
       
  4037 			}
       
  4038 		iParser = CParser::NewL(mode, *iScriptData, IoSession(), Stdin(), Stdout(), Stderr(), Env(), gShell->CommandFactory(), this);
       
  4039 		iParser->Start();
       
  4040 		}
       
  4041 	}
       
  4042 	
       
  4043 const TDesC& CCmdDebug::Name() const
       
  4044 	{
       
  4045 	_LIT(KName, "debug");
       
  4046 	return KName;
       
  4047 	}
       
  4048 
       
  4049 void CCmdDebug::ArgumentsL(RCommandArgumentList& aArguments)
       
  4050 	{
       
  4051 	_LIT(KArgFileName, "script_file_name");
       
  4052 	aArguments.AppendFileNameL(iFileName, KArgFileName);
       
  4053 
       
  4054 	_LIT(KArgArgs, "script_args");
       
  4055 	aArguments.AppendStringL(iArgs, KArgArgs);
       
  4056 	}
       
  4057 
       
  4058 void CCmdDebug::OptionsL(RCommandOptionList& aOptions)
       
  4059 	{
       
  4060 	_LIT(KOptKeepGoing, "keep-going");
       
  4061 	aOptions.AppendBoolL(iKeepGoing, KOptKeepGoing);
       
  4062 	}
       
  4063 
       
  4064 void CCmdDebug::HandleParserComplete(CParser&, const TError& aError)
       
  4065 	{
       
  4066 	Printf(_L("Completed with %d (%S)\r\n"), aError.Error(), Stringify::Error(aError.Error()));
       
  4067 	Complete(aError.Error());
       
  4068 	}
       
  4069 
       
  4070 void CCmdDebug::AboutToExecuteLine(const TDesC& aOrignalLine, const TDesC& aExpandedLine)
       
  4071 	{
       
  4072 	Write(aOrignalLine);
       
  4073 	Write(KNewLine);
       
  4074 	TRAP_IGNORE(InteractL(aExpandedLine));
       
  4075 	}
       
  4076 
       
  4077 void CCmdDebug::LineReturned(TInt aError)
       
  4078 	{
       
  4079 	Printf(_L("Returned %d (%S)\r\n"), aError, Stringify::Error(aError));
       
  4080 	}
       
  4081 
       
  4082 void CCmdDebug::InteractL(const TDesC& aExpandedLine)
       
  4083 	{
       
  4084 	FOREVER
       
  4085 		{
       
  4086 		TBuf<1> command;
       
  4087 		ReadL(command);
       
  4088 
       
  4089 		_LIT(KStep, "s");
       
  4090 		_LIT(KExpand, "x");
       
  4091 
       
  4092 		if (command == KStep)
       
  4093 			{
       
  4094 			return;
       
  4095 			}
       
  4096 		else if (command == KExpand)
       
  4097 			{
       
  4098 			Write(aExpandedLine);
       
  4099 			Write(KNewLine);
       
  4100 			}
       
  4101 		else
       
  4102 			{
       
  4103 			Write(_L("Unknown command\r\n"));
       
  4104 			}
       
  4105 		}
       
  4106 	}
       
  4107 
       
  4108 
       
  4109 //
       
  4110 // CCmdReadMem.
       
  4111 //
       
  4112 
       
  4113 CCommandBase* CCmdReadMem::NewLC()
       
  4114 	{
       
  4115 	CCmdReadMem* self = new(ELeave) CCmdReadMem();
       
  4116 	CleanupStack::PushL(self);
       
  4117 	self->BaseConstructL();
       
  4118 	return self;
       
  4119 	}
       
  4120 
       
  4121 CCmdReadMem::~CCmdReadMem()
       
  4122 	{
       
  4123 	}
       
  4124 
       
  4125 CCmdReadMem::CCmdReadMem()
       
  4126 	{
       
  4127 	}
       
  4128 
       
  4129 const TDesC& CCmdReadMem::Name() const
       
  4130 	{
       
  4131 	_LIT(KName, "readmem");
       
  4132 	return KName;
       
  4133 	}
       
  4134 
       
  4135 void CCmdReadMem::DoRunL()
       
  4136 	{
       
  4137 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  4138 	LoadMemoryAccessL();
       
  4139 
       
  4140 	if (iFileName.Length() > 0)
       
  4141 		{
       
  4142 		LeaveIfErr(iFile.Create(FsL(), iFileName, EFileWrite), _L("Unable to create \"%S\""), &iFileName);
       
  4143 		}
       
  4144 
       
  4145 	if (!iOptions.IsPresent(&iThreadId))
       
  4146 		{
       
  4147 		iThreadId = RThread().Id();
       
  4148 		}
       
  4149 
       
  4150 	TBuf8<KBlockSize> buf;
       
  4151 	TInt bytesRead = 0;
       
  4152 	TInt dumpPos = 0;
       
  4153 	while ((TUint)bytesRead < iSize)
       
  4154 		{
       
  4155 		buf.Zero();
       
  4156 		TThreadMemoryAccessParamsBuf memoryAccessParamsBuf;
       
  4157 		TThreadMemoryAccessParams& memoryAccessParams = memoryAccessParamsBuf();
       
  4158 		memoryAccessParams.iId = iThreadId;
       
  4159 		memoryAccessParams.iAddr = (TUint8*)iAddress + bytesRead;
       
  4160 		TInt bytesToRead = iSize - bytesRead;
       
  4161 		if (bytesToRead > KBlockSize)
       
  4162 			{
       
  4163 			bytesToRead = KBlockSize;
       
  4164 			}
       
  4165 		memoryAccessParams.iSize = bytesToRead;
       
  4166 		User::LeaveIfError(iMemAccess.GetThreadMem(memoryAccessParamsBuf, buf));
       
  4167 		if (iFile.SubSessionHandle())
       
  4168 			{
       
  4169 			User::LeaveIfError(iFile.Write(buf));
       
  4170 			}
       
  4171 		else
       
  4172 			{
       
  4173 			Dump(buf, *this, dumpPos);
       
  4174 			}
       
  4175 		bytesRead += bytesToRead;
       
  4176 		}
       
  4177 
       
  4178 #else
       
  4179 	PrintError(KErrNotSupported, _L("Unable to read memory because fshell was not built with FSHELL_MEMORY_ACCESS_SUPPORT defined. That probably means this plaform doesn't support the MemoryAccess device driver."));
       
  4180 	User::Leave(KErrNotSupported);
       
  4181 #endif
       
  4182 	}
       
  4183 
       
  4184 void CCmdReadMem::OptionsL(RCommandOptionList& aOptions)
       
  4185 	{
       
  4186 	_LIT(KCmdOptThreadId, "thread_id");
       
  4187 	aOptions.AppendIntL(iThreadId, KCmdOptThreadId);
       
  4188 	}
       
  4189 
       
  4190 void CCmdReadMem::ArgumentsL(RCommandArgumentList& aArguments)
       
  4191 	{
       
  4192 	_LIT(KCmdArgAddress, "address");
       
  4193 	_LIT(KCmdArgSize, "size");
       
  4194 	_LIT(KCmdArgFileName, "file_name");
       
  4195 
       
  4196 	aArguments.AppendUintL(iAddress, KCmdArgAddress);
       
  4197 	aArguments.AppendUintL(iSize, KCmdArgSize);
       
  4198 	aArguments.AppendFileNameL(iFileName, KCmdArgFileName);
       
  4199 	}
       
  4200 
       
  4201 
       
  4202 //
       
  4203 // CCmdE32Header.
       
  4204 //
       
  4205 
       
  4206 CCommandBase* CCmdE32Header::NewLC()
       
  4207 	{
       
  4208 	CCmdE32Header* self = new(ELeave) CCmdE32Header();
       
  4209 	CleanupStack::PushL(self);
       
  4210 	self->BaseConstructL();
       
  4211 	return self;
       
  4212 	}
       
  4213 
       
  4214 CCmdE32Header::~CCmdE32Header()
       
  4215 	{
       
  4216 	delete iFormatter;
       
  4217 	}
       
  4218 
       
  4219 CCmdE32Header::CCmdE32Header()
       
  4220 	{
       
  4221 	}
       
  4222 
       
  4223 const TDesC& CCmdE32Header::Name() const
       
  4224 	{
       
  4225 	_LIT(KName, "e32header");
       
  4226 	return KName;
       
  4227 	}
       
  4228 
       
  4229 #define CASE_LIT2(x, y) case x: { _LIT(KName, #y); return &KName; }
       
  4230 const TDesC* CompressionType(TUint aType)
       
  4231 	{
       
  4232 	switch (aType)
       
  4233 		{
       
  4234 		CASE_LIT2(0, KFormatNotCompressed)
       
  4235 		CASE_LIT2(0x101F7AFC, KUidCompressionDeflate)
       
  4236 		CASE_LIT2(0x102822AA, KUidCompressionBytePair)
       
  4237 		default:
       
  4238 			_LIT(KUnknown, "?");
       
  4239 			return &KUnknown;
       
  4240 		}
       
  4241 	}
       
  4242 
       
  4243 void CCmdE32Header::DoRunL()
       
  4244 	{
       
  4245 	if (iXip && iNotXip)
       
  4246 		{
       
  4247 		LeaveIfErr(KErrArgument, _L("--xip and --not-xip options are mutually exclusive"));
       
  4248 		}
       
  4249 
       
  4250 	RFile file;
       
  4251 	CleanupClosePushL(file);
       
  4252 	LeaveIfErr(file.Open(FsL(), iFileName, EFileRead), _L("Couldn't open \"%S\" for reading"), &iFileName);
       
  4253 
       
  4254 	iFormatter = CTextFormatter::NewL(Stdout());
       
  4255 	IoUtils::CTextBuffer* buf = IoUtils::CTextBuffer::NewLC(0x100);
       
  4256 
       
  4257 	if ((Fs().IsFileInRom(iFileName) || iXip) && !iNotXip)
       
  4258 		{
       
  4259 		TAny* ptr = Fs().IsFileInRom(iFileName);
       
  4260 		if (ptr)
       
  4261 			{
       
  4262 			buf->AppendFormatL(_L("ROM file address:\t0x%08x\r\n"), ptr);
       
  4263 			}
       
  4264 		TRomImageHeader imageHeader;
       
  4265 		TPckg<TRomImageHeader> pckg(imageHeader);
       
  4266 		LeaveIfErr(file.Read(pckg, sizeof(TRomImageHeader)), _L("Couldn't read E32 image header"));
       
  4267 		buf->AppendFormatL(_L("UIDs:\t0x%08x 0x%08x 0x%08x\r\n"), imageHeader.iUid1, imageHeader.iUid2, imageHeader.iUid3);
       
  4268 		buf->AppendFormatL(_L("UID checksum:\t0x%08x\r\n"), imageHeader.iUidChecksum);
       
  4269 		buf->AppendFormatL(_L("Entry point offset:\t0x%08x\r\n"), imageHeader.iEntryPoint);
       
  4270 		buf->AppendFormatL(_L("Code address:\t0x%08x\r\n"), imageHeader.iCodeAddress);
       
  4271 		buf->AppendFormatL(_L("Data address:\t0x%08x\r\n"), imageHeader.iDataAddress);
       
  4272 		buf->AppendFormatL(_L("Code size:\t%d\r\n"), imageHeader.iCodeSize);
       
  4273 		buf->AppendFormatL(_L("Text size:\t%d\r\n"), imageHeader.iTextSize);
       
  4274 		buf->AppendFormatL(_L("Data size:\t%d\r\n"), imageHeader.iDataSize);
       
  4275 		buf->AppendFormatL(_L("BSS size:\t%d\r\n"), imageHeader.iBssSize);
       
  4276 		buf->AppendFormatL(_L("Minimum heap size:\t%d\r\n"), imageHeader.iHeapSizeMin);
       
  4277 		buf->AppendFormatL(_L("Maximum heap size:\t%d\r\n"), imageHeader.iHeapSizeMax);
       
  4278 		buf->AppendFormatL(_L("Stack size:\t%d\r\n"), imageHeader.iStackSize);
       
  4279 		buf->AppendFormatL(_L("DLL ref table address:\t0x%08x\r\n"), imageHeader.iDllRefTable);
       
  4280 		buf->AppendFormatL(_L("Export dir count:\t%d\r\n"), imageHeader.iExportDirCount);
       
  4281 		buf->AppendFormatL(_L("Export dir address:\t0x%08x\r\n"), imageHeader.iExportDir);
       
  4282 		buf->AppendFormatL(_L("Secure ID:\t0x%08x\r\n"), imageHeader.iS.iSecureId);
       
  4283 		buf->AppendFormatL(_L("Vendor ID:\t0x%08x\r\n"), imageHeader.iS.iVendorId);
       
  4284 		buf->AppendFormatL(_L("Capabilities:\t0x%08x 0x%08x\r\n"), imageHeader.iS.iCaps[0], imageHeader.iS.iCaps[1]);
       
  4285 		TInt majorVersion = imageHeader.iToolsVersion.iMajor;
       
  4286 		TInt minorVersion = imageHeader.iToolsVersion.iMinor;
       
  4287 		TInt buildVersion = imageHeader.iToolsVersion.iBuild;
       
  4288 		buf->AppendFormatL(_L("Tools version:\t%d.%d (%d)\r\n"), majorVersion, minorVersion, buildVersion);
       
  4289 		buf->AppendFormatL(_L("Flags:\t0x%08x\r\n"), imageHeader.iFlags);
       
  4290 		buf->AppendFormatL(_L("Process priority:\t%d\r\n"), imageHeader.iPriority);
       
  4291 		buf->AppendFormatL(_L("Data BSS linear base:\t0x%08x\r\n"), imageHeader.iDataBssLinearBase);
       
  4292 		buf->AppendFormatL(_L("Next extension:\t0x%08x\r\n"), imageHeader.iNextExtension);
       
  4293 		buf->AppendFormatL(_L("Hardware variant:\t0x%08x\r\n"), imageHeader.iHardwareVariant);
       
  4294 		buf->AppendFormatL(_L("Total data size:\t%d\r\n"), imageHeader.iTotalDataSize);
       
  4295 		buf->AppendFormatL(_L("Module version:\t0x%08x (%d.%d)\r\n"), imageHeader.iModuleVersion, imageHeader.iModuleVersion>>16, imageHeader.iModuleVersion&0xFFFF);
       
  4296 		buf->AppendFormatL(_L("Exception descriptor:\t0x%08x\r\n"), imageHeader.iExceptionDescriptor);
       
  4297 		}
       
  4298 	else
       
  4299 		{
       
  4300 		E32ImageHeaderV* imageHeader = new(ELeave) E32ImageHeaderV;
       
  4301 		CleanupStack::PushL(imageHeader);
       
  4302 		TPckg<E32ImageHeaderV> pckg(*imageHeader);
       
  4303 		LeaveIfErr(file.Read(pckg, sizeof(E32ImageHeaderV)), _L("Couldn't read E32 image header"));
       
  4304 		buf->AppendFormatL(_L("UIDs:\t0x%08x 0x%08x 0x%08x\r\n"), imageHeader->iUid1, imageHeader->iUid2, imageHeader->iUid3);
       
  4305 		buf->AppendFormatL(_L("UID checksum:\t0x%08x\r\n"), imageHeader->iUidChecksum);
       
  4306 		buf->AppendFormatL(_L("Header CRC:\t0x%08x\r\n"), imageHeader->iHeaderCrc);
       
  4307 		buf->AppendFormatL(_L("Module version:\t0x%08x (%d.%d)\r\n"), imageHeader->iModuleVersion, imageHeader->iModuleVersion>>16, imageHeader->iModuleVersion&0xFFFF);
       
  4308 		buf->AppendFormatL(_L("Compression type:\t0x%08x (%S)\r\n"), imageHeader->iCompressionType, CompressionType(imageHeader->iCompressionType));
       
  4309 		TInt majorVersion = imageHeader->iToolsVersion.iMajor;
       
  4310 		TInt minorVersion = imageHeader->iToolsVersion.iMinor;
       
  4311 		TInt buildVersion = imageHeader->iToolsVersion.iBuild;
       
  4312 		buf->AppendFormatL(_L("Tools version:\t%d.%d (%d)\r\n"), majorVersion, minorVersion, buildVersion);
       
  4313 		buf->AppendFormatL(_L("Build time:\t0x%08x 0x%08x\r\n"), imageHeader->iTimeLo, imageHeader->iTimeHi);
       
  4314 		buf->AppendFormatL(_L("Flags:\t0x%08x\r\n"), imageHeader->iFlags);
       
  4315 		buf->AppendFormatL(_L("Code size:\t%d\r\n"), imageHeader->iCodeSize);
       
  4316 		buf->AppendFormatL(_L("Minimum heap size:\t%d\r\n"), imageHeader->iHeapSizeMin);
       
  4317 		buf->AppendFormatL(_L("Maximum heap size:\t%d\r\n"), imageHeader->iHeapSizeMax);
       
  4318 		buf->AppendFormatL(_L("Stack size:\t%d\r\n"), imageHeader->iStackSize);
       
  4319 		buf->AppendFormatL(_L("BSS size:\t%d\r\n"), imageHeader->iBssSize);
       
  4320 		buf->AppendFormatL(_L("Entry point offset:\t0x%08x\r\n"), imageHeader->iEntryPoint);
       
  4321 		buf->AppendFormatL(_L("Code base:\t0x%08x\r\n"), imageHeader->iCodeBase);
       
  4322 		buf->AppendFormatL(_L("Data base:\t0x%08x\r\n"), imageHeader->iDataBase);
       
  4323 		buf->AppendFormatL(_L("DLL ref table count:\t%d\r\n"), imageHeader->iDllRefTableCount);
       
  4324 		buf->AppendFormatL(_L("Export dir offset:\t0x%08x\r\n"), imageHeader->iExportDirOffset);
       
  4325 		buf->AppendFormatL(_L("Export dir count:\t%d\r\n"), imageHeader->iExportDirCount);
       
  4326 		buf->AppendFormatL(_L("Text size:\t%d\r\n"), imageHeader->iTextSize);
       
  4327 		buf->AppendFormatL(_L("Code offset:\t0x%08x\r\n"), imageHeader->iCodeOffset);
       
  4328 		buf->AppendFormatL(_L("Data offset:\t0x%08x\r\n"), imageHeader->iDataOffset);
       
  4329 		buf->AppendFormatL(_L("Import offset:\t0x%08x\r\n"), imageHeader->iImportOffset);
       
  4330 		buf->AppendFormatL(_L("Code reloc offset:\t0x%08x\r\n"), imageHeader->iCodeRelocOffset);
       
  4331 		buf->AppendFormatL(_L("Data reloc offset:\t0x%08x\r\n"), imageHeader->iDataRelocOffset);
       
  4332 		TInt temp; // Why use a temp here?
       
  4333 		temp = imageHeader->iProcessPriority;
       
  4334 		buf->AppendFormatL(_L("Process priority:\t%d\r\n"), temp);
       
  4335 		temp = imageHeader->iCpuIdentifier;
       
  4336 		buf->AppendFormatL(_L("CPU identifier:\t%d\r\n"), temp);
       
  4337 		buf->AppendFormatL(_L("Uncompressed size:\t%d\r\n"), imageHeader->iUncompressedSize);
       
  4338 		buf->AppendFormatL(_L("Secure ID:\t0x%08x\r\n"), imageHeader->iS.iSecureId);
       
  4339 		buf->AppendFormatL(_L("Vendor ID:\t0x%08x\r\n"), imageHeader->iS.iVendorId);
       
  4340 		buf->AppendFormatL(_L("Capabilities:\t0x%08x 0x%08x\r\n"), imageHeader->iS.iCaps[0], imageHeader->iS.iCaps[1]);
       
  4341 		buf->AppendFormatL(_L("Exception descriptor:\t0x%08x\r\n"), imageHeader->iExceptionDescriptor);
       
  4342 		buf->AppendFormatL(_L("Spare2:\t0x%08x\r\n"), imageHeader->iSpare2);
       
  4343 		temp = imageHeader->iExportDescSize;
       
  4344 		buf->AppendFormatL(_L("Export description size:\t%d\r\n"), temp);
       
  4345 		temp = imageHeader->iExportDescType;
       
  4346 		buf->AppendFormatL(_L("Export description type:\t%d\r\n"), temp);
       
  4347 		temp = imageHeader->iExportDesc[0];
       
  4348 		buf->AppendFormatL(_L("Export description:\t%d\r\n"), temp);
       
  4349 		CleanupStack::PopAndDestroy(imageHeader);
       
  4350 		}
       
  4351 
       
  4352 	iFormatter->TabulateL(0, 2, buf->Descriptor());
       
  4353 	Write(iFormatter->Descriptor());
       
  4354 	CleanupStack::PopAndDestroy(2, &file);
       
  4355 	}
       
  4356 
       
  4357 void CCmdE32Header::OptionsL(RCommandOptionList& aOptions)
       
  4358 	{
       
  4359 	_LIT(KCmdOptXip, "xip");
       
  4360 	_LIT(KCmdOptNotXip, "not-xip");
       
  4361 
       
  4362 	aOptions.AppendBoolL(iXip, KCmdOptXip);
       
  4363 	aOptions.AppendBoolL(iNotXip, KCmdOptNotXip);
       
  4364 	}
       
  4365 
       
  4366 void CCmdE32Header::ArgumentsL(RCommandArgumentList& aArguments)
       
  4367 	{
       
  4368 	_LIT(KCmdArgFileName, "file_name");
       
  4369 	aArguments.AppendFileNameL(iFileName, KCmdArgFileName);
       
  4370 	}
       
  4371 
       
  4372 
       
  4373 //
       
  4374 // CCmdObjInfo.
       
  4375 //
       
  4376 
       
  4377 CCommandBase* CCmdObjInfo::NewLC()
       
  4378 	{
       
  4379 	CCmdObjInfo* self = new(ELeave) CCmdObjInfo();
       
  4380 	CleanupStack::PushL(self);
       
  4381 	self->BaseConstructL();
       
  4382 	return self;
       
  4383 	}
       
  4384 
       
  4385 CCmdObjInfo::~CCmdObjInfo()
       
  4386 	{
       
  4387 	}
       
  4388 
       
  4389 CCmdObjInfo::CCmdObjInfo()
       
  4390 	{
       
  4391 	}
       
  4392 
       
  4393 const TDesC& CCmdObjInfo::Name() const
       
  4394 	{
       
  4395 	_LIT(KName, "objinfo");
       
  4396 	return KName;
       
  4397 	}
       
  4398 
       
  4399 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  4400 
       
  4401 #define CASE_RETURN_LIT(XXX) case XXX: { _LIT(_KLit, #XXX); return &_KLit; }
       
  4402 #define DEFAULT_RETURN_LIT(XXX) default: { _LIT(_KLit, XXX); return &_KLit; }
       
  4403 
       
  4404 EXPORT_C const TDesC* StringifyObjectType(TObjectType aObjectType)
       
  4405 	{
       
  4406 	switch (aObjectType)
       
  4407 		{
       
  4408 		CASE_RETURN_LIT(EThread);
       
  4409 		CASE_RETURN_LIT(EProcess);
       
  4410 		CASE_RETURN_LIT(EChunk);
       
  4411 		CASE_RETURN_LIT(ELibrary);
       
  4412 		CASE_RETURN_LIT(ESemaphore);
       
  4413 		CASE_RETURN_LIT(EMutex);
       
  4414 		CASE_RETURN_LIT(ETimer);
       
  4415 		CASE_RETURN_LIT(EServer);
       
  4416 		CASE_RETURN_LIT(ESession);
       
  4417 		CASE_RETURN_LIT(ELogicalDevice);
       
  4418 		CASE_RETURN_LIT(EPhysicalDevice);
       
  4419 		CASE_RETURN_LIT(ELogicalChannel);
       
  4420 		CASE_RETURN_LIT(EChangeNotifier);
       
  4421 		CASE_RETURN_LIT(EUndertaker);
       
  4422 		CASE_RETURN_LIT(EMsgQueue);
       
  4423 		CASE_RETURN_LIT(EPropertyRef);
       
  4424 		CASE_RETURN_LIT(ECondVar);
       
  4425 		CASE_RETURN_LIT(EIpcMessageD);
       
  4426 		CASE_RETURN_LIT(EIpcMessage);
       
  4427 		CASE_RETURN_LIT(EIpcClient);
       
  4428 		DEFAULT_RETURN_LIT("*** OBJECT TYPE UNKNOWN ***");
       
  4429 		}
       
  4430 	}
       
  4431 
       
  4432 void CCmdObjInfo::PrintObjectDetailsL(TUint aObjectAddress)
       
  4433 	{
       
  4434 	TObjectType objectType;
       
  4435 	TInt err = iMemAccess.GetObjectType((TUint8*)aObjectAddress, objectType);
       
  4436 	if (err == KErrNone)
       
  4437 		{
       
  4438 		TObjectKernelInfo objectInfo;
       
  4439 		TPckg<TObjectKernelInfo> objectInfoPckg(objectInfo);
       
  4440 		err = iMemAccess.GetObjectInfo(objectType, (TUint8*)(aObjectAddress), objectInfoPckg);
       
  4441 		if (err == KErrNone)
       
  4442 			{
       
  4443 			TFullName fullName;
       
  4444 			fullName.Copy(objectInfo.iFullName);
       
  4445 			Printf(_L("0x%08x %2d %S (type=%d) %S\r\n"), aObjectAddress, objectInfo.iAccessCount, StringifyObjectType(objectType), objectType, &fullName);
       
  4446 			}
       
  4447 		else
       
  4448 			{
       
  4449 			PrintWarning(_L("Couldn't read details of %S 0x%08x : %S(%d)"), StringifyObjectType(objectType), aObjectAddress, Stringify::Error(err), err);
       
  4450 			}
       
  4451 		}
       
  4452 	else
       
  4453 		{
       
  4454 		PrintWarning(_L("Couldn't find type of object 0x%08x : %S(%d)"), aObjectAddress, Stringify::Error(err), err);
       
  4455 		}
       
  4456 
       
  4457 	if (iReferencers)
       
  4458 		{
       
  4459 		PrintObjectReferencersL(aObjectAddress);
       
  4460 		}
       
  4461 	}
       
  4462 
       
  4463 void CCmdObjInfo::PrintObjectReferencersL(TUint aObjectAddress)
       
  4464 	{
       
  4465 	TInt err = KErrNone;
       
  4466 	TInt bufSize = 256;
       
  4467 	HBufC8* idBuf;
       
  4468 	do
       
  4469 		{
       
  4470 		idBuf = HBufC8::NewLC(bufSize);
       
  4471 		TPtr8 idPtr(idBuf->Des());
       
  4472 		err = iMemAccess.GetHandleOwners((TUint8*)aObjectAddress, idPtr);
       
  4473 		if (err == KErrOverflow)
       
  4474 			{
       
  4475 			CleanupStack::PopAndDestroy(idBuf);
       
  4476 			bufSize *= 2;
       
  4477 			}
       
  4478 		}
       
  4479 		while (err == KErrOverflow);
       
  4480 
       
  4481 	const TInt numIds = idBuf->Length() / sizeof(TUint);
       
  4482 	if (numIds > 0)
       
  4483 		{
       
  4484 		Write(_L("Referenced by:\r\n"));
       
  4485 		}
       
  4486 	for (TInt i = 0; i < numIds; i++)
       
  4487 		{
       
  4488 		TUint id = ((TUint*)idBuf->Ptr())[i];
       
  4489 		TBool isThread = ETrue;
       
  4490 		RHandleBase h;
       
  4491 		TInt err = ((RThread&)h).Open(TThreadId(id));
       
  4492 		if (err)
       
  4493 			{
       
  4494 			// Maybe it's a process id instead.
       
  4495 			isThread = EFalse;
       
  4496 			err = ((RProcess&)h).Open(TProcessId(id));
       
  4497 			}
       
  4498 
       
  4499 		if (err)
       
  4500 			{
       
  4501 			PrintWarning(_L("Unable to open thread or process for id %d: %S (%d)"), id, Stringify::Error(err), err);
       
  4502 			}
       
  4503 		else
       
  4504 			{
       
  4505 			TFullName name = h.FullName();
       
  4506 			_LIT(KThread,  "\tthread:  ");
       
  4507 			_LIT(KProcess, "\tprocess: ");
       
  4508 			Printf(_L("%S%u\t%S\r\n"), isThread ? &KThread : &KProcess, id, &name);
       
  4509 			}
       
  4510 		}
       
  4511 
       
  4512 	CleanupStack::PopAndDestroy(idBuf);
       
  4513 	}
       
  4514 
       
  4515 void CCmdObjInfo::PrintReferencedObjectDetailsL(TOwnerType aOwnerType, TUint aId)
       
  4516 	{
       
  4517 	TInt err = KErrNone;
       
  4518 	TInt bufSize = 256;
       
  4519 
       
  4520 	HBufC8* addressesBuf;
       
  4521 	do
       
  4522 		{
       
  4523 		addressesBuf = HBufC8::NewLC(bufSize);
       
  4524 		TPtr8 addressesPtr(addressesBuf->Des());
       
  4525 		if (aOwnerType == EOwnerProcess)
       
  4526 			{
       
  4527 			err = iMemAccess.GetProcessHandles(aId, addressesPtr);
       
  4528 			}
       
  4529 		else
       
  4530 			{
       
  4531 			err = iMemAccess.GetThreadHandles(aId, addressesPtr);
       
  4532 			}
       
  4533 		if (err == KErrOverflow)
       
  4534 			{
       
  4535 			CleanupStack::PopAndDestroy(addressesBuf);
       
  4536 			bufSize *= 2;
       
  4537 			}
       
  4538 		}
       
  4539 		while (err == KErrOverflow);
       
  4540 
       
  4541 	const TInt numAddresses = addressesBuf->Length() / sizeof(TUint32*);
       
  4542 	if (numAddresses == 0)
       
  4543 		{
       
  4544 		Write(_L("No objects found.\r\n"));
       
  4545 		}
       
  4546 	else
       
  4547 		{
       
  4548 		TUint32* p = (TUint32*)addressesBuf->Ptr();
       
  4549 		TInt offset = 0;
       
  4550 		while (offset < numAddresses)
       
  4551 			{
       
  4552 			TUint32* ptr = p + offset++;
       
  4553 			PrintObjectDetailsL(*ptr);
       
  4554 			}
       
  4555 		}
       
  4556 
       
  4557 	CleanupStack::PopAndDestroy(addressesBuf);
       
  4558 	}
       
  4559 
       
  4560 #endif // FSHELL_MEMORY_ACCESS_SUPPORT
       
  4561 
       
  4562 void CCmdObjInfo::DoRunL()
       
  4563 	{
       
  4564 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  4565 	LoadMemoryAccessL();
       
  4566 
       
  4567 	if (iObjectAddress)
       
  4568 		{
       
  4569 		PrintObjectDetailsL(iObjectAddress);
       
  4570 		}
       
  4571 	else if (iProcessId)
       
  4572 		{
       
  4573 		if (iAll)
       
  4574 			{
       
  4575 			RProcess process;
       
  4576 			LeaveIfErr(process.Open(iProcessId), _L("Couldn't open process with id \"%u\""), iProcessId);
       
  4577 			TFullName processName(process.Name());
       
  4578 			Printf(_L("Objects owned by process \"%S\":\r\n"), &processName);
       
  4579 			PrintReferencedObjectDetailsL(EOwnerProcess, iProcessId);
       
  4580 			Write(_L("\r\n"));
       
  4581 
       
  4582 			processName.Append(_L("*"));
       
  4583 			TFindThread threadFinder(processName);
       
  4584 			RThread thread;
       
  4585 			TFullName threadName;
       
  4586 			while (threadFinder.Next(threadName) == KErrNone)
       
  4587 				{
       
  4588 				TInt err = thread.Open(threadFinder);
       
  4589 				if (err)
       
  4590 					{
       
  4591 					continue;
       
  4592 					}
       
  4593 				Printf(_L("Objects owned by thread \"%S\":\r\n"), &threadName);
       
  4594 				PrintReferencedObjectDetailsL(EOwnerThread, thread.Id());
       
  4595 				Write(_L("\r\n"));
       
  4596 				}
       
  4597 			}
       
  4598 		else
       
  4599 			{
       
  4600 			PrintReferencedObjectDetailsL(EOwnerProcess, iProcessId);
       
  4601 			}
       
  4602 		}
       
  4603 	else if (iThreadId)
       
  4604 		{
       
  4605 		PrintReferencedObjectDetailsL(EOwnerThread, iThreadId);
       
  4606 		}
       
  4607 
       
  4608 #else
       
  4609 	PrintError(KErrNotSupported, _L("Unable to fetch object information because fshell was not built with FSHELL_MEMORY_ACCESS_SUPPORT defined. That probably means this plaform doesn't support the MemoryAccess device driver."));
       
  4610 	User::Leave(KErrNotSupported);
       
  4611 #endif
       
  4612 	}
       
  4613 
       
  4614 void CCmdObjInfo::OptionsL(RCommandOptionList& aOptions)
       
  4615 	{
       
  4616 	_LIT(KCmdOptReferencers, "referencers");
       
  4617 	_LIT(KCmdOptProcessId, "process-id");
       
  4618 	_LIT(KCmdOptThreadId, "thread-id");
       
  4619 	_LIT(KCmdOptAll, "all");
       
  4620 
       
  4621 	aOptions.AppendBoolL(iReferencers, KCmdOptReferencers);
       
  4622 	aOptions.AppendUintL(iProcessId, KCmdOptProcessId);
       
  4623 	aOptions.AppendUintL(iThreadId, KCmdOptThreadId);
       
  4624 	aOptions.AppendBoolL(iAll, KCmdOptAll);
       
  4625 	}
       
  4626 
       
  4627 void CCmdObjInfo::ArgumentsL(RCommandArgumentList& aArguments)
       
  4628 	{
       
  4629 	_LIT(KCmdArgObjectAddress, "object_address");
       
  4630 	aArguments.AppendUintL(iObjectAddress, KCmdArgObjectAddress);
       
  4631 	}
       
  4632 
       
  4633 //
       
  4634 // CCmdTouch.
       
  4635 //
       
  4636 
       
  4637 CCommandBase* CCmdTouch::NewLC()
       
  4638 	{
       
  4639 	CCmdTouch* self = new(ELeave) CCmdTouch();
       
  4640 	CleanupStack::PushL(self);
       
  4641 	self->BaseConstructL();
       
  4642 	return self;
       
  4643 	}
       
  4644 
       
  4645 CCmdTouch::~CCmdTouch()
       
  4646 	{
       
  4647 	}
       
  4648 
       
  4649 CCmdTouch::CCmdTouch()
       
  4650 	{
       
  4651 	}
       
  4652 
       
  4653 const TDesC& CCmdTouch::Name() const
       
  4654 	{
       
  4655 	_LIT(KName, "touch");
       
  4656 	return KName;
       
  4657 	}
       
  4658 
       
  4659 void CCmdTouch::ArgumentsL(RCommandArgumentList& aArguments)
       
  4660 	{
       
  4661 	_LIT(KCmdArgFile, "file");
       
  4662 	aArguments.AppendFileNameL(iFileName, KCmdArgFile);
       
  4663 	}
       
  4664 
       
  4665 void CCmdTouch::DoRunL()
       
  4666 	{
       
  4667 	TEntry e;
       
  4668 	TInt err = FsL().Entry(iFileName, e);
       
  4669 
       
  4670 	if (err == KErrNotFound || err == KErrPathNotFound)
       
  4671 		{
       
  4672 		RFile file;
       
  4673 		err = file.Create(Fs(), iFileName, EFileWrite);
       
  4674 		LeaveIfErr(err, _L("Couldn't create file %S"), &iFileName);
       
  4675 		file.Close();
       
  4676 		}
       
  4677 	else
       
  4678 		{
       
  4679 		LeaveIfErr(err, _L("Couldn't get file info for %S"), &iFileName);
       
  4680 		TTime now;
       
  4681 		now.UniversalTime();
       
  4682 		err = Fs().SetEntry(iFileName, now, 0, 0);
       
  4683 		LeaveIfErr(err, _L("Couldn't update last-modified date for %S"), &iFileName);
       
  4684 		}
       
  4685 	}
       
  4686 
       
  4687 
       
  4688 //
       
  4689 // CCmdDialog.
       
  4690 //
       
  4691 
       
  4692 CCommandBase* CCmdDialog::NewLC()
       
  4693 	{
       
  4694 	CCmdDialog* self = new(ELeave) CCmdDialog();
       
  4695 	CleanupStack::PushL(self);
       
  4696 	self->BaseConstructL();
       
  4697 	return self;
       
  4698 	}
       
  4699 
       
  4700 CCmdDialog::~CCmdDialog()
       
  4701 	{
       
  4702 	delete iTitle;
       
  4703 	delete iBody;
       
  4704 	delete iButton1;
       
  4705 	delete iButton2;
       
  4706 	}
       
  4707 
       
  4708 CCmdDialog::CCmdDialog() : CCommandBase(EManualComplete)
       
  4709 	{
       
  4710 	}
       
  4711 
       
  4712 const TDesC& CCmdDialog::Name() const
       
  4713 	{
       
  4714 	_LIT(KName, "dialog");
       
  4715 	return KName;
       
  4716 	}
       
  4717 
       
  4718 CCmdDialog::TMode CCmdDialog::ModeL() const
       
  4719 	{
       
  4720 	_LIT(KDialogImpl, "DIALOG_IMPL");
       
  4721 	_LIT(KImplNotifier, "notifier");
       
  4722 	_LIT(KImplConsole, "console");
       
  4723 	_LIT(KImplNull, "null");
       
  4724 
       
  4725 	TMode mode = EModeNotifier;
       
  4726 	if (Env().IsDefined(KDialogImpl))
       
  4727 		{
       
  4728 		const TDesC& impl = Env().GetAsDesL(KDialogImpl);
       
  4729 		if (impl == KImplNotifier)
       
  4730 			{
       
  4731 			mode = EModeNotifier;
       
  4732 			}
       
  4733 		else if (impl == KImplConsole)
       
  4734 			{
       
  4735 			mode = EModeConsole;
       
  4736 			}
       
  4737 		else if (impl == KImplNull)
       
  4738 			{
       
  4739 			mode = EModeNull;
       
  4740 			}
       
  4741 		}
       
  4742 
       
  4743 	return mode;
       
  4744 	}
       
  4745 
       
  4746 void CCmdDialog::DoRunL()
       
  4747 	{
       
  4748 	if (iTitle == NULL)
       
  4749 		{
       
  4750 		iTitle = _L("Attention").AllocL();
       
  4751 		}
       
  4752 	if ((iButton1 == NULL) && (iButton2 == NULL))
       
  4753 		{
       
  4754 		iButton1 = _L("OK").AllocL();
       
  4755 		iButton2 = _L("Cancel").AllocL();
       
  4756 		}
       
  4757 	else if (iButton2 == NULL)
       
  4758 		{
       
  4759 		iButton2 = KNullDesC().AllocL();
       
  4760 		}
       
  4761 	else if (iButton1 == NULL)
       
  4762 		{
       
  4763 		LeaveIfErr(KErrArgument, _L("First button not specified"));
       
  4764 		}
       
  4765 	
       
  4766 	if (iBody == NULL)
       
  4767 		{
       
  4768 		iBody = HBufC::NewL(0x200);
       
  4769 		Stdin().SetReadMode(RIoReadHandle::EFull);
       
  4770 		TPtr ptr(iBody->Des());
       
  4771 		Stdin().ReadL(ptr);
       
  4772 		}
       
  4773 	
       
  4774 	switch (ModeL())
       
  4775 		{
       
  4776 		case EModeNotifier:
       
  4777 			{
       
  4778 			RNotifier notifier;
       
  4779 			User::LeaveIfError(notifier.Connect());
       
  4780 			CleanupClosePushL(notifier);
       
  4781 
       
  4782 			TInt buttonValue;
       
  4783 			TRequestStatus status;
       
  4784 			notifier.Notify(*iTitle, *iBody, *iButton1, *iButton2, buttonValue, status);
       
  4785 			User::WaitForRequest(status);
       
  4786 			Complete(buttonValue);
       
  4787 
       
  4788 			CleanupStack::PopAndDestroy(&notifier);
       
  4789 			break;
       
  4790 			}
       
  4791 		case EModeConsole:
       
  4792 			{
       
  4793 			RIoConsole console;
       
  4794 			console.OpenL(IoSession(), Stdin());
       
  4795 			CleanupClosePushL(console);
       
  4796 			
       
  4797 			RIoConsoleWriteHandle consWriter;
       
  4798 			consWriter.CreateL(IoSession());
       
  4799 			CleanupClosePushL(consWriter);
       
  4800 			console.AttachL(consWriter);
       
  4801 			
       
  4802 			RIoConsoleReadHandle consReader;
       
  4803 			consReader.CreateL(IoSession());
       
  4804 			CleanupClosePushL(consReader);
       
  4805 			console.AttachL(consReader, RIoEndPoint::EForeground);
       
  4806 			
       
  4807 			consWriter.Write(*iTitle);
       
  4808 			consWriter.Write(KNewLine);
       
  4809 			consWriter.Write(KNewLine);
       
  4810 			consWriter.Write(*iBody);
       
  4811 			consWriter.Write(KNewLine);
       
  4812 			consWriter.Write(KNewLine);
       
  4813 				{
       
  4814 				TBuf<0x100> buf;
       
  4815 				buf.AppendFormat(_L("%S <enter / select> or %S <any other key> "), iButton1, iButton2);
       
  4816 				consWriter.Write(buf);
       
  4817 				}
       
  4818 			TBuf<1> buf;
       
  4819 			consReader.ReadL(buf);
       
  4820 			ClearLineL(consWriter);
       
  4821 			CleanupStack::PopAndDestroy(3); // consReader, consWriter, console
       
  4822 			switch (buf[0])
       
  4823 				{
       
  4824 				case EKeyEnter:
       
  4825 	#ifdef FSHELL_PLATFORM_S60
       
  4826 				case EKeyDevice3:
       
  4827 	#endif
       
  4828 					Complete(0);
       
  4829 					break;
       
  4830 				default:
       
  4831 					Complete(1);
       
  4832 					break;
       
  4833 				}
       
  4834 			break;
       
  4835 			}
       
  4836 		case EModeNull:
       
  4837 			{
       
  4838 			Complete(0);
       
  4839 			break;
       
  4840 			}
       
  4841 		}
       
  4842 	}
       
  4843 
       
  4844 void CCmdDialog::ClearLineL(RIoConsoleWriteHandle& aWriteHandle)
       
  4845 	{
       
  4846 	if (aWriteHandle.AttachedToConsole())
       
  4847 		{
       
  4848 		TPoint cursorPos;
       
  4849 		LeaveIfErr(aWriteHandle.GetCursorPos(cursorPos), _L("Couldn't get cursor position"));
       
  4850 		cursorPos.iX = 0;
       
  4851 		LeaveIfErr(aWriteHandle.SetCursorPosAbs(cursorPos), _L("Couldn't set cursor position to beginning of line"));
       
  4852 		LeaveIfErr(aWriteHandle.ClearToEndOfLine(), _L("Couldn't clear to end of line"));
       
  4853 		}
       
  4854 	else
       
  4855 		{
       
  4856 		aWriteHandle.Write(KNewLine);
       
  4857 		}
       
  4858 	}
       
  4859 
       
  4860 void CCmdDialog::OptionsL(RCommandOptionList& aOptions)
       
  4861 	{
       
  4862 	_LIT(KOptTitle, "title");
       
  4863 	_LIT(KOptButton1, "first-button");
       
  4864 	_LIT(KOptButton2, "second-button");
       
  4865 
       
  4866 	aOptions.AppendStringL(iTitle, KOptTitle);
       
  4867 	aOptions.AppendStringL(iButton1, KOptButton1);
       
  4868 	aOptions.AppendStringL(iButton2, KOptButton2);
       
  4869 	}
       
  4870 
       
  4871 void CCmdDialog::ArgumentsL(RCommandArgumentList& aArguments)
       
  4872 	{
       
  4873 	_LIT(KArgBody, "body");
       
  4874 	aArguments.AppendStringL(iBody, KArgBody);
       
  4875 	}
       
  4876 
       
  4877 
       
  4878 //
       
  4879 // CCmdJit.
       
  4880 //
       
  4881 
       
  4882 #ifdef __WINS__
       
  4883 
       
  4884 CCommandBase* CCmdJit::NewLC()
       
  4885 	{
       
  4886 	CCmdJit* self = new(ELeave) CCmdJit();
       
  4887 	CleanupStack::PushL(self);
       
  4888 	self->BaseConstructL();
       
  4889 	return self;
       
  4890 	}
       
  4891 
       
  4892 CCmdJit::~CCmdJit()
       
  4893 	{
       
  4894 	}
       
  4895 
       
  4896 CCmdJit::CCmdJit()
       
  4897 	{
       
  4898 	}
       
  4899 
       
  4900 const TDesC& CCmdJit::Name() const
       
  4901 	{
       
  4902 	_LIT(KName, "jit");
       
  4903 	return KName;
       
  4904 	}
       
  4905 
       
  4906 void CCmdJit::DoRunL()
       
  4907 	{
       
  4908 	switch (iOperation)
       
  4909 		{
       
  4910 		case EStatus:
       
  4911 			if (User::JustInTime())
       
  4912 				{
       
  4913 				Write(_L("on\r\n"));
       
  4914 				}
       
  4915 			else
       
  4916 				{
       
  4917 				Write(_L("off\r\n"));
       
  4918 				}
       
  4919 			break;
       
  4920 		case EOn:
       
  4921 			User::SetJustInTime(ETrue);
       
  4922 			break;
       
  4923 		case EOff:
       
  4924 			User::SetJustInTime(EFalse);
       
  4925 			break;
       
  4926 		default:
       
  4927 			LeaveIfErr(KErrArgument, _L("Unrecognised operation"));
       
  4928 		}
       
  4929 	}
       
  4930 
       
  4931 void CCmdJit::ArgumentsL(RCommandArgumentList& aArguments)
       
  4932 	{
       
  4933 	_LIT(KArgOperation, "operation");
       
  4934 	aArguments.AppendEnumL((TInt&)iOperation, KArgOperation);
       
  4935 	}
       
  4936 
       
  4937 #endif // __WINS__
       
  4938 
       
  4939 
       
  4940 //
       
  4941 // CCmdConsole.
       
  4942 //
       
  4943 
       
  4944 CCommandBase* CCmdConsole::NewLC()
       
  4945 	{
       
  4946 	CCmdConsole* self = new(ELeave) CCmdConsole();
       
  4947 	CleanupStack::PushL(self);
       
  4948 	self->BaseConstructL();
       
  4949 	return self;
       
  4950 	}
       
  4951 
       
  4952 CCmdConsole::~CCmdConsole()
       
  4953 	{
       
  4954 	}
       
  4955 
       
  4956 CCmdConsole::CCmdConsole()
       
  4957 	{
       
  4958 	}
       
  4959 
       
  4960 const TDesC& CCmdConsole::Name() const
       
  4961 	{
       
  4962 	_LIT(KName, "console");
       
  4963 	return KName;
       
  4964 	}
       
  4965 	
       
  4966 _LIT(KPersistentConsole, " (persistent console)");
       
  4967 
       
  4968 void CCmdConsole::DoRunL()
       
  4969 	{
       
  4970 	if (iIsRemote && iIsNull)
       
  4971 		{
       
  4972 		LeaveIfErr(KErrArgument, _L("-r and -n options are mutually exclusive"));
       
  4973 		}
       
  4974 
       
  4975 	RIoConsole console;
       
  4976 	LeaveIfErr(console.Open(IoSession(), Stdout()), _L("Couldn't open handle to console"));
       
  4977 	CleanupClosePushL(console);
       
  4978 	
       
  4979 	TFileName name;
       
  4980 	if (console.IsTypeL(RIoHandle::EPersistentConsole))
       
  4981 		{
       
  4982 		TInt err = console.ObjectName(name);
       
  4983 		if (err!=KErrOverflow) User::LeaveIfError(err);
       
  4984 		name.SetLength(Min(name.Length(), name.MaxLength()-KPersistentConsole().Length()));
       
  4985 		name.Append(KPersistentConsole);
       
  4986 		}
       
  4987 	else
       
  4988 		{
       
  4989 		LeaveIfErr(console.Implementation(name), _L("Couldn't read console implemenation name"));
       
  4990 		}
       
  4991 	if (iIsRemote)
       
  4992 		{
       
  4993 		_LIT(KRconsPattern, "rcons*");
       
  4994 		_LIT(KVt100Pattern, "vt100*");
       
  4995 		Complete(!((name.MatchF(KRconsPattern) == 0) || (name.MatchF(KVt100Pattern) == 0)));
       
  4996 		}
       
  4997 	else if (iIsNull)
       
  4998 		{
       
  4999 		_LIT(KNullPattern, "nullcons*");
       
  5000 		Complete(!(name.MatchF(KNullPattern) == 0));
       
  5001 		}
       
  5002 	else if (iVerbose)
       
  5003 		{
       
  5004 		TSize size;
       
  5005 		LeaveIfErr(Stdout().GetScreenSize(size), _L("Couldn't get screen size"));
       
  5006 		Printf(_L("Name: %S\r\n"), &name);
       
  5007 		Printf(_L("Size: %dx%d\r\n"), size.iWidth, size.iHeight);
       
  5008 		}
       
  5009 	else
       
  5010 		{
       
  5011 		Write(name);
       
  5012 		}
       
  5013 	CleanupStack::PopAndDestroy(&console);
       
  5014 	}
       
  5015 
       
  5016 void CCmdConsole::OptionsL(RCommandOptionList& aOptions)
       
  5017 	{
       
  5018 	_LIT(KOptIsRemote, "remote");
       
  5019 	_LIT(KOptIsNull, "null");
       
  5020 
       
  5021 	aOptions.AppendBoolL(iVerbose, KOptVerbose);
       
  5022 	aOptions.AppendBoolL(iIsRemote, KOptIsRemote);
       
  5023 	aOptions.AppendBoolL(iIsNull, KOptIsNull);
       
  5024 	}
       
  5025 
       
  5026 
       
  5027 //
       
  5028 // CCmdPcons.
       
  5029 //
       
  5030 
       
  5031 CCommandBase* CCmdPcons::NewLC()
       
  5032 	{
       
  5033 	CCmdPcons* self = new(ELeave) CCmdPcons();
       
  5034 	CleanupStack::PushL(self);
       
  5035 	self->BaseConstructL();
       
  5036 	return self;
       
  5037 	}
       
  5038 
       
  5039 CCmdPcons::~CCmdPcons()
       
  5040 	{
       
  5041 	delete iName;
       
  5042 	delete iCommand;
       
  5043 	delete iCommandArgs;
       
  5044 	}
       
  5045 
       
  5046 CCmdPcons::CCmdPcons()
       
  5047 	{
       
  5048 	}
       
  5049 
       
  5050 const TDesC& CCmdPcons::Name() const
       
  5051 	{
       
  5052 	_LIT(KName, "pcons");
       
  5053 	return KName;
       
  5054 	}
       
  5055 
       
  5056 _LIT(KNone, "-");
       
  5057 _LIT(KDefaultCommand, "fshell");
       
  5058 _LIT(KCurrentConsMarker, "(*)");
       
  5059 _LIT(KNew, "new");
       
  5060 _LIT(KExisting, "existing");
       
  5061 
       
  5062 void CCmdPcons::DoRunL()
       
  5063 	{
       
  5064 	RIoPersistentConsole pcons;
       
  5065 	CleanupClosePushL(pcons);
       
  5066 	if ((iOperation != ENew) && (iOperation != EStart) && iCommand)
       
  5067 		{
       
  5068 		TPtrC operation(iArguments.AsString(&iOperation));
       
  5069 		PrintWarning(_L("'command' argument being ignored for operation %S"), &operation);
       
  5070 		}
       
  5071 	
       
  5072 	switch (iOperation)
       
  5073 		{
       
  5074 	case EList:
       
  5075 		{
       
  5076 		RIoConsole thisCons;
       
  5077 		LeaveIfErr(thisCons.Open(IoSession(), Stdout()), _L("Couldn't open handle to current console"));
       
  5078 		CleanupClosePushL(thisCons);
       
  5079 
       
  5080 		const TDesC& matchStr = iName ? *iName : KMatchAll();
       
  5081 		TInt foundHandle;
       
  5082 		TName foundName;
       
  5083 		TBool foundCurrent = EFalse;
       
  5084 		
       
  5085 		CTextBuffer* buf = CTextBuffer::NewLC(0x20);
       
  5086 		_LIT(KColumnHeadings, "Name\tCreator\tReader\tWriter\r\n");
       
  5087 		buf->AppendL(KColumnHeadings);
       
  5088 		TInt err = IoSession().FindFirstHandle(RIoHandle::EConsole, matchStr, foundHandle, foundName);
       
  5089 		TInt count = 0;
       
  5090 		while (err==KErrNone)
       
  5091 			{
       
  5092 			RIoPersistentConsole pcons;
       
  5093 			pcons.OpenFoundHandleL(IoSession(), foundHandle);
       
  5094 			CleanupClosePushL(pcons);
       
  5095 			if (pcons.IsTypeL(RIoHandle::EPersistentConsole))
       
  5096 				{
       
  5097 				count++;
       
  5098 				buf->AppendL(foundName);
       
  5099 				if (pcons.EqualsL(thisCons))
       
  5100 					{
       
  5101 					buf->AppendL(KCurrentConsMarker);
       
  5102 					foundCurrent = ETrue;
       
  5103 					}
       
  5104 				buf->AppendL(KTab);
       
  5105 				
       
  5106 					{
       
  5107 					TThreadId creatorId = pcons.GetCreatorL();
       
  5108 					RThread creator;
       
  5109 					if (creator.Open(creatorId)==KErrNone)
       
  5110 						{
       
  5111 						TFullName name;
       
  5112 						LtkUtils::GetFriendlyThreadName(creator, name);
       
  5113 						creator.Close();
       
  5114 						buf->AppendL(name);
       
  5115 						buf->AppendL(KTab);
       
  5116 						}
       
  5117 					else
       
  5118 						{
       
  5119 						buf->AppendFormatL(_L("(%Ld)\t"), creatorId.Id());
       
  5120 						}
       
  5121 					}
       
  5122 				
       
  5123 					{
       
  5124 					TName readerName;
       
  5125 					TName writerName;
       
  5126 					pcons.GetAttachedReaderAndWriterNamesL(readerName, writerName);
       
  5127 					
       
  5128 					buf->AppendL(readerName.Length() ? readerName : KNone());
       
  5129 					buf->AppendL(KTab);
       
  5130 					buf->AppendL(writerName.Length() ? writerName : KNone());
       
  5131 					buf->AppendL(KNewLine);
       
  5132 					}
       
  5133 				}			
       
  5134 			CleanupStack::PopAndDestroy(&pcons);
       
  5135 			err = IoSession().FindNextHandle(foundHandle, foundName);
       
  5136 			}
       
  5137 		if (err!=KErrNotFound) User::LeaveIfError(err);
       
  5138 		if (count)
       
  5139 			{
       
  5140 			CTextFormatter* tf = CTextFormatter::NewLC(Stdout());
       
  5141 			// if this fails, it's probably just because the console is too narrow; just print it
       
  5142 			// untabulated in this case.
       
  5143 			TRAP(err, tf->TabulateL(0, 2, buf->Descriptor()));
       
  5144 			if (err==KErrNone)
       
  5145 				{
       
  5146 				Write(tf->Descriptor());
       
  5147 				}
       
  5148 			else
       
  5149 				{
       
  5150 				Write(buf->Descriptor());
       
  5151 				}
       
  5152 			CleanupStack::PopAndDestroy(tf);
       
  5153 			}
       
  5154 		if (foundCurrent)
       
  5155 			{
       
  5156 			Write(KCurrentConsMarker);
       
  5157 			Write(_L(" indicates current console"));
       
  5158 			}
       
  5159 		CleanupStack::PopAndDestroy(2, &thisCons);
       
  5160 		break;
       
  5161 		}
       
  5162 	case EStart:
       
  5163 		{
       
  5164 		if (!iName)
       
  5165 			{
       
  5166 			PrintError(KErrArgument, _L("A persistent console name to start to must be specified"));
       
  5167 			DisplayHelp();
       
  5168 			break;
       
  5169 			}
       
  5170 		TInt err = pcons.OpenByName(IoSession(), *iName);
       
  5171 		const TDesC* newOrExisting;
       
  5172 		if (err==KErrNone)
       
  5173 			{
       
  5174 			newOrExisting = &KExisting;
       
  5175 			if (iCommand)
       
  5176 				{
       
  5177 				PrintWarning(_L("Ignoring 'command' argument as console already exists."));
       
  5178 				}
       
  5179 			}
       
  5180 		else
       
  5181 			{
       
  5182 			newOrExisting = &KNew;
       
  5183 			CreateL(pcons);
       
  5184 			}
       
  5185 		AttachL(pcons, *newOrExisting, ETrue);
       
  5186 		break;
       
  5187 		}
       
  5188 	case EConnect:
       
  5189 		{
       
  5190 		if (!iName)
       
  5191 			{
       
  5192 			PrintError(KErrArgument, _L("A persistent console name to connect to must be specified"));
       
  5193 			DisplayHelp();
       
  5194 			break;
       
  5195 			}
       
  5196 		LeaveIfErr(pcons.OpenByName(IoSession(), *iName), _L("Couldn't open persistent console with name %S"), iName);
       
  5197 		AttachL(pcons, KExisting, EFalse);
       
  5198 		break;
       
  5199 		}
       
  5200 	case EDisconnect:
       
  5201 		{
       
  5202 		if (iName)
       
  5203 			{
       
  5204 			LeaveIfErr(pcons.OpenByName(IoSession(), *iName), _L("Couldn't open persistent console with name %S"), iName);
       
  5205 			}
       
  5206 		else
       
  5207 			{
       
  5208 			LeaveIfErr(pcons.Open(IoSession(), Stdout()), _L("Couldn't open handle to console"));
       
  5209 			if (!pcons.IsTypeL(RIoHandle::EPersistentConsole))
       
  5210 				{
       
  5211 				LeaveIfErr(KErrNotSupported, _L("Not connected to a persistent console"));
       
  5212 				}
       
  5213 			}
       
  5214 		pcons.DetachReader();
       
  5215 		pcons.DetachWriter();
       
  5216 		break;
       
  5217 		}
       
  5218 	case ENew:
       
  5219 		{
       
  5220 		if (!iName)
       
  5221 			{
       
  5222 			PrintError(KErrArgument, _L("A name for the new persistent console must be specified"));
       
  5223 			DisplayHelp();
       
  5224 			break;
       
  5225 			}
       
  5226 		CreateL(pcons);
       
  5227 		break;
       
  5228 		}
       
  5229 		}
       
  5230 	CleanupStack::PopAndDestroy(&pcons);
       
  5231 	}
       
  5232 	
       
  5233 void CCmdPcons::CreateL(RIoPersistentConsole& aPcons)
       
  5234 	{
       
  5235 	const TDesC& command(iCommand ? *iCommand : KDefaultCommand());
       
  5236 	const TDesC& args(iCommandArgs ? *iCommandArgs : KNullDesC());
       
  5237 
       
  5238 	LeaveIfErr(aPcons.Create(IoSession(), *iName, *iName), _L("Could not create persistent console '%S'"), iName);
       
  5239 
       
  5240 	RChildProcess proc;
       
  5241 	TRAPL(proc.CreateL(command, args, IoSession(), aPcons, &Env()), _L("Could not create process %S"), &command);
       
  5242 	
       
  5243 	proc.Detach();
       
  5244 	proc.Close();
       
  5245 	}
       
  5246 	
       
  5247 TInt CCmdPcons::DoAttach(RIoPersistentConsole& aPcons, RIoConsole& aNew, RIoPersistentConsole::TCloseBehaviour aOnClose)
       
  5248 	{
       
  5249 	TInt err = aPcons.AttachWriter(aNew, aOnClose);
       
  5250 	if (err==KErrNone)
       
  5251 		{
       
  5252 		err = aPcons.AttachReader(aNew, aOnClose);
       
  5253 		if (err!=KErrNone)
       
  5254 			{
       
  5255 			aPcons.DetachWriter();
       
  5256 			}
       
  5257 		}
       
  5258 	return err;
       
  5259 	}
       
  5260 	
       
  5261 void CCmdPcons::AttachL(RIoPersistentConsole& aPcons, const TDesC& aNewOrExisting, TBool aForce)
       
  5262 	{
       
  5263 	RIoConsole thisCons;
       
  5264 	LeaveIfErr(thisCons.Open(IoSession(), Stdout()), _L("Couldn't open handle to current console"));
       
  5265 	CleanupClosePushL(thisCons);
       
  5266 	
       
  5267 	TBool usingExistingConsole = !ConsoleImplementation();
       
  5268 	RIoPersistentConsole::TCloseBehaviour onClose = 
       
  5269 			usingExistingConsole ? 
       
  5270 			RIoPersistentConsole::EDetachOnHandleClose : 
       
  5271 			RIoPersistentConsole::EKeepAttachedOnHandleClose;
       
  5272 	
       
  5273 	if (usingExistingConsole)
       
  5274 		{
       
  5275 		Printf(_L("pcons: connecting to %S console %S.\r\n"), &aNewOrExisting, iName);
       
  5276 		}
       
  5277 	TInt err = DoAttach(aPcons, thisCons, onClose);
       
  5278 	if ((err == KErrInUse) && (aForce))
       
  5279 		{
       
  5280 		if (iVerbose) Printf(_L("Detaching existing connection from %S"), iName);
       
  5281 		aPcons.DetachReader();
       
  5282 		aPcons.DetachWriter();
       
  5283 		err = DoAttach(aPcons, thisCons, onClose);
       
  5284 		}
       
  5285 	LeaveIfErr(err, _L("Could not connect to persistent console %S"), iName);
       
  5286 	
       
  5287 	if (usingExistingConsole)
       
  5288 		{
       
  5289 		// we've not been a custom console implementation
       
  5290 		// so we need to wait until the persistent side is disconnected.
       
  5291 		TRequestStatus readerDetach;
       
  5292 		TRequestStatus writerDetach;
       
  5293 		aPcons.NotifyReaderDetach(readerDetach);
       
  5294 		aPcons.NotifyWriterDetach(writerDetach);
       
  5295 		User::WaitForRequest(readerDetach);
       
  5296 		if (iVerbose) Printf(_L("Persistent console reader detached; waiting for writer to detach\r\n"));
       
  5297 		User::WaitForRequest(writerDetach);		
       
  5298 		if (iVerbose) Printf(_L("Persistent console writer detached\r\n"));
       
  5299 		if (Stdout().GetCursorPosL().iX != 0) Printf(KNewLine);
       
  5300 		Printf(_L("pcons: disconnected from %S\r\n"), iName);
       
  5301 		}
       
  5302 
       
  5303 	CleanupStack::PopAndDestroy(&thisCons);		
       
  5304 	}
       
  5305 
       
  5306 void CCmdPcons::ArgumentsL(RCommandArgumentList& aArguments)
       
  5307 	{
       
  5308 	_LIT(KOperationName, "operation");
       
  5309 	_LIT(KNameName, "name");
       
  5310 	_LIT(KArgCommand, "command");
       
  5311 	_LIT(KCommandArgs, "command_args");
       
  5312 
       
  5313 	aArguments.AppendEnumL((TInt&)iOperation, KOperationName);
       
  5314 	aArguments.AppendStringL(iName, KNameName);
       
  5315 	aArguments.AppendStringL(iCommand, KArgCommand);
       
  5316 	aArguments.AppendStringL(iCommandArgs, KCommandArgs);
       
  5317 	}
       
  5318 
       
  5319 void CCmdPcons::OptionsL(RCommandOptionList& aOptions)
       
  5320 	{
       
  5321 	aOptions.AppendBoolL(iVerbose, KOptVerbose);
       
  5322 	}
       
  5323 
       
  5324 
       
  5325 //
       
  5326 // CCmdIoInfo.
       
  5327 //
       
  5328 
       
  5329 CCommandBase* CCmdIoInfo::NewLC()
       
  5330 	{
       
  5331 	CCmdIoInfo* self = new(ELeave) CCmdIoInfo();
       
  5332 	CleanupStack::PushL(self);
       
  5333 	self->BaseConstructL();
       
  5334 	return self;
       
  5335 	}
       
  5336 
       
  5337 CCmdIoInfo::~CCmdIoInfo()
       
  5338 	{
       
  5339 	delete iMatchString;
       
  5340 	}
       
  5341 
       
  5342 CCmdIoInfo::CCmdIoInfo()
       
  5343 	{
       
  5344 	}
       
  5345 
       
  5346 const TDesC& CCmdIoInfo::Name() const
       
  5347 	{
       
  5348 	_LIT(KName, "ioinfo");
       
  5349 	return KName;
       
  5350 	}
       
  5351 
       
  5352 void CCmdIoInfo::DoRunL()
       
  5353 	{
       
  5354 	TInt foundHandle;				
       
  5355 	TName name;
       
  5356 	TInt err = IoSession().FindFirstHandle(iObjectType, iMatchString ? *iMatchString : KMatchAll(), foundHandle, name);
       
  5357 	while (err==KErrNone)
       
  5358 		{
       
  5359 		Write(name);
       
  5360 		Write(KNewLine);
       
  5361 		err = IoSession().FindNextHandle(foundHandle, name);
       
  5362 		}
       
  5363 	if (err!=KErrNotFound) User::LeaveIfError(err);
       
  5364 	}
       
  5365 
       
  5366 void CCmdIoInfo::ArgumentsL(RCommandArgumentList& aArguments)
       
  5367 	{
       
  5368 	_LIT(KObjectType, "object_type");
       
  5369 	aArguments.AppendEnumL((TInt&)iObjectType, KObjectType);
       
  5370 	}
       
  5371 
       
  5372 void CCmdIoInfo::OptionsL(RCommandOptionList& aOptions)
       
  5373 	{
       
  5374 	_LIT(KMatch, "match");
       
  5375 	aOptions.AppendStringL(iMatchString, KMatch);
       
  5376 	}
       
  5377 
       
  5378 
       
  5379 //
       
  5380 // CCmdReattach.
       
  5381 //
       
  5382 
       
  5383 CCommandBase* CCmdReattach::NewLC()
       
  5384 	{
       
  5385 	CCmdReattach* self = new(ELeave) CCmdReattach();
       
  5386 	CleanupStack::PushL(self);
       
  5387 	self->BaseConstructL();
       
  5388 	return self;
       
  5389 	}
       
  5390 
       
  5391 CCmdReattach::~CCmdReattach()
       
  5392 	{
       
  5393 	delete iJobSpec;
       
  5394 	delete iStdinEndPointName;
       
  5395 	delete iStdoutEndPointName;
       
  5396 	delete iStderrEndPointName;
       
  5397 	}
       
  5398 
       
  5399 CCmdReattach::CCmdReattach() : CCommandBase(EManualComplete)
       
  5400 	{
       
  5401 	}
       
  5402 
       
  5403 const TDesC& CCmdReattach::Name() const
       
  5404 	{
       
  5405 	_LIT(KName, "reattach");
       
  5406 	return KName;
       
  5407 	}
       
  5408 
       
  5409 void CCmdReattach::OpenEndPointLC(RIoEndPoint& aEndPoint, const TDesC& aName)
       
  5410 	{
       
  5411 	TInt foundHandle;
       
  5412 	TName name;
       
  5413 	LeaveIfErr(IoSession().FindFirstHandle(RIoHandle::EEndPoint, aName, foundHandle, name), _L("Couldn't find and end point named \"%S\""), &aName);
       
  5414 	aEndPoint.OpenFoundHandleL(IoSession(), foundHandle);
       
  5415 	CleanupClosePushL(aEndPoint);
       
  5416 	}
       
  5417 
       
  5418 void CCmdReattach::DoRunL()
       
  5419 	{
       
  5420 	TInt jobId = -1;
       
  5421 	ParseJobSpecL(*iJobSpec, jobId);
       
  5422 	RIoEndPoint stdinEndPoint;
       
  5423 	RIoEndPoint stdoutEndPoint;
       
  5424 	RIoEndPoint stderrEndPoint;
       
  5425 	if (iStdinEndPointName)
       
  5426 		{
       
  5427 		OpenEndPointLC(stdinEndPoint, *iStdinEndPointName);
       
  5428 		}
       
  5429 	else
       
  5430 		{
       
  5431 		static_cast<RIoNull&>(stdinEndPoint).CreateL(IoSession());
       
  5432 		CleanupClosePushL(stdinEndPoint);
       
  5433 		}
       
  5434 	TInt numCleanupPushes = 1;
       
  5435 	if (iStdoutEndPointName)
       
  5436 		{
       
  5437 		OpenEndPointLC(stdoutEndPoint, *iStdoutEndPointName);
       
  5438 		++numCleanupPushes;
       
  5439 		}
       
  5440 	else
       
  5441 		{
       
  5442 		stdoutEndPoint = stdinEndPoint;
       
  5443 		}
       
  5444 	if (iStderrEndPointName)
       
  5445 		{
       
  5446 		OpenEndPointLC(stderrEndPoint, *iStderrEndPointName);
       
  5447 		++numCleanupPushes;
       
  5448 		}
       
  5449 	else
       
  5450 		{
       
  5451 		stderrEndPoint = stdoutEndPoint;
       
  5452 		}
       
  5453 
       
  5454 	gShell->ClaimJobsLockLC();
       
  5455 	CJob* job = gShell->Job(jobId);
       
  5456 	if (job)
       
  5457 		{
       
  5458 		TInt err = job->Reattach(stdinEndPoint, stdoutEndPoint, stderrEndPoint);
       
  5459 		CleanupStack::PopAndDestroy(); // jobs lock.
       
  5460 		if (err)
       
  5461 			{
       
  5462 			Complete(err, _L("Couldn't reattach job %S"), iJobSpec);
       
  5463 			}
       
  5464 		else
       
  5465 			{
       
  5466 			Complete();
       
  5467 			}
       
  5468 		}
       
  5469 	else
       
  5470 		{
       
  5471 		CleanupStack::PopAndDestroy(); // jobs lock.
       
  5472 		Complete(KErrNotFound, _L("Job %S not found"), iJobSpec);
       
  5473 		}
       
  5474 
       
  5475 	CleanupStack::PopAndDestroy(numCleanupPushes);
       
  5476 	}
       
  5477 
       
  5478 void CCmdReattach::ArgumentsL(RCommandArgumentList& aArguments)
       
  5479 	{
       
  5480 	_LIT(KArgJobSpec, "job");
       
  5481 	_LIT(KArgStdinEndPointName, "stdin");
       
  5482 	_LIT(KArgStdoutEndPointName, "stdout");
       
  5483 	_LIT(KArgStderrEndPointName, "stderr");
       
  5484 
       
  5485 	aArguments.AppendStringL(iJobSpec, KArgJobSpec);
       
  5486 	aArguments.AppendStringL(iStdinEndPointName, KArgStdinEndPointName);
       
  5487 	aArguments.AppendStringL(iStdoutEndPointName, KArgStdoutEndPointName);
       
  5488 	aArguments.AppendStringL(iStderrEndPointName, KArgStderrEndPointName);
       
  5489 	}
       
  5490 
       
  5491 
       
  5492 //
       
  5493 // CCmdDisown.
       
  5494 //
       
  5495 
       
  5496 CCommandBase* CCmdDisown::NewLC()
       
  5497 	{
       
  5498 	CCmdDisown* self = new(ELeave) CCmdDisown();
       
  5499 	CleanupStack::PushL(self);
       
  5500 	self->BaseConstructL();
       
  5501 	return self;
       
  5502 	}
       
  5503 
       
  5504 CCmdDisown::~CCmdDisown()
       
  5505 	{
       
  5506 	delete iJobSpec;
       
  5507 	}
       
  5508 
       
  5509 CCmdDisown::CCmdDisown() : CCommandBase(EManualComplete)
       
  5510 	{
       
  5511 	}
       
  5512 
       
  5513 const TDesC& CCmdDisown::Name() const
       
  5514 	{
       
  5515 	_LIT(KName, "disown");
       
  5516 	return KName;
       
  5517 	}
       
  5518 
       
  5519 void CCmdDisown::DoRunL()
       
  5520 	{
       
  5521 	TInt jobId = -1;
       
  5522 	ParseJobSpecL(*iJobSpec, jobId);
       
  5523 	gShell->ClaimJobsLockLC();
       
  5524 	TInt err = gShell->DisownJob(jobId);
       
  5525 	CleanupStack::PopAndDestroy(); // jobs lock.
       
  5526 	if (err)
       
  5527 		{
       
  5528 		Complete(err, _L("Couldn't disown job %S"), iJobSpec);
       
  5529 		}
       
  5530 	else
       
  5531 		{
       
  5532 		Complete();
       
  5533 		}
       
  5534 	}
       
  5535 
       
  5536 void CCmdDisown::ArgumentsL(RCommandArgumentList& aArguments)
       
  5537 	{
       
  5538 	_LIT(KArgJobSpec, "job_spec");
       
  5539 	aArguments.AppendStringL(iJobSpec, KArgJobSpec);
       
  5540 	}
       
  5541 
       
  5542 
       
  5543 //
       
  5544 // CCmdDebugPort
       
  5545 //
       
  5546 
       
  5547 CCommandBase* CCmdDebugPort::NewLC()
       
  5548 	{
       
  5549 	CCmdDebugPort* self = new(ELeave) CCmdDebugPort();
       
  5550 	CleanupStack::PushL(self);
       
  5551 	self->BaseConstructL();
       
  5552 	return self;
       
  5553 	}
       
  5554 
       
  5555 CCmdDebugPort::~CCmdDebugPort()
       
  5556 	{
       
  5557 	}
       
  5558 
       
  5559 CCmdDebugPort::CCmdDebugPort()
       
  5560 	{
       
  5561 	}
       
  5562 
       
  5563 const TDesC& CCmdDebugPort::Name() const
       
  5564 	{
       
  5565 	_LIT(KName, "debugport");
       
  5566 	return KName;
       
  5567 	}
       
  5568 
       
  5569 void CCmdDebugPort::DoRunL()
       
  5570 	{
       
  5571 	if (iArguments.IsPresent(0))
       
  5572 		{
       
  5573 		if (iForce)
       
  5574 			{
       
  5575 			LoadMemoryAccessL();
       
  5576 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  5577 			LeaveIfErr(iMemAccess.SetDebugPort(iPort), _L("Couldn't set debug port"));
       
  5578 #endif
       
  5579 			}
       
  5580 		else
       
  5581 			{
       
  5582 			LeaveIfErr(HAL::Set(HAL::EDebugPort, iPort), _L("Couldn't set debug port (Try --force)."));
       
  5583 			}
       
  5584 		}
       
  5585 	else
       
  5586 		{
       
  5587 		TInt debugport = 0;
       
  5588 		TInt err = HAL::Get(HAL::EDebugPort, debugport);
       
  5589 		LeaveIfErr(err, _L("Couldn't read debug port."));
       
  5590 		Printf(_L("Debug port: %d\r\n"), debugport);
       
  5591 		}
       
  5592 	}
       
  5593 
       
  5594 void CCmdDebugPort::ArgumentsL(RCommandArgumentList& aArguments)
       
  5595 	{
       
  5596 	_LIT(KArgPort, "port");
       
  5597 	aArguments.AppendIntL(iPort, KArgPort);
       
  5598 	}
       
  5599 
       
  5600 void CCmdDebugPort::OptionsL(RCommandOptionList& aOptions)
       
  5601 	{
       
  5602 	_LIT(KOptForce, "force");
       
  5603 	aOptions.AppendBoolL(iForce, KOptForce);
       
  5604 	}
       
  5605 
       
  5606 
       
  5607 //
       
  5608 // CCmdRom
       
  5609 //
       
  5610 
       
  5611 CCommandBase* CCmdRom::NewLC()
       
  5612 	{
       
  5613 	CCmdRom* self = new(ELeave) CCmdRom();
       
  5614 	CleanupStack::PushL(self);
       
  5615 	self->BaseConstructL();
       
  5616 	return self;
       
  5617 	}
       
  5618 
       
  5619 CCmdRom::~CCmdRom()
       
  5620 	{
       
  5621 	delete iBuffer;
       
  5622 	}
       
  5623 
       
  5624 CCmdRom::CCmdRom()
       
  5625 	{
       
  5626 	}
       
  5627 
       
  5628 const TDesC& CCmdRom::Name() const
       
  5629 	{
       
  5630 	_LIT(KName, "rom");
       
  5631 	return KName;
       
  5632 	}
       
  5633 
       
  5634 void CCmdRom::PrintIntL(TInt32 aInt32, const TDesC& aLabel, const TDesC& aDescription)
       
  5635 	{
       
  5636 	_LIT(KFormat, "%S:\t%d (0x%08x)\t%S\r\n");
       
  5637 	iBuffer->AppendFormatL(KFormat, &aLabel, aInt32, aInt32, &aDescription);
       
  5638 	}
       
  5639 
       
  5640 void CCmdRom::PrintIntL(TInt64 aInt64, const TDesC& aLabel, const TDesC& aDescription)
       
  5641 	{
       
  5642 	_LIT(KFormat, "%S:\t%Ld\t%S\r\n");
       
  5643 	iBuffer->AppendFormatL(KFormat, &aLabel, aInt64, &aDescription);
       
  5644 	}
       
  5645 
       
  5646 void CCmdRom::PrintUintL(TUint32 aUint32, const TDesC& aLabel, const TDesC& aDescription)
       
  5647 	{
       
  5648 	_LIT(KFormat, "%S:\t%u (0x%08x)\t%S\r\n");
       
  5649 	iBuffer->AppendFormatL(KFormat, &aLabel, aUint32, aUint32, &aDescription);
       
  5650 	}
       
  5651 
       
  5652 void CCmdRom::PrintUintL(TUint64 aUint64, const TDesC& aLabel, const TDesC& aDescription)
       
  5653 	{
       
  5654 	_LIT(KFormat, "%S:\t%Lu\t%S\r\n");
       
  5655 	iBuffer->AppendFormatL(KFormat, &aLabel, aUint64, &aDescription);
       
  5656 	}
       
  5657 
       
  5658 void CCmdRom::PrintAddressL(TLinAddr aAddress, const TDesC& aLabel, const TDesC& aDescription)
       
  5659 	{
       
  5660 	_LIT(KFormat, "%S:\t0x%08x\t%S\r\n");
       
  5661 	iBuffer->AppendFormatL(KFormat, &aLabel, aAddress, &aDescription, &aDescription);
       
  5662 	}
       
  5663 
       
  5664 void CCmdRom::PrintSizeL(TInt32 aSize, const TDesC& aLabel, const TDesC& aDescription)
       
  5665 	{
       
  5666 	if (iHumanReadable)
       
  5667 		{
       
  5668 		_LIT(KFormat1, "%S:\t");
       
  5669 		iBuffer->AppendFormatL(KFormat1, &aLabel);
       
  5670 		iBuffer->AppendHumanReadableSizeL((TInt)aSize, EUnaligned);
       
  5671 		_LIT(KFormat2, "\t%S\r\n");
       
  5672 		iBuffer->AppendFormatL(KFormat2, &aDescription);
       
  5673 		}
       
  5674 	else
       
  5675 		{
       
  5676 		PrintIntL(aSize, aLabel, aDescription);
       
  5677 		}
       
  5678 	}
       
  5679 
       
  5680 void CCmdRom::PrintTimeL(TInt64 aTime, const TDesC& aLabel, const TDesC& aDescription)
       
  5681 	{
       
  5682 	if (iHumanReadable)
       
  5683 		{
       
  5684 		TTime time(aTime);
       
  5685 		TDateTime dateTime(time.DateTime());
       
  5686 		_LIT(KFormat, "%S:\t%+02d/%+02d/%+04d %+02d:%+02d:%+02d.%+06d\t%S\r\n");
       
  5687 		iBuffer->AppendFormatL(KFormat, &aLabel, dateTime.Day() + 1, dateTime.Month() + 1, dateTime.Year(), dateTime.Hour(), dateTime.Minute(), dateTime.Second(), dateTime.MicroSecond(), &aDescription);
       
  5688 		}
       
  5689 	else
       
  5690 		{
       
  5691 		PrintIntL(aTime, aLabel, aDescription);
       
  5692 		}
       
  5693 	}
       
  5694 
       
  5695 void CCmdRom::PrintVersionL(TVersion aVersion, const TDesC& aLabel, const TDesC& aDescription)
       
  5696 	{
       
  5697 	_LIT(KFormat, "%S:\t%d.%d (build %d)\t%S\r\n");
       
  5698 	iBuffer->AppendFormatL(KFormat, &aLabel, aVersion.iMajor, aVersion.iMinor, aVersion.iBuild, &aDescription);
       
  5699 	}
       
  5700 
       
  5701 void CCmdRom::DoRunL()
       
  5702 	{
       
  5703 #ifdef __WINS__
       
  5704 	LeaveIfErr(KErrNotSupported, _L("This command is not supported on the emulator"));
       
  5705 #endif
       
  5706 
       
  5707 	TRomHeader* header = (TRomHeader*)UserSvr::RomHeaderAddress();
       
  5708 
       
  5709 	iBuffer = CTextBuffer::NewL(0x100);
       
  5710 
       
  5711 	PrintVersionL(header->iVersion, _L("iVersion"), _L("The ROM version number."));
       
  5712 	PrintTimeL(header->iTime, _L("iTime"), _L("The time and date that the ROM image was built."));
       
  5713 	PrintSizeL(header->iRomSize, _L("iRomSize"), _L("The size of the ROM image. This includes the second section for sectioned ROMs."));
       
  5714 	PrintUintL((TUint32)header->iCheckSum, _L("iCheckSum"), _L("A computed constant that causes the 32-bit checksum of the image to equal the value specified by the \"romchecksum\" keyword."));
       
  5715 	PrintUintL(header->iKernelConfigFlags, _L("iKernelConfigFlags"), _L("Contains the flags that define the security options in force. See TKernelConfigFlags for details."));
       
  5716 
       
  5717 	if (iVerbose)
       
  5718 		{
       
  5719 		PrintAddressL(header->iRestartVector, _L("iRestartVector"), _L("The restart vector"));
       
  5720 		PrintUintL(header->iTimeHi, _L("iTimeHi"), _L("The high order 32 bits of the ROM image build time and date."));
       
  5721 		PrintAddressL(header->iRomBase, _L("iRomBase"), _L("The virtual address of the base of the ROM."));
       
  5722 		PrintAddressL(header->iRomRootDirectoryList, _L("iRomRootDirectoryList"), _L("The virtual address of the TRomRootDirectoryList structure."));
       
  5723 		PrintAddressL(header->iKernDataAddress, _L("iKernDataAddress"), _L("The virtual address of kernel data, when in RAM."));
       
  5724 		PrintAddressL(header->iKernelLimit, _L("iKernelLimit"), _L("The virtual address of the top of the kernel region, when in RAM."));
       
  5725 		PrintAddressL(header->iPrimaryFile, _L("iPrimaryFile"), _L("The virtual address of the primarys ROM file image header."));
       
  5726 		PrintAddressL(header->iSecondaryFile, _L("iSecondaryFile"), _L("The virtual address of the secondarys ROM file image header."));
       
  5727 		PrintUintL(header->iHardware, _L("iHardware"), _L("A unique number identifying the hardware for which this ROM image has been built. Note that this is only used for testing purposes."));
       
  5728 		PrintIntL(header->iLanguage, _L("iLanguage"), _L("A bitmask identifying which of the languages are supported by the ROM image, as specified by the \"languages\" keyword. Note that this is only used for testing purposes."));
       
  5729 		PrintAddressL(header->iRomExceptionSearchTable, _L("iRomExceptionSearchTable"), _L("The virtual address of the TRomExceptionSearchTable structure."));
       
  5730 		PrintUintL(header->iRomHeaderSize, _L("iRomHeaderSize"), _L("Current size of ROM header (previously iUnused3). If value is 0x69966996 then header size is 0x100."));
       
  5731 		PrintAddressL(header->iRomSectionHeader, _L("iRomSectionHeader"), _L("The virtual address of the ROM section header, if the ROM is sectioned. See TRomSectionHeader for details."));
       
  5732 		PrintSizeL(header->iTotalSvDataSize, _L("iTotalSvDataSize"), _L("The total supervisor data size, i.e. the amount of memory mapped for the kernel data chunk."));
       
  5733 		PrintAddressL(header->iVariantFile, _L("iVariantFile"), _L("The virtual address of the TRomEntry for the Variant file. See TRomEntry for details."));
       
  5734 		PrintAddressL(header->iExtensionFile, _L("iExtensionFile"), _L("The virtual address of TRomEntry for the first extension file, if it exists. If there is more than one extension, then the next extension field in the extensions TRomImageHeader points to the TRomEntry for that next extension. See TRomEntry and TRomImageHeader for details."));
       
  5735 		PrintAddressL(header->iRelocInfo, _L("iRelocInfo"), _L("The old position of the kernel trace mask, see iTraceMask."));
       
  5736 		PrintUintL(header->iOldTraceMask, _L("iOldTraceMask"), _L("Current size of ROM header (previously iUnused3). If value is 0x69966996 then header size is 0x100."));
       
  5737 		PrintAddressL(header->iUserDataAddress, _L("iUserDataAddress"), _L("The virtual address of the user data area."));
       
  5738 		PrintSizeL(header->iTotalUserDataSize, _L("iTotalUserDataSize"), _L("The total size of the user data."));
       
  5739 		PrintUintL(header->iDebugPort, _L("iDebugPort"), _L("A value that is interpreted by the Bootstrap and kernel as the debug port to be used."));
       
  5740 		PrintUintL(header->iCompressionType, _L("iCompressionType"), _L("The type of compression used for the image. This is a UID, or 0 if there is no compression."));
       
  5741 		PrintSizeL(header->iCompressedSize, _L("iCompressedSize"), _L("The size of the image after compression."));
       
  5742 		PrintSizeL(header->iUncompressedSize, _L("iUncompressedSize"), _L("The size of the image before compression."));
       
  5743 		PrintUintL(header->iDisabledCapabilities[0], _L("iDisabledCapabilities[0]"), _L("Disabled capabilities."));
       
  5744 		PrintUintL(header->iDisabledCapabilities[1], _L("iDisabledCapabilities[1]"), _L("Disabled capabilities."));
       
  5745 		for (TInt i = 0; i < TRomHeader::KNumTraceMask; ++i)
       
  5746 			{
       
  5747 			TBuf<16> buf;
       
  5748 			_LIT(KFormat, "iTraceMask[%d]");
       
  5749 			buf.Format(KFormat, i);
       
  5750 			PrintUintL(header->iTraceMask[i], buf, _L("The initial value for one of the kernel trace masks."));
       
  5751 			}
       
  5752 #ifdef FSHELL_BTRACE_SUPPORT
       
  5753 		for (TInt i = 0; i < 9; ++i)
       
  5754 			{
       
  5755 			TBuf<32> buf;
       
  5756 			_LIT(KFormat, "iInitialBTraceFilter[%d]");
       
  5757 			buf.Format(KFormat, i);
       
  5758 			PrintUintL(header->iInitialBTraceFilter[i], buf, _L("Initial value for a btrace filter."));
       
  5759 			}
       
  5760 		PrintSizeL(header->iInitialBTraceBuffer, _L("iInitialBTraceBuffer"), _L("The initial btrace buffer size."));
       
  5761 		PrintUintL((TUint32)header->iInitialBTraceMode, _L("iInitialBTraceMode"), _L("The initial btrace mode."));
       
  5762 #endif
       
  5763 #ifndef FSHELL_9_1_SUPPORT
       
  5764 		PrintIntL((TInt32)header->iPageableRomStart, _L("iPageableRomStart"), _L("An offset, in bytes from ROM start, for the start of the pageable ROM area."));
       
  5765 		PrintSizeL(header->iPageableRomSize, _L("iPageableRomSize"), _L("The size of the pageable ROM area."));
       
  5766 		PrintIntL((TInt32)header->iRomPageIndex, _L("iRomPageIndex"), _L("An offset in bytes from ROM start, for the page index. (Array of SRomPageInfo objects.)"));
       
  5767 		PrintUintL((TUint32)header->iDemandPagingConfig.iMinPages, _L("iMinPages"), _L("The minimum number of demand pages."));
       
  5768 		PrintUintL((TUint32)header->iDemandPagingConfig.iMaxPages, _L("iMinPages"), _L("The maximum number of demand pages."));
       
  5769 		PrintUintL((TUint32)header->iDemandPagingConfig.iYoungOldRatio, _L("iYoungOldRatio"), _L("The young / old ration of demand pages."));
       
  5770 #endif
       
  5771 		}
       
  5772 
       
  5773 	CTextFormatter* formatter = CTextFormatter::NewLC(Stdout());
       
  5774 	formatter->TabulateL(0, 2, iBuffer->Descriptor(), EWrapLastColumn);
       
  5775 	formatter->Write();
       
  5776 	CleanupStack::PopAndDestroy(formatter);
       
  5777 	}
       
  5778 
       
  5779 void CCmdRom::OptionsL(RCommandOptionList& aOptions)
       
  5780 	{
       
  5781 	aOptions.AppendBoolL(iVerbose, KOptVerbose);
       
  5782 	aOptions.AppendBoolL(iHumanReadable, KOptHuman);
       
  5783 	}
       
  5784 
       
  5785 CCommandBase* CCmdWhich::NewLC()
       
  5786 	{
       
  5787 	CCmdWhich* self = new(ELeave) CCmdWhich();
       
  5788 	CleanupStack::PushL(self);
       
  5789 	self->BaseConstructL();
       
  5790 	return self;
       
  5791 	}
       
  5792 
       
  5793 CCmdWhich::~CCmdWhich()
       
  5794 	{
       
  5795 	delete iCommand;
       
  5796 	}
       
  5797 
       
  5798 CCmdWhich::CCmdWhich()
       
  5799 	{
       
  5800 	}
       
  5801 
       
  5802 const TDesC& CCmdWhich::Name() const
       
  5803 	{
       
  5804 	_LIT(KName, "which");
       
  5805 	return KName;
       
  5806 	}
       
  5807 	
       
  5808 void CCmdWhich::ArgumentsL(RCommandArgumentList& aArguments)
       
  5809 	{
       
  5810 	_LIT(KCommand, "command");
       
  5811 	aArguments.AppendStringL(iCommand, KCommand);
       
  5812 	}
       
  5813 	
       
  5814 void CCmdWhich::DoRunL()
       
  5815 	{
       
  5816 	LtkUtils::RLtkBuf desc;
       
  5817 	CleanupClosePushL(desc);
       
  5818 	TRAPD(err, gShell->CommandFactory().GetCommandInfoL(*iCommand, desc));
       
  5819 	_LIT(KFmt, "%S: %S\r\n");
       
  5820 	_LIT(KFailed, "%S not a built-in or an exe in \\sys\\bin\r\n");
       
  5821 	if (err == KErrNotFound)
       
  5822 		{
       
  5823 		// Must be an external non-fshell exe
       
  5824 		TFindFile find(FsL());
       
  5825 		TInt err = find.FindByDir(*iCommand, _L("Y:\\sys\\bin\\")); // Specify Y: to prevent it from checking the session path first
       
  5826 		if (err == KErrNone)
       
  5827 			{
       
  5828 			Printf(KFmt, iCommand, &find.File());
       
  5829 			}
       
  5830 		else if (err == KErrPermissionDenied)
       
  5831 			{
       
  5832 			// FShell must be built without AllFiles - try just creating it and getting its path
       
  5833 			RProcess proc;
       
  5834 			err = proc.Create(*iCommand, KNullDesC);
       
  5835 			if (err == KErrNone)
       
  5836 				{
       
  5837 				TFileName path = proc.FileName();
       
  5838 				Printf(KFmt, iCommand, &path);
       
  5839 				proc.Kill(KErrCancel);
       
  5840 				proc.Close();
       
  5841 				}
       
  5842 			else
       
  5843 				{
       
  5844 				Printf(KFailed, iCommand);
       
  5845 				}
       
  5846 			}
       
  5847 		else
       
  5848 			{
       
  5849 			Printf(KFailed, iCommand);
       
  5850 			}
       
  5851 		}
       
  5852 	else
       
  5853 		{
       
  5854 		LeaveIfErr(err, _L("Error finding command %S"), iCommand);
       
  5855 		Printf(_L("%S: %S\r\n"), iCommand, &desc);
       
  5856 		}
       
  5857 	CleanupStack::PopAndDestroy(&desc);
       
  5858 	}
       
  5859 
       
  5860 CCommandBase* CCmdTee::NewLC()
       
  5861 	{
       
  5862 	CCmdTee* self = new(ELeave) CCmdTee();
       
  5863 	CleanupStack::PushL(self);
       
  5864 	self->BaseConstructL();
       
  5865 	return self;
       
  5866 	}
       
  5867 
       
  5868 CCmdTee::~CCmdTee()
       
  5869 	{
       
  5870 	iFileNames.Close();
       
  5871 	for (TInt i = 0; i < iFiles.Count(); i++)
       
  5872 		{
       
  5873 		iFiles[i].Close();
       
  5874 		}
       
  5875 	iFiles.Close();
       
  5876 	}
       
  5877 
       
  5878 CCmdTee::CCmdTee()
       
  5879 	{
       
  5880 	}
       
  5881 
       
  5882 const TDesC& CCmdTee::Name() const
       
  5883 	{
       
  5884 	_LIT(KName, "tee");
       
  5885 	return KName;
       
  5886 	}
       
  5887 
       
  5888 void CCmdTee::ArgumentsL(RCommandArgumentList& aArguments)
       
  5889 	{
       
  5890 	aArguments.AppendFileNameL(iFileNames, _L("file"));
       
  5891 	}
       
  5892 
       
  5893 void CCmdTee::OptionsL(RCommandOptionList& aOptions)
       
  5894 	{
       
  5895 	aOptions.AppendBoolL(iAppend, _L("append"));
       
  5896 	aOptions.AppendBoolL(iRdebug, _L("rdebug"));
       
  5897 	}
       
  5898 	
       
  5899 void CCmdTee::DoRunL()
       
  5900 	{
       
  5901 	TUint filemode = EFileWrite | EFileShareAny | EFileStream; // Allow someone else to read it while we're writing
       
  5902 	for (TInt i = 0; i < iFileNames.Count(); i++)
       
  5903 		{
       
  5904 		RFile f;
       
  5905 		TInt err = KErrNone;
       
  5906 		if (iAppend)
       
  5907 			{
       
  5908 			err = f.Open(FsL(), iFileNames[i], filemode); // First try append
       
  5909 			if (err) err = f.Create(FsL(), iFileNames[i], filemode); // Then just create
       
  5910 			TInt whatDoesThisArgumentForSeekEndDoDoesAnybodyKnow = 0;
       
  5911 			f.Seek(ESeekEnd, whatDoesThisArgumentForSeekEndDoDoesAnybodyKnow);
       
  5912 			}
       
  5913 		else
       
  5914 			{
       
  5915 			err = f.Replace(FsL(), iFileNames[i], filemode);
       
  5916 			}
       
  5917 		LeaveIfErr(err, _L("Couldn't open file %S"), &iFileNames[i]);
       
  5918 		iFiles.AppendL(f);
       
  5919 		}
       
  5920 	
       
  5921 	RBuf readBuf;
       
  5922 	CleanupClosePushL(readBuf);
       
  5923 	readBuf.CreateL(512);
       
  5924 	LtkUtils::RLtkBuf8 writeBuf;
       
  5925 	CleanupClosePushL(writeBuf);
       
  5926 	writeBuf.CreateL(readBuf.MaxSize() * 4);
       
  5927 	Stdin().SetReadModeL(RIoReadHandle::EOneOrMore);
       
  5928 	while (Stdin().Read(readBuf) == KErrNone)
       
  5929 		{
       
  5930 		writeBuf.CopyAsUtf8L(readBuf);
       
  5931 		for (TInt i = 0; i < iFiles.Count(); i++)
       
  5932 			{
       
  5933 			TInt err = iFiles[i].Write(writeBuf);
       
  5934 			if (err) PrintWarning(_L("Failed to write to file %d: %d"), i, err);
       
  5935 			}
       
  5936 		if (iRdebug) LtkUtils::RawPrint(writeBuf);
       
  5937 		Stdout().Write(readBuf);
       
  5938 		}
       
  5939 	
       
  5940 	CleanupStack::PopAndDestroy(2, &readBuf);
       
  5941 	}
       
  5942 
       
  5943 CCommandBase* CCmdError::NewLC()
       
  5944 	{
       
  5945 	CCmdError* self = new(ELeave) CCmdError();
       
  5946 	CleanupStack::PushL(self);
       
  5947 	self->BaseConstructL();
       
  5948 	return self;
       
  5949 	}
       
  5950 
       
  5951 CCmdError::~CCmdError()
       
  5952 	{
       
  5953 	delete iErrorText;
       
  5954 	}
       
  5955 
       
  5956 CCmdError::CCmdError()
       
  5957 	: iErrorVal(KErrAbort)
       
  5958 	{
       
  5959 	}
       
  5960 
       
  5961 const TDesC& CCmdError::Name() const
       
  5962 	{
       
  5963 	_LIT(KName, "error");
       
  5964 	return KName;
       
  5965 	}
       
  5966 
       
  5967 void CCmdError::DoRunL()
       
  5968 	{
       
  5969 	if (iErrorVal >= 0) LeaveIfErr(KErrArgument, _L("Non-negative value %d passed to error command"), iErrorVal);
       
  5970 
       
  5971 	if (iErrorText)
       
  5972 		{
       
  5973 		LeaveIfErr(iErrorVal, *iErrorText);
       
  5974 		}
       
  5975 	else
       
  5976 		{
       
  5977 		User::Leave(iErrorVal);
       
  5978 		}
       
  5979 	}
       
  5980 
       
  5981 void CCmdError::ArgumentsL(RCommandArgumentList& aArguments)
       
  5982 	{
       
  5983 	aArguments.AppendIntL(iErrorVal, _L("error-number"));
       
  5984 	aArguments.AppendStringL(iErrorText, _L("text"));
       
  5985 	}
       
  5986 
       
  5987 	
       
  5988 //
       
  5989 // CCmdReboot
       
  5990 //
       
  5991 
       
  5992 CCommandBase* CCmdReboot::NewLC()
       
  5993 	{
       
  5994 	CCmdReboot* self = new(ELeave) CCmdReboot();
       
  5995 	CleanupStack::PushL(self);
       
  5996 	self->BaseConstructL();
       
  5997 	return self;
       
  5998 	}
       
  5999 
       
  6000 CCmdReboot::~CCmdReboot()
       
  6001 	{
       
  6002 	}
       
  6003 
       
  6004 CCmdReboot::CCmdReboot()
       
  6005 	{
       
  6006 	}
       
  6007 
       
  6008 const TDesC& CCmdReboot::Name() const
       
  6009 	{
       
  6010 	_LIT(KName, "reboot");
       
  6011 	return KName;
       
  6012 	}
       
  6013 
       
  6014 void CCmdReboot::DoRunL()
       
  6015 	{
       
  6016 	if (!iArguments.IsPresent(0))
       
  6017 		{
       
  6018 		iReason = 0x40000000; // On most baseports this represents 'soft reboot'
       
  6019 		}
       
  6020 
       
  6021 	LoadMemoryAccessL();
       
  6022 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
  6023 	iMemAccess.Reboot(iReason);
       
  6024 #endif
       
  6025 	}
       
  6026 
       
  6027 void CCmdReboot::ArgumentsL(RCommandArgumentList& aArguments)
       
  6028 	{
       
  6029 	_LIT(KArgReason, "reason");
       
  6030 	aArguments.AppendUintL(iReason, KArgReason);
       
  6031 	}
       
  6032 
       
  6033 	
       
  6034 //
       
  6035 // CCmdForEach
       
  6036 //
       
  6037 
       
  6038 CCommandBase* CCmdForEach::NewLC()
       
  6039 	{
       
  6040 	CCmdForEach* self = new(ELeave) CCmdForEach();
       
  6041 	CleanupStack::PushL(self);
       
  6042 	self->BaseConstructL();
       
  6043 	return self;
       
  6044 	}
       
  6045 
       
  6046 CCmdForEach::~CCmdForEach()
       
  6047 	{
       
  6048 	iDir.Close();
       
  6049 	}
       
  6050 
       
  6051 CCmdForEach::CCmdForEach()
       
  6052 	: iDirName(TFileName2::EDirectory)
       
  6053 	{
       
  6054 	}
       
  6055 
       
  6056 void CCmdForEach::DoNextL(TBool aFirstTime)
       
  6057 	{
       
  6058 	if (!aFirstTime) Env().RemoveAll(); // Remove all only does locals
       
  6059 
       
  6060 	delete iScriptData;
       
  6061 	iScriptData = NULL;
       
  6062 	delete iParser;
       
  6063 	iParser = NULL;
       
  6064 
       
  6065 	TEntry entry;
       
  6066 	TInt err = iDir.Read(entry);
       
  6067 	if (err == KErrEof)
       
  6068 		{
       
  6069 		Complete(iLastError);
       
  6070 		}
       
  6071 	else
       
  6072 		{
       
  6073 		LeaveIfErr(err, _L("Couldn't read directory '%S'"), &iDirName);
       
  6074 		// Update the first element of the argument array with the full name of the file we just found.
       
  6075 		TFileName2 fileName(iDirName);
       
  6076 		fileName.AppendComponentL(entry.iName, TFileName2::EFile);
       
  6077 
       
  6078 		RPointerArray<HBufC> extraArgs;
       
  6079 		LtkUtils::CleanupResetAndDestroyPushL(extraArgs);
       
  6080 		extraArgs.AppendL(fileName.AllocLC());
       
  6081 		CleanupStack::Pop(); // hbufc
       
  6082 
       
  6083 		TIoHandleSet ioHandles(IoSession(), Stdin(), Stdout(), Stderr());
       
  6084 		TBool helpPrinted;
       
  6085 		iScriptData = CShell::ReadScriptL(iFileName, iArgs, Env(), FsL(), ioHandles, helpPrinted, &extraArgs);
       
  6086 		CleanupStack::PopAndDestroy(&extraArgs);
       
  6087 		if (helpPrinted)
       
  6088 			{
       
  6089 			Complete();
       
  6090 			}
       
  6091 		else
       
  6092 			{
       
  6093 			TUint mode = CParser::EExportLineNumbers;
       
  6094 			if (iKeepGoing)
       
  6095 				{
       
  6096 				mode |= CParser::EKeepGoing;
       
  6097 				}
       
  6098 			iParser = CParser::NewL(mode, *iScriptData, IoSession(), Stdin(), Stdout(), Stderr(), Env(), gShell->CommandFactory(), this);
       
  6099 			iParser->Start();
       
  6100 			}
       
  6101 		}
       
  6102 	}
       
  6103 
       
  6104 const TDesC& CCmdForEach::Name() const
       
  6105 	{
       
  6106 	_LIT(KName, "foreach");
       
  6107 	return KName;
       
  6108 	}
       
  6109 
       
  6110 void CCmdForEach::DoRunL()
       
  6111 	{
       
  6112 	LeaveIfFileNotFound(iDirName);
       
  6113 	if (!iDirName.IsDirL(FsL()))
       
  6114 		{
       
  6115 		LeaveIfErr(KErrArgument, _L("'%S' is not a directory"), &iDirName);
       
  6116 		}
       
  6117 	LeaveIfErr(iDir.Open(FsL(), iDirName, KEntryAttNormal | KEntryAttDir), _L("Couldn't open directory '%S'"), &iDirName);
       
  6118 
       
  6119 	DoNextL(ETrue);
       
  6120 	}
       
  6121 
       
  6122 void CCmdForEach::ArgumentsL(RCommandArgumentList& aArguments)
       
  6123 	{
       
  6124 	_LIT(KArgDirectoryName, "directory_name");
       
  6125 	aArguments.AppendFileNameL(iDirName, KArgDirectoryName);
       
  6126 
       
  6127 	CCmdSource::ArgumentsL(aArguments);
       
  6128 	}
       
  6129 
       
  6130 void CCmdForEach::HandleParserComplete(CParser&, const TError& aError)
       
  6131 	{
       
  6132 	TInt err = aError.Error();
       
  6133 	if (err < 0)
       
  6134 		{
       
  6135 		aError.Report();
       
  6136 		PrintError(err, _L("Aborted \"%S\" at line %d"), &aError.ScriptFileName(), aError.ScriptLineNumber());
       
  6137 		iLastError = err;
       
  6138 		}
       
  6139 
       
  6140 	if ((err < 0) && !iKeepGoing)
       
  6141 		{
       
  6142 		Complete(iLastError);
       
  6143 		}
       
  6144 	else
       
  6145 		{
       
  6146 		TRAPD(err, DoNextL());
       
  6147 		if (err)
       
  6148 			{
       
  6149 			Complete(err);
       
  6150 			}
       
  6151 		}
       
  6152 	}