os/ossrv/genericopenlibs/cstdlib/USTLIB/POSIXIF.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	}