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