genericopenlibs/cstdlib/USTLIB/POSIXIF.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Client interface to the CPosixServer
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "POSIXIF.H"
       
    19 #include "LTIME.H"
       
    20 #include "LPOSIX.H"
       
    21 #include <fcntl.h>
       
    22 #include <sys/errno.h>
       
    23 #include <sys/serial.h>
       
    24 #include <sys/wait.h>
       
    25 
       
    26 
       
    27 #ifdef _DEBUG
       
    28 #define DebugPrint	RDebug::Print
       
    29 #else
       
    30 inline void DebugPrint(const TDesC&, ...) {}
       
    31 #endif
       
    32 
       
    33 // RPosixSession
       
    34 //
       
    35 // The message protocol is to pass the errno pointer in p[0] and a pointer to a PosixParams
       
    36 // in p[1]. The result is written back into the PosixParams.retval field.
       
    37 
       
    38 int RPosixSession::Request(TInt aFunction, int& anErrno, PosixParams& aParams) const
       
    39 	{
       
    40 	return SendReceive(aFunction,TIpcArgs(&anErrno,&aParams));
       
    41 	}
       
    42 
       
    43 void RPosixSession::Request(TInt aFunction, int& anErrno, PosixParams& aParams, TRequestStatus& aStatus) const
       
    44 	{
       
    45 	SendReceive(aFunction,TIpcArgs(&anErrno,&aParams),aStatus);	// asynchronous request
       
    46 	}
       
    47 
       
    48 void RPosixSession::Request(TInt aFunction, const TIpcArgs& aArg,TRequestStatus &aStatus) const
       
    49 	{
       
    50 	RSessionBase::SendReceive(aFunction,aArg,aStatus);
       
    51 	}
       
    52 TInt RPosixSession::Request(TInt aFunction, const TIpcArgs& aArg) const
       
    53 	{
       
    54 	return RSessionBase::SendReceive(aFunction,aArg);
       
    55 	}
       
    56 
       
    57 TVersion RPosixSession::Version()
       
    58 	{
       
    59 	return TVersion(KCPosixMajorVersionNumber,KCPosixMinorVersionNumber,0);
       
    60 	}
       
    61 
       
    62 TInt RPosixSession::Connect (TDesC& aServerName)
       
    63 	{
       
    64 	TVersion version=Version();
       
    65 	return CreateSession(aServerName,version,1+3);	// 3 extra message slots for pipes
       
    66 	}
       
    67 
       
    68 TInt RPosixSession::Connect ()
       
    69 	{
       
    70 	TBuf<80> serverName;
       
    71 	PosixServerName(serverName);
       
    72 	return CreateSession(serverName,Version(),1);
       
    73 	}
       
    74 
       
    75 // CPosixServer support functions exported from ESTLIB.DLL
       
    76 
       
    77 #if defined(__WINS__)
       
    78 
       
    79 // simple scheme to provide pretend processes on WINS
       
    80 
       
    81 extern "C" void getcwd(char*,int);
       
    82 typedef void (*FUNC)();
       
    83 
       
    84 static int id=1;
       
    85 EXPORT_C void NewProcessId () 
       
    86 	{ 
       
    87 	id += 10; 
       
    88 	}
       
    89 
       
    90 static FUNC procFn;
       
    91 EXPORT_C void NextProcessFn (TAny* aFn)
       
    92 	{
       
    93 	procFn=(FUNC)aFn;
       
    94 	}
       
    95 
       
    96 TInt threadhelper (TAny* aFn)
       
    97 	{
       
    98 	CTrapCleanup::New();
       
    99 	FUNC f=(FUNC)aFn;
       
   100 	(*f)();
       
   101 	return 0;
       
   102 	}
       
   103 TInt processhelper (TAny*)
       
   104 	{
       
   105 	// Do the MCRT0.OBJ things straight away
       
   106 	SpawnPosixServerThread();
       
   107 	char wd[80];
       
   108 	getcwd(wd, sizeof(wd));		// connect to CPosixServer
       
   109 	return threadhelper(procFn);
       
   110 	}
       
   111 #endif // __WINS__
       
   112 _LIT(SERVER_FORMAT,"Posix-%d");
       
   113 _LIT(SERVER_MATCH, "Posix-*");
       
   114 
       
   115 EXPORT_C void PosixServerName(TDes& aBuffer)
       
   116 //
       
   117 // Construct the name of the CPosixServer for this process
       
   118 //
       
   119 	{
       
   120 	TProcessId id=RProcess().Id();
       
   121 	aBuffer.Format(SERVER_FORMAT,*REINTERPRET_CAST(int*,&id));
       
   122 	}
       
   123 
       
   124 struct rendezvous 
       
   125 	{
       
   126 	RThread iCaller;
       
   127 	TRequestStatus* iStatus;
       
   128 	};
       
   129 
       
   130 EXPORT_C TInt SpawnPosixServerThread ()
       
   131 //
       
   132 // Try to start a PosixServer thread, assuming there isn't one already
       
   133 //
       
   134 	{
       
   135 	RPosixSession probe;
       
   136 	TInt err=probe.Connect();
       
   137 	probe.Close();
       
   138 	if (err==KErrNone)
       
   139 		return KErrNone;	// server already exists
       
   140 	TBuf<80> serverName;
       
   141 	PosixServerName(serverName);
       
   142 	TRequestStatus status(KRequestPending);
       
   143 	struct rendezvous rv;
       
   144 	rv.iCaller.Duplicate(RThread(),EOwnerProcess);
       
   145 	rv.iStatus=&status;
       
   146 	RThread server;
       
   147 	err=server.Create(serverName,CPosixServer::ThreadFunction,0x2000,NULL,&rv);
       
   148 	if (err==KErrNone) 
       
   149 		{
       
   150 		server.Resume();
       
   151 		User::WaitForRequest(status);
       
   152 		err=status.Int();
       
   153 		server.Close();
       
   154 		}
       
   155 	rv.iCaller.Close();
       
   156 	return err;
       
   157 	}
       
   158 
       
   159 EXPORT_C TInt InstallPosixServerActiveObject (TInt aPriority)
       
   160 	{
       
   161 	TRAPD(err, CPosixServer::InitL(aPriority));
       
   162 	return err;
       
   163 	}
       
   164 
       
   165 void CPosixServer::InitL(TInt aPriority)
       
   166 //
       
   167 // Construct and install a CPosixServer active object
       
   168 //
       
   169 	{
       
   170 	CPosixServer *pS=new(ELeave) CPosixServer(aPriority);
       
   171 	CleanupStack::PushL(pS);
       
   172 	TBuf<80> serverName;
       
   173 	PosixServerName(serverName);
       
   174 
       
   175 	User::LeaveIfError(pS->iFs.Connect());
       
   176 
       
   177 	pS->iFids.InitL();
       
   178 
       
   179 	// search for parent process
       
   180 	pS->FindParentL();
       
   181 
       
   182 	// set up default fids
       
   183 	pS->DefaultConsoleL();
       
   184 
       
   185 	DebugPrint(_L("Starting CPosixServer\n"));
       
   186 	pS->StartL(serverName);
       
   187 	CleanupStack::Pop(pS);
       
   188 // Leave pS on the clean up stack for the calling routine to clean up normally on 
       
   189 // Active Scheduler shutdown or in a failure case where  the scheduler does not 
       
   190 // start due to an error.
       
   191 
       
   192 	}
       
   193 
       
   194 // CPosixServer
       
   195 
       
   196 CPosixServer::CPosixServer(TInt aPriority)
       
   197 	: CServer2(aPriority)
       
   198 	{
       
   199 	__DECLARE_NAME(_S("CPosixServer"));
       
   200 	}
       
   201 
       
   202 TInt CPosixServer::ThreadFunction(TAny* aPtr)
       
   203 //
       
   204 // Create and run an active scheduler containing a CPosixServer
       
   205 //
       
   206 	{
       
   207 	CTrapCleanup* TheTrapCleanup=CTrapCleanup::New();
       
   208 
       
   209 	RLibrary stdlib;
       
   210 	stdlib.Load(_L("estlib"));	// workaround for RAM-loaded EXE calling RAM-loaded DLL
       
   211 
       
   212 	struct rendezvous* rvp = (struct rendezvous *)aPtr;
       
   213 	TInt ret=KErrNone;
       
   214 	// start scheduler and server
       
   215 	CActiveScheduler *pA=new CActiveScheduler;
       
   216 	if (pA!=NULL) 
       
   217 		{
       
   218 		CActiveScheduler::Install(pA);
       
   219 		ret=InstallPosixServerActiveObject();
       
   220 		}
       
   221 	// signal to the caller that we've started (or failed!)
       
   222 	rvp->iCaller.RequestComplete(rvp->iStatus,ret);
       
   223 	if (ret==KErrNone)
       
   224 		{
       
   225 		// start fielding requests from clients
       
   226 		CActiveScheduler::Start();
       
   227 		}
       
   228 	// finished
       
   229 	delete TheTrapCleanup;
       
   230 	return(KErrNone);
       
   231 	}
       
   232 
       
   233 CSession2* CPosixServer::NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const
       
   234 	{
       
   235 	TBool r=User::QueryVersionSupported(RPosixSession::Version(),aVersion);
       
   236 	if (!r)
       
   237 		User::Leave(KErrNotSupported);
       
   238 
       
   239 	RProcess clientProcess;
       
   240 	RThread clientThread;
       
   241 	User::LeaveIfError(aMessage.Client(clientThread));
       
   242 	CleanupClosePushL(clientThread);
       
   243 	User::LeaveIfError(clientThread.Process(clientProcess));
       
   244 	TProcessId clientId = clientProcess.Id();
       
   245 	clientProcess.Close();
       
   246 	CleanupStack::PopAndDestroy(1); //close thread
       
   247 
       
   248 	if (clientId!=RProcess().Id())
       
   249 		{
       
   250 		// A thread in a different process
       
   251 		if (iChildren==0)
       
   252 			User::Leave(KErrNotReady);	// quick rejection
       
   253 
       
   254 		// We need an explicit CONST_CAST so that the CPosixRequest objects have a
       
   255 		// mutable reference to the CPosixServer which holds the shared data structures
       
   256 		return new(ELeave) CPosixIPCSession(CONST_CAST(CPosixServer&,*this));
       
   257 		}
       
   258 	// A thread in the same process
       
   259 	return new(ELeave) CPosixSession(CONST_CAST(CPosixServer&,*this));
       
   260 	}
       
   261 
       
   262 void CPosixServer::ServerPanic (TPosixServerPanic aPanic)
       
   263 	{
       
   264 	_LIT(KPosixServerPanic, "Posix server");
       
   265 	User::Panic(KPosixServerPanic,aPanic);
       
   266 	}
       
   267 
       
   268 void CPosixServer::FindParentL()
       
   269 	{
       
   270 	TFullName parent;
       
   271 	TPosixIPCPid pid;
       
   272 	TPosixIPCReply reply;
       
   273 
       
   274 	TProcessId id=RProcess().Id();
       
   275 	pid = *REINTERPRET_CAST(TUint*,&id);	// my process id
       
   276 
       
   277 	TFindServer posixservers(SERVER_MATCH);
       
   278 	while (posixservers.Next(parent)==KErrNone)
       
   279 		{
       
   280 		DebugPrint(_L("Are you my mother, %S?"), &parent);
       
   281 		if (iParent.Connect(parent)!=KErrNone)
       
   282 			continue;
       
   283 		if (iParent.Request(PMAreYouMyMother,TIpcArgs(&pid, &reply))!=KErrNone)
       
   284 			{
       
   285 			iParent.Close();
       
   286 			continue;
       
   287 			}
       
   288 
       
   289 		// found parent
       
   290 		DebugPrint(_L("Found parent process %S"), &parent);
       
   291 
       
   292 		// Create any pipes that might be required
       
   293 		TUint mask=reply().iPipeMask;
       
   294 		CPipeChildDesc* pipes[3];
       
   295 		TInt i=0;
       
   296 		for (i=0; i<3; i++, mask>>=1)
       
   297 			{
       
   298 			pipes[i]=0;
       
   299 			if (mask&1)
       
   300 				{
       
   301 				CPipeChildDesc* pipe=new(ELeave) CPipeChildDesc(i,iParent);
       
   302 				pipes[i]=pipe;
       
   303 				pipe->PushLC();
       
   304 				}
       
   305 			}
       
   306 
       
   307 		// organise the necessary descriptors
       
   308 		TPtr env=HBufC::NewLC(reply().iEnvironmentSize)->Des();
       
   309 		TPtr cwd=HBufC::NewLC(reply().iWorkingDirectorySize)->Des();
       
   310 
       
   311 		// get the data from parent
       
   312 		TInt err=iParent.Request(PMHelloMum, TIpcArgs(&pid, &env, &cwd));
       
   313 		
       
   314 		DebugPrint(_L("Environment string: %S"), &env);
       
   315 		DebugPrint(_L("Working directory: %S"), &cwd);
       
   316 		
       
   317 		if(err!=KErrNone)
       
   318 			{
       
   319 			DebugPrint(_L("I've become an orphan"));
       
   320 			// release stuff
       
   321 			iParent.Close();
       
   322 			User::Leave(err);
       
   323 			break;
       
   324 			}
       
   325 		// apply to our process
       
   326 		iEnv.ConstructL(reply().iVarCount,env);
       
   327 		err=iFs.SetSessionPath(cwd);
       
   328 		User::LeaveIfError(err);
       
   329 
       
   330 		// free up the temporary descriptors
       
   331 		CleanupStack::PopAndDestroy(2);
       
   332 
       
   333 		// Attach the pipes!
       
   334 		for (i=0; i<3; i++)
       
   335 			{
       
   336 			iFids.Attach(i, pipes[i]);
       
   337 			if (pipes[i]!=0)
       
   338 				CleanupStack::Pop();
       
   339 			}
       
   340 		return;
       
   341 		}
       
   342 	DebugPrint(_L("Posix-%d is a top-level process"), pid());
       
   343 	User::LeaveIfError(PosixFilesystem::SetDefaultDir(iFs));
       
   344 	}
       
   345 
       
   346 int CPosixServer::POpen3(PosixParams* aParams, int& anErrno)
       
   347 	{
       
   348 	TInt err=KErrNoMemory;
       
   349 	//coverity[alloc_fn]
       
   350 	//coverity[assign]
       
   351 	CPosixProcess* proc= new CPosixProcess(*this);
       
   352 	if (proc!=0)
       
   353 		{
       
   354 		//coverity[leave_without_push]
       
   355 		err=iFids.Reserve(aParams->pint);
       
   356 		if (err==KErrNone)
       
   357 			{
       
   358 			TRAP(err,proc->POpen3L(aParams));
       
   359 			}
       
   360 		if (err==KErrNone)
       
   361 			{
       
   362 			DebugPrint(_L("POpen3 created process %d"), proc->iPid);
       
   363 			proc->iNextProcess=iChildren;
       
   364 			iChildren=proc;
       
   365 			return (int)proc->iPid;	// success
       
   366 			}
       
   367 		delete proc;
       
   368 		iFids.Detach(aParams->pint);
       
   369 		}
       
   370 	return MapError(err, anErrno);
       
   371 	}
       
   372 
       
   373 CPosixRequest* CPosixServer::Waiters() 
       
   374 	{
       
   375 	CPosixRequest* waiters=iWaitAnyQueue;
       
   376 	iWaitAnyQueue=0;
       
   377 	return waiters;
       
   378 	}
       
   379 
       
   380 // CPosixSession
       
   381 //
       
   382 // Each local thread gets one of these
       
   383 
       
   384 CPosixSession::CPosixSession(CPosixServer& aServer)
       
   385 	: iActive(aServer)
       
   386 	{
       
   387 	CActiveScheduler::Add(&iActive);
       
   388 	__DECLARE_NAME(_S("CPosixSession"));
       
   389 	}
       
   390 
       
   391 void CPosixSession::ServiceL(const RMessage2& aMessage)
       
   392 	{
       
   393 	iActive.Service(aMessage);
       
   394 	}
       
   395 
       
   396 // CPosixRequest
       
   397 //
       
   398 // An active object contained within the Session that handles the deferred completion
       
   399 // of asynchronous functions (e.g. read & write).
       
   400 
       
   401 CPosixRequest::CPosixRequest(CPosixServer& aServer)
       
   402 	: CActive(EPriorityStandard), iServer(aServer), iPtr(0,0)
       
   403 	{
       
   404 //	iFile=0;
       
   405 //	iNewF=0;
       
   406 //	iNewFid=0;
       
   407 	}
       
   408 
       
   409 void CPosixRequest::Service(const RMessage2& aMessage)
       
   410 //
       
   411 // The message protocol is to pass the errno pointer in p[0] and a pointer to a PosixParams
       
   412 // in p[1]. The result is written back into the PosixParams.retval field.
       
   413 //
       
   414 	{
       
   415 	if (aMessage.Function() == PMcancel)
       
   416 		{
       
   417 		Cancel();						// Cancel in the active scheduler
       
   418 		if (iFile)
       
   419 			EndAsynch(KErrCancel);		// Complete the cancelled request & clean up
       
   420 		aMessage.Complete(KErrNone);
       
   421 		return;
       
   422 		}
       
   423 
       
   424 	if (iFile!=0)
       
   425 		{
       
   426 		aMessage.Complete(KErrInUse);
       
   427 		return;
       
   428 		}
       
   429 	int& anErrno=*REINTERPRET_CAST(int*,CONST_CAST(TAny*,aMessage.Ptr0()));
       
   430 	PosixParams* params=REINTERPRET_CAST(PosixParams*,CONST_CAST(TAny*,aMessage.Ptr1()));
       
   431 	switch (aMessage.Function())
       
   432 		{
       
   433 
       
   434 	// Asynchronous functions need queuing, active objects etc.
       
   435 
       
   436 	case PMread:
       
   437 	case PMwrite:
       
   438 	case PMsendto:
       
   439 	case PMrecvfrom:
       
   440 		iPtr.Set((TText8*)params->ptr[0], params->len[0], params->len[0]);
       
   441 		// and fall through...
       
   442 	case PMfsync:
       
   443 	case PMconnect:
       
   444 	case PMshutdown:
       
   445 		{
       
   446 		TInt err=Fids().Asynch(params->fid,iFile);
       
   447 		if (!err)
       
   448 			{
       
   449 			QueueAsynch(aMessage);	// start operation or queue if busy
       
   450 			return;					// deferred completion through RunL
       
   451 			}
       
   452 		params->ret=MapError(err,anErrno);
       
   453 		}
       
   454 		break;
       
   455 
       
   456 	case PMaccept:
       
   457 		{
       
   458 		TInt err=Fids().Asynch(params->fid,iFile);
       
   459 		if (!err)
       
   460 			{
       
   461 			iNewF=0;
       
   462 			iNewFid=Fids().Reserve();	// reserve a fid for the accepted socket
       
   463 			err=iNewFid;
       
   464 			if (iNewFid>=0)
       
   465 				{
       
   466 				QueueAsynch(aMessage);	// start operation or queue if busy
       
   467 				return;					// deferred completion through RunL
       
   468 				}
       
   469 			}
       
   470 		params->ret=MapError(err,anErrno);
       
   471 		}
       
   472 		break;
       
   473 
       
   474 	case PMioctl:
       
   475 	case PMioctlN:
       
   476 		{
       
   477 		TInt err=Fids().Asynch(params->fid,iFile);
       
   478 		if (!err)
       
   479 			{
       
   480 			QueueAsynch(aMessage);	// start operation or queue if busy
       
   481 			return;					// deferred completion through RunL
       
   482 			}
       
   483 
       
   484 		aMessage.Complete(err);	// Different calling convention
       
   485 		return;
       
   486 		}
       
   487 
       
   488 	// complicated synchronous functions which might do their own completion
       
   489 
       
   490 	case PMwaitpid:
       
   491 		{
       
   492 		// check for invalid options or if an invalid pid is specified. currently there is no 
       
   493 		// support for process group id's so a pid less than -1 or equal to 0 is invalid
       
   494 		if((params->pint[1] & ~(WNOHANG|WUNTRACED))|| (params->pint[0] < -1) || (params->pint[0] ==0))
       
   495 			{
       
   496 			anErrno=EINVAL;
       
   497 			params->ret=-1;
       
   498 			break;
       
   499 			}
       
   500 		if (params->pint[0]==-1 && params->pint[1]==0)	/* wait for any child */
       
   501 			{
       
   502 			iMessage=aMessage;
       
   503 			iServer.WaitForAnyChild(this);
       
   504 			return; // wait for the next child to die
       
   505 			}
       
   506 		CPosixProcess* child=iServer.Child(params->pint[0]);
       
   507 		if (child!=0)
       
   508 			{
       
   509 			if (child->IsAlive())
       
   510 				{
       
   511 				if (params->pint[1]&1)	/* WNOHANG */
       
   512 					{
       
   513 					params->ret=0;
       
   514 					break;
       
   515 					}
       
   516 				iMessage=aMessage;
       
   517 				child->Queue(this);
       
   518 				return;	// wait for the child to die
       
   519 				}
       
   520 			params->pint[0]=child->iExitReason;
       
   521 			params->ret=child->iPid;
       
   522 			iServer.Release(child);
       
   523 			}
       
   524 		else
       
   525 			{
       
   526 			anErrno=ECHILD;
       
   527 			params->ret=-1;
       
   528 			}
       
   529 		}
       
   530 		break;
       
   531 
       
   532 	// simple synchronous functions
       
   533 
       
   534 	case PMdup:
       
   535 		params->ret=Fids().dup(params->fid,anErrno);
       
   536 		break;
       
   537 	case PMdup2:
       
   538 		params->ret=Fids().dup2(params->fid,params->pint[0],anErrno);
       
   539 		break;
       
   540 	case PMopen: 
       
   541 		{
       
   542 		const wchar_t* name = params->cwptr[0];
       
   543 		if	((L'C' == name[0]) && (L'O' == name[1]) && (L'M' == name[2]) && (L':' == name[4]) && ((name[3] >= L'1') && (name[3] <= L'9')) ||
       
   544 			(L'I' == name[0]) && (L'R' == name[1]) && (L'C' == name[2]) && (L'O' == name[3]) && (L'M' == name[4]) && (L':' == name[6]) && ((name[5] >= L'1') && (name[5] <= L'9')))
       
   545 			params->ret=Fids().open(params->cwptr[0],params->pint[0],params->pint[1],anErrno,Cs());
       
   546 		else
       
   547 			params->ret=Fids().open(params->cwptr[0],params->pint[0],params->pint[1],anErrno,Fs());
       
   548 
       
   549 		}
       
   550 		break;
       
   551 	case PMclose: 
       
   552 		params->ret=Fids().userclose(params->fid,anErrno);
       
   553 		break;
       
   554 	case PMlseek: 
       
   555 		params->ret=Fids().lseek(params->fid,params->pint[0],params->pint[1],anErrno);
       
   556 		break;
       
   557 	case PMfstat: 
       
   558 		params->ret=Fids().fstat(params->fid,(struct stat*)params->ptr[0],anErrno);
       
   559 		break;
       
   560 	case PMgetcwd: 
       
   561 //		params->ret=(int)PosixFilesystem::getcwd(Fs(),params->ptr[0],params->len[0],anErrno);
       
   562 		params->ret=(int)PosixFilesystem::getcwd(Fs(),params->wptr[0],params->len[0],anErrno);
       
   563 		break;
       
   564 	case PMchdir: 
       
   565 		params->ret=PosixFilesystem::chdir(Fs(),params->cwptr[0],anErrno);
       
   566 		break;
       
   567 	case PMmkdir: 
       
   568 //		params->ret=PosixFilesystem::mkdir(Fs(),params->cptr[0],params->pint[0],anErrno);
       
   569 		params->ret=PosixFilesystem::mkdir(Fs(),params->cwptr[0],params->pint[0],anErrno);
       
   570 		break;
       
   571 	case PMrmdir: 
       
   572 		params->ret=PosixFilesystem::rmdir(Fs(),params->cwptr[0],anErrno);
       
   573 		break;
       
   574 	case PMchmod: 
       
   575 		params->ret=PosixFilesystem::chmod(Fs(),params->cwptr[0],params->pint[0],anErrno);
       
   576 		break;
       
   577 	case PMunlink: 
       
   578 		params->ret=PosixFilesystem::unlink(Fs(),params->cwptr[0],anErrno);
       
   579 		break;
       
   580 	case PMstat: 
       
   581 		params->ret=PosixFilesystem::stat(Fs(),params->cwptr[0],(struct stat*)params->ptr[0],anErrno);
       
   582 		break;
       
   583 	case PMrename: 
       
   584 		params->ret=PosixFilesystem::rename(Fs(), params->cwptr[0],params->cwptr[1],anErrno);
       
   585 		break;
       
   586 	case PMResolvePath:
       
   587 //		params->ret=PosixFilesystem::ResolvePath(Fs(),
       
   588 //			*(TParse*)params->ptr[0],params->cptr[0],(TDes*)params->ptr[1]);
       
   589 		params->ret=PosixFilesystem::ResolvePath(Fs(),
       
   590 			*(TParse*)params->ptr[0],params->cwptr[0],(TDes*)params->ptr[1]);
       
   591 		break;
       
   592 	case PMsocket:
       
   593 		params->ret=Fids().socket(params->pint[0],params->pint[1],params->pint[2],anErrno,Ss());
       
   594 		break;
       
   595 	case PMbind:
       
   596 		params->ret=Fids().bind(params->fid,params->addr,anErrno);
       
   597 		break;
       
   598 	case PMlisten:
       
   599 		params->ret=Fids().listen(params->fid,params->pint[0],anErrno);
       
   600 		break;
       
   601 	case PMsockname:
       
   602 		params->ret=Fids().sockname(params->fid,params->addr,params->pint[0],anErrno);
       
   603 		break;
       
   604 	case PMgetsockopt:
       
   605 		params->ret=Fids().getsockopt(params->fid,params->pint[0],params->pint[1],
       
   606 			params->ptr[0],params->lenp[0],anErrno);
       
   607 		break;
       
   608 	case PMsetsockopt:
       
   609 		params->ret=Fids().setsockopt(params->fid,params->pint[0],params->pint[1],
       
   610 			params->ptr[0],params->len[0],anErrno);
       
   611 		break;
       
   612 	case PMgetenv:
       
   613 		params->ret=(int)Env().getenv(params->cwptr[0]);
       
   614 		break;
       
   615 	case PMunsetenv:
       
   616 		Env().unsetenv(params->cwptr[0]);	// no return value
       
   617 		break;
       
   618 	case PMsetenv:
       
   619 		params->ret=Env().setenv(params->cwptr[0],params->cwptr[1],params->pint[0],anErrno);
       
   620 		break;
       
   621 	case PMioctlcomplete:
       
   622 		params->ret=Fids().ioctlcomplete(params->fid,params->pint[0],params->ptr[0],*(REINTERPRET_CAST(TRequestStatus*, params->ptr[1])), anErrno);
       
   623 		break;
       
   624 	case PMTerminateProcess:
       
   625 		{
       
   626 		int status = params->fid;
       
   627 		RProcess().Kill(status);
       
   628 		}
       
   629 		break;
       
   630 	case PMpopen3:
       
   631 		params->ret=iServer.POpen3(params,anErrno);
       
   632 		break;
       
   633 	default:
       
   634 		aMessage.Complete(KErrNotSupported);
       
   635 		return;
       
   636 		}
       
   637 	// deal with completion of a synchronous request
       
   638 	aMessage.Complete(KErrNone);
       
   639 	}
       
   640 
       
   641 // Asynchronous requests
       
   642 //
       
   643 // 1. QueueAsynch() to get into the appropriate queue in the FileDesc
       
   644 // 2. FileDesc calls StartAsynch() when it's our turn
       
   645 // 3. StartAsynch() makes the relevant IO call and does SetActive()
       
   646 // 4a.    RunL() handles the completion of the IO call and calls EndAsynch()
       
   647 // 4b.    DoCancel() handles cancellation of the IO call, but doesn't call EndAsynch()
       
   648 // 5. EndAsynch() removes us from the FileDesc queue and completes iMessage
       
   649 //
       
   650 
       
   651 void CPosixRequest::QueueAsynch(const RMessage2& aMessage)
       
   652 //
       
   653 // Add this to the appropriate queue in the associated file
       
   654 //
       
   655 	{
       
   656 	iMessage=aMessage;	// Suggested by AndrewT to avoid code duplication
       
   657 	iQueue=CFileDescBase::IOwriteQ;
       
   658 	switch (aMessage.Function())
       
   659 		{
       
   660 	case PMread:
       
   661 	case PMrecvfrom:
       
   662 		iQueue=CFileDescBase::IOreadQ;
       
   663 		break;
       
   664 	case PMioctl:
       
   665 		iQueue=CFileDescBase::IOioctlQ;
       
   666 		break;
       
   667 	case PMioctlN:
       
   668 		iQueue=CFileDescBase::IOioctlNQ;
       
   669 		break;
       
   670 	default:
       
   671 		// everything else uses the IOwriteQ, including Accept and Connect
       
   672 		break;
       
   673 		}
       
   674 
       
   675 	__ASSERT_ALWAYS(iFile!=0,CPosixServer::ServerPanic(EPosix_NoPendingIO));
       
   676 	iFile->AddLast(*this,iQueue);
       
   677 	}
       
   678 
       
   679 void CPosixRequest::StartAsynch()
       
   680 //
       
   681 // The request has reached the front of the queue and can now be actioned
       
   682 //
       
   683 	{
       
   684 	PosixParams* params=REINTERPRET_CAST(PosixParams*,CONST_CAST(TAny*,iMessage.Ptr1()));
       
   685 	switch (iMessage.Function())
       
   686 		{
       
   687 	case PMread:
       
   688 		{
       
   689 		
       
   690 		//if we need to have a timer for this operation to cancel it later
       
   691 		if (iFile->TimedRead())
       
   692 			{
       
   693 			iFile->ReadIsTimed = ETrue;
       
   694 			TRAPD(tRes, {iFile->TimedMessage = CSerialTimer::NewL(iFile);});
       
   695 			if (tRes != KErrNone)
       
   696 				{
       
   697 				//we have a problem here
       
   698 				//basically, fake the async request completing with the returned error
       
   699 				iStatus = KRequestPending;
       
   700 				SetActive();
       
   701 				TRequestStatus * ps = &iStatus;
       
   702 				User::RequestComplete(ps, tRes);
       
   703 				return;
       
   704 				}
       
   705 
       
   706 			iFile->TimedMessage->IssueRequest();
       
   707 			}
       
   708 		else
       
   709 			iFile->ReadIsTimed = EFalse;
       
   710 
       
   711 		iFile->ReadWasCancelled = EFalse;
       
   712 
       
   713 		iFile->Read(iPtr,iStatus);
       
   714 		
       
   715 		}
       
   716 		break;
       
   717 	case PMrecvfrom:
       
   718 		iFile->RecvFrom(iPtr,params->addr,params->pint[0],iStatus);
       
   719 		break;
       
   720 	case PMwrite:
       
   721 		iFile->Write(iPtr,iStatus);
       
   722 		break;
       
   723 	case PMsendto:
       
   724 		iFile->SendTo(iPtr,params->addr,params->pint[0],iStatus);
       
   725 		break;
       
   726 	case PMfsync:
       
   727 		iFile->Sync(iStatus);
       
   728 		break;
       
   729 	case PMconnect:
       
   730 		iFile->Connect(params->addr,iStatus);
       
   731 		break;
       
   732 	case PMshutdown:
       
   733 		iFile->Shutdown(params->pint[0],iStatus);
       
   734 		break;
       
   735 	case PMaccept:
       
   736 		iFile->Accept(iNewF,iStatus,Ss());
       
   737 		break;
       
   738 	case PMioctl:
       
   739 		iFile->Ioctl(params->pint[0],params->ptr[0],iStatus);
       
   740 		break;
       
   741 	case PMioctlN:
       
   742 		iFile->Ioctl(params->pint[0],params->ptr[0],iStatus);
       
   743 		break;
       
   744 	default:
       
   745 		EndAsynch(KErrGeneral);
       
   746 		return;
       
   747 		}
       
   748 	SetActive();	// for asynchronous completion via RunL
       
   749 	return;
       
   750 	}
       
   751 
       
   752 void CPosixRequest::RunL()
       
   753 //
       
   754 // The pending IO has completed, so handle the result
       
   755 //
       
   756 	{
       
   757 	__ASSERT_ALWAYS(iFile!=0,CPosixServer::ServerPanic(EPosix_NoPendingIO));
       
   758 	TInt completion=KErrNone;
       
   759 	int& anErrno=*REINTERPRET_CAST(int*,CONST_CAST(TAny*,iMessage.Ptr0()));
       
   760 	PosixParams* params=REINTERPRET_CAST(PosixParams*,CONST_CAST(TAny*,iMessage.Ptr1()));
       
   761 	switch (iMessage.Function())
       
   762 		{
       
   763 	case PMread:
       
   764 		{
       
   765 		if (iFile->ReadIsTimed)
       
   766 			{
       
   767 				//need to stop the timer
       
   768 				delete iFile->TimedMessage;
       
   769 				iFile->TimedMessage = NULL;
       
   770 				iFile->ReadIsTimed = EFalse;
       
   771 			}
       
   772 
       
   773 		TInt err=iFile->ReadCompletion(iPtr, iStatus.Int());
       
   774 		if (err==0)
       
   775 			{
       
   776 			params->ret=iPtr.Length();
       
   777 			break;
       
   778 			}
       
   779 		//if the read was cancelled and we are to patch it due to me cancelling it
       
   780 
       
   781 		if (iFile->ReadWasCancelled)
       
   782 			{
       
   783 			err = ETIMEDOUT;
       
   784 			iFile->ReadWasCancelled = EFalse;
       
   785 			}
       
   786 
       
   787 		params->ret=MapError(err,anErrno);
       
   788 		}
       
   789 		break;
       
   790 	case PMwrite:
       
   791 		{
       
   792 		TInt err=iFile->WriteCompletion(iPtr, iStatus.Int());
       
   793 		if (err==0)
       
   794 			{
       
   795 			params->ret=iPtr.Length();
       
   796 			break;
       
   797 			}
       
   798 		params->ret=MapError(err,anErrno);
       
   799 		}
       
   800 		break;
       
   801 	case PMconnect:
       
   802 	case PMshutdown:
       
   803 	case PMfsync:
       
   804 		params->ret=MapError(iStatus.Int(),anErrno);
       
   805 		break;
       
   806 	case PMsendto:
       
   807 		{
       
   808 		TInt err=iFile->SendToCompletion(iPtr, iStatus.Int());
       
   809 		if (err==0)
       
   810 			{
       
   811 			params->ret=iPtr.Length();
       
   812 			break;
       
   813 			}
       
   814 		params->ret=MapError(err,anErrno);
       
   815 		}
       
   816 		break;
       
   817 	case PMrecvfrom:
       
   818 		{
       
   819 		TInt err=iFile->RecvFromCompletion(params->ret, iStatus.Int());
       
   820 		if (err==0)
       
   821 			{
       
   822 			params->ret=iPtr.Length();
       
   823 			break;
       
   824 			}
       
   825 		params->ret=MapError(err,anErrno);
       
   826 		}
       
   827 		break;
       
   828 	case PMaccept:
       
   829 		{
       
   830 		TInt err=iStatus.Int();
       
   831 		if (err)
       
   832 			Fids().Attach(iNewFid,0);	// cancel the reservation
       
   833 		else
       
   834 			{
       
   835 			err=Fids().Attach(iNewFid,iNewF);
       
   836 			if (!err)
       
   837 				{
       
   838 				params->ret=iNewFid;
       
   839 				break;	// so that we return the new fid
       
   840 				}
       
   841 			delete iNewF;
       
   842 			iNewF=0;
       
   843 			}
       
   844 		params->ret=MapError(err,anErrno);
       
   845 		}
       
   846 		break;
       
   847 
       
   848 	case PMioctlN:
       
   849 		{
       
   850 		completion=iStatus.Int();	// caller picks up completion explicitly 
       
   851 		}
       
   852 		break;
       
   853 
       
   854 	case PMioctl:
       
   855 		{
       
   856 		completion=iStatus.Int();	// caller picks up completion explicitly 
       
   857 //		TInt err=iFile->IoctlCompletion(params->pint[0], &params->ret, iStatus.Int());
       
   858 //		params->ret=MapError(err,anErrno);
       
   859 		}
       
   860 		break;
       
   861 
       
   862 	default:
       
   863 		completion=KErrGeneral;	// arrgh - I imagine that it's going to die if we get here...
       
   864 		break;
       
   865 		}
       
   866 	EndAsynch(completion);
       
   867 	}
       
   868 
       
   869 void CPosixRequest::EndAsynch(TInt aResult)
       
   870 // 
       
   871 // finish an asynchronous operation and complete iMessage
       
   872 //
       
   873 	{
       
   874 	__ASSERT_ALWAYS(iFile!=0,CPosixServer::ServerPanic(EPosix_NoPendingIO));
       
   875 	iFile->Remove(*this,iQueue);
       
   876 	iFile->Close();	// balances the Dup() in CFileTable::Asynch(), may delete object!
       
   877 	iFile=0;
       
   878 	iMessage.Complete(aResult);	
       
   879 	}
       
   880 
       
   881 
       
   882 void CPosixRequest::DoCancel()
       
   883 //
       
   884 // The pending IO has been cancelled, so cancel the outstanding request
       
   885 // Needs to deal with all of the cases in RunL, but doesn't call EndAsynch().
       
   886 // This is called from CActive::Cancel() only when the object is active, but
       
   887 // EndAsynch() needs to be called when the object is active or when it's just
       
   888 // waiting in a FileDesc queue.
       
   889 //
       
   890 	{
       
   891 	__ASSERT_ALWAYS(iFile!=0,CPosixServer::ServerPanic(EPosix_NoPendingIO));
       
   892 	switch (iMessage.Function())
       
   893 		{
       
   894 	case PMread:
       
   895 		iFile->ReadCancel();
       
   896 		break;
       
   897 	case PMrecvfrom:
       
   898 		iFile->RecvFromCancel();
       
   899 		break;
       
   900 	case PMwrite:
       
   901 		iFile->WriteCancel();
       
   902 		break;
       
   903 	case PMsendto:
       
   904 		iFile->SendToCancel();
       
   905 		break;
       
   906 	case PMfsync:
       
   907 		iFile->SyncCancel();
       
   908 		break;
       
   909 	case PMconnect:
       
   910 		iFile->ConnectCancel();
       
   911 		break;
       
   912 	case PMshutdown:
       
   913 		iFile->ShutdownCancel();
       
   914 		break;
       
   915 	case PMaccept:
       
   916 		iFile->AcceptCancel();
       
   917 		Fids().Attach(iNewFid,0);	// cancel the reservation
       
   918 		break;
       
   919 	case PMioctl:
       
   920 		iFile->IoctlCancel();
       
   921 		break;
       
   922 	default:
       
   923 		// it would be wrong to get here, so leave well alone
       
   924 		break;
       
   925 		}
       
   926 	}
       
   927 
       
   928 CPosixRequest::~CPosixRequest()
       
   929 	{
       
   930 	Cancel();
       
   931 	if (iFile)
       
   932 		EndAsynch(KErrCancel);
       
   933 	}
       
   934 
       
   935 // Handling waiting on other processes
       
   936 //
       
   937 void CPosixRequest::EnList(CPosixRequest*& aHead)
       
   938 	{
       
   939 	iNext=aHead;
       
   940 	aHead=this;
       
   941 	}
       
   942 
       
   943 void CPosixRequest::WaitCompleted(TInt aPid, TInt aReason)
       
   944 	{
       
   945 	PosixParams* params=REINTERPRET_CAST(PosixParams*,CONST_CAST(TAny*,iMessage.Ptr1()));
       
   946 
       
   947 	__ASSERT_DEBUG(iMessage.Function()==PMwaitpid, CPosixServer::ServerPanic(EPosix_BadWaitCompletion));
       
   948 	params->pint[0]=aReason;
       
   949 	params->ret=aPid;
       
   950 	iMessage.Complete(KErrNone);
       
   951 
       
   952 	CPosixRequest* next=iNext;
       
   953 	iNext=0;
       
   954 	if (next)
       
   955 		next->WaitCompleted(aPid, aReason);
       
   956 	}
       
   957 
       
   958 static void ClosePipes(CPipeDesc* aPipes[3])
       
   959 	{
       
   960 	TInt i=0;
       
   961 	for (i=0; i<3; i++)
       
   962 		{
       
   963 		CPipeDesc* pipe=aPipes[i];
       
   964 		aPipes[i]=0;
       
   965 		if (pipe)
       
   966 			pipe->ClientClose();
       
   967 		}
       
   968 	}
       
   969 
       
   970 TInt CPosixIPCSession::AreYouMyMotherL(const RMessage2& aMessage)
       
   971 	{
       
   972 	TPosixIPCPid pid;
       
   973 	TPosixIPCReply reply;
       
   974 	aMessage.ReadL(0,pid);
       
   975 	DebugPrint(_L("Process %d asks am I its mother?"), pid());
       
   976 	CPosixServer* pServ = const_cast<CPosixServer*>(static_cast<const CPosixServer*>(Server()));
       
   977 	CPosixProcess* child=pServ->Child(pid());
       
   978 	if (!child)
       
   979 		return KErrNotFound;	// you are no child of mine
       
   980 	DebugPrint(_L("Found child process"));
       
   981 	child->Sizes(reply);
       
   982 	aMessage.Write(1,reply);
       
   983 	return KErrNone;
       
   984 	}
       
   985 
       
   986 TInt CPosixIPCSession::HelloMumL(const RMessage2& aMessage)
       
   987 	{
       
   988 	TPosixIPCPid pid;
       
   989 	aMessage.ReadL(0,pid);
       
   990 
       
   991 	DebugPrint(_L("Process %d is requesting its inheritance"),pid());
       
   992 
       
   993 	CPosixServer* pServ = const_cast<CPosixServer*>(static_cast<const CPosixServer*>(Server()));
       
   994 	CPosixProcess* child=pServ->Child(pid());
       
   995 	if (!child)
       
   996 		return KErrNotFound;	// you are no child of mine
       
   997 
       
   998 	// CopyToChildL will pull out the second and third element out directly so as
       
   999 	// to copy data to it. This is why data is passed in this way.
       
  1000 	child->CopyToChildL(aMessage);
       
  1001 	return KErrNone;
       
  1002 	}
       
  1003 
       
  1004 void CPosixIPCSession::PipeRead(const RMessage2& aMessage)
       
  1005 	{
       
  1006 	TInt index=aMessage.Int0();
       
  1007 	if (iPipes[index]==0)
       
  1008 		aMessage.Complete(KErrEof);	// go away, incorrect thing!
       
  1009 	else
       
  1010 		iPipes[index]->ClientRead(aMessage);
       
  1011 	}
       
  1012 
       
  1013 void CPosixIPCSession::PipeWrite(const RMessage2& aMessage)
       
  1014 	{
       
  1015 	TInt index=aMessage.Int0();
       
  1016 	if (iPipes[index]==0)
       
  1017 		aMessage.Complete(KErrEof);	// go away, incorrect thing!
       
  1018 	else
       
  1019 		iPipes[index]->ClientWrite(aMessage);
       
  1020 	}
       
  1021 
       
  1022 void CPosixIPCSession::PipeIoctl(const RMessage2& aMessage)
       
  1023 	{
       
  1024 	TInt index=aMessage.Int0();
       
  1025 	if (iPipes[index]==0)
       
  1026 		aMessage.Complete(KErrEof);	// go away, incorrect thing!
       
  1027 	else
       
  1028 		iPipes[index]->ClientIoctl(aMessage);
       
  1029 	}
       
  1030 
       
  1031 void CPosixIPCSession::PipeClose(const RMessage2& aMessage)
       
  1032 	{
       
  1033 	TInt index=aMessage.Int0();
       
  1034 	if (iPipes[index]!=0)
       
  1035 		iPipes[index]->ClientClose();
       
  1036 	aMessage.Complete(KErrNone);
       
  1037 	}
       
  1038 
       
  1039 void CPosixIPCSession::PipeCancel(const RMessage2& aMessage)
       
  1040 	{
       
  1041 	TInt index=aMessage.Int0();
       
  1042 	if (iPipes[index]!=0)
       
  1043 		iPipes[index]->ClientCancel(aMessage);
       
  1044 	aMessage.Complete(KErrNone);
       
  1045 	}
       
  1046 
       
  1047 void CPosixIPCSession::ServiceL(const RMessage2& aMessage)
       
  1048 //
       
  1049 // Handle the communication between CPosixServers
       
  1050 //
       
  1051 	{
       
  1052 	TInt response=KErrNone;
       
  1053 	switch (aMessage.Function())
       
  1054 		{
       
  1055 	case PMAreYouMyMother:
       
  1056 		response=AreYouMyMotherL(aMessage);
       
  1057 		break;
       
  1058 	case PMHelloMum:
       
  1059 		response=HelloMumL(aMessage);
       
  1060 		break;
       
  1061 
       
  1062 	case PMPipeRead:
       
  1063 		PipeRead(aMessage);
       
  1064 		return;	// handles completion
       
  1065 	case PMPipeWrite:
       
  1066 		PipeWrite(aMessage);
       
  1067 		return; // handles completion
       
  1068 	case PMPipeIoctl:
       
  1069 		PipeIoctl(aMessage);
       
  1070 		return; // handles completion
       
  1071 	case PMPipeClose:
       
  1072 		PipeClose(aMessage);
       
  1073 		return; // handles completion
       
  1074 
       
  1075 	case PMPipeCancel:
       
  1076 		PipeCancel(aMessage);
       
  1077 		return;
       
  1078 
       
  1079 	default:
       
  1080 		response=KErrNotSupported;
       
  1081 		break;
       
  1082 		}
       
  1083 	aMessage.Complete(response);
       
  1084 	}
       
  1085 
       
  1086 void CPosixIPCSession::SetPipes(CPipeDesc* aPipes[3])
       
  1087 //
       
  1088 // Accept ownership of the pipes between child and parent
       
  1089 //
       
  1090 	{
       
  1091 	TInt i=0;
       
  1092 	for (i=0; i<3; i++)
       
  1093 		{
       
  1094 		CPipeDesc* pipe=aPipes[i];
       
  1095 		iPipes[i]=pipe;
       
  1096 		aPipes[i]=0;
       
  1097 		if (pipe)
       
  1098 			pipe->SetClientSide(iPipes[i]);
       
  1099 		}
       
  1100 	}
       
  1101 
       
  1102 CPosixIPCSession::~CPosixIPCSession()
       
  1103 	{
       
  1104 	ClosePipes(iPipes);
       
  1105 	}
       
  1106 
       
  1107 // Active Object representing a POSIX process
       
  1108 
       
  1109 CPosixProcess::CPosixProcess(CPosixServer& aServer)
       
  1110 	: CActive(EPriorityStandard), iServer(aServer)
       
  1111 	{
       
  1112 	// iPid=0;
       
  1113 	// iWaiters=0;
       
  1114 	// iNextProcess=0;
       
  1115 	// iEnvironment=0;
       
  1116 	// iWorkingDirectory=0;
       
  1117 	}
       
  1118 
       
  1119 CPosixProcess* CPosixProcess::Find(CPosixProcess* proc, TInt pid)
       
  1120 	{
       
  1121 	while (proc!=0)
       
  1122 		{
       
  1123 		if (proc->iPid==pid)
       
  1124 			return proc;
       
  1125 		if (pid==-1 && !proc->IsAlive())	// for waitpid(WAIT_ANY,...)
       
  1126 			return proc;
       
  1127 		proc=proc->iNextProcess;
       
  1128 		}
       
  1129 	return 0;
       
  1130 	}
       
  1131 
       
  1132 void CPosixProcess::Release(CPosixProcess** aHead, CPosixProcess* aChild)
       
  1133 	{
       
  1134 	while (*aHead!=0)
       
  1135 		{
       
  1136 		if ((*aHead)==aChild)
       
  1137 			{
       
  1138 			(*aHead)=aChild->iNextProcess;
       
  1139 			aChild->iNextProcess=0;
       
  1140 			delete aChild;
       
  1141 			return;
       
  1142 			}
       
  1143 		aHead=&(*aHead)->iNextProcess;
       
  1144 		}
       
  1145 	}
       
  1146 
       
  1147 
       
  1148 
       
  1149 void CPosixProcess::POpen3L(PosixParams* aParams)
       
  1150 	{
       
  1151 	TInt i=0;
       
  1152 	CPipeDesc* pipes[3];
       
  1153 	for (i=0; i<3; i++)
       
  1154 		{
       
  1155 		if (aParams->pint[i]<0)
       
  1156 			pipes[i]=0;
       
  1157 		else
       
  1158 			{
       
  1159 			pipes[i]=new(ELeave) CPipeDesc(i);
       
  1160 			pipes[i]->PushLC();
       
  1161 			}
       
  1162 		}
       
  1163 	// truncate fileName to get the name of the executable
       
  1164 	TPtrC16 fileName((TText16*)aParams->wptr[0]);
       
  1165 	TPtrC16 commandLine((TText16*)aParams->cwptr[0]);
       
  1166 
       
  1167 	HBufC16* env=Env().ExternalizeLC(iVarCount,aParams->eptr[0]);
       
  1168 	TFullName workingDirectory;
       
  1169 	TInt err=Fs().SessionPath(workingDirectory);
       
  1170 	User::LeaveIfError(err);
       
  1171 	HBufC* cwd=workingDirectory.AllocLC();
       
  1172 
       
  1173 	// Use real processes
       
  1174 	err=iChild.Create(fileName,commandLine,EOwnerThread);
       
  1175 	User::LeaveIfError(err);
       
  1176 	TProcessId id=iChild.Id();
       
  1177 	iPid=*REINTERPRET_CAST(int*,&id);
       
  1178 	iChild.Logon(iStatus);
       
  1179 	CActiveScheduler::Add(this);
       
  1180 	SetActive();
       
  1181 	iChild.Resume();
       
  1182 	iEnvironment=env;
       
  1183 	iWorkingDirectory=cwd;
       
  1184 	CleanupStack::Pop(2);
       
  1185 	// Sort out the pipes
       
  1186 	for (i=0; i<3; i++)
       
  1187 		{
       
  1188 		CPipeDesc* pipe=pipes[i];
       
  1189 		iPipes[i]=pipe;
       
  1190 		if (pipe!=0)
       
  1191 			{
       
  1192 			CleanupStack::Pop();
       
  1193 			Fids().Attach(aParams->pint[i],pipe);
       
  1194 			pipe->SetClientSide(iPipes[i]);	// for FinalClose
       
  1195 			}
       
  1196 		}
       
  1197 	}
       
  1198 
       
  1199 void CPosixProcess::Sizes(TPosixIPCReply& aReply) const
       
  1200 	{
       
  1201 	aReply().iWorkingDirectorySize=iWorkingDirectory->Length();
       
  1202 	aReply().iEnvironmentSize=iEnvironment->Length();
       
  1203 	aReply().iVarCount=iVarCount;
       
  1204 	TUint mask=0;
       
  1205 	TInt i=0;
       
  1206 	for (i=0; i<3; i++)
       
  1207 		{
       
  1208 		if (iPipes[i]!=0)
       
  1209 			mask |= 1<<i;
       
  1210 		}
       
  1211 	aReply().iPipeMask=mask;
       
  1212 	}
       
  1213 
       
  1214 void CPosixProcess::CopyToChildL(const RMessage2& aMessage)
       
  1215 	{
       
  1216 	// copy iWorkingDirectory and iEnvironment to params
       
  1217 	aMessage.WriteL(1, *iEnvironment);
       
  1218 	aMessage.WriteL(2, *iWorkingDirectory);
       
  1219 
       
  1220 	// don't need this data anymore
       
  1221 	delete iWorkingDirectory;
       
  1222 	iWorkingDirectory=0;
       
  1223 	delete iEnvironment;
       
  1224 	iEnvironment=0;
       
  1225 
       
  1226 	(static_cast<CPosixIPCSession*>(aMessage.Session()))->SetPipes(iPipes);
       
  1227 	}
       
  1228 
       
  1229 void CPosixProcess::RunL()
       
  1230 //
       
  1231 // Detects termination of the child process 
       
  1232 //
       
  1233 	{
       
  1234 	iExitReason=iStatus.Int();
       
  1235 	iChild.Close();
       
  1236 	DebugPrint(_L("Process %d appears to have terminated with status %d"), iPid, iExitReason);
       
  1237 	ClosePipes(iPipes);
       
  1238 
       
  1239 	TInt reported=0;
       
  1240 	CPosixRequest* waiters=iWaiters;
       
  1241 	iWaiters=0;
       
  1242 	if (waiters) 
       
  1243 		{
       
  1244 		waiters->WaitCompleted(iPid,iExitReason);
       
  1245 		reported=1;
       
  1246 		}
       
  1247 
       
  1248 	// And any of the outstanding "wait for any" requests held in the server
       
  1249 	waiters=iServer.Waiters();
       
  1250 	if (waiters)
       
  1251 		{
       
  1252 		waiters->WaitCompleted(iPid,iExitReason);
       
  1253 		reported=1;
       
  1254 		}
       
  1255 	if (reported)
       
  1256 		iServer.Release(this);
       
  1257 	}
       
  1258 
       
  1259 void CPosixProcess::DoCancel()
       
  1260 	{
       
  1261 	// panic if iNextProcess or iWaiters is non-zero?
       
  1262 	iChild.LogonCancel(iStatus);
       
  1263 	iChild.Close();
       
  1264 	delete iEnvironment;
       
  1265 	iEnvironment=0;
       
  1266 	delete iWorkingDirectory;
       
  1267 	iWorkingDirectory=0;
       
  1268 	ClosePipes(iPipes);
       
  1269 	}
       
  1270 
       
  1271 CPosixProcess::~CPosixProcess()
       
  1272 	{
       
  1273 	Cancel();
       
  1274 	}
       
  1275 
       
  1276 // System Interface for process form of STDLIB
       
  1277 
       
  1278 CProcessSystemInterface::CProcessSystemInterface()
       
  1279 	{}
       
  1280 
       
  1281 CProcessSystemInterface::~CProcessSystemInterface()
       
  1282 	{
       
  1283 	iSession.Close();
       
  1284 	}
       
  1285 
       
  1286 MSystemInterface& CProcessSystemInterface::Clone()
       
  1287 	{
       
  1288 	return *(new CProcessSystemInterface);
       
  1289 	}
       
  1290 
       
  1291 void CProcessSystemInterface::Release()
       
  1292 	{
       
  1293 	delete this;
       
  1294 	}
       
  1295 
       
  1296 TInt CProcessSystemInterface::Connect()
       
  1297 	{
       
  1298 	return iSession.Connect();	// is this the right thread though?
       
  1299 	}
       
  1300 
       
  1301 // CProcessSystemInterface functions
       
  1302 //
       
  1303 // These functions just package up their arguments for transmission to the
       
  1304 // CPosixServer which will unpack them and call the corresponding function in
       
  1305 // its associated CLocalSystemInterface, except for the asynchronous functions 
       
  1306 // (currently read/write/fsync) which the server handles separately using an active 
       
  1307 // object to defer the RMessage::Complete until the asynchronous operation has completed.
       
  1308 
       
  1309 static void doPanic(TInt aFunction, TInt aErr)
       
  1310 	{
       
  1311 	TBuf<100> detail;
       
  1312 	_LIT(KProcessSystemInterfacePanic, "POSIXIF (%d)");
       
  1313 	detail.Format(KProcessSystemInterfacePanic, aFunction);
       
  1314 	User::Panic(detail,aErr);
       
  1315 	}
       
  1316 
       
  1317 int CProcessSystemInterface::Request (TInt aFunction, int& anErrno)
       
  1318 	{
       
  1319 	TInt err=iSession.Request(aFunction,anErrno,iParams);
       
  1320 	// KErrServerTerminated?
       
  1321 	if (err!=KErrNone)
       
  1322 		doPanic(aFunction,err);	// moved out of line to reduce stack requirement
       
  1323 	return iParams.ret;
       
  1324 	}
       
  1325 
       
  1326 void CProcessSystemInterface::Request (TInt aFunction, int& anErrno, TRequestStatus& aStatus)
       
  1327 	{
       
  1328 	iSession.Request(aFunction,anErrno,iParams,aStatus);
       
  1329 	}
       
  1330 
       
  1331 void CProcessSystemInterface::TerminateProcess (int status)
       
  1332 	{
       
  1333 	int anErrno;
       
  1334 	iParams.fid=status;
       
  1335 	Request(PMTerminateProcess,anErrno);
       
  1336 	RProcess().Terminate(status);	// just in case...
       
  1337 	}
       
  1338 
       
  1339 int CProcessSystemInterface::dup (int fid, int& anErrno)
       
  1340 	{
       
  1341 	iParams.fid=fid;
       
  1342 	return Request(PMdup,anErrno);
       
  1343 	}
       
  1344 
       
  1345 int CProcessSystemInterface::dup2 (int fid, int fid2, int& anErrno)
       
  1346 	{
       
  1347 	iParams.fid=fid;
       
  1348 	iParams.pint[0]=fid2;
       
  1349 	return Request(PMdup2,anErrno);
       
  1350 	}
       
  1351 	
       
  1352 int CProcessSystemInterface::open (const wchar_t* name, int mode, int perms, int& anErrno)
       
  1353 	{
       
  1354 	iParams.cwptr[0]=name;
       
  1355 	iParams.pint[0]=mode;
       
  1356 	iParams.pint[1]=perms;
       
  1357 	return Request(PMopen,anErrno);
       
  1358 	}
       
  1359 
       
  1360 int CProcessSystemInterface::read (int fid, char* buf, unsigned long len, int& anErrno)
       
  1361 	{
       
  1362 	iParams.fid=fid;
       
  1363 	iParams.ptr[0]=buf;
       
  1364 	iParams.len[0]=len;
       
  1365 	return Request(PMread,anErrno);
       
  1366 	}
       
  1367 
       
  1368 int CProcessSystemInterface::write (int fid, const char* buf, unsigned long len, int& anErrno)
       
  1369 	{
       
  1370 	iParams.fid=fid;
       
  1371 	iParams.ptr[0]=CONST_CAST(char*,buf);
       
  1372 	iParams.len[0]=len;
       
  1373 	return Request(PMwrite,anErrno);
       
  1374 	}
       
  1375 
       
  1376 int CProcessSystemInterface::fsync (int fid, int& anErrno)
       
  1377 	{
       
  1378 	iParams.fid=fid;
       
  1379 	return Request(PMfsync,anErrno);
       
  1380 	}
       
  1381 
       
  1382 int CProcessSystemInterface::close (int fid, int& anErrno)
       
  1383 	{
       
  1384 	iParams.fid=fid;
       
  1385 	return Request(PMclose,anErrno);
       
  1386 	}
       
  1387 
       
  1388 int CProcessSystemInterface::lseek (int fid, int offset, int whence, int& anErrno)
       
  1389 	{
       
  1390 	iParams.fid=fid;
       
  1391 	iParams.pint[0]=offset;
       
  1392 	iParams.pint[1]=whence;
       
  1393 	return Request(PMlseek,anErrno);
       
  1394 	}
       
  1395 
       
  1396 int CProcessSystemInterface::fstat (int fid, struct stat *st, int& anErrno)
       
  1397 	{
       
  1398 	iParams.fid=fid;
       
  1399 	iParams.ptr[0]=(char*)st;
       
  1400 	return Request(PMfstat,anErrno);
       
  1401 	}
       
  1402 
       
  1403 
       
  1404 wchar_t * CProcessSystemInterface::getcwd (wchar_t* buf, unsigned long len, int& anErrno)
       
  1405 	{
       
  1406 	iParams.wptr[0]=buf;
       
  1407 
       
  1408 	iParams.len[0]=len;
       
  1409 	return (wchar_t *)Request(PMgetcwd,anErrno);
       
  1410 	}
       
  1411 
       
  1412 
       
  1413 int CProcessSystemInterface::chdir (const wchar_t* aPath, int& anErrno)
       
  1414 	{
       
  1415 	iParams.cwptr[0]=aPath;
       
  1416 	return Request(PMchdir,anErrno);
       
  1417 	}
       
  1418 
       
  1419 int CProcessSystemInterface::mkdir (const wchar_t* aPath, int perms, int& anErrno)
       
  1420 	{
       
  1421 	iParams.cwptr[0]=aPath;
       
  1422 	iParams.pint[0]=perms;
       
  1423 	return Request(PMmkdir,anErrno);
       
  1424 	}
       
  1425 
       
  1426 int CProcessSystemInterface::rmdir (const wchar_t* aPath, int& anErrno)
       
  1427 	{
       
  1428 	iParams.cwptr[0]=aPath;
       
  1429 	return Request(PMrmdir,anErrno);
       
  1430 	}
       
  1431 
       
  1432 int CProcessSystemInterface::stat (const wchar_t* name, struct stat *st, int& anErrno)
       
  1433 	{
       
  1434 	iParams.cwptr[0]=name;
       
  1435 	iParams.ptr[0]=(char*)st;
       
  1436 	return Request(PMstat,anErrno);
       
  1437 	}
       
  1438 
       
  1439 int CProcessSystemInterface::chmod (const wchar_t* name, int perms, int& anErrno)
       
  1440 	{
       
  1441 	iParams.cwptr[0]=name;
       
  1442 	iParams.pint[0]=perms;
       
  1443 	return Request(PMchmod,anErrno);
       
  1444 	}
       
  1445 
       
  1446 int CProcessSystemInterface::unlink (const wchar_t* name, int& anErrno)
       
  1447 	{
       
  1448 	iParams.cwptr[0]=name;
       
  1449 	return Request(PMunlink,anErrno);
       
  1450 	}
       
  1451 
       
  1452 int CProcessSystemInterface::rename (const wchar_t* oldname, const wchar_t* newname, int& anErrno)
       
  1453 	{
       
  1454 	iParams.cwptr[0]=oldname;
       
  1455 	iParams.cwptr[1]=newname;
       
  1456 	return Request(PMrename,anErrno);
       
  1457 	}
       
  1458 
       
  1459 TInt CProcessSystemInterface::ResolvePath (TParse& aResult, const wchar_t* path, TDes* aFilename)
       
  1460 	{
       
  1461 	TInt ignored;
       
  1462 	iParams.ptr[0]=(char*)&aResult;
       
  1463 	iParams.cwptr[0]=path;
       
  1464 	iParams.ptr[1]=(char*)aFilename;
       
  1465 	return Request(PMResolvePath,ignored);
       
  1466 	}
       
  1467 
       
  1468 TInt CProcessSystemInterface::socket (int family, int style, int protocol, int& anErrno)
       
  1469 	{
       
  1470 	iParams.pint[0]=family;
       
  1471 	iParams.pint[1]=style;
       
  1472 	iParams.pint[2]=protocol;
       
  1473 	return Request(PMsocket,anErrno);
       
  1474 	}
       
  1475 
       
  1476 TInt CProcessSystemInterface::shutdown (int fid, int how, int& anErrno)
       
  1477 	{
       
  1478 	iParams.fid=fid;
       
  1479 	iParams.pint[0]=how;
       
  1480 	return Request(PMshutdown,anErrno);
       
  1481 	}
       
  1482 
       
  1483 TInt CProcessSystemInterface::listen (int fid, int n, int& anErrno)
       
  1484 	{
       
  1485 	iParams.fid=fid;
       
  1486 	iParams.pint[0]=n;
       
  1487 	return Request(PMlisten,anErrno);
       
  1488 	}
       
  1489 
       
  1490 TInt CProcessSystemInterface::accept (int fid, int& anErrno)
       
  1491 	{
       
  1492 	iParams.fid=fid;
       
  1493 	return Request(PMaccept,anErrno);
       
  1494 	}
       
  1495 
       
  1496 TInt CProcessSystemInterface::bind (int fid, struct sockaddr* addr, unsigned long size, int& anErrno)
       
  1497 	{
       
  1498 	iParams.fid=fid;
       
  1499 	iParams.addr.Set(addr, size);
       
  1500 	return Request(PMbind,anErrno);
       
  1501 	}
       
  1502 
       
  1503 TInt CProcessSystemInterface::connect (int fid, struct sockaddr* addr, unsigned long size, int& anErrno)
       
  1504 	{
       
  1505 	iParams.fid=fid;
       
  1506 	iParams.addr.Set(addr, size);
       
  1507 	return Request(PMconnect,anErrno);
       
  1508 	}
       
  1509 
       
  1510 TInt CProcessSystemInterface::recvfrom (int fid, char* buf, unsigned long len, int flags, struct sockaddr* from, unsigned long* fromsize, int& anErrno)
       
  1511 	{
       
  1512 	iParams.fid=fid;
       
  1513 	iParams.ptr[0]=buf;
       
  1514 	iParams.len[0]=len;
       
  1515 	iParams.pint[0]=flags;
       
  1516 	iParams.addr.Prepare(from);
       
  1517 	TInt nbytes=Request(PMrecvfrom,anErrno);
       
  1518 	if (nbytes>=0) // i.e. no error
       
  1519 		iParams.addr.Get(from,fromsize);
       
  1520 	return nbytes;
       
  1521 	}
       
  1522 
       
  1523 TInt CProcessSystemInterface::sendto (int fid, const char* buf, unsigned long len, int flags, struct sockaddr* to, unsigned long tosize, int& anErrno)
       
  1524 	{
       
  1525 	iParams.fid=fid;
       
  1526 	iParams.ptr[0]=CONST_CAST(char*,buf);
       
  1527 	iParams.len[0]=len;
       
  1528 	iParams.pint[0]=flags;
       
  1529 	iParams.addr.Set(to,tosize);
       
  1530 	return Request(PMsendto,anErrno);
       
  1531 	}
       
  1532 
       
  1533 TInt CProcessSystemInterface::getsockopt (int fid, int level, int opt, void* buf, unsigned long* len, int& anErrno)
       
  1534 	{
       
  1535 	iParams.fid=fid;
       
  1536 	iParams.pint[0]=level;
       
  1537 	iParams.pint[1]=opt;
       
  1538 	iParams.ptr[0]=(char*)buf;
       
  1539 	iParams.lenp[0]=len;
       
  1540 	return Request(PMgetsockopt,anErrno);
       
  1541 	}
       
  1542 
       
  1543 TInt CProcessSystemInterface::setsockopt (int fid, int level, int opt, void* buf, unsigned long len, int& anErrno)
       
  1544 	{
       
  1545 	iParams.fid=fid;
       
  1546 	iParams.pint[0]=level;
       
  1547 	iParams.pint[1]=opt;
       
  1548 	iParams.ptr[0]=(char*)buf;
       
  1549 	iParams.len[0]=len;
       
  1550 	return Request(PMsetsockopt,anErrno);
       
  1551 	}
       
  1552 
       
  1553 TInt CProcessSystemInterface::sockname (int fid, struct sockaddr* addr, unsigned long* size, int anEnd, int& anErrno)
       
  1554 	{
       
  1555 	iParams.fid=fid;
       
  1556 	iParams.addr.Prepare(addr);
       
  1557 	iParams.pint[0]=anEnd;
       
  1558 	TInt err=Request(PMsockname,anErrno);
       
  1559 	if (err==0)
       
  1560 		iParams.addr.Get(addr,size);
       
  1561 	return err;
       
  1562 	}
       
  1563 
       
  1564 TInt CProcessSystemInterface::ioctl (int fid, int cmd, void* param, int& anErrno)
       
  1565 	{
       
  1566 	TRequestStatus ioctlStatus;
       
  1567 	TInt err=ioctl(fid,cmd,param,ioctlStatus,anErrno);
       
  1568 	if (err==KErrNone)
       
  1569 		{
       
  1570 		User::WaitForRequest(ioctlStatus);
       
  1571 		err=ioctl_complete(fid,cmd,param,ioctlStatus,anErrno);
       
  1572 		}
       
  1573 	return err;
       
  1574 	}
       
  1575 
       
  1576 wchar_t* CProcessSystemInterface::getenv (const wchar_t* name)
       
  1577 	{
       
  1578 	int dummy;
       
  1579 	iParams.cwptr[0]=name;
       
  1580 	return (wchar_t*)Request(PMgetenv,dummy);
       
  1581 	}
       
  1582 
       
  1583 void CProcessSystemInterface::unsetenv (const wchar_t* name)
       
  1584 	{
       
  1585 	int dummy;
       
  1586 	iParams.cwptr[0]=name;
       
  1587 	Request(PMunsetenv,dummy);
       
  1588 	}
       
  1589 
       
  1590 int CProcessSystemInterface::setenv (const wchar_t* name, const wchar_t* value, int rewrite, int& anErrno)
       
  1591 	{
       
  1592 	iParams.cwptr[0]=name;
       
  1593 	iParams.cwptr[1]=value;
       
  1594 	iParams.pint[0]=rewrite;
       
  1595 	return Request(PMsetenv,anErrno);
       
  1596 	}
       
  1597 
       
  1598 int CProcessSystemInterface::popen3 (const wchar_t* file, const wchar_t* cmd, const wchar_t* mode, wchar_t** env, int fids[3], int& anErrno)
       
  1599 	{
       
  1600 	iParams.wptr[0]=(wchar_t*)file;
       
  1601 	iParams.cwptr[0]=cmd;
       
  1602 	iParams.cwptr[1]=mode;
       
  1603 	iParams.eptr[0]=env;
       
  1604 	iParams.pint[0]=fids[0];
       
  1605 	iParams.pint[1]=fids[1];
       
  1606 	iParams.pint[2]=fids[2];
       
  1607 	TInt child=Request(PMpopen3,anErrno);
       
  1608 	if (child>=0)
       
  1609 		{
       
  1610 		fids[0]=iParams.pint[0];
       
  1611 		fids[1]=iParams.pint[1];
       
  1612 		fids[2]=iParams.pint[2];
       
  1613 		};
       
  1614 	return child;
       
  1615 	}
       
  1616 
       
  1617 int CProcessSystemInterface::waitpid (int pid, int* status, int options, int& anErrno)
       
  1618 	{
       
  1619 	iParams.pint[0]=pid;
       
  1620 	iParams.pint[1]=options;
       
  1621 	TInt ret=Request(PMwaitpid,anErrno);
       
  1622 	if (iParams.ret>=0 && status!=0)
       
  1623 		{
       
  1624 		*status=iParams.pint[0];
       
  1625 		return 	iParams.ret;
       
  1626 		}
       
  1627 		
       
  1628 	return ret;
       
  1629 	}
       
  1630 
       
  1631 // C++ version of asynchronous ioctl
       
  1632 //
       
  1633 // WARNING - this stuff is fairly insecure. We give no guarantees about whether the ioctl or
       
  1634 // the completion will read the parameter information (sometimes it's both).
       
  1635 // 
       
  1636 
       
  1637 int CProcessSystemInterface::ioctl (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno)
       
  1638 	{
       
  1639 	iParams.fid=fid;
       
  1640 	iParams.pint[0]=cmd;
       
  1641 	iParams.ptr[0]=(char*)param;
       
  1642 
       
  1643 	if (cmd & 0x4000)
       
  1644 		Request(PMioctlN,anErrno,aStatus);
       
  1645 	else
       
  1646 		Request(PMioctl,anErrno,aStatus);
       
  1647 	
       
  1648 	return KErrNone;
       
  1649 	}
       
  1650 
       
  1651 int CProcessSystemInterface::ioctl_complete (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno)
       
  1652 	{
       
  1653 	iParams.fid=fid;
       
  1654 	iParams.pint[0]=cmd;
       
  1655 	iParams.ptr[0]=(char*)param;
       
  1656 	iParams.ptr[1]=(char*)&aStatus;
       
  1657 	return Request(PMioctlcomplete,anErrno);
       
  1658 	}
       
  1659 
       
  1660 int CProcessSystemInterface::ioctl_cancel (int /*fid*/, int& /*anErrno*/)
       
  1661 //
       
  1662 // Actually a generic Cancel function for any outstanding operation
       
  1663 //
       
  1664 	{
       
  1665 	TIpcArgs args;
       
  1666 	return iSession.Request(PMcancel,args);
       
  1667 	}