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