xref: /AOO41X/main/sal/osl/os2/process.c (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "system.h"
25 #include <osl/thread.h>
26 
27 #include <osl/diagnose.h>
28 //#include <osl/socket.h>
29 
30 #ifndef _OSL_FILE_PATH_HELPER_H_
31 #include "file_path_helper.h"
32 #endif
33 
34 #include "procimpl.h"
35 //#include "sockimpl.h"
36 //#include "secimpl.h"
37 
38 #include <ctype.h>
39 
40 //#ifndef _RTL_USTRING_HXX_
41 #include <rtl/ustring.hxx>
42 //#endif
43 
44 // for exception logging
45 #include <stdio.h>
46 #include <setjmp.h>
47 #include "helpers/except.h"
48 
49 
50 #define MAX_ARGS 255
51 #define PIPENAMEMASK  "\\PIPE\\OSL_PIPE_%u"
52 #define SEMNAMEMASK   "\\SEM32\\OSL_SEM_%u"
53 
54 typedef enum {
55     MSG_DATA,
56     MSG_END,
57     MSG_ACK,
58     MSG_REL,
59     MSG_UNKNOWN
60 } MessageType;
61 
62 typedef struct {
63     MessageType       m_Type;
64     oslDescriptorFlag m_Flags;
65     oslDescriptorType m_Data;
66     HANDLE            m_Value;
67 } Message;
68 
69 typedef struct {
70     HPIPE   m_hPipe;
71 } Pipe;
72 
73 typedef struct _oslSocketCallbackArg {
74     HANDLE  m_socket;
75     Pipe*   m_pipe;
76 } oslSocketCallbackArg;
77 
78 /* process termination queue */
79 static sal_Bool            bInitSessionTerm = sal_False;
80 static const sal_Char * const SessionTermQueueName = "\\QUEUES\\SESSIONS.QUE";
81 static HQUEUE             SessionTermQueue;
82 
83 /******************************************************************************
84  *
85  *                  Function Declarations
86  *
87  *****************************************************************************/
88 
89 oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
90                                                 sal_Char *pszArguments[],
91                                                 oslProcessOption Options,
92                                                 oslSecurity Security,
93                                                 sal_Char *pszDirectory,
94                                                 sal_Char *pszEnvironments[],
95                                                 oslProcess *pProcess,
96                                                 oslFileHandle *pInputWrite,
97                                                 oslFileHandle *pOutputRead,
98                                                 oslFileHandle *pErrorRead );
99 
100 /* implemented in file.c */
101 extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
102 
103 static sal_Bool InitSessionTerm( void )
104 {
105     DosCreateQueue( &SessionTermQueue, QUE_FIFO, (PCSZ) SessionTermQueueName );
106 
107     return sal_True;
108 }
109 
110 /******************************************************************************
111  *
112  *                  Functions for starting a process
113  *
114  *****************************************************************************/
115 
116 /**********************************************
117  osl_executeProcess_WithRedirectedIO
118  *********************************************/
119 
120 oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
121                                             rtl_uString *ustrImageName,
122                                             rtl_uString *ustrArguments[],
123                                             sal_uInt32   nArguments,
124                                             oslProcessOption Options,
125                                             oslSecurity Security,
126                                             rtl_uString *ustrWorkDir,
127                                             rtl_uString *ustrEnvironment[],
128                                             sal_uInt32   nEnvironmentVars,
129                                             oslProcess *pProcess,
130                                             oslFileHandle   *pInputWrite,
131                                             oslFileHandle   *pOutputRead,
132                                             oslFileHandle   *pErrorRead
133                                             )
134 {
135 
136     oslProcessError Error;
137     sal_Char* pszWorkDir=0;
138     sal_Char** pArguments=0;
139     sal_Char** pEnvironment=0;
140     unsigned int index;
141 
142     char szImagePath[PATH_MAX] = "";
143     char szWorkDir[PATH_MAX] = "";
144 
145 #if 0
146     if (Options & osl_Process_SEARCHPATH)
147     {
148         const rtl::OUString PATH1;
149         OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH"));
150 
151         rtl_uString * pSearchPath = 0;
152         osl_getEnvironment (PATH.pData, &pSearchPath);
153         if (pSearchPath)
154         {
155             rtl_uString * pSearchResult = 0;
156             osl_searchPath (ustrImageName, pSearchPath, &pSearchResult);
157             if (pSearchResult)
158             {
159                 rtl_uString_assign (ustrImageName, pSearchResult);
160                 rtl_uString_release (pSearchResult);
161             }
162             rtl_uString_release (pSearchPath);
163         }
164     }
165 #endif
166 
167     if ( ustrImageName && ustrImageName->length )
168     {
169         FileURLToPath( szImagePath, PATH_MAX, ustrImageName );
170     }
171 
172     if ( ustrWorkDir != 0 && ustrWorkDir->length )
173     {
174         FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir );
175         pszWorkDir = szWorkDir;
176     }
177 
178     if ( pArguments == 0 && nArguments > 0 )
179     {
180         pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) );
181     }
182 
183 
184     for ( index = 0 ; index < nArguments ; ++index )
185     {
186         rtl_String* strArg =0;
187 
188 
189         rtl_uString2String( &strArg,
190                             rtl_uString_getStr(ustrArguments[index]),
191                             rtl_uString_getLength(ustrArguments[index]),
192                             osl_getThreadTextEncoding(),
193                             OUSTRING_TO_OSTRING_CVTFLAGS );
194 
195         pArguments[index]=strdup(rtl_string_getStr(strArg));
196         rtl_string_release(strArg);
197         pArguments[index+1]=0;
198     }
199 
200     for ( index = 0 ; index < nEnvironmentVars ; ++index )
201     {
202         rtl_String* strEnv=0;
203 
204         if ( pEnvironment == 0 )
205         {
206             pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) );
207         }
208 
209         rtl_uString2String( &strEnv,
210                             rtl_uString_getStr(ustrEnvironment[index]),
211                             rtl_uString_getLength(ustrEnvironment[index]),
212                             osl_getThreadTextEncoding(),
213                             OUSTRING_TO_OSTRING_CVTFLAGS );
214 
215         pEnvironment[index]=strdup(rtl_string_getStr(strEnv));
216         rtl_string_release(strEnv);
217         pEnvironment[index+1]=0;
218     }
219 
220     int     rc, pid;
221     int     saveOutput = -1, saveInput = -1, saveError = -1;
222     int     stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 };
223     FILE    *i, *o, *e;
224 
225     if (pInputWrite)
226         pipe( stdInput);
227     if (pOutputRead)
228         pipe( stdOutput);
229     if (pErrorRead)
230         pipe( stdError);
231 
232     fcntl( stdInput[0], F_SETFD, FD_CLOEXEC);
233     fcntl( stdInput[1], F_SETFD, FD_CLOEXEC);
234     fcntl( stdOutput[0], F_SETFD, FD_CLOEXEC);
235     fcntl( stdOutput[1], F_SETFD, FD_CLOEXEC);
236     fcntl( stdError[0], F_SETFD, FD_CLOEXEC);
237     fcntl( stdError[1], F_SETFD, FD_CLOEXEC);
238 
239     saveInput = dup( STDIN_FILENO);
240     fcntl( saveInput, F_SETFD, FD_CLOEXEC);
241     dup2( stdInput[0], STDIN_FILENO );
242     close( stdInput[0] );
243 
244     saveOutput = dup( STDOUT_FILENO);
245     fcntl( saveOutput, F_SETFD, FD_CLOEXEC);
246     dup2( stdOutput[1], STDOUT_FILENO );
247     close( stdOutput[1] );
248 
249     saveError = dup( STDERR_FILENO);
250     fcntl( saveError, F_SETFD, FD_CLOEXEC);
251     dup2( stdError[1], STDERR_FILENO );
252     close( stdError[1] );
253 
254     Error = osl_psz_executeProcess(szImagePath,
255                                    pArguments,
256                                    Options,
257                                    Security,
258                                    pszWorkDir,
259                                    pEnvironment,
260                                    pProcess,
261                                    pInputWrite,
262                                    pOutputRead,
263                                    pErrorRead
264                                    );
265 
266     if ( pInputWrite )
267         *(pInputWrite) = osl_createFileHandleFromFD( stdInput[1] );
268 
269     if ( pOutputRead )
270         *(pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] );
271 
272     if ( pErrorRead )
273         *(pErrorRead) = osl_createFileHandleFromFD( stdError[0] );
274 
275     // restore handles
276     dup2( saveInput, STDIN_FILENO);
277     close( saveInput);
278     dup2( saveOutput, STDOUT_FILENO);
279     close( saveOutput);
280     dup2( saveError, STDERR_FILENO);
281     close( saveError);
282 
283     if ( pArguments != 0 )
284     {
285         for ( index = 0 ; index < nArguments ; ++index )
286         {
287             if ( pArguments[index] != 0 )
288             {
289                 free(pArguments[index]);
290             }
291         }
292         free(pArguments);
293     }
294 
295     if ( pEnvironment != 0 )
296     {
297         for ( index = 0 ; index < nEnvironmentVars ; ++index )
298         {
299             if ( pEnvironment[index] != 0 )
300             {
301                 free(pEnvironment[index]);
302             }
303         }
304         free(pEnvironment);
305     }
306 
307     return Error;
308 }
309 
310 /**********************************************
311  osl_executeProcess
312  *********************************************/
313 
314 oslProcessError SAL_CALL osl_executeProcess(
315                                             rtl_uString *ustrImageName,
316                                             rtl_uString *ustrArguments[],
317                                             sal_uInt32   nArguments,
318                                             oslProcessOption Options,
319                                             oslSecurity Security,
320                                             rtl_uString *ustrWorkDir,
321                                             rtl_uString *ustrEnvironment[],
322                                             sal_uInt32   nEnvironmentVars,
323                                             oslProcess *pProcess
324                                             )
325 {
326     return osl_executeProcess_WithRedirectedIO(
327         ustrImageName,
328         ustrArguments,
329         nArguments,
330         Options,
331         Security,
332         ustrWorkDir,
333         ustrEnvironment,
334         nEnvironmentVars,
335         pProcess,
336         NULL,
337         NULL,
338         NULL
339         );
340 }
341 
342 /**********************************************
343  osl_psz_executeProcess
344  *********************************************/
345 
346 oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
347                                                 sal_Char *pszArguments[],
348                                                 oslProcessOption Options,
349                                                 oslSecurity Security,
350                                                 sal_Char *pszDirectory,
351                                                 sal_Char *pszEnvironments[],
352                                                 oslProcess *pProcess,
353                                                 oslFileHandle   *pInputWrite,
354                                                 oslFileHandle   *pOutputRead,
355                                                 oslFileHandle   *pErrorRead
356                                                 )
357 {
358     ULONG ulSessID  = 0;          /* Session ID returned          */
359     PID pidProcess;
360     APIRET rc;
361     sal_Char* pStr;
362     sal_Char*        args;
363     sal_Char*        envs;
364     int i;
365     int n = 1;
366     oslProcessImpl* pProcImpl;
367     ULONG nAppType, nOwnAppType;
368     ULONG nCurrentDisk, nDriveMap, nBufSize;
369     int  first = 0;
370     sal_Char path[ _MAX_PATH ];
371     sal_Char currentDir[ _MAX_PATH ];
372     sal_Char ownfilename[ _MAX_PATH ];
373     RESULTCODES resultCode;
374     char** p;
375 
376     /* get imagename from arg list, if not specified */
377     if (pszImageName == NULL)
378         pszImageName = pszArguments[first++];
379 
380     OSL_ASSERT(pszImageName != NULL);
381 
382     /* check application type */
383     rc = DosQueryAppType( (PCSZ) pszImageName, &nAppType );
384     if( rc != NO_ERROR )
385     {
386         if( (rc == ERROR_FILE_NOT_FOUND) || (rc == ERROR_PATH_NOT_FOUND) )
387             return osl_Process_E_NotFound;
388         else
389             return osl_Process_E_Unknown;
390     }
391 
392     /* backup current disk information */
393     if(DosQueryCurrentDisk(&nCurrentDisk, &nDriveMap))
394     {
395         nCurrentDisk = 0;
396     }
397 
398     /* backup current directory information */
399     nBufSize = _MAX_PATH;
400     if(DosQueryCurrentDir(0, (BYTE*)currentDir, &nBufSize))
401     {
402         *currentDir = '\0';
403     }
404 
405     /* change to working directory */
406     if(pszDirectory && pszDirectory[1] == ':')
407     {
408         BYTE nDrive = toupper(pszDirectory[0]) - 'A' + 1;
409 
410         if(NO_ERROR == DosSetDefaultDisk(nDrive))
411         {
412             DosSetCurrentDir((PSZ) pszDirectory);
413         }
414     }
415 
416     /* query current executable filename and application type */
417     {
418         CHAR    szName[CCHMAXPATH];
419         PPIB    ppib;
420         PTIB    ptib;
421         APIRET  rc;
422         rc = DosGetInfoBlocks(&ptib, &ppib);
423         rc = DosQueryModuleName(ppib->pib_hmte, sizeof(szName), szName);
424         DosQueryAppType( (PCSZ)szName, &nOwnAppType );
425     }
426 
427     /* combination of flags WAIT and DETACHED not supported */
428     if( (Options & osl_Process_DETACHED) && (Options & osl_Process_WAIT) )
429         Options &= !osl_Process_DETACHED;
430 
431     /* start in same session if possible and detached flag not set */
432     if( ((nAppType & 0x00000007) == (nOwnAppType & 0x00000007))
433 /*      && ((Options & osl_Process_DETACHED) == 0) */ )
434     {
435         CHAR szbuf[CCHMAXPATH];
436 
437         /* calculate needed space for arguments */
438         n = strlen( pszImageName ) + 1;
439         if( pszArguments )
440             for (i = first; pszArguments[i] != NULL; i++)
441                 n += strlen(pszArguments[i]) + 1;
442 
443         /* allocate space for arguments */
444         args = (sal_Char*)malloc(n + 1);
445         pStr = args;
446 
447         /* add program name as first string to arguments */
448         memcpy(pStr, pszImageName, strlen( pszImageName ) );
449         pStr += strlen( pszImageName );
450         *pStr++ = '\0';
451 
452         /* add given strings to arguments */
453         if( pszArguments )
454             for (i = first; pszArguments[i] != NULL; i++)
455             {
456                 memcpy(pStr, pszArguments[i], strlen( pszArguments[i] ) );
457                 pStr += strlen( pszArguments[i] );
458                 if (pszArguments[i+1] != NULL)
459                     *pStr++ = ' ';
460             }
461 
462         /* set end marker for arguments */
463         *pStr++ = '\0';
464         *pStr = '\0';
465 
466         OSL_TRACE( "osl_executeProcess with DosExecPgm (args: %s)\n", args );
467 
468         /* calculate needed space for environment: since enviroment var search
469            is a linear scan of the current enviroment, we place new variables
470            before existing ones; so the child will find new definitions before
471            olders; this doesn't require us to replace existing vars */
472         // existing enviroment size
473         n = 0;
474         p = environ;
475         while( *p)
476         {
477             int l = strlen( *p);
478             n += l + 1;
479             p++;
480         }
481         // new env size (if exists)
482         if( pszEnvironments )
483         {
484             for (i = 0; pszEnvironments[i] != NULL; i++)
485                 n += strlen(pszEnvironments[i]) + 1;
486         }
487         /* allocate space for environment */
488         envs = (sal_Char*)malloc(n + 1);
489         pStr = envs;
490 
491         // add new vars
492         if( pszEnvironments )
493         {
494             /* add given strings to environment */
495             for (i = 0; pszEnvironments[i] != NULL; i++)
496             {
497                 memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) );
498                 pStr += strlen( pszEnvironments[i] );
499                 *pStr++ = '\0';
500             }
501         }
502         // add existing vars
503         p = environ;
504         while( *p)
505         {
506             memcpy(pStr, *p, strlen( *p ) );
507             pStr += strlen( *p );
508             *pStr++ = '\0';
509             p++;
510         }
511         /* set end marker for environment */
512         *pStr = '\0';
513 
514 
515         if(Options & osl_Process_DETACHED)
516         {
517             rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_BACKGROUND,
518                              (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName );
519         }
520         else
521         {
522             rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_ASYNCRESULT,
523                              (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName );
524         }
525 
526         pidProcess = resultCode.codeTerminate;
527 
528         /* cleanup */
529         free(envs);
530         free(args);
531 
532         /* error handling */
533         if( rc != NO_ERROR )
534             return osl_Process_E_Unknown;
535     }
536 
537     else
538     {
539         STARTDATA SData = { 0 };
540         UCHAR achObjBuf[ 256 ] = { 0 };
541 
542         /* combine arguments separated by spaces */
543         if( pszArguments )
544         {
545             for (i = first; pszArguments[i] != NULL; i++)
546                 n += strlen(pszArguments[i]) + 1;
547             // YD DosStartSession requires low-mem buffers!
548             args = (sal_Char*)_tmalloc(n);
549             *args = '\0';
550             for (i = first; pszArguments[i] != NULL; i++)
551             {
552                 strcat(args, pszArguments[i]);
553                 strcat(args, " ");
554             }
555         }
556         else
557             args = NULL;
558 
559         /* combine environment separated by NULL */
560         if( pszEnvironments )
561         {
562             for (i = 0; pszEnvironments[i] != NULL; i++)
563                 n += strlen(pszEnvironments[i]) + 1;
564             // YD DosStartSession requires low-mem buffers!
565             envs = (sal_Char*)_tmalloc(n + 1);
566             pStr = (sal_Char*)envs;
567             for (i = 0; pszEnvironments[i] != NULL; i++)
568             {
569                 memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) );
570                 pStr += strlen( pszEnvironments[i] );
571                 *pStr = '\0';
572                 pStr++;
573             }
574             *pStr = '\0';
575         }
576         else
577             envs = NULL;
578 
579         /* initialize data structure */
580         memset( &SData, 0, sizeof( STARTDATA ) );
581         SData.Length  = sizeof(STARTDATA);
582 
583         OSL_TRACE( "osl_executeProcess with DosStartSession (args: %s)\n", args );
584 
585         /* OS/2 Application ? */
586         if(nAppType & 0x00000007)
587         {
588 
589             /* inherit options from parent */
590             SData.InheritOpt = SSF_INHERTOPT_PARENT;
591 
592             switch (Options & (osl_Process_NORMAL | osl_Process_MINIMIZED |
593                             osl_Process_MAXIMIZED | osl_Process_FULLSCREEN))
594             {
595                 case osl_Process_MINIMIZED:
596                     SData.SessionType = SSF_TYPE_DEFAULT;
597                     SData.PgmControl |= SSF_CONTROL_MINIMIZE;
598                     break;
599 
600                 case osl_Process_MAXIMIZED:
601                     SData.SessionType = SSF_TYPE_DEFAULT;
602                     SData.PgmControl |= SSF_CONTROL_MAXIMIZE;
603                     break;
604 
605                 case osl_Process_FULLSCREEN:
606                     SData.SessionType = SSF_TYPE_FULLSCREEN;
607                     break;
608 
609                 default:
610                     SData.SessionType = SSF_TYPE_DEFAULT;
611             } /* switch */
612         }
613 
614 
615         if( Options & osl_Process_DETACHED )
616         {
617             /* start an independent session */
618             SData.Related = SSF_RELATED_INDEPENDENT;
619             SData.TermQ = NULL;
620         }
621         else
622         {
623             /* start a child session and set Termination Queue */
624             SData.Related = SSF_RELATED_CHILD;
625 
626             if(! bInitSessionTerm)
627                 bInitSessionTerm = InitSessionTerm();
628 
629             SData.TermQ = (BYTE*) SessionTermQueueName;
630         }
631 
632         SData.FgBg  = SSF_FGBG_FORE;      /* start session in foreground  */
633         SData.TraceOpt = SSF_TRACEOPT_NONE;   /* No trace                */
634 
635         SData.PgmTitle = NULL;
636         SData.PgmInputs = (BYTE*)args;
637         SData.PgmName = (PSZ) pszImageName;
638         SData.Environment = (BYTE*)envs;
639 
640         if( Options & osl_Process_HIDDEN )
641             SData.PgmControl |= SSF_CONTROL_INVISIBLE;
642         else
643             SData.PgmControl |= SSF_CONTROL_VISIBLE;
644 
645         SData.ObjectBuffer  = (PSZ) achObjBuf;
646         SData.ObjectBuffLen = (ULONG) sizeof(achObjBuf);
647 
648 
649         /* Start the session */
650         rc = DosStartSession( &SData, &ulSessID, &pidProcess );
651 
652         /* ignore error "session started in background" */
653         if( rc == ERROR_SMG_START_IN_BACKGROUND )
654             rc = NO_ERROR;
655 
656 
657         if(envs)
658             _tfree(envs);
659         if(args)
660             _tfree(args);
661 
662         if( rc != NO_ERROR )
663             return osl_Process_E_Unknown;
664 
665     } /* else */
666 
667 
668     /* restore current disk */
669     if(nCurrentDisk)
670     {
671         DosSetDefaultDisk(nCurrentDisk);
672     }
673 
674     /* restore current drive information */
675     if(*currentDir)
676     {
677         DosSetCurrentDir((PCSZ)currentDir);
678     }
679 
680     /* allocate intern process structure and store child process ID */
681     pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl));
682     pProcImpl->pProcess = pidProcess;
683     pProcImpl->nSessionID = ulSessID;
684 
685     pProcImpl->bResultCodeValid = FALSE;
686 
687     if( Options & osl_Process_WAIT )
688         osl_joinProcess(pProcImpl);
689 
690     *pProcess = (oslProcess)pProcImpl;
691 
692     if( rc == NO_ERROR )
693         return osl_Process_E_None;
694     else
695 
696         return osl_Process_E_Unknown;
697 }
698 
699 /*----------------------------------------------------------------------------*/
700 
701 oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
702 {
703     if (Process == NULL)
704         return osl_Process_E_Unknown;
705 
706     /* Stop the session */
707     DosStopSession( STOP_SESSION_SPECIFIED, ((oslProcessImpl*)Process)->nSessionID );
708 
709     return osl_Process_E_None;
710 }
711 
712 /*----------------------------------------------------------------------------*/
713 
714 oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
715 {
716     HANDLE        hProcess;
717     oslProcessImpl* pProcImpl;
718 
719     /* check, if given PID is a valid process */
720     if (FALSE)
721     {
722         pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl));
723 /*
724         pProcImpl->pProcess = pidProcess;
725         pProcImpl->nSessionID = ulSessID;
726 */
727     }
728     else
729         pProcImpl = NULL;
730 
731     return (pProcImpl);
732 }
733 
734 /*----------------------------------------------------------------------------*/
735 
736 void SAL_CALL osl_freeProcessHandle(oslProcess Process)
737 {
738     /* free intern process structure */
739     if (Process != NULL)
740         free((oslProcessImpl*)Process);
741 }
742 
743 /*----------------------------------------------------------------------------*/
744 
745 oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
746 {
747     oslProcessImpl* pProcImpl = (oslProcessImpl*) Process;
748     APIRET rc;
749 
750     if (Process == NULL)
751         return osl_Process_E_Unknown;
752 
753     /* process of same session ? */
754     if( pProcImpl->nSessionID == 0 )
755     {
756         RESULTCODES resultCode;
757         PID pidEnded;
758 
759         rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode,
760                 &pidEnded, pProcImpl->pProcess );
761 
762         if( rc == NO_ERROR )
763         {
764             pProcImpl->nResultCode = resultCode.codeResult;
765             pProcImpl->bResultCodeValid = TRUE;
766 
767             return osl_Process_E_None;
768         }
769     }
770     else
771     {
772         ULONG pcbData, ulElement = 0;
773         REQUESTDATA rdData;
774         BYTE bPriority;
775         struct {
776             USHORT SessionID;
777             USHORT ReturnValue;
778         } *pvBuffer;
779 
780         /* search/wait for the correct entry in termination queue */
781         while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData,
782                         (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT,
783                         &bPriority, NULLHANDLE )) == NO_ERROR )
784         {
785 
786             if( pvBuffer->SessionID == pProcImpl->nSessionID )
787             {
788                 pProcImpl->nResultCode = pvBuffer->ReturnValue;
789                 pProcImpl->bResultCodeValid = TRUE;
790 
791                 /* remove item from queue */
792                 rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData,
793                        (PPVOID)&pvBuffer, ulElement, DCWW_WAIT,
794                        &bPriority, NULLHANDLE );
795 
796                 if( rc == NO_ERROR )
797                     return osl_Process_E_None;
798                 else
799                     return osl_Process_E_Unknown;
800             }
801         } /* while */
802     }
803     return osl_Process_E_Unknown;
804 }
805 
806 /***************************************************************************/
807 
808 //YD FIXME incomplete!
809 oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
810 {
811     return osl_joinProcess( Process);
812 }
813 
814 /*----------------------------------------------------------------------------*/
815 
816 oslProcessError SAL_CALL osl_getCommandArgs( sal_Char* pszBuffer, sal_uInt32 Max)
817 {
818 
819     static int  CmdLen = -1;
820     static sal_Char CmdLine[_MAX_CMD];
821 
822     OSL_ASSERT(pszBuffer);
823     OSL_ASSERT(Max > 1);
824 
825     /* Query commandline during first call of function only */
826     if (CmdLen < 0)
827     {
828         sal_Bool bEscaped = sal_False;
829         sal_Bool bSeparated = sal_True;
830         sal_Char* pszBufferOrg = pszBuffer;
831         sal_Char* pszCmdLine;
832 
833         /* get pointer to commandline */
834         {
835             PTIB pptib = NULL;
836             PPIB pppib = NULL;
837 
838             DosGetInfoBlocks(&pptib, &pppib);
839             pszCmdLine = pppib->pib_pchcmd;
840         }
841 
842         /* skip first string */
843         while( *pszCmdLine )
844             pszCmdLine++;
845 
846         /* concatenate commandline arguments for the given string */
847         Max -= 2;
848         while ( !((*pszCmdLine == '\0') && (*(pszCmdLine + 1) == '\0')) && (Max > 0))
849         {
850             /*
851              *  C-Runtime expects char to be unsigned and so to be
852              *  preceeded with 00 instead of FF when converting to int
853              */
854             int n = *((unsigned char *) pszCmdLine);
855             if (! (isspace(n) || (*pszCmdLine == '\0')) )
856             {
857                 if (*pszCmdLine == '"')
858                 {
859                     if (*(pszCmdLine + 1) != '"')
860                         bEscaped = ! bEscaped;
861                     else
862                     {
863                         pszCmdLine++;
864                         *pszBuffer++ = *pszCmdLine;
865                         Max--;
866                     }
867                 }
868                 else
869                 {
870                     *pszBuffer++ = *pszCmdLine;
871                     Max--;
872                 }
873                 bSeparated = sal_False;
874             }
875             else
876             {
877                 if (bEscaped)
878                     *pszBuffer++ = *pszCmdLine;
879                 else
880                     if (! bSeparated)
881                     {
882                         *pszBuffer++ = '\0';
883                         bSeparated = sal_True;
884                     }
885                 Max--;
886             }
887 
888             pszCmdLine++;
889         }
890 
891         *pszBuffer++ = '\0';
892         *pszBuffer++ = '\0';
893 
894         /* restore pointer and save commandline for next query */
895         CmdLen = pszBuffer - pszBufferOrg;
896         pszBuffer = pszBufferOrg;
897         memcpy( CmdLine, pszBuffer, CmdLen );
898     }
899     else
900        memcpy( pszBuffer, CmdLine, CmdLen );
901 
902     OSL_TRACE( "osl_getCommandArgs (args: %s)\n", pszBuffer );
903 
904     return osl_Process_E_None;
905 }
906 
907 /*----------------------------------------------------------------------------*/
908 
909 oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields,
910                                    oslProcessInfo* pInfo)
911 {
912     if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
913         return osl_Process_E_Unknown;
914 
915     pInfo->Fields = 0;
916 
917     if (Fields & osl_Process_IDENTIFIER)
918     {
919         if( Process == NULL )
920         {
921             PTIB pptib = NULL;
922             PPIB pppib = NULL;
923 
924             DosGetInfoBlocks( &pptib, &pppib );
925             pInfo->Ident = pppib->pib_ulpid;
926         }
927         else
928             pInfo->Ident = ((oslProcessImpl*)Process)->pProcess;
929 
930         pInfo->Fields |= osl_Process_IDENTIFIER;
931     }
932 
933     if (Fields & osl_Process_EXITCODE)
934     {
935         oslProcessImpl* pProcImpl = (oslProcessImpl*) Process;
936 
937         if( pProcImpl->bResultCodeValid )
938         {
939             pInfo->Code = pProcImpl->nResultCode;
940             pInfo->Fields |= osl_Process_EXITCODE;
941         }
942         else
943         {
944             APIRET rc;
945 
946             if( pProcImpl->nSessionID == 0 )
947             {
948                 RESULTCODES resultCode;
949                 PID pidEnded;
950 
951                 rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode,
952                         &pidEnded, pProcImpl->pProcess );
953 
954                 if( rc == NO_ERROR )
955                 {
956                     pProcImpl->nResultCode = resultCode.codeResult;
957                     pProcImpl->bResultCodeValid = TRUE;
958 
959                     pInfo->Code = pProcImpl->nResultCode;
960                     pInfo->Fields |= osl_Process_EXITCODE;
961 
962                     return osl_Process_E_None;
963                 }
964             }
965             else
966             {
967                 ULONG pcbData, ulElement = 0;
968                 REQUESTDATA rdData;
969                 BYTE bPriority;
970                 struct {
971                     USHORT SessionID;
972                     USHORT ReturnValue;
973                 } *pvBuffer;
974 
975                 /* search/wait for the correct entry in termination queue */
976                 while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData,
977                                 (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT,
978                                 &bPriority, NULLHANDLE )) == NO_ERROR )
979                 {
980 
981                     if( pvBuffer->SessionID == pProcImpl->nSessionID )
982                     {
983                         pProcImpl->nResultCode = pvBuffer->ReturnValue;
984                         pProcImpl->bResultCodeValid = TRUE;
985 
986                         pInfo->Code = pProcImpl->nResultCode;
987                         pInfo->Fields |= osl_Process_EXITCODE;
988 
989                         /* remove item from queue */
990                         rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData,
991                             (PPVOID)&pvBuffer, ulElement, DCWW_WAIT,
992                                &bPriority, NULLHANDLE );
993 
994                         break;
995                     }
996                 }
997             }
998         }
999     }
1000 
1001     if (Fields & osl_Process_HEAPUSAGE)
1002     {
1003     }
1004     if (Fields & osl_Process_CPUTIMES)
1005     {
1006     }
1007 
1008     return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
1009 }
1010