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 public static GType getType() 139 { 140 return g_subprocess_get_type(); 141 } 142 143 /** 144 * Create a new process with the given flags and argument list. 145 * 146 * The argument list is expected to be %NULL-terminated. 147 * 148 * Params: 149 * argv = commandline arguments for the subprocess 150 * flags = flags that define the behaviour of the subprocess 151 * 152 * Return: A newly created #GSubprocess, or %NULL on error (and @error 153 * will be set) 154 * 155 * Since: 2.40 156 * 157 * Throws: GException on failure. 158 * Throws: ConstructionException GTK+ fails to create the object. 159 */ 160 public this(string[] argv, GSubprocessFlags flags) 161 { 162 GError* err = null; 163 164 auto p = g_subprocess_newv(Str.toStringzArray(argv), flags, &err); 165 166 if (err !is null) 167 { 168 throw new GException( new ErrorG(err) ); 169 } 170 171 if(p is null) 172 { 173 throw new ConstructionException("null returned by newv"); 174 } 175 176 this(cast(GSubprocess*) p, true); 177 } 178 179 /** 180 * Communicate with the subprocess until it terminates, and all input 181 * and output has been completed. 182 * 183 * If @stdin_buf is given, the subprocess must have been created with 184 * %G_SUBPROCESS_FLAGS_STDIN_PIPE. The given data is fed to the 185 * stdin of the subprocess and the pipe is closed (ie: EOF). 186 * 187 * At the same time (as not to cause blocking when dealing with large 188 * amounts of data), if %G_SUBPROCESS_FLAGS_STDOUT_PIPE or 189 * %G_SUBPROCESS_FLAGS_STDERR_PIPE were used, reads from those 190 * streams. The data that was read is returned in @stdout and/or 191 * the @stderr. 192 * 193 * If the subprocess was created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 194 * @stdout_buf will contain the data read from stdout. Otherwise, for 195 * subprocesses not created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 196 * @stdout_buf will be set to %NULL. Similar provisions apply to 197 * @stderr_buf and %G_SUBPROCESS_FLAGS_STDERR_PIPE. 198 * 199 * As usual, any output variable may be given as %NULL to ignore it. 200 * 201 * If you desire the stdout and stderr data to be interleaved, create 202 * the subprocess with %G_SUBPROCESS_FLAGS_STDOUT_PIPE and 203 * %G_SUBPROCESS_FLAGS_STDERR_MERGE. The merged result will be returned 204 * in @stdout_buf and @stderr_buf will be set to %NULL. 205 * 206 * In case of any error (including cancellation), %FALSE will be 207 * returned with @error set. Some or all of the stdin data may have 208 * been written. Any stdout or stderr data that has been read will be 209 * discarded. None of the out variables (aside from @error) will have 210 * been set to anything in particular and should not be inspected. 211 * 212 * In the case that %TRUE is returned, the subprocess has exited and the 213 * exit status inspection APIs (eg: g_subprocess_get_if_exited(), 214 * g_subprocess_get_exit_status()) may be used. 215 * 216 * You should not attempt to use any of the subprocess pipes after 217 * starting this function, since they may be left in strange states, 218 * even if the operation was cancelled. You should especially not 219 * attempt to interact with the pipes while the operation is in progress 220 * (either from another thread or if using the asynchronous version). 221 * 222 * Params: 223 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 224 * cancellable = a #GCancellable 225 * stdoutBuf = data read from the subprocess stdout 226 * stderrBuf = data read from the subprocess stderr 227 * 228 * Return: %TRUE if successful 229 * 230 * Since: 2.40 231 * 232 * Throws: GException on failure. 233 */ 234 public bool communicate(Bytes stdinBuf, Cancellable cancellable, out Bytes stdoutBuf, out Bytes stderrBuf) 235 { 236 GBytes* outstdoutBuf = null; 237 GBytes* outstderrBuf = null; 238 GError* err = null; 239 240 auto p = g_subprocess_communicate(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 241 242 if (err !is null) 243 { 244 throw new GException( new ErrorG(err) ); 245 } 246 247 stdoutBuf = new Bytes(outstdoutBuf); 248 stderrBuf = new Bytes(outstderrBuf); 249 250 return p; 251 } 252 253 /** 254 * Asynchronous version of g_subprocess_communicate(). Complete 255 * invocation with g_subprocess_communicate_finish(). 256 * 257 * Params: 258 * stdinBuf = Input data, or %NULL 259 * cancellable = Cancellable 260 * callback = Callback 261 * userData = User data 262 */ 263 public void communicateAsync(Bytes stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 264 { 265 g_subprocess_communicate_async(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 266 } 267 268 /** 269 * Complete an invocation of g_subprocess_communicate_async(). 270 * 271 * Params: 272 * result = Result 273 * stdoutBuf = Return location for stdout data 274 * stderrBuf = Return location for stderr data 275 * 276 * Throws: GException on failure. 277 */ 278 public bool communicateFinish(AsyncResultIF result, out Bytes stdoutBuf, out Bytes stderrBuf) 279 { 280 GBytes* outstdoutBuf = null; 281 GBytes* outstderrBuf = null; 282 GError* err = null; 283 284 auto p = g_subprocess_communicate_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 285 286 if (err !is null) 287 { 288 throw new GException( new ErrorG(err) ); 289 } 290 291 stdoutBuf = new Bytes(outstdoutBuf); 292 stderrBuf = new Bytes(outstderrBuf); 293 294 return p; 295 } 296 297 /** 298 * Like g_subprocess_communicate(), but validates the output of the 299 * process as UTF-8, and returns it as a regular NUL terminated string. 300 * 301 * Params: 302 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 303 * cancellable = a #GCancellable 304 * stdoutBuf = data read from the subprocess stdout 305 * stderrBuf = data read from the subprocess stderr 306 * 307 * Throws: GException on failure. 308 */ 309 public bool communicateUtf8(string stdinBuf, Cancellable cancellable, out string stdoutBuf, out string stderrBuf) 310 { 311 char* outstdoutBuf = null; 312 char* outstderrBuf = null; 313 GError* err = null; 314 315 auto p = g_subprocess_communicate_utf8(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 316 317 if (err !is null) 318 { 319 throw new GException( new ErrorG(err) ); 320 } 321 322 stdoutBuf = Str.toString(outstdoutBuf); 323 stderrBuf = Str.toString(outstderrBuf); 324 325 return p; 326 } 327 328 /** 329 * Asynchronous version of g_subprocess_communicate_utf8(). Complete 330 * invocation with g_subprocess_communicate_utf8_finish(). 331 * 332 * Params: 333 * stdinBuf = Input data, or %NULL 334 * cancellable = Cancellable 335 * callback = Callback 336 * userData = User data 337 */ 338 public void communicateUtf8Async(string stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 339 { 340 g_subprocess_communicate_utf8_async(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 341 } 342 343 /** 344 * Complete an invocation of g_subprocess_communicate_utf8_async(). 345 * 346 * Params: 347 * result = Result 348 * stdoutBuf = Return location for stdout data 349 * stderrBuf = Return location for stderr data 350 * 351 * Throws: GException on failure. 352 */ 353 public bool communicateUtf8Finish(AsyncResultIF result, out string stdoutBuf, out string stderrBuf) 354 { 355 char* outstdoutBuf = null; 356 char* outstderrBuf = null; 357 GError* err = null; 358 359 auto p = g_subprocess_communicate_utf8_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 360 361 if (err !is null) 362 { 363 throw new GException( new ErrorG(err) ); 364 } 365 366 stdoutBuf = Str.toString(outstdoutBuf); 367 stderrBuf = Str.toString(outstderrBuf); 368 369 return p; 370 } 371 372 /** 373 * Use an operating-system specific method to attempt an immediate, 374 * forceful termination of the process. There is no mechanism to 375 * determine whether or not the request itself was successful; 376 * however, you can use g_subprocess_wait() to monitor the status of 377 * the process after calling this function. 378 * 379 * On Unix, this function sends %SIGKILL. 380 * 381 * Since: 2.40 382 */ 383 public void forceExit() 384 { 385 g_subprocess_force_exit(gSubprocess); 386 } 387 388 /** 389 * Check the exit status of the subprocess, given that it exited 390 * normally. This is the value passed to the exit() system call or the 391 * return value from main. 392 * 393 * This is equivalent to the system WEXITSTATUS macro. 394 * 395 * It is an error to call this function before g_subprocess_wait() and 396 * unless g_subprocess_get_if_exited() returned %TRUE. 397 * 398 * Return: the exit status 399 * 400 * Since: 2.40 401 */ 402 public int getExitStatus() 403 { 404 return g_subprocess_get_exit_status(gSubprocess); 405 } 406 407 /** 408 * On UNIX, returns the process ID as a decimal string. 409 * On Windows, returns the result of GetProcessId() also as a string. 410 */ 411 public string getIdentifier() 412 { 413 return Str.toString(g_subprocess_get_identifier(gSubprocess)); 414 } 415 416 /** 417 * Check if the given subprocess exited normally (ie: by way of exit() 418 * or return from main()). 419 * 420 * This is equivalent to the system WIFEXITED macro. 421 * 422 * It is an error to call this function before g_subprocess_wait() has 423 * returned. 424 * 425 * Return: %TRUE if the case of a normal exit 426 * 427 * Since: 2.40 428 */ 429 public bool getIfExited() 430 { 431 return g_subprocess_get_if_exited(gSubprocess) != 0; 432 } 433 434 /** 435 * Check if the given subprocess terminated in response to a signal. 436 * 437 * This is equivalent to the system WIFSIGNALED macro. 438 * 439 * It is an error to call this function before g_subprocess_wait() has 440 * returned. 441 * 442 * Return: %TRUE if the case of termination due to a signal 443 * 444 * Since: 2.40 445 */ 446 public bool getIfSignaled() 447 { 448 return g_subprocess_get_if_signaled(gSubprocess) != 0; 449 } 450 451 /** 452 * Gets the raw status code of the process, as from waitpid(). 453 * 454 * This value has no particular meaning, but it can be used with the 455 * macros defined by the system headers such as WIFEXITED. It can also 456 * be used with g_spawn_check_exit_status(). 457 * 458 * It is more likely that you want to use g_subprocess_get_if_exited() 459 * followed by g_subprocess_get_exit_status(). 460 * 461 * It is an error to call this function before g_subprocess_wait() has 462 * returned. 463 * 464 * Return: the (meaningless) waitpid() exit status from the kernel 465 * 466 * Since: 2.40 467 */ 468 public int getStatus() 469 { 470 return g_subprocess_get_status(gSubprocess); 471 } 472 473 /** 474 * Gets the #GInputStream from which to read the stderr output of 475 * @subprocess. 476 * 477 * The process must have been created with 478 * %G_SUBPROCESS_FLAGS_STDERR_PIPE. 479 * 480 * Return: the stderr pipe 481 * 482 * Since: 2.40 483 */ 484 public InputStream getStderrPipe() 485 { 486 auto p = g_subprocess_get_stderr_pipe(gSubprocess); 487 488 if(p is null) 489 { 490 return null; 491 } 492 493 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) p); 494 } 495 496 /** 497 * Gets the #GOutputStream that you can write to in order to give data 498 * to the stdin of @subprocess. 499 * 500 * The process must have been created with 501 * %G_SUBPROCESS_FLAGS_STDIN_PIPE. 502 * 503 * Return: the stdout pipe 504 * 505 * Since: 2.40 506 */ 507 public OutputStream getStdinPipe() 508 { 509 auto p = g_subprocess_get_stdin_pipe(gSubprocess); 510 511 if(p is null) 512 { 513 return null; 514 } 515 516 return ObjectG.getDObject!(OutputStream)(cast(GOutputStream*) p); 517 } 518 519 /** 520 * Gets the #GInputStream from which to read the stdout output of 521 * @subprocess. 522 * 523 * The process must have been created with 524 * %G_SUBPROCESS_FLAGS_STDOUT_PIPE. 525 * 526 * Return: the stdout pipe 527 * 528 * Since: 2.40 529 */ 530 public InputStream getStdoutPipe() 531 { 532 auto p = g_subprocess_get_stdout_pipe(gSubprocess); 533 534 if(p is null) 535 { 536 return null; 537 } 538 539 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) p); 540 } 541 542 /** 543 * Checks if the process was "successful". A process is considered 544 * successful if it exited cleanly with an exit status of 0, either by 545 * way of the exit() system call or return from main(). 546 * 547 * It is an error to call this function before g_subprocess_wait() has 548 * returned. 549 * 550 * Return: %TRUE if the process exited cleanly with a exit status of 0 551 * 552 * Since: 2.40 553 */ 554 public bool getSuccessful() 555 { 556 return g_subprocess_get_successful(gSubprocess) != 0; 557 } 558 559 /** 560 * Get the signal number that caused the subprocess to terminate, given 561 * that it terminated due to a signal. 562 * 563 * This is equivalent to the system WTERMSIG macro. 564 * 565 * It is an error to call this function before g_subprocess_wait() and 566 * unless g_subprocess_get_if_signaled() returned %TRUE. 567 * 568 * Return: the signal causing termination 569 * 570 * Since: 2.40 571 */ 572 public int getTermSig() 573 { 574 return g_subprocess_get_term_sig(gSubprocess); 575 } 576 577 /** 578 * Sends the UNIX signal @signal_num to the subprocess, if it is still 579 * running. 580 * 581 * This API is race-free. If the subprocess has terminated, it will not 582 * be signalled. 583 * 584 * This API is not available on Windows. 585 * 586 * Params: 587 * signalNum = the signal number to send 588 * 589 * Since: 2.40 590 */ 591 public void sendSignal(int signalNum) 592 { 593 g_subprocess_send_signal(gSubprocess, signalNum); 594 } 595 596 /** 597 * Synchronously wait for the subprocess to terminate. 598 * 599 * After the process terminates you can query its exit status with 600 * functions such as g_subprocess_get_if_exited() and 601 * g_subprocess_get_exit_status(). 602 * 603 * This function does not fail in the case of the subprocess having 604 * abnormal termination. See g_subprocess_wait_check() for that. 605 * 606 * Cancelling @cancellable doesn't kill the subprocess. Call 607 * g_subprocess_force_exit() if it is desirable. 608 * 609 * Params: 610 * cancellable = a #GCancellable 611 * 612 * Return: %TRUE on success, %FALSE if @cancellable was cancelled 613 * 614 * Since: 2.40 615 * 616 * Throws: GException on failure. 617 */ 618 public bool wait(Cancellable cancellable) 619 { 620 GError* err = null; 621 622 auto p = g_subprocess_wait(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 623 624 if (err !is null) 625 { 626 throw new GException( new ErrorG(err) ); 627 } 628 629 return p; 630 } 631 632 /** 633 * Wait for the subprocess to terminate. 634 * 635 * This is the asynchronous version of g_subprocess_wait(). 636 * 637 * Params: 638 * cancellable = a #GCancellable, or %NULL 639 * callback = a #GAsyncReadyCallback to call when the operation is complete 640 * userData = user_data for @callback 641 * 642 * Since: 2.40 643 */ 644 public void waitAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 645 { 646 g_subprocess_wait_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 647 } 648 649 /** 650 * Combines g_subprocess_wait() with g_spawn_check_exit_status(). 651 * 652 * Params: 653 * cancellable = a #GCancellable 654 * 655 * Return: %TRUE on success, %FALSE if process exited abnormally, or 656 * @cancellable was cancelled 657 * 658 * Since: 2.40 659 * 660 * Throws: GException on failure. 661 */ 662 public bool waitCheck(Cancellable cancellable) 663 { 664 GError* err = null; 665 666 auto p = g_subprocess_wait_check(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 667 668 if (err !is null) 669 { 670 throw new GException( new ErrorG(err) ); 671 } 672 673 return p; 674 } 675 676 /** 677 * Combines g_subprocess_wait_async() with g_spawn_check_exit_status(). 678 * 679 * This is the asynchronous version of g_subprocess_wait_check(). 680 * 681 * Params: 682 * cancellable = a #GCancellable, or %NULL 683 * callback = a #GAsyncReadyCallback to call when the operation is complete 684 * userData = user_data for @callback 685 * 686 * Since: 2.40 687 */ 688 public void waitCheckAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 689 { 690 g_subprocess_wait_check_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 691 } 692 693 /** 694 * Collects the result of a previous call to 695 * g_subprocess_wait_check_async(). 696 * 697 * Params: 698 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 699 * 700 * Return: %TRUE if successful, or %FALSE with @error set 701 * 702 * Since: 2.40 703 * 704 * Throws: GException on failure. 705 */ 706 public bool waitCheckFinish(AsyncResultIF result) 707 { 708 GError* err = null; 709 710 auto p = g_subprocess_wait_check_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 711 712 if (err !is null) 713 { 714 throw new GException( new ErrorG(err) ); 715 } 716 717 return p; 718 } 719 720 /** 721 * Collects the result of a previous call to 722 * g_subprocess_wait_async(). 723 * 724 * Params: 725 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 726 * 727 * Return: %TRUE if successful, or %FALSE with @error set 728 * 729 * Since: 2.40 730 * 731 * Throws: GException on failure. 732 */ 733 public bool waitFinish(AsyncResultIF result) 734 { 735 GError* err = null; 736 737 auto p = g_subprocess_wait_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 738 739 if (err !is null) 740 { 741 throw new GException( new ErrorG(err) ); 742 } 743 744 return p; 745 } 746 }