1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gio.Subprocess; 26 27 private import gio.AsyncResultIF; 28 private import gio.Cancellable; 29 private import gio.InitableIF; 30 private import gio.InitableT; 31 private import gio.InputStream; 32 private import gio.OutputStream; 33 private import gio.c.functions; 34 public import gio.c.types; 35 private import glib.Bytes; 36 private import glib.ConstructionException; 37 private import glib.ErrorG; 38 private import glib.GException; 39 private import glib.Str; 40 private import gobject.ObjectG; 41 public import gtkc.giotypes; 42 43 44 /** 45 * #GSubprocess allows the creation of and interaction with child 46 * processes. 47 * 48 * Processes can be communicated with using standard GIO-style APIs (ie: 49 * #GInputStream, #GOutputStream). There are GIO-style APIs to wait for 50 * process termination (ie: cancellable and with an asynchronous 51 * variant). 52 * 53 * There is an API to force a process to terminate, as well as a 54 * race-free API for sending UNIX signals to a subprocess. 55 * 56 * One major advantage that GIO brings over the core GLib library is 57 * comprehensive API for asynchronous I/O, such 58 * g_output_stream_splice_async(). This makes GSubprocess 59 * significantly more powerful and flexible than equivalent APIs in 60 * some other languages such as the `subprocess.py` 61 * included with Python. For example, using #GSubprocess one could 62 * create two child processes, reading standard output from the first, 63 * processing it, and writing to the input stream of the second, all 64 * without blocking the main loop. 65 * 66 * A powerful g_subprocess_communicate() API is provided similar to the 67 * `communicate()` method of `subprocess.py`. This enables very easy 68 * interaction with a subprocess that has been opened with pipes. 69 * 70 * #GSubprocess defaults to tight control over the file descriptors open 71 * in the child process, avoiding dangling-fd issues that are caused by 72 * a simple fork()/exec(). The only open file descriptors in the 73 * spawned process are ones that were explicitly specified by the 74 * #GSubprocess API (unless %G_SUBPROCESS_FLAGS_INHERIT_FDS was 75 * specified). 76 * 77 * #GSubprocess will quickly reap all child processes as they exit, 78 * avoiding "zombie processes" remaining around for long periods of 79 * time. g_subprocess_wait() can be used to wait for this to happen, 80 * but it will happen even without the call being explicitly made. 81 * 82 * As a matter of principle, #GSubprocess has no API that accepts 83 * shell-style space-separated strings. It will, however, match the 84 * typical shell behaviour of searching the PATH for executables that do 85 * not contain a directory separator in their name. 86 * 87 * #GSubprocess attempts to have a very simple API for most uses (ie: 88 * spawning a subprocess with arguments and support for most typical 89 * kinds of input and output redirection). See g_subprocess_new(). The 90 * #GSubprocessLauncher API is provided for more complicated cases 91 * (advanced types of redirection, environment variable manipulation, 92 * change of working directory, child setup functions, etc). 93 * 94 * A typical use of #GSubprocess will involve calling 95 * g_subprocess_new(), followed by g_subprocess_wait_async() or 96 * g_subprocess_wait(). After the process exits, the status can be 97 * checked using functions such as g_subprocess_get_if_exited() (which 98 * are similar to the familiar WIFEXITED-style POSIX macros). 99 * 100 * Since: 2.40 101 */ 102 public class Subprocess : ObjectG, InitableIF 103 { 104 /** the main Gtk struct */ 105 protected GSubprocess* gSubprocess; 106 107 /** Get the main Gtk struct */ 108 public GSubprocess* getSubprocessStruct(bool transferOwnership = false) 109 { 110 if (transferOwnership) 111 ownedRef = false; 112 return gSubprocess; 113 } 114 115 /** the main Gtk struct as a void* */ 116 protected override void* getStruct() 117 { 118 return cast(void*)gSubprocess; 119 } 120 121 /** 122 * Sets our main struct and passes it to the parent class. 123 */ 124 public this (GSubprocess* gSubprocess, bool ownedRef = false) 125 { 126 this.gSubprocess = gSubprocess; 127 super(cast(GObject*)gSubprocess, ownedRef); 128 } 129 130 // add the Initable capabilities 131 mixin InitableT!(GSubprocess); 132 133 134 /** */ 135 public static GType getType() 136 { 137 return g_subprocess_get_type(); 138 } 139 140 /** 141 * Create a new process with the given flags and argument list. 142 * 143 * The argument list is expected to be %NULL-terminated. 144 * 145 * Params: 146 * argv = commandline arguments for the subprocess 147 * flags = flags that define the behaviour of the subprocess 148 * 149 * Returns: A newly created #GSubprocess, or %NULL on error (and @error 150 * will be set) 151 * 152 * Since: 2.40 153 * 154 * Throws: GException on failure. 155 * Throws: ConstructionException GTK+ fails to create the object. 156 */ 157 public this(string[] argv, GSubprocessFlags flags) 158 { 159 GError* err = null; 160 161 auto p = g_subprocess_newv(Str.toStringzArray(argv), flags, &err); 162 163 if (err !is null) 164 { 165 throw new GException( new ErrorG(err) ); 166 } 167 168 if(p is null) 169 { 170 throw new ConstructionException("null returned by newv"); 171 } 172 173 this(cast(GSubprocess*) p, true); 174 } 175 176 /** 177 * Communicate with the subprocess until it terminates, and all input 178 * and output has been completed. 179 * 180 * If @stdin_buf is given, the subprocess must have been created with 181 * %G_SUBPROCESS_FLAGS_STDIN_PIPE. The given data is fed to the 182 * stdin of the subprocess and the pipe is closed (ie: EOF). 183 * 184 * At the same time (as not to cause blocking when dealing with large 185 * amounts of data), if %G_SUBPROCESS_FLAGS_STDOUT_PIPE or 186 * %G_SUBPROCESS_FLAGS_STDERR_PIPE were used, reads from those 187 * streams. The data that was read is returned in @stdout and/or 188 * the @stderr. 189 * 190 * If the subprocess was created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 191 * @stdout_buf will contain the data read from stdout. Otherwise, for 192 * subprocesses not created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 193 * @stdout_buf will be set to %NULL. Similar provisions apply to 194 * @stderr_buf and %G_SUBPROCESS_FLAGS_STDERR_PIPE. 195 * 196 * As usual, any output variable may be given as %NULL to ignore it. 197 * 198 * If you desire the stdout and stderr data to be interleaved, create 199 * the subprocess with %G_SUBPROCESS_FLAGS_STDOUT_PIPE and 200 * %G_SUBPROCESS_FLAGS_STDERR_MERGE. The merged result will be returned 201 * in @stdout_buf and @stderr_buf will be set to %NULL. 202 * 203 * In case of any error (including cancellation), %FALSE will be 204 * returned with @error set. Some or all of the stdin data may have 205 * been written. Any stdout or stderr data that has been read will be 206 * discarded. None of the out variables (aside from @error) will have 207 * been set to anything in particular and should not be inspected. 208 * 209 * In the case that %TRUE is returned, the subprocess has exited and the 210 * exit status inspection APIs (eg: g_subprocess_get_if_exited(), 211 * g_subprocess_get_exit_status()) may be used. 212 * 213 * You should not attempt to use any of the subprocess pipes after 214 * starting this function, since they may be left in strange states, 215 * even if the operation was cancelled. You should especially not 216 * attempt to interact with the pipes while the operation is in progress 217 * (either from another thread or if using the asynchronous version). 218 * 219 * Params: 220 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 221 * cancellable = a #GCancellable 222 * stdoutBuf = data read from the subprocess stdout 223 * stderrBuf = data read from the subprocess stderr 224 * 225 * Returns: %TRUE if successful 226 * 227 * Since: 2.40 228 * 229 * Throws: GException on failure. 230 */ 231 public bool communicate(Bytes stdinBuf, Cancellable cancellable, out Bytes stdoutBuf, out Bytes stderrBuf) 232 { 233 GBytes* outstdoutBuf = null; 234 GBytes* outstderrBuf = null; 235 GError* err = null; 236 237 auto p = g_subprocess_communicate(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 238 239 if (err !is null) 240 { 241 throw new GException( new ErrorG(err) ); 242 } 243 244 stdoutBuf = new Bytes(outstdoutBuf); 245 stderrBuf = new Bytes(outstderrBuf); 246 247 return p; 248 } 249 250 /** 251 * Asynchronous version of g_subprocess_communicate(). Complete 252 * invocation with g_subprocess_communicate_finish(). 253 * 254 * Params: 255 * stdinBuf = Input data, or %NULL 256 * cancellable = Cancellable 257 * callback = Callback 258 * userData = User data 259 */ 260 public void communicateAsync(Bytes stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 261 { 262 g_subprocess_communicate_async(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 263 } 264 265 /** 266 * Complete an invocation of g_subprocess_communicate_async(). 267 * 268 * Params: 269 * result = Result 270 * stdoutBuf = Return location for stdout data 271 * stderrBuf = Return location for stderr data 272 * 273 * Throws: GException on failure. 274 */ 275 public bool communicateFinish(AsyncResultIF result, out Bytes stdoutBuf, out Bytes stderrBuf) 276 { 277 GBytes* outstdoutBuf = null; 278 GBytes* outstderrBuf = null; 279 GError* err = null; 280 281 auto p = g_subprocess_communicate_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 282 283 if (err !is null) 284 { 285 throw new GException( new ErrorG(err) ); 286 } 287 288 stdoutBuf = new Bytes(outstdoutBuf); 289 stderrBuf = new Bytes(outstderrBuf); 290 291 return p; 292 } 293 294 /** 295 * Like g_subprocess_communicate(), but validates the output of the 296 * process as UTF-8, and returns it as a regular NUL terminated string. 297 * 298 * Params: 299 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 300 * cancellable = a #GCancellable 301 * stdoutBuf = data read from the subprocess stdout 302 * stderrBuf = data read from the subprocess stderr 303 * 304 * Throws: GException on failure. 305 */ 306 public bool communicateUtf8(string stdinBuf, Cancellable cancellable, out string stdoutBuf, out string stderrBuf) 307 { 308 char* outstdoutBuf = null; 309 char* outstderrBuf = null; 310 GError* err = null; 311 312 auto p = g_subprocess_communicate_utf8(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 313 314 if (err !is null) 315 { 316 throw new GException( new ErrorG(err) ); 317 } 318 319 stdoutBuf = Str.toString(outstdoutBuf); 320 stderrBuf = Str.toString(outstderrBuf); 321 322 return p; 323 } 324 325 /** 326 * Asynchronous version of g_subprocess_communicate_utf8(). Complete 327 * invocation with g_subprocess_communicate_utf8_finish(). 328 * 329 * Params: 330 * stdinBuf = Input data, or %NULL 331 * cancellable = Cancellable 332 * callback = Callback 333 * userData = User data 334 */ 335 public void communicateUtf8Async(string stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 336 { 337 g_subprocess_communicate_utf8_async(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 338 } 339 340 /** 341 * Complete an invocation of g_subprocess_communicate_utf8_async(). 342 * 343 * Params: 344 * result = Result 345 * stdoutBuf = Return location for stdout data 346 * stderrBuf = Return location for stderr data 347 * 348 * Throws: GException on failure. 349 */ 350 public bool communicateUtf8Finish(AsyncResultIF result, out string stdoutBuf, out string stderrBuf) 351 { 352 char* outstdoutBuf = null; 353 char* outstderrBuf = null; 354 GError* err = null; 355 356 auto p = g_subprocess_communicate_utf8_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 357 358 if (err !is null) 359 { 360 throw new GException( new ErrorG(err) ); 361 } 362 363 stdoutBuf = Str.toString(outstdoutBuf); 364 stderrBuf = Str.toString(outstderrBuf); 365 366 return p; 367 } 368 369 /** 370 * Use an operating-system specific method to attempt an immediate, 371 * forceful termination of the process. There is no mechanism to 372 * determine whether or not the request itself was successful; 373 * however, you can use g_subprocess_wait() to monitor the status of 374 * the process after calling this function. 375 * 376 * On Unix, this function sends %SIGKILL. 377 * 378 * Since: 2.40 379 */ 380 public void forceExit() 381 { 382 g_subprocess_force_exit(gSubprocess); 383 } 384 385 /** 386 * Check the exit status of the subprocess, given that it exited 387 * normally. This is the value passed to the exit() system call or the 388 * return value from main. 389 * 390 * This is equivalent to the system WEXITSTATUS macro. 391 * 392 * It is an error to call this function before g_subprocess_wait() and 393 * unless g_subprocess_get_if_exited() returned %TRUE. 394 * 395 * Returns: the exit status 396 * 397 * Since: 2.40 398 */ 399 public int getExitStatus() 400 { 401 return g_subprocess_get_exit_status(gSubprocess); 402 } 403 404 /** 405 * On UNIX, returns the process ID as a decimal string. 406 * On Windows, returns the result of GetProcessId() also as a string. 407 */ 408 public string getIdentifier() 409 { 410 return Str.toString(g_subprocess_get_identifier(gSubprocess)); 411 } 412 413 /** 414 * Check if the given subprocess exited normally (ie: by way of exit() 415 * or return from main()). 416 * 417 * This is equivalent to the system WIFEXITED macro. 418 * 419 * It is an error to call this function before g_subprocess_wait() has 420 * returned. 421 * 422 * Returns: %TRUE if the case of a normal exit 423 * 424 * Since: 2.40 425 */ 426 public bool getIfExited() 427 { 428 return g_subprocess_get_if_exited(gSubprocess) != 0; 429 } 430 431 /** 432 * Check if the given subprocess terminated in response to a signal. 433 * 434 * This is equivalent to the system WIFSIGNALED macro. 435 * 436 * It is an error to call this function before g_subprocess_wait() has 437 * returned. 438 * 439 * Returns: %TRUE if the case of termination due to a signal 440 * 441 * Since: 2.40 442 */ 443 public bool getIfSignaled() 444 { 445 return g_subprocess_get_if_signaled(gSubprocess) != 0; 446 } 447 448 /** 449 * Gets the raw status code of the process, as from waitpid(). 450 * 451 * This value has no particular meaning, but it can be used with the 452 * macros defined by the system headers such as WIFEXITED. It can also 453 * be used with g_spawn_check_exit_status(). 454 * 455 * It is more likely that you want to use g_subprocess_get_if_exited() 456 * followed by g_subprocess_get_exit_status(). 457 * 458 * It is an error to call this function before g_subprocess_wait() has 459 * returned. 460 * 461 * Returns: the (meaningless) waitpid() exit status from the kernel 462 * 463 * Since: 2.40 464 */ 465 public int getStatus() 466 { 467 return g_subprocess_get_status(gSubprocess); 468 } 469 470 /** 471 * Gets the #GInputStream from which to read the stderr output of 472 * @subprocess. 473 * 474 * The process must have been created with 475 * %G_SUBPROCESS_FLAGS_STDERR_PIPE. 476 * 477 * Returns: the stderr pipe 478 * 479 * Since: 2.40 480 */ 481 public InputStream getStderrPipe() 482 { 483 auto p = g_subprocess_get_stderr_pipe(gSubprocess); 484 485 if(p is null) 486 { 487 return null; 488 } 489 490 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) p); 491 } 492 493 /** 494 * Gets the #GOutputStream that you can write to in order to give data 495 * to the stdin of @subprocess. 496 * 497 * The process must have been created with 498 * %G_SUBPROCESS_FLAGS_STDIN_PIPE. 499 * 500 * Returns: the stdout pipe 501 * 502 * Since: 2.40 503 */ 504 public OutputStream getStdinPipe() 505 { 506 auto p = g_subprocess_get_stdin_pipe(gSubprocess); 507 508 if(p is null) 509 { 510 return null; 511 } 512 513 return ObjectG.getDObject!(OutputStream)(cast(GOutputStream*) p); 514 } 515 516 /** 517 * Gets the #GInputStream from which to read the stdout output of 518 * @subprocess. 519 * 520 * The process must have been created with 521 * %G_SUBPROCESS_FLAGS_STDOUT_PIPE. 522 * 523 * Returns: the stdout pipe 524 * 525 * Since: 2.40 526 */ 527 public InputStream getStdoutPipe() 528 { 529 auto p = g_subprocess_get_stdout_pipe(gSubprocess); 530 531 if(p is null) 532 { 533 return null; 534 } 535 536 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) p); 537 } 538 539 /** 540 * Checks if the process was "successful". A process is considered 541 * successful if it exited cleanly with an exit status of 0, either by 542 * way of the exit() system call or return from main(). 543 * 544 * It is an error to call this function before g_subprocess_wait() has 545 * returned. 546 * 547 * Returns: %TRUE if the process exited cleanly with a exit status of 0 548 * 549 * Since: 2.40 550 */ 551 public bool getSuccessful() 552 { 553 return g_subprocess_get_successful(gSubprocess) != 0; 554 } 555 556 /** 557 * Get the signal number that caused the subprocess to terminate, given 558 * that it terminated due to a signal. 559 * 560 * This is equivalent to the system WTERMSIG macro. 561 * 562 * It is an error to call this function before g_subprocess_wait() and 563 * unless g_subprocess_get_if_signaled() returned %TRUE. 564 * 565 * Returns: the signal causing termination 566 * 567 * Since: 2.40 568 */ 569 public int getTermSig() 570 { 571 return g_subprocess_get_term_sig(gSubprocess); 572 } 573 574 /** 575 * Sends the UNIX signal @signal_num to the subprocess, if it is still 576 * running. 577 * 578 * This API is race-free. If the subprocess has terminated, it will not 579 * be signalled. 580 * 581 * This API is not available on Windows. 582 * 583 * Params: 584 * signalNum = the signal number to send 585 * 586 * Since: 2.40 587 */ 588 public void sendSignal(int signalNum) 589 { 590 g_subprocess_send_signal(gSubprocess, signalNum); 591 } 592 593 /** 594 * Synchronously wait for the subprocess to terminate. 595 * 596 * After the process terminates you can query its exit status with 597 * functions such as g_subprocess_get_if_exited() and 598 * g_subprocess_get_exit_status(). 599 * 600 * This function does not fail in the case of the subprocess having 601 * abnormal termination. See g_subprocess_wait_check() for that. 602 * 603 * Cancelling @cancellable doesn't kill the subprocess. Call 604 * g_subprocess_force_exit() if it is desirable. 605 * 606 * Params: 607 * cancellable = a #GCancellable 608 * 609 * Returns: %TRUE on success, %FALSE if @cancellable was cancelled 610 * 611 * Since: 2.40 612 * 613 * Throws: GException on failure. 614 */ 615 public bool wait(Cancellable cancellable) 616 { 617 GError* err = null; 618 619 auto p = g_subprocess_wait(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 620 621 if (err !is null) 622 { 623 throw new GException( new ErrorG(err) ); 624 } 625 626 return p; 627 } 628 629 /** 630 * Wait for the subprocess to terminate. 631 * 632 * This is the asynchronous version of g_subprocess_wait(). 633 * 634 * Params: 635 * cancellable = a #GCancellable, or %NULL 636 * callback = a #GAsyncReadyCallback to call when the operation is complete 637 * userData = user_data for @callback 638 * 639 * Since: 2.40 640 */ 641 public void waitAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 642 { 643 g_subprocess_wait_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 644 } 645 646 /** 647 * Combines g_subprocess_wait() with g_spawn_check_exit_status(). 648 * 649 * Params: 650 * cancellable = a #GCancellable 651 * 652 * Returns: %TRUE on success, %FALSE if process exited abnormally, or 653 * @cancellable was cancelled 654 * 655 * Since: 2.40 656 * 657 * Throws: GException on failure. 658 */ 659 public bool waitCheck(Cancellable cancellable) 660 { 661 GError* err = null; 662 663 auto p = g_subprocess_wait_check(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 664 665 if (err !is null) 666 { 667 throw new GException( new ErrorG(err) ); 668 } 669 670 return p; 671 } 672 673 /** 674 * Combines g_subprocess_wait_async() with g_spawn_check_exit_status(). 675 * 676 * This is the asynchronous version of g_subprocess_wait_check(). 677 * 678 * Params: 679 * cancellable = a #GCancellable, or %NULL 680 * callback = a #GAsyncReadyCallback to call when the operation is complete 681 * userData = user_data for @callback 682 * 683 * Since: 2.40 684 */ 685 public void waitCheckAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 686 { 687 g_subprocess_wait_check_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 688 } 689 690 /** 691 * Collects the result of a previous call to 692 * g_subprocess_wait_check_async(). 693 * 694 * Params: 695 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 696 * 697 * Returns: %TRUE if successful, or %FALSE with @error set 698 * 699 * Since: 2.40 700 * 701 * Throws: GException on failure. 702 */ 703 public bool waitCheckFinish(AsyncResultIF result) 704 { 705 GError* err = null; 706 707 auto p = g_subprocess_wait_check_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 708 709 if (err !is null) 710 { 711 throw new GException( new ErrorG(err) ); 712 } 713 714 return p; 715 } 716 717 /** 718 * Collects the result of a previous call to 719 * g_subprocess_wait_async(). 720 * 721 * Params: 722 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 723 * 724 * Returns: %TRUE if successful, or %FALSE with @error set 725 * 726 * Since: 2.40 727 * 728 * Throws: GException on failure. 729 */ 730 public bool waitFinish(AsyncResultIF result) 731 { 732 GError* err = null; 733 734 auto p = g_subprocess_wait_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 735 736 if (err !is null) 737 { 738 throw new GException( new ErrorG(err) ); 739 } 740 741 return p; 742 } 743 }