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