xref: /AOO41X/main/soldep/bootstrp/command.cxx (revision d9e04f7d457e8d4292f3a8dc854ee7656a676fbb)
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 /*****************************************************************************/
operator int()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 /*****************************************************************************/
operator int()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