1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
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"
49 #pragma warning (push,1)
63 //#define MH_TEST2 1 // fuers direkte Testen
65 #if defined(WNT) || defined(OS2)
67 #pragma warning (push,1)
69 #include <process.h> // for _SPAWN
75 #include <sys/types.h>
77 #if ( defined NETBSD ) || defined (FREEBSD) || defined (AIX) \
78 || defined (HPUX) || defined (MACOSX)
83 #define P_WAIT 1 // erstmal einen dummz
87 #include <tools/svwin.h>
90 #if defined(WNT) || defined(OS2)
91 #define cPathSeperator ';'
94 #define cPathSeperator ':'
97 /*****************************************************************************/
98 CommandLine::CommandLine(BOOL bWrite
)
99 /*****************************************************************************/
102 CommandBuffer
= new char [1];
103 if (CommandBuffer
== NULL
) {
104 //cout << "Error: nospace" << endl;
107 CommandBuffer
[0] = '\0';
109 ppArgv
= new char * [1];
112 ComShell
= new char [128];
113 char* pTemp
= getenv("COMMAND_SHELL");
115 strcpy(ComShell
,COMMAND_SHELL
);
117 strcpy(ComShell
,pTemp
);
119 strcpy(&ComShell
[strlen(ComShell
)]," -C ");
122 /*****************************************************************************/
123 CommandLine::CommandLine(const char *CommandString
, BOOL bWrite
)
124 /*****************************************************************************/
127 CommandBuffer
= new char [1];
128 if (CommandBuffer
== NULL
) {
129 //cout << "Error: nospace" << endl;
133 ppArgv
= new char * [1];
136 ComShell
= new char [128];
137 char* pTemp
= getenv("COMMAND_SHELL");
139 strcpy(ComShell
,COMMAND_SHELL
);
141 strcpy(ComShell
,pTemp
);
143 strcpy(&ComShell
[strlen(ComShell
)]," -C ");
145 BuildCommand(CommandString
);
148 /*****************************************************************************/
149 CommandLine::CommandLine(const CommandLine
& CCommandLine
, BOOL bWrite
)
150 /*****************************************************************************/
153 CommandBuffer
= new char [1];
154 if (CommandBuffer
== NULL
) {
155 //cout << "Error: nospace" << endl;
159 ppArgv
= new char * [1];
162 ComShell
= new char [128];
163 char* pTemp
= getenv("COMMAND_SHELL");
165 strcpy(ComShell
,COMMAND_SHELL
);
167 strcpy(ComShell
,pTemp
);
169 strcpy(&ComShell
[strlen(ComShell
)]," -C ");
171 BuildCommand(CCommandLine
.CommandBuffer
);
174 /*****************************************************************************/
175 CommandLine::~CommandLine()
176 /*****************************************************************************/
178 delete [] CommandBuffer
;
180 //for (int i = 0; ppArgv[i] != '\0'; i++) {
181 for (int i
= 0; ppArgv
[i
] != 0; i
++) {
188 /*****************************************************************************/
189 CommandLine
& CommandLine::operator=(const CommandLine
& CCommandLine
)
190 /*****************************************************************************/
192 strcpy (CommandBuffer
, CCommandLine
.CommandBuffer
);
193 for (int i
= 0; i
!= nArgc
; i
++) {
197 ppArgv
= new char * [1];
199 BuildCommand(CommandBuffer
);
203 /*****************************************************************************/
204 CommandLine
& CommandLine::operator=(const char *CommandString
)
205 /*****************************************************************************/
207 strcpy (CommandBuffer
, CommandString
);
208 for (int i
= 0; i
!= nArgc
; i
++) {
212 ppArgv
= new char * [1];
214 BuildCommand(CommandBuffer
);
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;
238 char WorkString
[1024];
240 strcpy(WorkString
,CommandString
);
242 //falls LogWindow -> in tmpfile schreiben
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;
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
++) {
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;
281 // flush the white space
283 while ( isspace(*CommandString
) )
288 // start the loop to build all the individual tokens
290 while (*CommandString
!= '\0') {
294 // copy the token until white space is found
296 while ( !isspace(*CommandString
) && *CommandString
!= '\0') {
298 buffer
[pos
++] = *CommandString
++;
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;
314 strcpy (ppArgv
[index
++], buffer
);
318 while ( isspace(*CommandString
) )
323 // finish by setting the las pointer to NULL
328 /*****************************************************************************/
329 void CommandLine::Strtokens(const char *CommandString
)
330 /*****************************************************************************/
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
++;
355 /*****************************************************************************/
356 CCommand::CCommand( ByteString
&rString
)
357 /*****************************************************************************/
359 rString
.SearchAndReplace( '\t', ' ' );
360 aCommand
= rString
.GetToken( 0, ' ' );
361 aCommandLine
= Search();
363 aCommandLine
+= " /c ";
365 aCommandLine
+= " -c ";
368 ByteString
sCmd( rString
.GetToken( 0, ' ' ));
369 ByteString
sParam( rString
.Copy( sCmd
.Len()));
371 aCommandLine
+= Search( thePath
, sCmd
);
372 aCommandLine
+= sParam
;
377 /*****************************************************************************/
378 CCommand::CCommand( const char *pChar
)
379 /*****************************************************************************/
381 ByteString aString
= pChar
;
382 aString
.SearchAndReplace( '\t', ' ' );
383 aCommand
= aString
.GetToken( 0, ' ' );
385 aCommandLine
= Search();
387 aCommandLine
+= " /c ";
389 aCommandLine
+= " -c ";
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
;
402 /*****************************************************************************/
403 void CCommand::ImplInit()
404 /*****************************************************************************/
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
;
427 USHORT nWo
= aCommandLine
.Search("csh -c ");
428 if (nWo
!= STRING_NOTFOUND
)
429 aCommandLine
.Erase(0, nWo
+ 7);
431 aCommandLine
.Erase(0, 16);
433 strcpy( pChar
, aCommandLine
.GetBuffer() );
434 *pPtr
= (sal_uIntPtr
) pChar
;
442 /*****************************************************************************/
443 CCommand::operator int()
444 /*****************************************************************************/
448 nRet
= _spawnv( P_WAIT
, ppArgv
[0], (const char **) ppArgv
);
450 nRet
= _spawnv( P_WAIT
, ppArgv
[0], ppArgv
);
452 //fprintf( stderr, "CComand : operator (int) not implemented\n");
453 // **** Unix Implementierung ***************
456 if (( pid
= fork()) < 0 )
458 DBG_ASSERT( FALSE
, "fork error" );
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" );
477 nError
= COMMAND_TOOBIG
;
480 nError
= COMMAND_INVALID
;
483 nError
= COMMAND_NOTFOUND
;
486 nError
= COMMAND_NOEXEC
;
489 nError
= COMMAND_NOMEM
;
492 nError
= COMMAND_UNKNOWN
;
496 fprintf( stderr
, "Program returned with errros\n");
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
507 if ( sItem
.Equals( COMMAND_SHELL
))
509 ByteString aComspec
= GetEnv( "COMSPEC" );
510 if ( !aComspec
.Equals(""))
514 DirEntry
aItem( String( sItem
, RTL_TEXTENCODING_ASCII_US
));
518 ByteString aEntry
, sReturn
;
519 ByteString
sEnv( aEnv
);
520 ByteString sEnvironment
= GetEnv( sEnv
.GetBuffer());
521 xub_StrLen nCount
= sEnvironment
.GetTokenCount( cPathSeperator
);
525 for ( xub_StrLen i
=0; i
<nCount
&& !bFound
; i
++ )
527 aEntry
= sEnvironment
.GetToken(i
, cPathSeperator
);
535 String
sEntry( aEntry
, RTL_TEXTENCODING_ASCII_US
);
536 DirEntry
aDirEntry( sEntry
);
538 if ( aDirEntry
.Exists()) {
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
);
558 String
sEntry( aEntry
, RTL_TEXTENCODING_ASCII_US
);
559 DirEntry
aDirEntry( sEntry
);
561 if ( aDirEntry
.Exists()) {
568 if ( sReturn
.Equals( "" ))
574 /*****************************************************************************/
575 CCommandd::CCommandd( ByteString
&rString
, CommandBits nBits
)
576 /*****************************************************************************/
577 : CCommand( rString
),
583 /*****************************************************************************/
584 CCommandd::CCommandd( const char *pChar
, CommandBits nBits
)
585 /*****************************************************************************/
591 /*****************************************************************************/
592 CCommandd::operator int()
593 /*****************************************************************************/
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
;
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
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;
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
);
669 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
672 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
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
);
689 fprintf( stderr
, "Can not start Process !" );