sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "SYSIF.H" sl@0: #include sl@0: #include "FDESC.H" sl@0: #include "PIPEDESC.H" sl@0: #include sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: const TInt KCPosixMajorVersionNumber=2; sl@0: const TInt KCPosixMinorVersionNumber=0; sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: enum TPosixServerPanic sl@0: { sl@0: EPosix_BadWaitCompletion=1, sl@0: EPosix_NoPendingIO=2, sl@0: }; sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: enum PosixMessage { sl@0: // asynchronous operations which need SetActive/RunL sl@0: PMread, PMwrite, PMfsync, sl@0: PMsendto, PMrecvfrom, PMconnect, PMshutdown, PMaccept, sl@0: //NOTIFY PROBLEM sl@0: // PMioctl, sl@0: PMioctl, PMioctlN, sl@0: // asynchronous operations which just delay completion sl@0: PMwaitpid, sl@0: // synchronous operations sl@0: PMdup, PMdup2, sl@0: PMopen, PMclose, PMlseek, PMfstat, sl@0: PMgetcwd, sl@0: PMchdir, PMmkdir, PMrmdir, sl@0: PMchmod, PMunlink, PMstat, PMrename, sl@0: PMResolvePath, sl@0: PMsocket, PMbind, PMlisten, PMsockname, PMgetsockopt, PMsetsockopt, sl@0: PMioctlcomplete, PMcancel, sl@0: PMTerminateProcess, sl@0: PMgetenv, PMsetenv, PMunsetenv, sl@0: PMpopen3, sl@0: // inter-process operations sl@0: PMAreYouMyMother, PMHelloMum, PMPipeWrite, PMPipeRead, PMPipeIoctl, PMPipeClose, PMPipeCancel sl@0: }; sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: struct PosixParams sl@0: { sl@0: int ret; sl@0: int fid; sl@0: int pint[3]; sl@0: const char* cptr[2]; sl@0: char* ptr[2]; sl@0: const wchar_t* cwptr[2]; sl@0: wchar_t* wptr[2]; sl@0: wchar_t** eptr[1]; sl@0: unsigned long len[1]; sl@0: unsigned long* lenp[1]; sl@0: TUSockAddr addr; sl@0: }; sl@0: sl@0: /** sl@0: Package which holds client's process Id. sl@0: @internalComponent sl@0: */ sl@0: typedef TPckgBuf TPosixIPCPid; sl@0: sl@0: /** sl@0: Package used by server to pass data to client. sl@0: @internalComponent sl@0: */ sl@0: struct PosixIPCReply sl@0: { sl@0: TUint iVarCount; sl@0: TUint iEnvironmentSize; sl@0: TUint iWorkingDirectorySize; sl@0: TUint iPipeMask; sl@0: }; sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: typedef TPckgBuf TPosixIPCReply; sl@0: sl@0: sl@0: // sl@0: class RPosixSession : public RSessionBase sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: { sl@0: public: sl@0: TInt Connect(); sl@0: TInt Connect(TDesC& aServerName); sl@0: sl@0: // for specific posix functions sl@0: int Request(TInt aFunction, int& anErrno, PosixParams& params) const; sl@0: void Request(TInt aFunction, int& anErrno, PosixParams& params, TRequestStatus& aStatus) const; sl@0: // for generic messages sl@0: TInt Request(TInt aFunction, const TIpcArgs& aArg) const; sl@0: void Request(TInt aFunction, const TIpcArgs& aArg, TRequestStatus &aStatus) const; sl@0: sl@0: static TVersion Version(); sl@0: }; sl@0: sl@0: sl@0: // sl@0: class CPosixRequest; sl@0: class CPosixServer; sl@0: class CPosixIPCSession; sl@0: NONSHARABLE_CLASS(CPosixProcess) : public CActive sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: { sl@0: public: sl@0: CPosixProcess(CPosixServer& aServer); sl@0: ~CPosixProcess(); sl@0: void POpen3L(PosixParams* aParams); sl@0: static CPosixProcess* Find(CPosixProcess* head, TInt pid); sl@0: static void Release(CPosixProcess** aHead, CPosixProcess* aProc); sl@0: void Sizes(TPosixIPCReply& aReply) const; sl@0: void CopyToChildL(const RMessage2& aMessage); sl@0: inline TInt IsAlive() const {return IsActive();} sl@0: inline void Queue(CPosixRequest* aWaiter); sl@0: protected: sl@0: void RunL(); sl@0: void DoCancel(); sl@0: sl@0: private: sl@0: inline CEnvironment& Env() const; sl@0: inline CFileTable& Fids() const; sl@0: inline RFs& Fs() const; sl@0: inline RCommServ& Cs() const; sl@0: sl@0: public: sl@0: CPosixProcess* iNextProcess; sl@0: TInt iPid; sl@0: TInt iExitReason; sl@0: private: sl@0: CPosixServer& iServer; sl@0: sl@0: RProcess iChild; sl@0: CPosixRequest* iWaiters; sl@0: sl@0: TUint iVarCount; sl@0: HBufC16* iEnvironment; sl@0: HBufC* iWorkingDirectory; sl@0: CPipeDesc* iPipes[3]; sl@0: }; sl@0: // sl@0: class CPosixRequest; sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: NONSHARABLE_CLASS(CPosixServer) : public CServer2 sl@0: { sl@0: public: sl@0: static TInt ThreadFunction(TAny* aPtr); sl@0: static void InitL(TInt aPriority); sl@0: RFs& Fs() { return iFs; } sl@0: RCommServ& Cs() { return iCs; } sl@0: CFileTable& Fids() { return iFids; } sl@0: RSocketServ& Ss() { return iSs; } sl@0: CEnvironment& Env() { return iEnv; } sl@0: sl@0: int POpen3(PosixParams* aParams, int& anErrno); sl@0: CPosixProcess* Child(TInt pid) { return CPosixProcess::Find(iChildren, pid); } sl@0: void Release(CPosixProcess* aChild) { CPosixProcess::Release(&iChildren, aChild); } sl@0: inline void WaitForAnyChild(CPosixRequest* aWaiter); sl@0: CPosixRequest* Waiters(); sl@0: static void ServerPanic(TPosixServerPanic aPanic); sl@0: sl@0: protected: sl@0: CPosixServer(TInt aPriority); sl@0: CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; sl@0: void FindParentL(); sl@0: void DefaultConsoleL(); sl@0: private: sl@0: RFs iFs; sl@0: CFileTable iFids; sl@0: RSocketServ iSs; sl@0: RCommServ iCs; sl@0: sl@0: CEnvironment iEnv; sl@0: RPosixSession iParent; sl@0: CPosixProcess* iChildren; sl@0: CPosixRequest* iWaitAnyQueue; sl@0: }; sl@0: sl@0: // sl@0: class CPosixSession; sl@0: NONSHARABLE_CLASS(CPosixRequest) : public CActive sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: { sl@0: public: sl@0: CPosixRequest(CPosixServer& aServer); sl@0: ~CPosixRequest(); sl@0: void Service(const RMessage2& aMessage); sl@0: void EnList(CPosixRequest*& aHead); // simple single linked list sl@0: void WaitCompleted(TInt aPid, TInt aReason); sl@0: protected: sl@0: void RunL(); sl@0: void DoCancel(); sl@0: private: sl@0: RFs& Fs() const { return iServer.Fs(); } sl@0: RCommServ& Cs() const { return iServer.Cs(); } sl@0: CFileTable& Fids() const { return iServer.Fids(); } sl@0: RSocketServ& Ss() const { return iServer.Ss(); } sl@0: CEnvironment& Env() const { return iServer.Env(); } sl@0: private: sl@0: void QueueAsynch(const RMessage2& aMessage); sl@0: void StartAsynch(); sl@0: void EndAsynch(TInt aResult); sl@0: sl@0: CPosixServer& iServer; sl@0: sl@0: RMessage2 iMessage; sl@0: sl@0: CFileDescBase* iFile; sl@0: CSocketDesc* iNewF; sl@0: int iNewFid; sl@0: TPtr8 iPtr; sl@0: sl@0: CPosixRequest* iNext; // for Enlist sl@0: TSglQueLink iLink; sl@0: enum CFileDescBase::IOQueues iQueue; sl@0: sl@0: friend class TPosixRequestQueue; sl@0: friend class CFileDescBase; // friend functions AddLast & Remove perhaps? sl@0: }; sl@0: // sl@0: inline CEnvironment& CPosixProcess::Env() const { return iServer.Env(); } sl@0: inline CFileTable& CPosixProcess::Fids() const { return iServer.Fids(); } sl@0: inline RFs& CPosixProcess::Fs() const { return iServer.Fs(); } sl@0: inline RCommServ& CPosixProcess::Cs() const { return iServer.Cs(); } sl@0: inline void CPosixProcess::Queue(CPosixRequest* aWaiter) { aWaiter->EnList(iWaiters); } sl@0: inline void CPosixServer::WaitForAnyChild(CPosixRequest* aWaiter) { aWaiter->EnList(iWaitAnyQueue); } sl@0: sl@0: // sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: NONSHARABLE_CLASS(CPosixSession) : public CSession2 sl@0: { sl@0: public: sl@0: CPosixSession(CPosixServer& aServer); sl@0: virtual void ServiceL(const RMessage2& aMessage); sl@0: protected: sl@0: CPosixRequest iActive; sl@0: }; sl@0: sl@0: NONSHARABLE_CLASS(CPosixIPCSession) : public CPosixSession sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: { sl@0: public: sl@0: inline CPosixIPCSession(CPosixServer& aServer) sl@0: : CPosixSession(aServer) {} sl@0: virtual void ServiceL(const RMessage2& aMessage); // override the local ServiceL sl@0: void SetPipes(CPipeDesc* aPipes[3]); sl@0: ~CPosixIPCSession(); sl@0: sl@0: private: sl@0: TInt AreYouMyMotherL(const RMessage2& aMessage); sl@0: TInt HelloMumL(const RMessage2& aMessage); sl@0: void PipeRead(const RMessage2& aMessage); sl@0: void PipeWrite(const RMessage2& aMessage); sl@0: void PipeIoctl(const RMessage2& aMessage); sl@0: void PipeClose(const RMessage2& aMessage); sl@0: void PipeCancel(const RMessage2& aMessage); sl@0: sl@0: CPipeDesc* iPipes[3]; sl@0: }; sl@0: // sl@0: NONSHARABLE_CLASS(CProcessSystemInterface) : public MSystemInterface, public CBase sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: { sl@0: public: sl@0: CProcessSystemInterface(); sl@0: ~CProcessSystemInterface(); sl@0: sl@0: TInt Connect(); sl@0: virtual MSystemInterface& Clone(); sl@0: virtual void Release(); sl@0: virtual void TerminateProcess(int status); sl@0: sl@0: virtual int dup (int fid, int& anErrno); sl@0: virtual int dup2 (int fid, int fid2, int& anErrno); sl@0: virtual int open (const wchar_t* name, int mode, int perms, int& anErrno); sl@0: virtual int read (int fid, char* buf, unsigned long len, int& anErrno); sl@0: virtual int write (int fid, const char* buf, unsigned long len, int& anErrno); sl@0: virtual int fsync (int fid, int& anErrno); sl@0: virtual int close (int fid, int& anErrno); sl@0: virtual int lseek (int fid, int offset, int whence, int& anErrno); sl@0: virtual int fstat (int fid, struct stat *st, int& anErrno); sl@0: virtual int ioctl (int fid, int cmd, void* param, int& anErrno); sl@0: virtual int ioctl (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno); sl@0: virtual int ioctl_complete (int fid, int cmd, void* param, TRequestStatus& aStatus, int& anErrno); sl@0: virtual int ioctl_cancel (int fid, int& anErrno); sl@0: sl@0: virtual wchar_t * getcwd (wchar_t * buf, unsigned long len, int& anErrno); sl@0: sl@0: virtual int chdir (const wchar_t* path, int& anErrno); sl@0: virtual int mkdir (const wchar_t* path, int perms, int& anErrno); sl@0: virtual int rmdir (const wchar_t* path, int& anErrno); sl@0: virtual int chmod (const wchar_t* path, int perms, int& anErrno); sl@0: virtual int unlink (const wchar_t* path, int& anErrno); sl@0: virtual int stat (const wchar_t* name, struct stat *st, int& anErrno); sl@0: virtual int rename (const wchar_t* oldname, const wchar_t* newname, int& anErrno); sl@0: sl@0: virtual TInt ResolvePath (TParse& aResult, const wchar_t* path, TDes* aFilename); sl@0: sl@0: virtual int socket (int family, int style, int protocol, int& anErrno); sl@0: virtual int recvfrom (int fd, char* buf, unsigned long cnt, int flags, struct sockaddr* from, unsigned long* fromsize, int& anErrno); sl@0: virtual int sendto (int fd, const char* buf, unsigned long cnt, int flags, struct sockaddr* to, unsigned long tosize, int& anErrno); sl@0: virtual int shutdown (int fd, int how, int& anErrno); sl@0: virtual int listen (int fd, int n, int& anErrno); sl@0: virtual int accept (int fd, int& anErrno); sl@0: virtual int bind (int fd, struct sockaddr* addr, unsigned long size, int& anErrno); sl@0: virtual int connect (int fd, struct sockaddr* addr, unsigned long size, int& anErrno); sl@0: virtual int sockname (int fd, struct sockaddr* addr, unsigned long* size, int anEnd, int& anErrno); sl@0: virtual int getsockopt (int fd, int level, int opt, void* buf, unsigned long* len, int& anErrno); sl@0: virtual int setsockopt (int fd, int level, int opt, void* buf, unsigned long len, int& anErrno); sl@0: sl@0: virtual wchar_t* getenv (const wchar_t* name); sl@0: virtual void unsetenv (const wchar_t* name); sl@0: virtual int setenv (const wchar_t* name, const wchar_t* value, int rewrite, int& anErrno); sl@0: sl@0: virtual int popen3 (const wchar_t *file, const wchar_t *cmd, const wchar_t *mode, wchar_t** envp, int fids[3], int& anErrno); sl@0: virtual int waitpid (int pid, int* status, int options, int& anErrno); sl@0: sl@0: private: sl@0: int Request(TInt aFunction, int& anErrno); sl@0: void Request(TInt aFunction, int& anErrno, TRequestStatus& aStatus); sl@0: RPosixSession iSession; sl@0: PosixParams iParams; sl@0: };