merge the formfield patch from ooo-build
[ooovba.git] / tools / bootstrp / command.cxx
blob1582524f96cefcc0c95723bc5bf64915a91edbfc
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: command.cxx,v $
10 * $Revision: 1.18.40.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #ifdef SCO
35 #define _IOSTREAM_H
36 #endif
38 #ifdef PRECOMPILED
39 #include "first.hxx"
40 #endif
42 #include <tools/fsys.hxx>
43 #include <tools/stream.hxx>
44 #include "bootstrp/command.hxx"
45 #include <tools/debug.hxx>
46 #include "bootstrp/appdef.hxx"
48 #ifdef _MSC_VER
49 #pragma warning (push,1)
50 #endif
52 #include <iostream>
53 #include <string.h>
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <ctype.h>
57 #include <errno.h>
59 #ifdef _MSC_VER
60 #pragma warning (pop)
61 #endif
63 //#define MH_TEST2 1 // fuers direkte Testen
65 #if defined(WNT) || defined(OS2)
66 #ifdef _MSC_VER
67 #pragma warning (push,1)
68 #endif
69 #include <process.h> // for _SPAWN
70 #ifdef _MSC_VER
71 #pragma warning (pop)
72 #endif
73 #endif
74 #ifdef UNX
75 #include <sys/types.h>
76 #include <unistd.h>
77 #if ( defined NETBSD ) || defined (FREEBSD) || defined (AIX) \
78 || defined (HPUX) || defined (MACOSX)
79 #include <sys/wait.h>
80 #else
81 #include <wait.h>
82 #endif
83 #define P_WAIT 1 // erstmal einen dummz
84 #endif
86 #if defined WNT
87 #include <tools/svwin.h>
88 #endif
90 #if defined(WNT) || defined(OS2)
91 #define cPathSeperator ';'
92 #endif
93 #ifdef UNX
94 #define cPathSeperator ':'
95 #endif
97 /*****************************************************************************/
98 CommandLine::CommandLine(BOOL bWrite)
99 /*****************************************************************************/
100 : bTmpWrite(bWrite)
102 CommandBuffer = new char [1];
103 if (CommandBuffer == NULL) {
104 //cout << "Error: nospace" << endl;
105 exit(0);
107 CommandBuffer[0] = '\0';
108 nArgc = 0;
109 ppArgv = new char * [1];
110 ppArgv[0] = NULL;
112 ComShell = new char [128];
113 char* pTemp = getenv("COMMAND_SHELL");
114 if(!pTemp)
115 strcpy(ComShell,COMMAND_SHELL);
116 else
117 strcpy(ComShell,pTemp);
119 strcpy(&ComShell[strlen(ComShell)]," -C ");
122 /*****************************************************************************/
123 CommandLine::CommandLine(const char *CommandString, BOOL bWrite)
124 /*****************************************************************************/
125 : bTmpWrite(bWrite)
127 CommandBuffer = new char [1];
128 if (CommandBuffer == NULL) {
129 //cout << "Error: nospace" << endl;
130 exit(0);
132 nArgc = 0;
133 ppArgv = new char * [1];
134 ppArgv[0] = NULL;
136 ComShell = new char [128];
137 char* pTemp = getenv("COMMAND_SHELL");
138 if(!pTemp)
139 strcpy(ComShell,COMMAND_SHELL);
140 else
141 strcpy(ComShell,pTemp);
143 strcpy(&ComShell[strlen(ComShell)]," -C ");
145 BuildCommand(CommandString);
148 /*****************************************************************************/
149 CommandLine::CommandLine(const CommandLine& CCommandLine, BOOL bWrite)
150 /*****************************************************************************/
151 : bTmpWrite(bWrite)
153 CommandBuffer = new char [1];
154 if (CommandBuffer == NULL) {
155 //cout << "Error: nospace" << endl;
156 exit(0);
158 nArgc = 0;
159 ppArgv = new char * [1];
160 ppArgv[0] = NULL;
162 ComShell = new char [128];
163 char* pTemp = getenv("COMMAND_SHELL");
164 if(!pTemp)
165 strcpy(ComShell,COMMAND_SHELL);
166 else
167 strcpy(ComShell,pTemp);
169 strcpy(&ComShell[strlen(ComShell)]," -C ");
171 BuildCommand(CCommandLine.CommandBuffer);
174 /*****************************************************************************/
175 CommandLine::~CommandLine()
176 /*****************************************************************************/
178 delete [] CommandBuffer;
179 delete [] ComShell;
180 //for (int i = 0; ppArgv[i] != '\0'; i++) {
181 for (int i = 0; ppArgv[i] != 0; i++) {
182 delete [] ppArgv[i];
184 delete [] ppArgv;
188 /*****************************************************************************/
189 CommandLine& CommandLine::operator=(const CommandLine& CCommandLine)
190 /*****************************************************************************/
192 strcpy (CommandBuffer, CCommandLine.CommandBuffer);
193 for (int i = 0; i != nArgc; i++) {
194 delete [] ppArgv[i];
196 delete [] ppArgv;
197 ppArgv = new char * [1];
198 ppArgv[0] = NULL;
199 BuildCommand(CommandBuffer);
200 return *this;
203 /*****************************************************************************/
204 CommandLine& CommandLine::operator=(const char *CommandString)
205 /*****************************************************************************/
207 strcpy (CommandBuffer, CommandString);
208 for (int i = 0; i != nArgc; i++) {
209 delete [] ppArgv[i];
211 delete [] ppArgv;
212 ppArgv = new char * [1];
213 ppArgv[0] = NULL;
214 BuildCommand(CommandBuffer);
216 return *this;
219 /*****************************************************************************/
220 void CommandLine::Print()
221 /*****************************************************************************/
223 //cout << "******* start print *******" << endl;
224 //cout << "nArgc = " << nArgc << endl;
225 //cout << "CommandBuffer = " << CommandBuffer << endl;
226 for (int i = 0; ppArgv[i] != NULL; i++) {
227 //cout << "ppArgv[" << i << "] = " << ppArgv[i] << endl;
229 //cout << "******** end print ********" << endl;
232 /*****************************************************************************/
233 void CommandLine::BuildCommand(const char *CommandString)
234 /*****************************************************************************/
236 int index = 0, pos=0;
237 char buffer[1024];
238 char WorkString[1024];
240 strcpy(WorkString,CommandString);
242 //falls LogWindow -> in tmpfile schreiben
243 if(bTmpWrite)
245 strcpy(&WorkString[strlen(WorkString)]," >&");
246 strcpy(&WorkString[strlen(WorkString)],getenv("TMP"));
247 strcpy(&WorkString[strlen(WorkString)],TMPNAME);
250 // delete old memory and get some new memory for CommandBuffer
252 delete [] CommandBuffer;
253 CommandBuffer = new char [strlen(ComShell)+strlen(WorkString)+1];
254 if (CommandBuffer == NULL) {
255 //cout << "Error: nospace" << endl;
256 exit(0);
258 strcpy (CommandBuffer, ComShell);
259 strcpy (&CommandBuffer[strlen(ComShell)], WorkString);
261 CommandString = CommandBuffer;
263 // get the number of tokens
264 Strtokens(CommandString);
266 // delete the space for the old CommandLine
268 for (int i = 0; ppArgv[i] != 0; i++) {
269 delete [] ppArgv[i];
271 delete [] ppArgv;
273 /* get space for the new command line */
275 ppArgv = (char **) new char * [nArgc+1];
276 if (ppArgv == NULL) {
277 //cout << "Error: no space" << endl;
278 exit(0);
281 // flush the white space
283 while ( isspace(*CommandString) )
284 CommandString++;
286 index = 0;
288 // start the loop to build all the individual tokens
290 while (*CommandString != '\0') {
292 pos = 0;
294 // copy the token until white space is found
296 while ( !isspace(*CommandString) && *CommandString != '\0') {
298 buffer[pos++] = *CommandString++;
302 buffer[pos] = '\0';
304 // get space for the individual tokens
306 ppArgv[index] = (char *) new char [strlen(buffer)+1];
307 if (ppArgv[index] == NULL) {
308 //cout << "Error: nospace" << endl;
309 exit(0);
312 // copy the token
314 strcpy (ppArgv[index++], buffer);
316 // flush while space
318 while ( isspace(*CommandString) )
319 CommandString++;
323 // finish by setting the las pointer to NULL
324 ppArgv[nArgc]= NULL;
328 /*****************************************************************************/
329 void CommandLine::Strtokens(const char *CommandString)
330 /*****************************************************************************/
332 int count = 0;
333 const char *temp;
335 temp = CommandString;
337 /* bypass white space */
339 while (isspace(*temp)) temp++;
341 for (count=0; *temp != '\0'; count++) {
343 /* continue until white space of string terminator is found */
345 while ((!isspace(*temp)) && (*temp != '\0')) temp++;
347 /* bypass white space */
349 while (isspace(*temp)) temp++;
352 nArgc = count;
355 /*****************************************************************************/
356 CCommand::CCommand( ByteString &rString )
357 /*****************************************************************************/
359 rString.SearchAndReplace( '\t', ' ' );
360 aCommand = rString.GetToken( 0, ' ' );
361 aCommandLine = Search();
362 #ifndef UNX
363 aCommandLine += " /c ";
364 #else
365 aCommandLine += " -c ";
366 #endif
368 ByteString sCmd( rString.GetToken( 0, ' ' ));
369 ByteString sParam( rString.Copy( sCmd.Len()));
371 aCommandLine += Search( thePath, sCmd );
372 aCommandLine += sParam;
374 ImplInit();
377 /*****************************************************************************/
378 CCommand::CCommand( const char *pChar )
379 /*****************************************************************************/
381 ByteString aString = pChar;
382 aString.SearchAndReplace( '\t', ' ' );
383 aCommand = aString.GetToken( 0, ' ' );
385 aCommandLine = Search();
386 #ifndef UNX
387 aCommandLine += " /c ";
388 #else
389 aCommandLine += " -c ";
390 #endif
391 ByteString rString( pChar );
393 ByteString sCmd( rString.GetToken( 0, ' ' ));
394 ByteString sParam( rString.Copy( sCmd.Len()));
396 aCommandLine += Search( thePath, sCmd );
397 aCommandLine += sParam;
399 ImplInit();
402 /*****************************************************************************/
403 void CCommand::ImplInit()
404 /*****************************************************************************/
406 char pTmpStr[255];
407 size_t *pPtr;
408 char *pChar;
409 int nVoid = sizeof( size_t * );
410 nArgc = aCommandLine.GetTokenCount(' ');
411 ULONG nLen = aCommandLine.Len();
413 ppArgv = (char **) new char[ (ULONG)(nLen + nVoid * (nArgc +2) + nArgc ) ];
414 pChar = (char *) ppArgv + ( (1+nArgc) * nVoid );
415 pPtr = (size_t *) ppArgv;
416 for ( xub_StrLen i=0; i<nArgc; i++ )
418 (void) strcpy( pTmpStr, aCommandLine.GetToken(i, ' ' ).GetBuffer() );
419 size_t nStrLen = strlen( pTmpStr ) + 1;
420 strcpy( pChar, pTmpStr );
421 *pPtr = (sal_uIntPtr) pChar;
422 pChar += nStrLen;
423 pPtr += 1;
424 #ifdef UNX
425 if ( i == 1 )
427 USHORT nWo = aCommandLine.Search("csh -c ");
428 if (nWo != STRING_NOTFOUND)
429 aCommandLine.Erase(0, nWo + 7);
430 else
431 aCommandLine.Erase(0, 16);
432 i = nArgc;
433 strcpy( pChar, aCommandLine.GetBuffer() );
434 *pPtr = (sal_uIntPtr) pChar;
435 pPtr += 1;
437 #endif
439 *pPtr = 0;
442 /*****************************************************************************/
443 CCommand::operator int()
444 /*****************************************************************************/
446 int nRet;
447 #if defined WNT
448 nRet = _spawnv( P_WAIT, ppArgv[0], (const char **) ppArgv );
449 #elif defined OS2
450 nRet = _spawnv( P_WAIT, ppArgv[0], ppArgv );
451 #elif defined UNX
452 //fprintf( stderr, "CComand : operator (int) not implemented\n");
453 // **** Unix Implementierung ***************
454 pid_t pid;
456 if (( pid = fork()) < 0 )
458 DBG_ASSERT( FALSE, "fork error" );
460 else if ( pid == 0 )
462 if ( execv( ppArgv[0], (char * const *) ppArgv ) < 0 )
464 DBG_ASSERT( FALSE, "execv failed" );
467 //fprintf( stderr, "parent: %s %s\n", ppArgv[0] , ppArgv[1] );
468 if ( (nRet = waitpid( pid, NULL, 0 ) < 0) )
470 DBG_ASSERT( FALSE, "wait error" );
472 #endif
474 switch ( errno )
476 case E2BIG :
477 nError = COMMAND_TOOBIG;
478 break;
479 case EINVAL :
480 nError = COMMAND_INVALID;
481 break;
482 case ENOENT:
483 nError = COMMAND_NOTFOUND;
484 break;
485 case ENOEXEC :
486 nError = COMMAND_NOEXEC;
487 break;
488 case ENOMEM :
489 nError = COMMAND_NOMEM;
490 break;
491 default:
492 nError = COMMAND_UNKNOWN;
495 if ( nRet )
496 fprintf( stderr, "Program returned with errros\n");
497 return nRet;
500 /*****************************************************************************/
501 ByteString CCommand::Search(ByteString aEnv, ByteString sItem)
502 /*****************************************************************************/
504 // default wird eine Shell im Path gesucht,
505 // wenn aber compsec gestzt ist holen wir uns die
506 // Shell von dort
507 if ( sItem.Equals( COMMAND_SHELL ))
509 ByteString aComspec = GetEnv( "COMSPEC" );
510 if ( !aComspec.Equals(""))
511 return aComspec;
514 DirEntry aItem( String( sItem, RTL_TEXTENCODING_ASCII_US ));
515 if ( aItem.Exists())
516 return sItem;
518 ByteString aEntry, sReturn;
519 ByteString sEnv( aEnv );
520 ByteString sEnvironment = GetEnv( sEnv.GetBuffer());
521 xub_StrLen nCount = sEnvironment.GetTokenCount( cPathSeperator );
523 BOOL bFound = FALSE;
525 for ( xub_StrLen i=0; i<nCount && !bFound; i++ )
527 aEntry = sEnvironment.GetToken(i, cPathSeperator );
528 #ifndef UNX
529 aEntry += '\\';
530 #else
531 aEntry += '/';
532 #endif
533 aEntry += sItem;
535 String sEntry( aEntry, RTL_TEXTENCODING_ASCII_US );
536 DirEntry aDirEntry( sEntry );
537 aDirEntry.ToAbs();
538 if ( aDirEntry.Exists()) {
539 sReturn = aEntry;
540 bFound = TRUE;
543 if ( !bFound )
545 sEnv = sEnv.ToUpperAscii();
546 ByteString sEnvironment2 = GetEnv(sEnv.GetBuffer() );
547 xub_StrLen nCount2 = sEnvironment2.GetTokenCount( cPathSeperator );
548 for ( xub_StrLen i=0; i<nCount2 && !bFound; i++ )
550 aEntry = sEnvironment2.GetToken(i, cPathSeperator );
551 #ifndef UNX
552 aEntry += '\\';
553 #else
554 aEntry += '/';
555 #endif
556 aEntry += sItem;
558 String sEntry( aEntry, RTL_TEXTENCODING_ASCII_US );
559 DirEntry aDirEntry( sEntry );
560 aDirEntry.ToAbs();
561 if ( aDirEntry.Exists()) {
562 sReturn = aEntry;
563 bFound = TRUE;
568 if ( sReturn.Equals( "" ))
569 sReturn = sItem;
571 return sReturn;
574 /*****************************************************************************/
575 CCommandd::CCommandd( ByteString &rString, CommandBits nBits )
576 /*****************************************************************************/
577 : CCommand( rString ),
578 nFlag( nBits )
583 /*****************************************************************************/
584 CCommandd::CCommandd( const char *pChar, CommandBits nBits )
585 /*****************************************************************************/
586 : CCommand( pChar ),
587 nFlag( nBits )
591 /*****************************************************************************/
592 CCommandd::operator int()
593 /*****************************************************************************/
595 int nRet = 0;
597 #ifdef WNT
598 LPCTSTR lpApplicationName = NULL;
599 LPTSTR lpCommandLine = (char *) GetCommandLine_().GetBuffer();
600 LPSECURITY_ATTRIBUTES lpProcessAttributes = NULL;
601 LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
602 BOOL bInheritHandles = TRUE;
604 // wie wuenschen wir denn gestartet zu werden ??
605 DWORD dwCreationFlags;
607 if ( nFlag & COMMAND_EXECUTE_START )
608 dwCreationFlags = DETACHED_PROCESS;
609 else
610 dwCreationFlags = CREATE_NEW_CONSOLE;
612 // wir erben vom Vaterprozess
613 LPVOID lpEnvironment = NULL;
615 // das exe im Pfad suchen
616 LPCTSTR lpCurrentDirectory = NULL;
618 // in dieser Struktur bekommen wir die erzeugte Processinfo
619 // zurueck
620 PROCESS_INFORMATION aProcessInformation;
622 // weiteres Startupinfo anlegen
623 STARTUPINFO aStartupInfo;
625 aStartupInfo.cb = sizeof( STARTUPINFO );
626 aStartupInfo.lpReserved = NULL;
627 aStartupInfo.lpDesktop = NULL;
629 // das Fenster bekommt den Namen des Exes
630 aStartupInfo.lpTitle = NULL;
631 aStartupInfo.dwX = 100;
632 aStartupInfo.dwY = 100;
633 //aStartupInfo.dwXSize = 400;
634 //aStartupInfo.dwYSize = 400;
635 aStartupInfo.dwXCountChars = 40;
636 aStartupInfo.dwYCountChars = 40;
638 // Farben setzen
639 aStartupInfo.dwFillAttribute = FOREGROUND_RED | BACKGROUND_RED |
640 BACKGROUND_BLUE | BACKGROUND_GREEN;
642 // aStartupInfo.dwFlags = STARTF_USESTDHANDLES;
643 //aStartupInfo.wShowWindow = SW_NORMAL; //SW_SHOWDEFAULT;
644 //aStartupInfo.wShowWindow = SW_HIDE; //SW_SHOWNOACTIVATE;
645 aStartupInfo.wShowWindow = SW_SHOWNOACTIVATE;
646 aStartupInfo.cbReserved2 = NULL;
647 aStartupInfo.lpReserved2 = NULL;
648 //aStartupInfo.hStdInput = stdin;
649 //aStartupInfo.hStdOutput = stdout;
650 //aStartupInfo.hStdError = stderr;
652 if ( nFlag & COMMAND_EXECUTE_HIDDEN )
654 aStartupInfo.wShowWindow = SW_HIDE;
655 aStartupInfo.dwFlags = aStartupInfo.dwFlags | STARTF_USESHOWWINDOW;
658 bool bProcess = CreateProcess( lpApplicationName,
659 lpCommandLine, lpProcessAttributes,
660 lpThreadAttributes, bInheritHandles,
661 dwCreationFlags, lpEnvironment, lpCurrentDirectory,
662 &aStartupInfo, &aProcessInformation );
664 LPVOID lpMsgBuf;
666 if ( bProcess )
668 FormatMessage(
669 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
670 NULL,
671 GetLastError(),
672 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
673 (LPTSTR) &lpMsgBuf,
675 NULL );
677 ByteString aErrorString = (char *) lpMsgBuf;
679 if ( nFlag & COMMAND_EXECUTE_WAIT )
681 DWORD aProcessState = STILL_ACTIVE;
682 while(aProcessState == STILL_ACTIVE)
684 GetExitCodeProcess(aProcessInformation.hProcess,&aProcessState);
688 else
689 fprintf( stderr, "Can not start Process !" );
691 #endif
692 return nRet;