| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "system.h" |
| #include <osl/thread.h> |
| |
| #include <osl/diagnose.h> |
| //#include <osl/socket.h> |
| |
| #ifndef _OSL_FILE_PATH_HELPER_H_ |
| #include "file_path_helper.h" |
| #endif |
| |
| #include "procimpl.h" |
| //#include "sockimpl.h" |
| //#include "secimpl.h" |
| |
| #include <ctype.h> |
| |
| //#ifndef _RTL_USTRING_HXX_ |
| #include <rtl/ustring.hxx> |
| //#endif |
| |
| // for exception logging |
| #include <stdio.h> |
| #include <setjmp.h> |
| |
| |
| #define MAX_ARGS 255 |
| #define PIPENAMEMASK "\\PIPE\\OSL_PIPE_%u" |
| #define SEMNAMEMASK "\\SEM32\\OSL_SEM_%u" |
| |
| typedef enum { |
| MSG_DATA, |
| MSG_END, |
| MSG_ACK, |
| MSG_REL, |
| MSG_UNKNOWN |
| } MessageType; |
| |
| typedef struct { |
| MessageType m_Type; |
| oslDescriptorFlag m_Flags; |
| oslDescriptorType m_Data; |
| HANDLE m_Value; |
| } Message; |
| |
| typedef struct { |
| HPIPE m_hPipe; |
| } Pipe; |
| |
| typedef struct _oslSocketCallbackArg { |
| HANDLE m_socket; |
| Pipe* m_pipe; |
| } oslSocketCallbackArg; |
| |
| /* process termination queue */ |
| static sal_Bool bInitSessionTerm = sal_False; |
| static const sal_Char * const SessionTermQueueName = "\\QUEUES\\SESSIONS.QUE"; |
| static HQUEUE SessionTermQueue; |
| |
| /****************************************************************************** |
| * |
| * Function Declarations |
| * |
| *****************************************************************************/ |
| |
| oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName, |
| sal_Char *pszArguments[], |
| oslProcessOption Options, |
| oslSecurity Security, |
| sal_Char *pszDirectory, |
| sal_Char *pszEnvironments[], |
| oslProcess *pProcess, |
| oslFileHandle *pInputWrite, |
| oslFileHandle *pOutputRead, |
| oslFileHandle *pErrorRead ); |
| |
| /* implemented in file.c */ |
| extern oslFileError FileURLToPath( char *, size_t, rtl_uString* ); |
| |
| static sal_Bool InitSessionTerm( void ) |
| { |
| DosCreateQueue( &SessionTermQueue, QUE_FIFO, (PCSZ) SessionTermQueueName ); |
| |
| return sal_True; |
| } |
| |
| /****************************************************************************** |
| * |
| * Functions for starting a process |
| * |
| *****************************************************************************/ |
| |
| /********************************************** |
| osl_executeProcess_WithRedirectedIO |
| *********************************************/ |
| |
| oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO( |
| rtl_uString *ustrImageName, |
| rtl_uString *ustrArguments[], |
| sal_uInt32 nArguments, |
| oslProcessOption Options, |
| oslSecurity Security, |
| rtl_uString *ustrWorkDir, |
| rtl_uString *ustrEnvironment[], |
| sal_uInt32 nEnvironmentVars, |
| oslProcess *pProcess, |
| oslFileHandle *pInputWrite, |
| oslFileHandle *pOutputRead, |
| oslFileHandle *pErrorRead |
| ) |
| { |
| |
| oslProcessError Error; |
| sal_Char* pszWorkDir=0; |
| sal_Char** pArguments=0; |
| sal_Char** pEnvironment=0; |
| unsigned int index; |
| |
| char szImagePath[PATH_MAX] = ""; |
| char szWorkDir[PATH_MAX] = ""; |
| |
| #if 0 |
| if (Options & osl_Process_SEARCHPATH) |
| { |
| const rtl::OUString PATH1; |
| OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH")); |
| |
| rtl_uString * pSearchPath = 0; |
| osl_getEnvironment (PATH.pData, &pSearchPath); |
| if (pSearchPath) |
| { |
| rtl_uString * pSearchResult = 0; |
| osl_searchPath (ustrImageName, pSearchPath, &pSearchResult); |
| if (pSearchResult) |
| { |
| rtl_uString_assign (ustrImageName, pSearchResult); |
| rtl_uString_release (pSearchResult); |
| } |
| rtl_uString_release (pSearchPath); |
| } |
| } |
| #endif |
| |
| if ( ustrImageName && ustrImageName->length ) |
| { |
| FileURLToPath( szImagePath, PATH_MAX, ustrImageName ); |
| } |
| |
| if ( ustrWorkDir != 0 && ustrWorkDir->length ) |
| { |
| FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir ); |
| pszWorkDir = szWorkDir; |
| } |
| |
| if ( pArguments == 0 && nArguments > 0 ) |
| { |
| pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) ); |
| } |
| |
| |
| for ( index = 0 ; index < nArguments ; ++index ) |
| { |
| rtl_String* strArg =0; |
| |
| |
| rtl_uString2String( &strArg, |
| rtl_uString_getStr(ustrArguments[index]), |
| rtl_uString_getLength(ustrArguments[index]), |
| osl_getThreadTextEncoding(), |
| OUSTRING_TO_OSTRING_CVTFLAGS ); |
| |
| pArguments[index]=strdup(rtl_string_getStr(strArg)); |
| rtl_string_release(strArg); |
| pArguments[index+1]=0; |
| } |
| |
| for ( index = 0 ; index < nEnvironmentVars ; ++index ) |
| { |
| rtl_String* strEnv=0; |
| |
| if ( pEnvironment == 0 ) |
| { |
| pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) ); |
| } |
| |
| rtl_uString2String( &strEnv, |
| rtl_uString_getStr(ustrEnvironment[index]), |
| rtl_uString_getLength(ustrEnvironment[index]), |
| osl_getThreadTextEncoding(), |
| OUSTRING_TO_OSTRING_CVTFLAGS ); |
| |
| pEnvironment[index]=strdup(rtl_string_getStr(strEnv)); |
| rtl_string_release(strEnv); |
| pEnvironment[index+1]=0; |
| } |
| |
| int rc, pid; |
| int saveOutput = -1, saveInput = -1, saveError = -1; |
| int stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 }; |
| FILE *i, *o, *e; |
| |
| if (pInputWrite) |
| pipe( stdInput); |
| if (pOutputRead) |
| pipe( stdOutput); |
| if (pErrorRead) |
| pipe( stdError); |
| |
| fcntl( stdInput[0], F_SETFD, FD_CLOEXEC); |
| fcntl( stdInput[1], F_SETFD, FD_CLOEXEC); |
| fcntl( stdOutput[0], F_SETFD, FD_CLOEXEC); |
| fcntl( stdOutput[1], F_SETFD, FD_CLOEXEC); |
| fcntl( stdError[0], F_SETFD, FD_CLOEXEC); |
| fcntl( stdError[1], F_SETFD, FD_CLOEXEC); |
| |
| saveInput = dup( STDIN_FILENO); |
| fcntl( saveInput, F_SETFD, FD_CLOEXEC); |
| dup2( stdInput[0], STDIN_FILENO ); |
| close( stdInput[0] ); |
| |
| saveOutput = dup( STDOUT_FILENO); |
| fcntl( saveOutput, F_SETFD, FD_CLOEXEC); |
| dup2( stdOutput[1], STDOUT_FILENO ); |
| close( stdOutput[1] ); |
| |
| saveError = dup( STDERR_FILENO); |
| fcntl( saveError, F_SETFD, FD_CLOEXEC); |
| dup2( stdError[1], STDERR_FILENO ); |
| close( stdError[1] ); |
| |
| Error = osl_psz_executeProcess(szImagePath, |
| pArguments, |
| Options, |
| Security, |
| pszWorkDir, |
| pEnvironment, |
| pProcess, |
| pInputWrite, |
| pOutputRead, |
| pErrorRead |
| ); |
| |
| if ( pInputWrite ) |
| *(pInputWrite) = osl_createFileHandleFromFD( stdInput[1] ); |
| |
| if ( pOutputRead ) |
| *(pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] ); |
| |
| if ( pErrorRead ) |
| *(pErrorRead) = osl_createFileHandleFromFD( stdError[0] ); |
| |
| // restore handles |
| dup2( saveInput, STDIN_FILENO); |
| close( saveInput); |
| dup2( saveOutput, STDOUT_FILENO); |
| close( saveOutput); |
| dup2( saveError, STDERR_FILENO); |
| close( saveError); |
| |
| if ( pArguments != 0 ) |
| { |
| for ( index = 0 ; index < nArguments ; ++index ) |
| { |
| if ( pArguments[index] != 0 ) |
| { |
| free(pArguments[index]); |
| } |
| } |
| free(pArguments); |
| } |
| |
| if ( pEnvironment != 0 ) |
| { |
| for ( index = 0 ; index < nEnvironmentVars ; ++index ) |
| { |
| if ( pEnvironment[index] != 0 ) |
| { |
| free(pEnvironment[index]); |
| } |
| } |
| free(pEnvironment); |
| } |
| |
| return Error; |
| } |
| |
| /********************************************** |
| osl_executeProcess |
| *********************************************/ |
| |
| oslProcessError SAL_CALL osl_executeProcess( |
| rtl_uString *ustrImageName, |
| rtl_uString *ustrArguments[], |
| sal_uInt32 nArguments, |
| oslProcessOption Options, |
| oslSecurity Security, |
| rtl_uString *ustrWorkDir, |
| rtl_uString *ustrEnvironment[], |
| sal_uInt32 nEnvironmentVars, |
| oslProcess *pProcess |
| ) |
| { |
| return osl_executeProcess_WithRedirectedIO( |
| ustrImageName, |
| ustrArguments, |
| nArguments, |
| Options, |
| Security, |
| ustrWorkDir, |
| ustrEnvironment, |
| nEnvironmentVars, |
| pProcess, |
| NULL, |
| NULL, |
| NULL |
| ); |
| } |
| |
| /********************************************** |
| osl_psz_executeProcess |
| *********************************************/ |
| |
| oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName, |
| sal_Char *pszArguments[], |
| oslProcessOption Options, |
| oslSecurity Security, |
| sal_Char *pszDirectory, |
| sal_Char *pszEnvironments[], |
| oslProcess *pProcess, |
| oslFileHandle *pInputWrite, |
| oslFileHandle *pOutputRead, |
| oslFileHandle *pErrorRead |
| ) |
| { |
| ULONG ulSessID = 0; /* Session ID returned */ |
| PID pidProcess; |
| APIRET rc; |
| sal_Char* pStr; |
| sal_Char* args; |
| sal_Char* envs; |
| int i; |
| int n = 1; |
| oslProcessImpl* pProcImpl; |
| ULONG nAppType, nOwnAppType; |
| ULONG nCurrentDisk, nDriveMap, nBufSize; |
| int first = 0; |
| sal_Char path[ _MAX_PATH ]; |
| sal_Char currentDir[ _MAX_PATH ]; |
| sal_Char ownfilename[ _MAX_PATH ]; |
| RESULTCODES resultCode; |
| char** p; |
| |
| /* get imagename from arg list, if not specified */ |
| if (pszImageName == NULL) |
| pszImageName = pszArguments[first++]; |
| |
| OSL_ASSERT(pszImageName != NULL); |
| |
| /* check application type */ |
| rc = DosQueryAppType( (PCSZ) pszImageName, &nAppType ); |
| if( rc != NO_ERROR ) |
| { |
| if( (rc == ERROR_FILE_NOT_FOUND) || (rc == ERROR_PATH_NOT_FOUND) ) |
| return osl_Process_E_NotFound; |
| else |
| return osl_Process_E_Unknown; |
| } |
| |
| /* backup current disk information */ |
| if(DosQueryCurrentDisk(&nCurrentDisk, &nDriveMap)) |
| { |
| nCurrentDisk = 0; |
| } |
| |
| /* backup current directory information */ |
| nBufSize = _MAX_PATH; |
| if(DosQueryCurrentDir(0, (BYTE*)currentDir, &nBufSize)) |
| { |
| *currentDir = '\0'; |
| } |
| |
| /* change to working directory */ |
| if(pszDirectory && pszDirectory[1] == ':') |
| { |
| BYTE nDrive = toupper(pszDirectory[0]) - 'A' + 1; |
| |
| if(NO_ERROR == DosSetDefaultDisk(nDrive)) |
| { |
| DosSetCurrentDir((PSZ) pszDirectory); |
| } |
| } |
| |
| /* query current executable filename and application type */ |
| { |
| CHAR szName[CCHMAXPATH]; |
| PPIB ppib; |
| PTIB ptib; |
| APIRET rc; |
| rc = DosGetInfoBlocks(&ptib, &ppib); |
| rc = DosQueryModuleName(ppib->pib_hmte, sizeof(szName), szName); |
| DosQueryAppType( (PCSZ)szName, &nOwnAppType ); |
| } |
| |
| /* combination of flags WAIT and DETACHED not supported */ |
| if( (Options & osl_Process_DETACHED) && (Options & osl_Process_WAIT) ) |
| Options &= !osl_Process_DETACHED; |
| |
| /* start in same session if possible and detached flag not set */ |
| if( ((nAppType & 0x00000007) == (nOwnAppType & 0x00000007)) |
| /* && ((Options & osl_Process_DETACHED) == 0) */ ) |
| { |
| CHAR szbuf[CCHMAXPATH]; |
| |
| /* calculate needed space for arguments */ |
| n = strlen( pszImageName ) + 1; |
| if( pszArguments ) |
| for (i = first; pszArguments[i] != NULL; i++) |
| n += strlen(pszArguments[i]) + 1; |
| |
| /* allocate space for arguments */ |
| args = (sal_Char*)malloc(n + 1); |
| pStr = args; |
| |
| /* add program name as first string to arguments */ |
| memcpy(pStr, pszImageName, strlen( pszImageName ) ); |
| pStr += strlen( pszImageName ); |
| *pStr++ = '\0'; |
| |
| /* add given strings to arguments */ |
| if( pszArguments ) |
| for (i = first; pszArguments[i] != NULL; i++) |
| { |
| memcpy(pStr, pszArguments[i], strlen( pszArguments[i] ) ); |
| pStr += strlen( pszArguments[i] ); |
| if (pszArguments[i+1] != NULL) |
| *pStr++ = ' '; |
| } |
| |
| /* set end marker for arguments */ |
| *pStr++ = '\0'; |
| *pStr = '\0'; |
| |
| OSL_TRACE( "osl_executeProcess with DosExecPgm (args: %s)\n", args ); |
| |
| /* calculate needed space for environment: since environment var search |
| is a linear scan of the current environment, we place new variables |
| before existing ones; so the child will find new definitions before |
| olders; this doesn't require us to replace existing vars */ |
| // existing environment size |
| n = 0; |
| p = environ; |
| while( *p) |
| { |
| int l = strlen( *p); |
| n += l + 1; |
| p++; |
| } |
| // new env size (if exists) |
| if( pszEnvironments ) |
| { |
| for (i = 0; pszEnvironments[i] != NULL; i++) |
| n += strlen(pszEnvironments[i]) + 1; |
| } |
| /* allocate space for environment */ |
| envs = (sal_Char*)malloc(n + 1); |
| pStr = envs; |
| |
| // add new vars |
| if( pszEnvironments ) |
| { |
| /* add given strings to environment */ |
| for (i = 0; pszEnvironments[i] != NULL; i++) |
| { |
| memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) ); |
| pStr += strlen( pszEnvironments[i] ); |
| *pStr++ = '\0'; |
| } |
| } |
| // add existing vars |
| p = environ; |
| while( *p) |
| { |
| memcpy(pStr, *p, strlen( *p ) ); |
| pStr += strlen( *p ); |
| *pStr++ = '\0'; |
| p++; |
| } |
| /* set end marker for environment */ |
| *pStr = '\0'; |
| |
| |
| if(Options & osl_Process_DETACHED) |
| { |
| rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_BACKGROUND, |
| (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName ); |
| } |
| else |
| { |
| rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_ASYNCRESULT, |
| (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName ); |
| } |
| |
| pidProcess = resultCode.codeTerminate; |
| |
| /* cleanup */ |
| free(envs); |
| free(args); |
| |
| /* error handling */ |
| if( rc != NO_ERROR ) |
| return osl_Process_E_Unknown; |
| } |
| |
| else |
| { |
| STARTDATA SData = { 0 }; |
| UCHAR achObjBuf[ 256 ] = { 0 }; |
| |
| /* combine arguments separated by spaces */ |
| if( pszArguments ) |
| { |
| for (i = first; pszArguments[i] != NULL; i++) |
| n += strlen(pszArguments[i]) + 1; |
| // YD DosStartSession requires low-mem buffers! |
| args = (sal_Char*)_tmalloc(n); |
| *args = '\0'; |
| for (i = first; pszArguments[i] != NULL; i++) |
| { |
| strcat(args, pszArguments[i]); |
| strcat(args, " "); |
| } |
| } |
| else |
| args = NULL; |
| |
| /* combine environment separated by NULL */ |
| if( pszEnvironments ) |
| { |
| for (i = 0; pszEnvironments[i] != NULL; i++) |
| n += strlen(pszEnvironments[i]) + 1; |
| // YD DosStartSession requires low-mem buffers! |
| envs = (sal_Char*)_tmalloc(n + 1); |
| pStr = (sal_Char*)envs; |
| for (i = 0; pszEnvironments[i] != NULL; i++) |
| { |
| memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) ); |
| pStr += strlen( pszEnvironments[i] ); |
| *pStr = '\0'; |
| pStr++; |
| } |
| *pStr = '\0'; |
| } |
| else |
| envs = NULL; |
| |
| /* initialize data structure */ |
| memset( &SData, 0, sizeof( STARTDATA ) ); |
| SData.Length = sizeof(STARTDATA); |
| |
| OSL_TRACE( "osl_executeProcess with DosStartSession (args: %s)\n", args ); |
| |
| /* OS/2 Application ? */ |
| if(nAppType & 0x00000007) |
| { |
| |
| /* inherit options from parent */ |
| SData.InheritOpt = SSF_INHERTOPT_PARENT; |
| |
| switch (Options & (osl_Process_NORMAL | osl_Process_MINIMIZED | |
| osl_Process_MAXIMIZED | osl_Process_FULLSCREEN)) |
| { |
| case osl_Process_MINIMIZED: |
| SData.SessionType = SSF_TYPE_DEFAULT; |
| SData.PgmControl |= SSF_CONTROL_MINIMIZE; |
| break; |
| |
| case osl_Process_MAXIMIZED: |
| SData.SessionType = SSF_TYPE_DEFAULT; |
| SData.PgmControl |= SSF_CONTROL_MAXIMIZE; |
| break; |
| |
| case osl_Process_FULLSCREEN: |
| SData.SessionType = SSF_TYPE_FULLSCREEN; |
| break; |
| |
| default: |
| SData.SessionType = SSF_TYPE_DEFAULT; |
| } /* switch */ |
| } |
| |
| |
| if( Options & osl_Process_DETACHED ) |
| { |
| /* start an independent session */ |
| SData.Related = SSF_RELATED_INDEPENDENT; |
| SData.TermQ = NULL; |
| } |
| else |
| { |
| /* start a child session and set Termination Queue */ |
| SData.Related = SSF_RELATED_CHILD; |
| |
| if(! bInitSessionTerm) |
| bInitSessionTerm = InitSessionTerm(); |
| |
| SData.TermQ = (BYTE*) SessionTermQueueName; |
| } |
| |
| SData.FgBg = SSF_FGBG_FORE; /* start session in foreground */ |
| SData.TraceOpt = SSF_TRACEOPT_NONE; /* No trace */ |
| |
| SData.PgmTitle = NULL; |
| SData.PgmInputs = (BYTE*)args; |
| SData.PgmName = (PSZ) pszImageName; |
| SData.Environment = (BYTE*)envs; |
| |
| if( Options & osl_Process_HIDDEN ) |
| SData.PgmControl |= SSF_CONTROL_INVISIBLE; |
| else |
| SData.PgmControl |= SSF_CONTROL_VISIBLE; |
| |
| SData.ObjectBuffer = (PSZ) achObjBuf; |
| SData.ObjectBuffLen = (ULONG) sizeof(achObjBuf); |
| |
| |
| /* Start the session */ |
| rc = DosStartSession( &SData, &ulSessID, &pidProcess ); |
| |
| /* ignore error "session started in background" */ |
| if( rc == ERROR_SMG_START_IN_BACKGROUND ) |
| rc = NO_ERROR; |
| |
| |
| if(envs) |
| _tfree(envs); |
| if(args) |
| _tfree(args); |
| |
| if( rc != NO_ERROR ) |
| return osl_Process_E_Unknown; |
| |
| } /* else */ |
| |
| |
| /* restore current disk */ |
| if(nCurrentDisk) |
| { |
| DosSetDefaultDisk(nCurrentDisk); |
| } |
| |
| /* restore current drive information */ |
| if(*currentDir) |
| { |
| DosSetCurrentDir((PCSZ)currentDir); |
| } |
| |
| /* allocate intern process structure and store child process ID */ |
| pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl)); |
| pProcImpl->pProcess = pidProcess; |
| pProcImpl->nSessionID = ulSessID; |
| |
| pProcImpl->bResultCodeValid = FALSE; |
| |
| if( Options & osl_Process_WAIT ) |
| osl_joinProcess(pProcImpl); |
| |
| *pProcess = (oslProcess)pProcImpl; |
| |
| if( rc == NO_ERROR ) |
| return osl_Process_E_None; |
| else |
| |
| return osl_Process_E_Unknown; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| |
| oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process) |
| { |
| if (Process == NULL) |
| return osl_Process_E_Unknown; |
| |
| /* Stop the session */ |
| DosStopSession( STOP_SESSION_SPECIFIED, ((oslProcessImpl*)Process)->nSessionID ); |
| |
| return osl_Process_E_None; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| |
| oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident) |
| { |
| HANDLE hProcess; |
| oslProcessImpl* pProcImpl; |
| |
| /* check, if given PID is a valid process */ |
| if (FALSE) |
| { |
| pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl)); |
| /* |
| pProcImpl->pProcess = pidProcess; |
| pProcImpl->nSessionID = ulSessID; |
| */ |
| } |
| else |
| pProcImpl = NULL; |
| |
| return (pProcImpl); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| |
| void SAL_CALL osl_freeProcessHandle(oslProcess Process) |
| { |
| /* free intern process structure */ |
| if (Process != NULL) |
| free((oslProcessImpl*)Process); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| |
| oslProcessError SAL_CALL osl_joinProcess(oslProcess Process) |
| { |
| oslProcessImpl* pProcImpl = (oslProcessImpl*) Process; |
| APIRET rc; |
| |
| if (Process == NULL) |
| return osl_Process_E_Unknown; |
| |
| /* process of same session ? */ |
| if( pProcImpl->nSessionID == 0 ) |
| { |
| RESULTCODES resultCode; |
| PID pidEnded; |
| |
| rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode, |
| &pidEnded, pProcImpl->pProcess ); |
| |
| if( rc == NO_ERROR ) |
| { |
| pProcImpl->nResultCode = resultCode.codeResult; |
| pProcImpl->bResultCodeValid = TRUE; |
| |
| return osl_Process_E_None; |
| } |
| } |
| else |
| { |
| ULONG pcbData, ulElement = 0; |
| REQUESTDATA rdData; |
| BYTE bPriority; |
| struct { |
| USHORT SessionID; |
| USHORT ReturnValue; |
| } *pvBuffer; |
| |
| /* search/wait for the correct entry in termination queue */ |
| while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData, |
| (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT, |
| &bPriority, NULLHANDLE )) == NO_ERROR ) |
| { |
| |
| if( pvBuffer->SessionID == pProcImpl->nSessionID ) |
| { |
| pProcImpl->nResultCode = pvBuffer->ReturnValue; |
| pProcImpl->bResultCodeValid = TRUE; |
| |
| /* remove item from queue */ |
| rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData, |
| (PPVOID)&pvBuffer, ulElement, DCWW_WAIT, |
| &bPriority, NULLHANDLE ); |
| |
| if( rc == NO_ERROR ) |
| return osl_Process_E_None; |
| else |
| return osl_Process_E_Unknown; |
| } |
| } /* while */ |
| } |
| return osl_Process_E_Unknown; |
| } |
| |
| /***************************************************************************/ |
| |
| //YD FIXME incomplete! |
| oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout) |
| { |
| return osl_joinProcess( Process); |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| |
| oslProcessError SAL_CALL osl_getCommandArgs( sal_Char* pszBuffer, sal_uInt32 Max) |
| { |
| |
| static int CmdLen = -1; |
| static sal_Char CmdLine[_MAX_CMD]; |
| |
| OSL_ASSERT(pszBuffer); |
| OSL_ASSERT(Max > 1); |
| |
| /* Query commandline during first call of function only */ |
| if (CmdLen < 0) |
| { |
| sal_Bool bEscaped = sal_False; |
| sal_Bool bSeparated = sal_True; |
| sal_Char* pszBufferOrg = pszBuffer; |
| sal_Char* pszCmdLine; |
| |
| /* get pointer to commandline */ |
| { |
| PTIB pptib = NULL; |
| PPIB pppib = NULL; |
| |
| DosGetInfoBlocks(&pptib, &pppib); |
| pszCmdLine = pppib->pib_pchcmd; |
| } |
| |
| /* skip first string */ |
| while( *pszCmdLine ) |
| pszCmdLine++; |
| |
| /* concatenate commandline arguments for the given string */ |
| Max -= 2; |
| while ( !((*pszCmdLine == '\0') && (*(pszCmdLine + 1) == '\0')) && (Max > 0)) |
| { |
| /* |
| * C-Runtime expects char to be unsigned and so to be |
| * preceded with 00 instead of FF when converting to int |
| */ |
| int n = *((unsigned char *) pszCmdLine); |
| if (! (isspace(n) || (*pszCmdLine == '\0')) ) |
| { |
| if (*pszCmdLine == '"') |
| { |
| if (*(pszCmdLine + 1) != '"') |
| bEscaped = ! bEscaped; |
| else |
| { |
| pszCmdLine++; |
| *pszBuffer++ = *pszCmdLine; |
| Max--; |
| } |
| } |
| else |
| { |
| *pszBuffer++ = *pszCmdLine; |
| Max--; |
| } |
| bSeparated = sal_False; |
| } |
| else |
| { |
| if (bEscaped) |
| *pszBuffer++ = *pszCmdLine; |
| else |
| if (! bSeparated) |
| { |
| *pszBuffer++ = '\0'; |
| bSeparated = sal_True; |
| } |
| Max--; |
| } |
| |
| pszCmdLine++; |
| } |
| |
| *pszBuffer++ = '\0'; |
| *pszBuffer++ = '\0'; |
| |
| /* restore pointer and save commandline for next query */ |
| CmdLen = pszBuffer - pszBufferOrg; |
| pszBuffer = pszBufferOrg; |
| memcpy( CmdLine, pszBuffer, CmdLen ); |
| } |
| else |
| memcpy( pszBuffer, CmdLine, CmdLen ); |
| |
| OSL_TRACE( "osl_getCommandArgs (args: %s)\n", pszBuffer ); |
| |
| return osl_Process_E_None; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| |
| oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, |
| oslProcessInfo* pInfo) |
| { |
| if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo))) |
| return osl_Process_E_Unknown; |
| |
| pInfo->Fields = 0; |
| |
| if (Fields & osl_Process_IDENTIFIER) |
| { |
| if( Process == NULL ) |
| { |
| PTIB pptib = NULL; |
| PPIB pppib = NULL; |
| |
| DosGetInfoBlocks( &pptib, &pppib ); |
| pInfo->Ident = pppib->pib_ulpid; |
| } |
| else |
| pInfo->Ident = ((oslProcessImpl*)Process)->pProcess; |
| |
| pInfo->Fields |= osl_Process_IDENTIFIER; |
| } |
| |
| if (Fields & osl_Process_EXITCODE) |
| { |
| oslProcessImpl* pProcImpl = (oslProcessImpl*) Process; |
| |
| if( pProcImpl->bResultCodeValid ) |
| { |
| pInfo->Code = pProcImpl->nResultCode; |
| pInfo->Fields |= osl_Process_EXITCODE; |
| } |
| else |
| { |
| APIRET rc; |
| |
| if( pProcImpl->nSessionID == 0 ) |
| { |
| RESULTCODES resultCode; |
| PID pidEnded; |
| |
| rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode, |
| &pidEnded, pProcImpl->pProcess ); |
| |
| if( rc == NO_ERROR ) |
| { |
| pProcImpl->nResultCode = resultCode.codeResult; |
| pProcImpl->bResultCodeValid = TRUE; |
| |
| pInfo->Code = pProcImpl->nResultCode; |
| pInfo->Fields |= osl_Process_EXITCODE; |
| |
| return osl_Process_E_None; |
| } |
| } |
| else |
| { |
| ULONG pcbData, ulElement = 0; |
| REQUESTDATA rdData; |
| BYTE bPriority; |
| struct { |
| USHORT SessionID; |
| USHORT ReturnValue; |
| } *pvBuffer; |
| |
| /* search/wait for the correct entry in termination queue */ |
| while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData, |
| (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT, |
| &bPriority, NULLHANDLE )) == NO_ERROR ) |
| { |
| |
| if( pvBuffer->SessionID == pProcImpl->nSessionID ) |
| { |
| pProcImpl->nResultCode = pvBuffer->ReturnValue; |
| pProcImpl->bResultCodeValid = TRUE; |
| |
| pInfo->Code = pProcImpl->nResultCode; |
| pInfo->Fields |= osl_Process_EXITCODE; |
| |
| /* remove item from queue */ |
| rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData, |
| (PPVOID)&pvBuffer, ulElement, DCWW_WAIT, |
| &bPriority, NULLHANDLE ); |
| |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| if (Fields & osl_Process_HEAPUSAGE) |
| { |
| } |
| if (Fields & osl_Process_CPUTIMES) |
| { |
| } |
| |
| return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown; |
| } |