xref: /aoo42x/main/sal/osl/os2/process.c (revision cdf0e10c)
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