xref: /aoo4110/main/soldep/bootstrp/command.cxx (revision b1cdbd2c)
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 #ifdef SCO
25 #define _IOSTREAM_H
26 #endif
27 
28 #include <tools/fsys.hxx>
29 #include <tools/stream.hxx>
30 #include "soldep/command.hxx"
31 #include <tools/debug.hxx>
32 #include <soldep/appdef.hxx>
33 
34 #ifdef _MSC_VER
35 #pragma warning (push,1)
36 #endif
37 
38 #include <iostream>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <errno.h>
44 
45 #ifdef _MSC_VER
46 #pragma warning (pop)
47 #endif
48 
49 //#define MH_TEST2	1			// fuers direkte Testen
50 
51 #if defined(WNT) || defined(OS2)
52 #ifdef _MSC_VER
53 #pragma warning (push,1)
54 #endif
55 #include <process.h>    // for _SPAWN
56 #ifdef _MSC_VER
57 #pragma warning (pop)
58 #endif
59 #endif
60 #ifdef UNX
61 #include <sys/types.h>
62 #include <unistd.h>
63 #if ( defined NETBSD ) || defined (FREEBSD) || defined (AIX) \
64     || defined (HPUX) || defined (MACOSX)
65 #include <sys/wait.h>
66 #else
67 #include <wait.h>
68 #endif
69 #define P_WAIT 1 		// erstmal einen dummz
70 #endif
71 
72 #if defined WNT
73 #include <tools/svwin.h>
74 #endif
75 
76 #if defined(WNT) || defined(OS2)
77 #define  	cPathSeperator ';'
78 #endif
79 #ifdef UNX
80 #define	 	cPathSeperator	':'
81 #endif
82 
83 /*****************************************************************************/
CommandLine(sal_Bool bWrite)84 CommandLine::CommandLine(sal_Bool bWrite)
85 /*****************************************************************************/
86 				: bTmpWrite(bWrite)
87 {
88 	CommandBuffer = new char [1];
89 	if (CommandBuffer == NULL) {
90 		//cout << "Error: nospace" << endl;
91 		exit(0);
92 	}
93 	CommandBuffer[0] = '\0';
94 	nArgc = 0;
95 	ppArgv = new char * [1];
96 	ppArgv[0] = NULL;
97 
98 	ComShell = new char [128];
99 	char* pTemp = getenv("COMMAND_SHELL");
100 	if(!pTemp)
101 		strcpy(ComShell,COMMAND_SHELL);
102 	else
103 		strcpy(ComShell,pTemp);
104 
105 	strcpy(&ComShell[strlen(ComShell)]," -C ");
106 }
107 
108 /*****************************************************************************/
CommandLine(const char * CommandString,sal_Bool bWrite)109 CommandLine::CommandLine(const char *CommandString, sal_Bool bWrite)
110 /*****************************************************************************/
111 				: bTmpWrite(bWrite)
112 {
113 	CommandBuffer = new char [1];
114 	if (CommandBuffer == NULL) {
115 		//cout << "Error: nospace" << endl;
116 		exit(0);
117 	}
118 	nArgc = 0;
119 	ppArgv = new char * [1];
120 	ppArgv[0] = NULL;
121 
122 	ComShell = new char [128];
123 	char* pTemp = getenv("COMMAND_SHELL");
124 	if(!pTemp)
125 		strcpy(ComShell,COMMAND_SHELL);
126 	else
127 		strcpy(ComShell,pTemp);
128 
129 	strcpy(&ComShell[strlen(ComShell)]," -C ");
130 
131 	BuildCommand(CommandString);
132 }
133 
134 /*****************************************************************************/
CommandLine(const CommandLine & CCommandLine,sal_Bool bWrite)135 CommandLine::CommandLine(const CommandLine& CCommandLine, sal_Bool bWrite)
136 /*****************************************************************************/
137 				: bTmpWrite(bWrite)
138 {
139 	CommandBuffer = new char [1];
140 	if (CommandBuffer == NULL) {
141 		//cout << "Error: nospace" << endl;
142 		exit(0);
143 	}
144 	nArgc = 0;
145 	ppArgv = new char * [1];
146 	ppArgv[0] = NULL;
147 
148 	ComShell = new char [128];
149 	char* pTemp = getenv("COMMAND_SHELL");
150 	if(!pTemp)
151 		strcpy(ComShell,COMMAND_SHELL);
152 	else
153 		strcpy(ComShell,pTemp);
154 
155 	strcpy(&ComShell[strlen(ComShell)]," -C ");
156 
157 	BuildCommand(CCommandLine.CommandBuffer);
158 }
159 
160 /*****************************************************************************/
~CommandLine()161 CommandLine::~CommandLine()
162 /*****************************************************************************/
163 {
164 	delete [] CommandBuffer;
165 	delete [] ComShell;
166 	//for (int i = 0; ppArgv[i] != '\0'; i++) {
167 	for (int i = 0; ppArgv[i] != 0; i++) {
168 		delete [] ppArgv[i];
169 	}
170 	delete [] ppArgv;
171 
172 }
173 
174 /*****************************************************************************/
operator =(const CommandLine & CCommandLine)175 CommandLine& CommandLine::operator=(const CommandLine& CCommandLine)
176 /*****************************************************************************/
177 {
178 	strcpy (CommandBuffer, CCommandLine.CommandBuffer);
179 	for (int i = 0; i != nArgc; i++) {
180 		delete [] ppArgv[i];
181 	}
182 	delete [] ppArgv;
183         ppArgv = new char * [1];
184         ppArgv[0] = NULL;
185 	BuildCommand(CommandBuffer);
186 	return *this;
187 }
188 
189 /*****************************************************************************/
operator =(const char * CommandString)190 CommandLine& CommandLine::operator=(const char *CommandString)
191 /*****************************************************************************/
192 {
193 	strcpy (CommandBuffer, CommandString);
194 	for (int i = 0; i != nArgc; i++) {
195 		delete [] ppArgv[i];
196 	}
197 	delete [] ppArgv;
198         ppArgv = new char * [1];
199         ppArgv[0] = NULL;
200 	BuildCommand(CommandBuffer);
201 
202 	return *this;
203 }
204 
205 /*****************************************************************************/
Print()206 void CommandLine::Print()
207 /*****************************************************************************/
208 {
209 	//cout << "******* start print *******" << endl;
210 	//cout << "nArgc = " << nArgc << endl;
211 	//cout << "CommandBuffer = " << CommandBuffer << endl;
212 	for (int i = 0; ppArgv[i] != NULL; i++) {
213 		//cout << "ppArgv[" << i << "] = " << ppArgv[i] << endl;
214 	}
215 	//cout << "******** end print ********" << endl;
216 }
217 
218 /*****************************************************************************/
BuildCommand(const char * CommandString)219 void CommandLine::BuildCommand(const char *CommandString)
220 /*****************************************************************************/
221 {
222 	int index = 0, pos=0;
223 	char buffer[1024];
224 	char WorkString[1024];
225 
226 	strcpy(WorkString,CommandString);
227 
228 	//falls LogWindow -> in tmpfile schreiben
229 	if(bTmpWrite)
230 	{
231 		strcpy(&WorkString[strlen(WorkString)]," >&");
232 		strcpy(&WorkString[strlen(WorkString)],getenv("TMP"));
233 		strcpy(&WorkString[strlen(WorkString)],TMPNAME);
234 	}
235 
236 	// delete old memory and get some new memory for CommandBuffer
237 
238 	delete [] CommandBuffer;
239 	CommandBuffer =  new char [strlen(ComShell)+strlen(WorkString)+1];
240 	if (CommandBuffer == NULL) {
241 		//cout << "Error: nospace" << endl;
242 		exit(0);
243 	}
244 	strcpy (CommandBuffer, ComShell);
245 	strcpy (&CommandBuffer[strlen(ComShell)], WorkString);
246 
247 	CommandString = CommandBuffer;
248 
249 	// get the number of tokens
250 	Strtokens(CommandString);
251 
252 	// delete the space for the old CommandLine
253 
254 	for (int i = 0; ppArgv[i] != 0; i++) {
255 		delete [] ppArgv[i];
256 	}
257 	delete [] ppArgv;
258 
259 	/* get space for the new command line */
260 
261 	ppArgv = (char **) new char * [nArgc+1];
262 	if (ppArgv == NULL) {
263 		//cout << "Error: no space" << endl;
264 		exit(0);
265 	}
266 
267 	// flush the white space
268 
269 	while ( isspace(*CommandString) )
270 		CommandString++;
271 
272 	index = 0;
273 
274 	// start the loop to build all the individual tokens
275 
276 	while (*CommandString != '\0') {
277 
278 		pos = 0;
279 
280 		// copy the token until white space is found
281 
282 		while ( !isspace(*CommandString) && *CommandString != '\0') {
283 
284 			buffer[pos++] = *CommandString++;
285 
286 		}
287 
288 		buffer[pos] = '\0';
289 
290 		// get space for the individual tokens
291 
292 		ppArgv[index] = (char *) new char [strlen(buffer)+1];
293 		if (ppArgv[index] == NULL) {
294 			//cout << "Error: nospace" << endl;
295 			exit(0);
296 		}
297 
298 		// copy the token
299 
300 		strcpy (ppArgv[index++], buffer);
301 
302 		// flush while space
303 
304 		while ( isspace(*CommandString) )
305 			CommandString++;
306 
307 	}
308 
309 	// finish by setting the las pointer to NULL
310 	ppArgv[nArgc]= NULL;
311 
312 }
313 
314 /*****************************************************************************/
Strtokens(const char * CommandString)315 void CommandLine::Strtokens(const char *CommandString)
316 /*****************************************************************************/
317 {
318 	int count = 0;
319 	const char *temp;
320 
321 	temp = CommandString;
322 
323 	/* bypass white space */
324 
325 	while (isspace(*temp)) temp++;
326 
327 	for (count=0; *temp != '\0'; count++) {
328 
329 		/* continue until white space of string terminator is found */
330 
331 		while ((!isspace(*temp)) && (*temp != '\0')) temp++;
332 
333 		/* bypass white space */
334 
335 		while (isspace(*temp)) temp++;
336 
337 	}
338 	nArgc = count;
339 }
340 
341 /*****************************************************************************/
CCommand(ByteString & rString)342 CCommand::CCommand( ByteString &rString )
343 /*****************************************************************************/
344 {
345 	rString.SearchAndReplace( '\t', ' ' );
346 	aCommand = rString.GetToken( 0, ' ' );
347 	aCommandLine = Search( "PATH" );
348 #ifndef UNX
349 	aCommandLine += " /c ";
350 #else
351 	aCommandLine += " -c ";
352 #endif
353 
354 	ByteString sCmd( rString.GetToken( 0, ' ' ));
355 	ByteString sParam( rString.Copy( sCmd.Len()));
356 
357 	aCommandLine += Search( "PATH", sCmd );
358 	aCommandLine += sParam;
359 
360 	ImplInit();
361 }
362 
363 /*****************************************************************************/
CCommand(const char * pChar)364 CCommand::CCommand( const char *pChar )
365 /*****************************************************************************/
366 {
367 	ByteString aString = pChar;
368 	aString.SearchAndReplace( '\t', ' ' );
369 	aCommand = aString.GetToken( 0, ' ' );
370 
371 	aCommandLine = Search( "PATH" );
372 #ifndef UNX
373 	aCommandLine += " /c ";
374 #else
375 	aCommandLine += " -c ";
376 #endif
377 	ByteString rString( pChar );
378 
379 	ByteString sCmd( rString.GetToken( 0, ' ' ));
380 	ByteString sParam( rString.Copy( sCmd.Len()));
381 
382 	aCommandLine += Search( "PATH", sCmd );
383 	aCommandLine += sParam;
384 
385 	ImplInit();
386 }
387 
388 /*****************************************************************************/
ImplInit()389 void CCommand::ImplInit()
390 /*****************************************************************************/
391 {
392 	char pTmpStr[255];
393 	size_t *pPtr;
394 	char *pChar;
395 	int nVoid = sizeof( size_t * );
396 	nArgc = aCommandLine.GetTokenCount(' ');
397 	sal_uIntPtr nLen = aCommandLine.Len();
398 
399 	ppArgv = (char **) new char[ (sal_uIntPtr)(nLen + nVoid * (nArgc +2) + nArgc ) ];
400 	pChar = (char *) ppArgv + ( (1+nArgc) * nVoid );
401 	pPtr = (size_t *) ppArgv;
402 	for ( xub_StrLen i=0; i<nArgc; i++ )
403 	{
404 		(void) strcpy( pTmpStr, aCommandLine.GetToken(i, ' ' ).GetBuffer() );
405 		size_t nStrLen = strlen( pTmpStr ) + 1;
406 		strcpy( pChar, pTmpStr );
407 		*pPtr = (sal_uIntPtr) pChar;
408 		pChar += nStrLen;
409 		pPtr += 1;
410 #ifdef UNX
411 		if ( i == 1 )
412 		{
413 			sal_uInt16 nWo = aCommandLine.Search("csh -c ");
414 			if (nWo != STRING_NOTFOUND)
415 				aCommandLine.Erase(0, nWo + 7);
416 			else
417 				aCommandLine.Erase(0, 16);
418 			i = nArgc;
419 			strcpy( pChar, aCommandLine.GetBuffer() );
420 			*pPtr = (sal_uIntPtr) pChar;
421 			pPtr += 1;
422 		}
423 #endif
424 	}
425 	*pPtr = 0;
426 }
427 
428 /*****************************************************************************/
429 CCommand::operator int()
430 /*****************************************************************************/
431 {
432 	int nRet;
433 #if defined WNT
434 	nRet = _spawnv( P_WAIT, ppArgv[0], (const char **) ppArgv );
435 #elif defined OS2
436 	nRet = _spawnv( P_WAIT, ppArgv[0], ppArgv );
437 #elif defined UNX
438 	//fprintf( stderr, "CComand : operator (int) not implemented\n");
439 	// **** Unix Implementierung ***************
440 	pid_t pid;
441 
442 	if (( pid = fork()) < 0 )
443 	{
444 		DBG_ASSERT( sal_False, "fork error" );
445 	}
446 	else if ( pid == 0 )
447 	{
448 		if ( execv( ppArgv[0], (char * const *) ppArgv ) < 0 )
449 		{
450 			DBG_ASSERT( sal_False, "execv failed" );
451 		}
452 	}
453 	//fprintf( stderr, "parent: %s %s\n", ppArgv[0] , ppArgv[1] );
454 	if ( (nRet = waitpid( pid, NULL, 0 ) < 0) )
455 	{
456 		DBG_ASSERT( sal_False, "wait error" );
457 	}
458 #endif
459 
460 	switch ( errno )
461 	{
462 		case	E2BIG :
463 					nError = COMMAND_TOOBIG;
464 					break;
465 		case	EINVAL :
466 					nError = COMMAND_INVALID;
467 					break;
468 		case	ENOENT:
469 					nError = COMMAND_NOTFOUND;
470 					break;
471 		case 	ENOEXEC :
472 					nError = COMMAND_NOEXEC;
473 					break;
474 		case	ENOMEM :
475 					nError = COMMAND_NOMEM;
476 					break;
477 		default:
478 				nError = COMMAND_UNKNOWN;
479 	}
480 
481 	if ( nRet )
482 		fprintf( stderr, "Program returned with errros\n");
483 	return nRet;
484 }
485 
486 /*****************************************************************************/
Search(ByteString aEnv,ByteString sItem)487 ByteString CCommand::Search(ByteString aEnv, ByteString sItem)
488 /*****************************************************************************/
489 {
490 	// default wird eine Shell im Path gesucht,
491 	// wenn aber compsec gestzt ist holen wir uns die
492 	// Shell von dort
493 	if ( sItem.Equals( COMMAND_SHELL ))
494 	{
495 		ByteString aComspec = GetEnv( "COMSPEC" );
496 		if ( !aComspec.Equals(""))
497 			return aComspec;
498 	}
499 
500 	DirEntry aItem( String( sItem, RTL_TEXTENCODING_ASCII_US ));
501 	if ( aItem.Exists())
502 		return sItem;
503 
504 	ByteString aEntry, sReturn;
505 	ByteString sEnv( aEnv );
506 	ByteString sEnvironment = GetEnv( sEnv.GetBuffer());
507 	xub_StrLen nCount = sEnvironment.GetTokenCount( cPathSeperator );
508 
509 	sal_Bool bFound = sal_False;
510 
511 	for ( xub_StrLen i=0; i<nCount && !bFound; i++ )
512 	{
513 		aEntry = sEnvironment.GetToken(i, cPathSeperator );
514 #ifndef UNX
515 		aEntry += '\\';
516 #else
517 		aEntry += '/';
518 #endif
519 		aEntry += sItem;
520 
521 		String sEntry( aEntry, RTL_TEXTENCODING_ASCII_US );
522 		DirEntry aDirEntry( sEntry );
523 		aDirEntry.ToAbs();
524 		if ( aDirEntry.Exists()) {
525 			sReturn = aEntry;
526 			bFound = sal_True;
527 		}
528 	}
529 	if ( !bFound )
530 	{
531 		sEnv = sEnv.ToUpperAscii();
532 		ByteString sEnvironment2 = GetEnv(sEnv.GetBuffer() );
533 		xub_StrLen nCount2 = sEnvironment2.GetTokenCount( cPathSeperator );
534 		for ( xub_StrLen i=0; i<nCount2 && !bFound; i++ )
535 		{
536 			aEntry = sEnvironment2.GetToken(i, cPathSeperator );
537 #ifndef UNX
538 			aEntry += '\\';
539 #else
540 			aEntry += '/';
541 #endif
542 			aEntry += sItem;
543 
544 			String sEntry( aEntry, RTL_TEXTENCODING_ASCII_US );
545 			DirEntry aDirEntry( sEntry );
546 			aDirEntry.ToAbs();
547 			if ( aDirEntry.Exists()) {
548 				sReturn = aEntry;
549 				bFound = sal_True;
550 			}
551 		}
552 	}
553 
554 	if ( sReturn.Equals( "" ))
555 		sReturn = sItem;
556 
557 	return sReturn;
558 }
559 
560 /*****************************************************************************/
CCommandd(ByteString & rString,CommandBits nBits)561 CCommandd::CCommandd( ByteString &rString, CommandBits nBits )
562 /*****************************************************************************/
563 				: CCommand( rString ),
564 				nFlag( nBits )
565 {
566 }
567 
568 
569 /*****************************************************************************/
CCommandd(const char * pChar,CommandBits nBits)570 CCommandd::CCommandd( const char *pChar, CommandBits nBits )
571 /*****************************************************************************/
572 				: CCommand( pChar ),
573 				nFlag( nBits )
574 {
575 }
576 
577 /*****************************************************************************/
578 CCommandd::operator int()
579 /*****************************************************************************/
580 {
581 	int nRet = 0;
582 
583 #ifdef WNT
584 	LPCTSTR lpApplicationName = NULL;
585 	LPTSTR lpCommandLine = (char *) GetCommandLine_().GetBuffer();
586 	LPSECURITY_ATTRIBUTES lpProcessAttributes = NULL;
587 	LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
588 	sal_Bool bInheritHandles = sal_True;
589 
590 	// wie wuenschen wir denn gestartet zu werden ??
591 	DWORD dwCreationFlags;
592 
593 	if ( nFlag & COMMAND_EXECUTE_START )
594 		dwCreationFlags = DETACHED_PROCESS;
595 	else
596 		dwCreationFlags = CREATE_NEW_CONSOLE;
597 
598 	// wir erben vom Vaterprozess
599 	LPVOID lpEnvironment = NULL;
600 
601 	// das exe im Pfad suchen
602 	LPCTSTR lpCurrentDirectory = NULL;
603 
604 	// in dieser Struktur bekommen wir die erzeugte Processinfo
605 	// zurueck
606 	PROCESS_INFORMATION aProcessInformation;
607 
608 	// weiteres Startupinfo anlegen
609 	STARTUPINFO aStartupInfo;
610 
611 	aStartupInfo.cb = sizeof( STARTUPINFO );
612 	aStartupInfo.lpReserved = NULL;
613 	aStartupInfo.lpDesktop = NULL;
614 
615 	// das Fenster bekommt den Namen des Exes
616 	aStartupInfo.lpTitle = NULL;
617 	aStartupInfo.dwX = 100;
618 	aStartupInfo.dwY = 100;
619 	//aStartupInfo.dwXSize = 400;
620 	//aStartupInfo.dwYSize = 400;
621 	aStartupInfo.dwXCountChars = 40;
622 	aStartupInfo.dwYCountChars = 40;
623 
624 	// Farben setzen
625 	aStartupInfo.dwFillAttribute = FOREGROUND_RED | BACKGROUND_RED |
626 								BACKGROUND_BLUE | BACKGROUND_GREEN;
627 
628 //	aStartupInfo.dwFlags = STARTF_USESTDHANDLES;
629 	//aStartupInfo.wShowWindow = SW_NORMAL; //SW_SHOWDEFAULT;
630 	//aStartupInfo.wShowWindow = SW_HIDE; //SW_SHOWNOACTIVATE;
631 	aStartupInfo.wShowWindow = SW_SHOWNOACTIVATE;
632 	aStartupInfo.cbReserved2 = NULL;
633 	aStartupInfo.lpReserved2 = NULL;
634 	//aStartupInfo.hStdInput = stdin;
635 	//aStartupInfo.hStdOutput = stdout;
636 	//aStartupInfo.hStdError = stderr;
637 
638 	if ( nFlag & COMMAND_EXECUTE_HIDDEN )
639 	{
640 		aStartupInfo.wShowWindow = SW_HIDE;
641 		aStartupInfo.dwFlags = aStartupInfo.dwFlags | STARTF_USESHOWWINDOW;
642 	}
643 
644 	bool bProcess = CreateProcess( lpApplicationName,
645 						lpCommandLine, lpProcessAttributes,
646 						lpThreadAttributes, bInheritHandles,
647 						dwCreationFlags, lpEnvironment, lpCurrentDirectory,
648 						&aStartupInfo, &aProcessInformation );
649 
650 	LPVOID lpMsgBuf;
651 
652 	if ( bProcess )
653 	{
654 		FormatMessage(
655 			    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
656 			    NULL,
657 			    GetLastError(),
658 			    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
659 			    (LPTSTR) &lpMsgBuf,
660 			    0,
661 			    NULL );
662 
663 		ByteString aErrorString = (char *) lpMsgBuf;
664 
665 		if ( nFlag & COMMAND_EXECUTE_WAIT )
666 		{
667 			DWORD aProcessState = STILL_ACTIVE;
668 			while(aProcessState == STILL_ACTIVE)
669 			{
670 				GetExitCodeProcess(aProcessInformation.hProcess,&aProcessState);
671 			}
672 		}
673 	}
674 	else
675 		fprintf( stderr, "Can not start Process !" );
676 
677 #endif
678 	return nRet;
679 }
680