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.
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], &params->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
	}