1 /*------------------------------------------------------------------------- 2 * drawElements Utility Library 3 * ---------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * 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, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Process abstraction. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "deProcess.h" 25 #include "deMemory.h" 26 #include "deString.h" 27 28 #if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) 29 30 #include "deCommandLine.h" 31 32 #include <sys/types.h> 33 #include <sys/wait.h> 34 #include <unistd.h> 35 #include <stdlib.h> 36 #include <signal.h> 37 #include <fcntl.h> 38 #include <errno.h> 39 40 typedef enum ProcessState_e 41 { 42 PROCESSSTATE_NOT_STARTED = 0, 43 PROCESSSTATE_RUNNING, 44 PROCESSSTATE_FINISHED, 45 46 PROCESSSTATE_LAST 47 } ProcessState; 48 49 struct deProcess_s 50 { 51 ProcessState state; 52 int exitCode; 53 char* lastError; 54 55 pid_t pid; 56 deFile* standardIn; 57 deFile* standardOut; 58 deFile* standardErr; 59 }; 60 61 static void die (int statusPipe, const char* message) 62 { 63 int msgLen = strlen(message); 64 int res = 0; 65 printf("Process launch failed: %s\n", message); 66 res = (int)write(statusPipe, message, msgLen+1); 67 DE_UNREF(res); /* No need to check result. */ 68 exit(-1); 69 } 70 71 static void dieLastError (int statusPipe, const char* message) 72 { 73 char msgBuf[256]; 74 int lastErr = errno; 75 deSprintf(msgBuf, sizeof(msgBuf), "%s, error %d: %s", message, lastErr, strerror(lastErr)); 76 die(statusPipe, msgBuf); 77 } 78 79 DE_INLINE deBool beginsWithPath (const char* fileName, const char* pathPrefix) 80 { 81 int pathLen = strlen(pathPrefix); 82 83 /* Strip trailing / */ 84 while (pathLen > 0 && pathPrefix[pathLen-1] == '/') 85 pathLen -= 1; 86 87 return pathLen > 0 && deMemoryEqual(fileName, pathPrefix, pathLen) && fileName[pathLen] == '/'; 88 } 89 90 static void stripLeadingPath (char* fileName, const char* pathPrefix) 91 { 92 int pathLen = strlen(pathPrefix); 93 int fileNameLen = strlen(fileName); 94 95 DE_ASSERT(beginsWithPath(fileName, pathPrefix)); 96 97 /* Strip trailing / */ 98 while (pathLen > 0 && pathPrefix[pathLen-1] == '/') 99 pathLen -= 1; 100 101 DE_ASSERT(pathLen > 0); 102 DE_ASSERT(fileName[pathLen] == '/'); 103 104 memmove(&fileName[0], &fileName[0]+pathLen+1, fileNameLen-pathLen); 105 } 106 107 /* Doesn't return on success. */ 108 static void execProcess (const char* commandLine, const char* workingDirectory, int statusPipe) 109 { 110 deCommandLine* cmdLine = deCommandLine_parse(commandLine); 111 char** argList = cmdLine ? (char**)deCalloc(sizeof(char*)*(cmdLine->numArgs+1)) : DE_NULL; 112 113 if (!cmdLine || !argList) 114 die(statusPipe, "Command line parsing failed (out of memory)"); 115 116 if (workingDirectory && chdir(workingDirectory) != 0) 117 dieLastError(statusPipe, "chdir() failed"); 118 119 { 120 int argNdx; 121 for (argNdx = 0; argNdx < cmdLine->numArgs; argNdx++) 122 argList[argNdx] = cmdLine->args[argNdx]; 123 argList[argNdx] = DE_NULL; /* Terminate with 0. */ 124 } 125 126 if (workingDirectory && beginsWithPath(argList[0], workingDirectory)) 127 stripLeadingPath(argList[0], workingDirectory); 128 129 execv(argList[0], argList); 130 131 /* Failed. */ 132 dieLastError(statusPipe, "execv() failed"); 133 } 134 135 deProcess* deProcess_create (void) 136 { 137 deProcess* process = (deProcess*)deCalloc(sizeof(deProcess)); 138 if (!process) 139 return DE_FALSE; 140 141 process->state = PROCESSSTATE_NOT_STARTED; 142 143 return process; 144 } 145 146 static void deProcess_cleanupHandles (deProcess* process) 147 { 148 if (process->standardIn) 149 deFile_destroy(process->standardIn); 150 151 if (process->standardOut) 152 deFile_destroy(process->standardOut); 153 154 if (process->standardErr) 155 deFile_destroy(process->standardErr); 156 157 process->pid = 0; 158 process->standardIn = DE_NULL; 159 process->standardOut = DE_NULL; 160 process->standardErr = DE_NULL; 161 } 162 163 void deProcess_destroy (deProcess* process) 164 { 165 /* Never leave child processes running. Otherwise we'll have zombies. */ 166 if (deProcess_isRunning(process)) 167 { 168 deProcess_kill(process); 169 deProcess_waitForFinish(process); 170 } 171 172 deProcess_cleanupHandles(process); 173 deFree(process->lastError); 174 deFree(process); 175 } 176 177 const char* deProcess_getLastError (const deProcess* process) 178 { 179 return process->lastError ? process->lastError : "No error"; 180 } 181 182 int deProcess_getExitCode (const deProcess* process) 183 { 184 return process->exitCode; 185 } 186 187 static deBool deProcess_setError (deProcess* process, const char* error) 188 { 189 if (process->lastError) 190 { 191 deFree(process->lastError); 192 process->lastError = DE_NULL; 193 } 194 195 process->lastError = deStrdup(error); 196 return process->lastError != DE_NULL; 197 } 198 199 static deBool deProcess_setErrorFromErrno (deProcess* process, const char* message) 200 { 201 char msgBuf[256]; 202 int lastErr = errno; 203 deSprintf(msgBuf, sizeof(msgBuf), "%s, error %d: %s", message, lastErr, strerror(lastErr)); 204 return deProcess_setError(process, message); 205 } 206 207 static void closePipe (int p[2]) 208 { 209 if (p[0] >= 0) 210 close(p[0]); 211 if (p[1] >= 0) 212 close(p[1]); 213 } 214 215 deBool deProcess_start (deProcess* process, const char* commandLine, const char* workingDirectory) 216 { 217 pid_t pid = 0; 218 int pipeIn[2] = { -1, -1 }; 219 int pipeOut[2] = { -1, -1 }; 220 int pipeErr[2] = { -1, -1 }; 221 int statusPipe[2] = { -1, -1 }; 222 223 if (process->state == PROCESSSTATE_RUNNING) 224 { 225 deProcess_setError(process, "Process already running"); 226 return DE_FALSE; 227 } 228 else if (process->state == PROCESSSTATE_FINISHED) 229 { 230 deProcess_cleanupHandles(process); 231 process->state = PROCESSSTATE_NOT_STARTED; 232 } 233 234 if (pipe(pipeIn) < 0 || pipe(pipeOut) < 0 || pipe(pipeErr) < 0 || pipe(statusPipe) < 0) 235 { 236 deProcess_setErrorFromErrno(process, "pipe() failed"); 237 238 closePipe(pipeIn); 239 closePipe(pipeOut); 240 closePipe(pipeErr); 241 closePipe(statusPipe); 242 243 return DE_FALSE; 244 } 245 246 pid = fork(); 247 248 if (pid < 0) 249 { 250 deProcess_setErrorFromErrno(process, "fork() failed"); 251 252 closePipe(pipeIn); 253 closePipe(pipeOut); 254 closePipe(pipeErr); 255 closePipe(statusPipe); 256 257 return DE_FALSE; 258 } 259 260 if (pid == 0) 261 { 262 /* Child process. */ 263 264 /* Close unused endpoints. */ 265 close(pipeIn[1]); 266 close(pipeOut[0]); 267 close(pipeErr[0]); 268 close(statusPipe[0]); 269 270 /* Set status pipe to close on exec(). That way parent will know that exec() succeeded. */ 271 if (fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC) != 0) 272 dieLastError(statusPipe[1], "Failed to set FD_CLOEXEC"); 273 274 /* Map stdin. */ 275 if (pipeIn[0] != STDIN_FILENO && 276 dup2(pipeIn[0], STDIN_FILENO) != STDIN_FILENO) 277 dieLastError(statusPipe[1], "dup2() failed"); 278 close(pipeIn[0]); 279 280 /* Stdout. */ 281 if (pipeOut[1] != STDOUT_FILENO && 282 dup2(pipeOut[1], STDOUT_FILENO) != STDOUT_FILENO) 283 dieLastError(statusPipe[1], "dup2() failed"); 284 close(pipeOut[1]); 285 286 /* Stderr. */ 287 if (pipeErr[1] != STDERR_FILENO && 288 dup2(pipeErr[1], STDERR_FILENO) != STDERR_FILENO) 289 dieLastError(statusPipe[1], "dup2() failed"); 290 close(pipeErr[1]); 291 292 /* Doesn't return. */ 293 execProcess(commandLine, workingDirectory, statusPipe[1]); 294 } 295 else 296 { 297 /* Parent process. */ 298 299 /* Check status. */ 300 { 301 char errBuf[256]; 302 int result = 0; 303 304 close(statusPipe[1]); 305 while ((result = read(statusPipe[0], errBuf, 1)) == -1) 306 if (errno != EAGAIN && errno != EINTR) break; 307 308 if (result > 0) 309 { 310 /* Read full error msg. */ 311 int errPos = 1; 312 while (errPos < DE_LENGTH_OF_ARRAY(errBuf)) 313 { 314 result = read(statusPipe[0], errBuf+errPos, 1); 315 if (result == -1) 316 break; /* Done. */ 317 318 errPos += 1; 319 } 320 321 /* Make sure str is null-terminated. */ 322 errBuf[errPos] = 0; 323 324 /* Close handles. */ 325 close(statusPipe[0]); 326 closePipe(pipeIn); 327 closePipe(pipeOut); 328 closePipe(pipeErr); 329 330 /* Run waitpid to clean up zombie. */ 331 waitpid(pid, &result, 0); 332 333 deProcess_setError(process, errBuf); 334 335 return DE_FALSE; 336 } 337 338 /* Status pipe is not needed. */ 339 close(statusPipe[0]); 340 } 341 342 /* Set running state. */ 343 process->pid = pid; 344 process->state = PROCESSSTATE_RUNNING; 345 346 /* Stdin, stdout. */ 347 close(pipeIn[0]); 348 close(pipeOut[1]); 349 close(pipeErr[1]); 350 351 process->standardIn = deFile_createFromHandle(pipeIn[1]); 352 process->standardOut = deFile_createFromHandle(pipeOut[0]); 353 process->standardErr = deFile_createFromHandle(pipeErr[0]); 354 355 if (!process->standardIn) 356 close(pipeIn[1]); 357 358 if (!process->standardOut) 359 close(pipeOut[0]); 360 361 if (!process->standardErr) 362 close(pipeErr[0]); 363 } 364 365 return DE_TRUE; 366 } 367 368 deBool deProcess_isRunning (deProcess* process) 369 { 370 if (process->state == PROCESSSTATE_RUNNING) 371 { 372 int status = 0; 373 374 if (waitpid(process->pid, &status, WNOHANG) == 0) 375 return DE_TRUE; /* No status available. */ 376 377 if (WIFEXITED(status) || WIFSIGNALED(status)) 378 { 379 /* Child has finished. */ 380 process->state = PROCESSSTATE_FINISHED; 381 return DE_FALSE; 382 } 383 else 384 return DE_TRUE; 385 } 386 else 387 return DE_FALSE; 388 } 389 390 deBool deProcess_waitForFinish (deProcess* process) 391 { 392 int status = 0; 393 pid_t waitResult; 394 395 if (process->state != PROCESSSTATE_RUNNING) 396 { 397 deProcess_setError(process, "Process is not running"); 398 return DE_FALSE; 399 } 400 401 /* \note [pyry] Crazy hack for OS X Lion. Stupid Apple. */ 402 while ((waitResult = waitpid(process->pid, &status, 0)) != process->pid) 403 if (errno != ENOENT) break; 404 405 if (waitResult != process->pid) 406 { 407 deProcess_setErrorFromErrno(process, "waitpid() failed"); 408 return DE_FALSE; /* waitpid() failed. */ 409 } 410 411 if (!WIFEXITED(status) && !WIFSIGNALED(status)) 412 { 413 deProcess_setErrorFromErrno(process, "waitpid() failed"); 414 return DE_FALSE; /* Something strange happened. */ 415 } 416 417 process->exitCode = WEXITSTATUS(status); 418 process->state = PROCESSSTATE_FINISHED; 419 return DE_TRUE; 420 } 421 422 static deBool deProcess_sendSignal (deProcess* process, int sigNum) 423 { 424 if (process->state != PROCESSSTATE_RUNNING) 425 { 426 deProcess_setError(process, "Process is not running"); 427 return DE_FALSE; 428 } 429 430 if (kill(process->pid, sigNum) == 0) 431 return DE_TRUE; 432 else 433 { 434 deProcess_setErrorFromErrno(process, "kill() failed"); 435 return DE_FALSE; 436 } 437 } 438 439 deBool deProcess_terminate (deProcess* process) 440 { 441 return deProcess_sendSignal(process, SIGTERM); 442 } 443 444 deBool deProcess_kill (deProcess* process) 445 { 446 return deProcess_sendSignal(process, SIGKILL); 447 } 448 449 deFile* deProcess_getStdIn (deProcess* process) 450 { 451 return process->standardIn; 452 } 453 454 deFile* deProcess_getStdOut (deProcess* process) 455 { 456 return process->standardOut; 457 } 458 459 deFile* deProcess_getStdErr (deProcess* process) 460 { 461 return process->standardErr; 462 } 463 464 deBool deProcess_closeStdIn (deProcess* process) 465 { 466 if (process->standardIn) 467 { 468 deFile_destroy(process->standardIn); 469 process->standardIn = DE_NULL; 470 return DE_TRUE; 471 } 472 else 473 return DE_FALSE; 474 } 475 476 deBool deProcess_closeStdOut (deProcess* process) 477 { 478 if (process->standardOut) 479 { 480 deFile_destroy(process->standardOut); 481 process->standardOut = DE_NULL; 482 return DE_TRUE; 483 } 484 else 485 return DE_FALSE; 486 } 487 488 deBool deProcess_closeStdErr (deProcess* process) 489 { 490 if (process->standardErr) 491 { 492 deFile_destroy(process->standardErr); 493 process->standardErr = DE_NULL; 494 return DE_TRUE; 495 } 496 else 497 return DE_FALSE; 498 } 499 500 #elif (DE_OS == DE_OS_WIN32) 501 502 #define VC_EXTRALEAN 503 #define WIN32_LEAN_AND_MEAN 504 #include <windows.h> 505 #include <strsafe.h> 506 507 typedef enum ProcessState_e 508 { 509 PROCESSSTATE_NOT_STARTED = 0, 510 PROCESSSTATE_RUNNING, 511 PROCESSSTATE_FINISHED, 512 513 PROCESSSTATE_LAST 514 } ProcessState; 515 516 struct deProcess_s 517 { 518 ProcessState state; 519 char* lastError; 520 int exitCode; 521 522 PROCESS_INFORMATION procInfo; 523 deFile* standardIn; 524 deFile* standardOut; 525 deFile* standardErr; 526 }; 527 528 static deBool deProcess_setError (deProcess* process, const char* error) 529 { 530 if (process->lastError) 531 { 532 deFree(process->lastError); 533 process->lastError = DE_NULL; 534 } 535 536 process->lastError = deStrdup(error); 537 return process->lastError != DE_NULL; 538 } 539 540 static deBool deProcess_setErrorFromWin32 (deProcess* process, const char* msg) 541 { 542 DWORD error = GetLastError(); 543 LPSTR msgBuf; 544 char errBuf[256]; 545 546 #if defined(UNICODE) 547 # error Unicode not supported. 548 #endif 549 550 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 551 NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, DE_NULL) > 0) 552 { 553 deSprintf(errBuf, sizeof(errBuf), "%s, error %d: %s", msg, error, msgBuf); 554 LocalFree(msgBuf); 555 return deProcess_setError(process, errBuf); 556 } 557 else 558 { 559 /* Failed to get error str. */ 560 deSprintf(errBuf, sizeof(errBuf), "%s, error %d", msg, error); 561 return deProcess_setError(process, errBuf); 562 } 563 } 564 565 deProcess* deProcess_create (void) 566 { 567 deProcess* process = (deProcess*)deCalloc(sizeof(deProcess)); 568 if (!process) 569 return DE_NULL; 570 571 process->state = PROCESSSTATE_NOT_STARTED; 572 573 return process; 574 } 575 576 void deProcess_cleanupHandles (deProcess* process) 577 { 578 DE_ASSERT(!deProcess_isRunning(process)); 579 580 if (process->standardErr) 581 deFile_destroy(process->standardErr); 582 583 if (process->standardOut) 584 deFile_destroy(process->standardOut); 585 586 if (process->standardIn) 587 deFile_destroy(process->standardIn); 588 589 if (process->procInfo.hProcess) 590 CloseHandle(process->procInfo.hProcess); 591 592 if (process->procInfo.hThread) 593 CloseHandle(process->procInfo.hThread); 594 595 process->standardErr = DE_NULL; 596 process->standardOut = DE_NULL; 597 process->standardIn = DE_NULL; 598 process->procInfo.hProcess = DE_NULL; 599 process->procInfo.hThread = DE_NULL; 600 } 601 602 void deProcess_destroy (deProcess* process) 603 { 604 if (deProcess_isRunning(process)) 605 { 606 deProcess_kill(process); 607 deProcess_waitForFinish(process); 608 } 609 610 deProcess_cleanupHandles(process); 611 deFree(process->lastError); 612 deFree(process); 613 } 614 615 const char* deProcess_getLastError (const deProcess* process) 616 { 617 return process->lastError ? process->lastError : "No error"; 618 } 619 620 int deProcess_getExitCode (const deProcess* process) 621 { 622 return process->exitCode; 623 } 624 625 deBool deProcess_start (deProcess* process, const char* commandLine, const char* workingDirectory) 626 { 627 SECURITY_ATTRIBUTES securityAttr; 628 STARTUPINFO startInfo; 629 630 /* Pipes. */ 631 HANDLE stdInRead = DE_NULL; 632 HANDLE stdInWrite = DE_NULL; 633 HANDLE stdOutRead = DE_NULL; 634 HANDLE stdOutWrite = DE_NULL; 635 HANDLE stdErrRead = DE_NULL; 636 HANDLE stdErrWrite = DE_NULL; 637 638 if (process->state == PROCESSSTATE_RUNNING) 639 { 640 deProcess_setError(process, "Process already running"); 641 return DE_FALSE; 642 } 643 else if (process->state == PROCESSSTATE_FINISHED) 644 { 645 /* Process finished, clean up old cruft. */ 646 deProcess_cleanupHandles(process); 647 process->state = PROCESSSTATE_NOT_STARTED; 648 } 649 650 deMemset(&startInfo, 0, sizeof(startInfo)); 651 deMemset(&securityAttr, 0, sizeof(securityAttr)); 652 653 /* Security attributes for inheriting handle. */ 654 securityAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 655 securityAttr.bInheritHandle = TRUE; 656 securityAttr.lpSecurityDescriptor = DE_NULL; 657 658 /* Create pipes. \todo [2011-10-03 pyry] Clean up handles on error! */ 659 if (!CreatePipe(&stdInRead, &stdInWrite, &securityAttr, 0) || 660 !SetHandleInformation(stdInWrite, HANDLE_FLAG_INHERIT, 0)) 661 { 662 deProcess_setErrorFromWin32(process, "CreatePipe() failed"); 663 CloseHandle(stdInRead); 664 CloseHandle(stdInWrite); 665 return DE_FALSE; 666 } 667 668 if (!CreatePipe(&stdOutRead, &stdOutWrite, &securityAttr, 0) || 669 !SetHandleInformation(stdOutRead, HANDLE_FLAG_INHERIT, 0)) 670 { 671 deProcess_setErrorFromWin32(process, "CreatePipe() failed"); 672 CloseHandle(stdInRead); 673 CloseHandle(stdInWrite); 674 CloseHandle(stdOutRead); 675 CloseHandle(stdOutWrite); 676 return DE_FALSE; 677 } 678 679 if (!CreatePipe(&stdErrRead, &stdErrWrite, &securityAttr, 0) || 680 !SetHandleInformation(stdErrRead, HANDLE_FLAG_INHERIT, 0)) 681 { 682 deProcess_setErrorFromWin32(process, "CreatePipe() failed"); 683 CloseHandle(stdInRead); 684 CloseHandle(stdInWrite); 685 CloseHandle(stdOutRead); 686 CloseHandle(stdOutWrite); 687 CloseHandle(stdErrRead); 688 CloseHandle(stdErrWrite); 689 return DE_FALSE; 690 } 691 692 /* Setup startup info. */ 693 startInfo.cb = sizeof(startInfo); 694 startInfo.hStdError = stdErrWrite; 695 startInfo.hStdOutput = stdOutWrite; 696 startInfo.hStdInput = stdInRead; 697 startInfo.dwFlags |= STARTF_USESTDHANDLES; 698 699 if (!CreateProcess(DE_NULL, (LPTSTR)commandLine, DE_NULL, DE_NULL, TRUE /* inherit handles */, 0, DE_NULL, workingDirectory, &startInfo, &process->procInfo)) 700 { 701 /* Store error info. */ 702 deProcess_setErrorFromWin32(process, "CreateProcess() failed"); 703 704 /* Close all handles. */ 705 CloseHandle(stdInRead); 706 CloseHandle(stdInWrite); 707 CloseHandle(stdOutRead); 708 CloseHandle(stdOutWrite); 709 CloseHandle(stdErrRead); 710 CloseHandle(stdErrWrite); 711 712 return DE_FALSE; 713 } 714 715 process->state = PROCESSSTATE_RUNNING; 716 717 /* Close our ends of handles.*/ 718 CloseHandle(stdErrWrite); 719 CloseHandle(stdOutWrite); 720 CloseHandle(stdInRead); 721 722 /* Construct stdio file objects \note May fail, not detected. */ 723 process->standardIn = deFile_createFromHandle((deUintptr)stdInWrite); 724 process->standardOut = deFile_createFromHandle((deUintptr)stdOutRead); 725 process->standardErr = deFile_createFromHandle((deUintptr)stdErrRead); 726 727 return DE_TRUE; 728 } 729 730 deBool deProcess_isRunning (deProcess* process) 731 { 732 if (process->state == PROCESSSTATE_RUNNING) 733 { 734 int exitCode; 735 BOOL result = GetExitCodeProcess(process->procInfo.hProcess, (LPDWORD)&exitCode); 736 737 if (result != TRUE) 738 { 739 deProcess_setErrorFromWin32(process, "GetExitCodeProcess() failed"); 740 return DE_FALSE; 741 } 742 743 if (exitCode == STILL_ACTIVE) 744 return DE_TRUE; 745 else 746 { 747 /* Done. */ 748 process->exitCode = exitCode; 749 process->state = PROCESSSTATE_FINISHED; 750 return DE_FALSE; 751 } 752 } 753 else 754 return DE_FALSE; 755 } 756 757 deBool deProcess_waitForFinish (deProcess* process) 758 { 759 if (process->state == PROCESSSTATE_RUNNING) 760 { 761 if (WaitForSingleObject(process->procInfo.hProcess, INFINITE) != WAIT_OBJECT_0) 762 { 763 deProcess_setErrorFromWin32(process, "WaitForSingleObject() failed"); 764 return DE_FALSE; 765 } 766 return !deProcess_isRunning(process); 767 } 768 else 769 { 770 deProcess_setError(process, "Process is not running"); 771 return DE_FALSE; 772 } 773 } 774 775 static deBool stopProcess (deProcess* process, deBool kill) 776 { 777 if (process->state == PROCESSSTATE_RUNNING) 778 { 779 if (!TerminateProcess(process->procInfo.hProcess, kill ? -1 : 0)) 780 { 781 deProcess_setErrorFromWin32(process, "TerminateProcess() failed"); 782 return DE_FALSE; 783 } 784 else 785 return DE_TRUE; 786 } 787 else 788 { 789 deProcess_setError(process, "Process is not running"); 790 return DE_FALSE; 791 } 792 } 793 794 deBool deProcess_terminate (deProcess* process) 795 { 796 return stopProcess(process, DE_FALSE); 797 } 798 799 deBool deProcess_kill (deProcess* process) 800 { 801 return stopProcess(process, DE_TRUE); 802 } 803 804 deFile* deProcess_getStdIn (deProcess* process) 805 { 806 return process->standardIn; 807 } 808 809 deFile* deProcess_getStdOut (deProcess* process) 810 { 811 return process->standardOut; 812 } 813 814 deFile* deProcess_getStdErr (deProcess* process) 815 { 816 return process->standardErr; 817 } 818 819 deBool deProcess_closeStdIn (deProcess* process) 820 { 821 if (process->standardIn) 822 { 823 deFile_destroy(process->standardIn); 824 process->standardIn = DE_NULL; 825 return DE_TRUE; 826 } 827 else 828 return DE_FALSE; 829 } 830 831 deBool deProcess_closeStdOut (deProcess* process) 832 { 833 if (process->standardOut) 834 { 835 deFile_destroy(process->standardOut); 836 process->standardOut = DE_NULL; 837 return DE_TRUE; 838 } 839 else 840 return DE_FALSE; 841 } 842 843 deBool deProcess_closeStdErr (deProcess* process) 844 { 845 if (process->standardErr) 846 { 847 deFile_destroy(process->standardErr); 848 process->standardErr = DE_NULL; 849 return DE_TRUE; 850 } 851 else 852 return DE_FALSE; 853 } 854 855 #else 856 # error Implement deProcess for your OS. 857 #endif 858