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