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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 561 CCommandd::CCommandd( ByteString &rString, CommandBits nBits ) 562 /*****************************************************************************/ 563 : CCommand( rString ), 564 nFlag( nBits ) 565 { 566 } 567 568 569 /*****************************************************************************/ 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