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