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