2 * spawn.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2013 Dimitar Toshkov Zhekov <dimitar(dot)zhekov(at)gmail(dot)com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 /* An ongoing effort to improve the tool spawning situation under Windows.
23 * - There is no g_shell_parse_argv() for windows. It's not hard to write one,
24 * but the command line recreated by mscvrt may be wrong.
25 * - GLib converts the argument vector to UNICODE. For non-UTF8 arguments,
26 * the result is often "Invalid string in argument vector at %d: %s: Invalid
27 * byte sequence in conversion input" (YMMV). Our tools (make, grep, gcc, ...)
28 * are "ANSI", so converting to UNICODE and then back only causes problems.
29 * - For various reasons, GLib uses an intermediate program to start children
30 * (see gspawn-win32.c), the result being that the grandchildren output (such
31 * as make -> gcc) is not captured.
32 * - With non-blocking pipes, the g_io_add_watch() callbacks are never invoked,
33 * while with blocking pipes, g_io_channel_read_line() blocks.
34 * - Some other problems are explained in separate comments below.
36 * Even under Unix, using g_io_channel_read_line() is not a good idea, since it may
37 * buffer lines of unlimited length.
39 * This module does not depend on Geany when compiled for testing (-DSPAWN_TEST).
52 # include <ctype.h> /* isspace() */
53 # include <fcntl.h> /* _O_RDONLY, _O_WRONLY */
54 # include <io.h> /* _open_osfhandle, _close */
56 #else /* G_OS_WIN32 */
58 #endif /* G_OS_WIN32 */
67 /* Each 4KB under Windows seem to come in 2 portions, so 2K + 2K is more
68 balanced than 4095 + 1. May be different on the latest Windows/glib? */
69 # define DEFAULT_IO_LENGTH 2048
71 # define DEFAULT_IO_LENGTH 4096
74 #define G_IO_FAILURE (G_IO_ERR | G_IO_HUP | G_IO_NVAL) /* always used together */
78 * Checks whether a command line is syntactically valid and extracts the program name from it.
81 * - any leading spaces, tabs and new lines are skipped
82 * - an empty command is invalid
84 * - the standard shell quoting and escaping rules are used, see @c g_shell_parse_argv()
85 * - as a consequence, an unqouted # at the start of an argument comments to the end of line
87 * - leading carriage returns are skipped too
88 * - a quoted program name must be entirely inside the quotes. No "C:\Foo\Bar".pdf or
89 * "C:\Foo\Bar".bat, which would be executed by Windows as C:\Foo\Bar.exe
90 * - an unquoted program name may not contain spaces. Foo Bar Qux will not be considered
91 * "Foo Bar.exe" Qux or "Foo Bar Qux.exe", depending on what executables exist, as
92 * Windows normally does.
93 * - the program name must be separated from the arguments by at least one space or tab
94 * - the standard Windows quoting and escaping rules are used: double quote is escaped with
95 * backslash, and any literal backslashes before a double quote must be duplicated.
97 * @param command_line the command line to check and get the program name from.
98 * @param error return location for error.
100 * @return allocated string with the program name on success, @c NULL on error.
105 gchar
*spawn_get_program_name(const gchar
*command_line
, GError
**error
)
110 gboolean open_quote
= FALSE
;
111 const gchar
*s
, *arguments
;
113 g_return_val_if_fail(command_line
!= NULL
, FALSE
);
115 while (*command_line
&& strchr(" \t\r\n", *command_line
))
120 /* TL note: from glib */
121 g_set_error(error
, G_SHELL_ERROR
, G_SHELL_ERROR_EMPTY_STRING
,
122 _("Text was empty (or contained only whitespace)"));
126 /* To prevent Windows from doing something weird, we want to be 100% sure that the
127 character after the program name is a delimiter, so we allow space and tab only. */
129 if (*command_line
== '"')
132 /* Windows allows "foo.exe, but we may have extra arguments */
133 if ((s
= strchr(command_line
, '"')) == NULL
)
135 /* TL note: from glib */
136 g_set_error(error
, G_SHELL_ERROR
, G_SHELL_ERROR_BAD_QUOTING
,
137 _("Text ended before matching quote was found for %c."
138 " (The text was '%s')"), '"', command_line
);
142 if (!strchr(" \t", s
[1])) /* strchr() catches s[1] == '\0' */
144 g_set_error(error
, G_SHELL_ERROR
, G_SHELL_ERROR_BAD_QUOTING
,
145 _("A quoted Windows program name must be entirely inside the quotes"));
151 const gchar
*quote
= strchr(command_line
, '"');
153 /* strchr() catches *s == '\0', and the for body is empty */
154 for (s
= command_line
; !strchr(" \t", *s
); s
++);
156 if (quote
&& quote
< s
)
158 g_set_error(error
, G_SHELL_ERROR
, G_SHELL_ERROR_BAD_QUOTING
,
159 _("A quoted Windows program name must be entirely inside the quotes"));
164 program
= g_strndup(command_line
, s
- command_line
);
165 arguments
= s
+ (*s
== '"');
167 for (s
= arguments
; *s
; s
++)
173 for (slash
= s
; slash
> arguments
&& slash
[-1] == '\\'; slash
--);
174 if ((s
- slash
) % 2 == 0)
181 /* TL note: from glib */
182 g_set_error(error
, G_SHELL_ERROR
, G_SHELL_ERROR_BAD_QUOTING
,
183 _("Text ended before matching quote was found for %c."
184 " (The text was '%s')"), '"', command_line
);
188 #else /* G_OS_WIN32 */
192 if (!g_shell_parse_argv(command_line
, &argc
, &argv
, error
))
195 /* empty string results in parse error, so argv[0] is not NULL */
196 program
= g_strdup(argv
[0]);
198 #endif /* G_OS_WIN32 */
205 * Checks whether a command line is valid.
207 * Checks if @a command_line is syntactically valid using @c spawn_get_program_name().
209 * If @a execute is TRUE, also checks, using @c g_find_program_in_path(), if the program
210 * specified in @a command_line exists and is executable.
212 * @param command_line the command line to check.
213 * @param execute whether to check if the command line is really executable.
214 * @param error return location for error.
216 * @return @c TRUE on success, @c FALSE on error.
221 gboolean
spawn_check_command(const gchar
*command_line
, gboolean execute
, GError
**error
)
223 gchar
*program
= spawn_get_program_name(command_line
, error
);
230 gchar
*executable
= g_find_program_in_path(program
);
234 g_set_error(error
, G_SHELL_ERROR
, G_SHELL_ERROR_FAILED
, /* or SPAWN error? */
235 _("Program '%s' not found"), program
);
251 * @param pid id of the process to kill.
252 * @param error return location for error.
254 * On Unix, sends a SIGTERM to the process.
256 * On Windows, terminates the process with exit code 255 (used sometimes as "generic"
257 * error code, or for programs terminated with Ctrl+C / Ctrl+Break).
259 * @return @c TRUE on success, @c FALSE on error.
264 gboolean
spawn_kill_process(GPid pid
, GError
**error
)
267 if (!TerminateProcess(pid
, 255))
269 gchar
*message
= g_win32_error_message(GetLastError());
271 g_set_error(error
, G_SPAWN_ERROR
, G_SPAWN_ERROR_FAILED
,
272 _("TerminateProcess() failed: %s"), message
);
277 if (kill(pid
, SIGTERM
))
279 g_set_error(error
, G_SPAWN_ERROR
, G_SPAWN_ERROR_FAILED
, "%s", g_strerror(errno
));
288 static gchar
*spawn_create_process_with_pipes(char *command_line
, const char *working_directory
,
289 void *environment
, HANDLE
*hprocess
, int *stdin_fd
, int *stdout_fd
, int *stderr_fd
)
291 enum { WRITE_STDIN
, READ_STDOUT
, READ_STDERR
, READ_STDIN
, WRITE_STDOUT
, WRITE_STDERR
};
293 PROCESS_INFORMATION process
;
294 HANDLE hpipe
[6] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
295 int *fd
[3] = { stdin_fd
, stdout_fd
, stderr_fd
};
296 const char *failed
; /* failed WIN32/CRTL function, if any */
297 gchar
*message
= NULL
; /* glib WIN32/CTRL error message */
298 gchar
*failure
= NULL
; /* full error text */
302 ZeroMemory(&startup
, sizeof startup
);
303 startup
.cb
= sizeof startup
;
304 pipe_io
= stdin_fd
|| stdout_fd
|| stderr_fd
;
308 startup
.dwFlags
|= STARTF_USESTDHANDLES
;
310 /* not all programs accept mixed NULL and non-NULL hStd*, so we create all */
311 for (i
= 0; i
< 3; i
++)
313 static int pindex
[3][2] = { { READ_STDIN
, WRITE_STDIN
},
314 { READ_STDOUT
, WRITE_STDOUT
}, { READ_STDERR
, WRITE_STDERR
} };
316 if (!CreatePipe(&hpipe
[pindex
[i
][0]], &hpipe
[pindex
[i
][1]], NULL
, 0))
318 hpipe
[pindex
[i
][0]] = hpipe
[pindex
[i
][1]] = NULL
;
319 failed
= "CreatePipe";
325 static int mode
[3] = { _O_WRONLY
, _O_RDONLY
, _O_RDONLY
};
327 if ((*fd
[i
] = _open_osfhandle((intptr_t) hpipe
[i
], mode
[i
])) == -1)
329 failed
= "_open_osfhandle";
330 message
= g_strdup(g_strerror(errno
));
334 else if (!CloseHandle(hpipe
[i
]))
336 failed
= "CloseHandle";
340 if (!SetHandleInformation(hpipe
[i
+ 3], HANDLE_FLAG_INHERIT
,
341 HANDLE_FLAG_INHERIT
))
343 failed
= "SetHandleInformation";
349 startup
.hStdInput
= hpipe
[READ_STDIN
];
350 startup
.hStdOutput
= hpipe
[WRITE_STDOUT
];
351 startup
.hStdError
= hpipe
[WRITE_STDERR
];
353 if (!CreateProcess(NULL
, command_line
, NULL
, NULL
, TRUE
, pipe_io
? CREATE_NO_WINDOW
: 0,
354 environment
, working_directory
, &startup
, &process
))
356 failed
= "CreateProcess";
357 /* further errors will not be reported */
362 CloseHandle(process
.hThread
); /* we don't need this */
363 *hprocess
= process
.hProcess
;
370 message
= g_win32_error_message(GetLastError());
372 failure
= g_strdup_printf("%s() failed: %s", failed
, message
);
378 for (i
= 0; i
< 3; i
++)
382 if (fd
[i
] && *fd
[i
] != -1)
385 CloseHandle(hpipe
[i
]);
389 CloseHandle(hpipe
[i
+ 3]);
397 static void spawn_append_argument(GString
*command
, const char *text
)
402 g_string_append_c(command
, ' ');
404 for (s
= text
; *s
; s
++)
406 /* g_ascii_isspace() fails for '\v', and locale spaces (if any) will do no harm */
407 if (*s
== '"' || isspace(*s
))
412 g_string_append(command
, text
);
415 g_string_append_c(command
, '"');
417 for (s
= text
; *s
; s
++)
421 for (slash
= s
; *slash
== '\\'; slash
++);
425 g_string_append_len(command
, s
, slash
- s
);
427 if (!*slash
|| *slash
== '"')
429 g_string_append_len(command
, s
, slash
- s
);
439 g_string_append_c(command
, '\\');
441 g_string_append_c(command
, *s
);
444 g_string_append_c(command
, '"');
449 static void spawn_close_pid(GPid pid
, G_GNUC_UNUSED gint status
, G_GNUC_UNUSED gpointer data
)
451 g_spawn_close_pid(pid
);
453 #endif /* G_OS_WIN32 */
457 * Executes a child program asynchronously and setups pipes.
459 * This is the low-level spawning function. Please use @c spawn_with_callbacks() unless
460 * you need to setup specific event source(s).
462 * A command line or an argument vector must be passed. If both are present, the argument
463 * vector is appended to the command line. An empty command line is not allowed.
465 * Under Windows, if the child is a console application, and at least one file descriptor is
466 * specified, the new child console (if any) will be hidden.
468 * If a @a child_pid is passed, it's your responsibility to invoke @c g_spawn_close_pid().
470 * @param working_directory child's current working directory, or @c NULL.
471 * @param command_line child program and arguments, or @c NULL.
472 * @param argv child's argument vector, or @c NULL.
473 * @param envp child's environment, or @c NULL.
474 * @param child_pid return location for child process ID, or @c NULL.
475 * @param stdin_fd return location for file descriptor to write to child's stdin, or @c NULL.
476 * @param stdout_fd return location for file descriptor to read child's stdout, or @c NULL.
477 * @param stderr_fd return location for file descriptor to read child's stderr, or @c NULL.
478 * @param error return location for error.
480 * @return @c TRUE on success, @c FALSE on error.
485 gboolean
spawn_async_with_pipes(const gchar
*working_directory
, const gchar
*command_line
,
486 gchar
**argv
, gchar
**envp
, GPid
*child_pid
, gint
*stdin_fd
, gint
*stdout_fd
,
487 gint
*stderr_fd
, GError
**error
)
489 g_return_val_if_fail(command_line
!= NULL
|| argv
!= NULL
, FALSE
);
499 gchar
*program
= spawn_get_program_name(command_line
, error
);
500 const gchar
*arguments
;
505 command
= g_string_new(NULL
);
506 arguments
= strstr(command_line
, program
) + strlen(program
);
508 if (*arguments
== '"')
510 g_string_append(command
, program
);
515 /* quote the first token, to avoid Windows attemps to run two or more
516 unquoted tokens as a program until an existing file name is found */
517 g_string_printf(command
, "\"%s\"", program
);
520 g_string_append(command
, arguments
);
524 command
= g_string_new(NULL
);
526 environment
= g_array_new(TRUE
, FALSE
, sizeof(char));
528 while (argv
&& *argv
)
529 spawn_append_argument(command
, *argv
++);
532 g_message("full spawn command line: %s\n", command
->str
);
535 while (envp
&& *envp
)
537 g_array_append_vals(environment
, *envp
, strlen(*envp
) + 1);
541 failure
= spawn_create_process_with_pipes(command
->str
, working_directory
,
542 envp
? environment
->data
: NULL
, child_pid
? child_pid
: &pid
,
543 stdin_fd
, stdout_fd
, stderr_fd
);
545 g_string_free(command
, TRUE
);
546 g_array_free(environment
, TRUE
);
550 g_set_error(error
, G_SPAWN_ERROR
, G_SPAWN_ERROR_FAILED
, "%s", failure
);
555 g_child_watch_add(pid
, spawn_close_pid
, NULL
);
558 #else /* G_OS_WIN32 */
568 if (!g_shell_parse_argv(command_line
, &cl_argc
, &cl_argv
, error
))
572 for (argc
= 0; argv
[argc
]; argc
++);
574 full_argv
= g_renew(gchar
*, cl_argv
, cl_argc
+ argc
+ 1);
575 memcpy(full_argv
+ cl_argc
, argv
, argc
* sizeof(gchar
*));
576 full_argv
[cl_argc
+ argc
] = NULL
;
581 spawned
= g_spawn_async_with_pipes(working_directory
, full_argv
, envp
,
582 G_SPAWN_SEARCH_PATH
| (child_pid
? G_SPAWN_DO_NOT_REAP_CHILD
: 0), NULL
, NULL
,
583 child_pid
, stdin_fd
, stdout_fd
, stderr_fd
, error
);
585 if (full_argv
!= argv
)
587 full_argv
[cl_argc
] = NULL
;
588 g_strfreev(full_argv
);
592 #endif /* G_OS_WIN32 */
597 * Executes a child asynchronously.
599 * See @c spawn_async_with_pipes() for a full description; this function simply calls
600 * @c g_spawn_async_with_pipes() without any pipes.
605 gboolean
spawn_async(const gchar
*working_directory
, const gchar
*command_line
, gchar
**argv
,
606 gchar
**envp
, GPid
*child_pid
, GError
**error
)
608 return spawn_async_with_pipes(working_directory
, command_line
, argv
, envp
, child_pid
,
609 NULL
, NULL
, NULL
, error
);
614 * Spawn with callbacks - general event sequence:
616 * - Launch the child.
617 * - Setup any I/O callbacks and a child watch callback.
618 * - On sync execution, run a main loop.
619 * - Wait for the child to terminate.
620 * - Check for active I/O sources. If any, add a timeout source to watch them, they should
621 * become inactive real soon now that the child is dead. Otherwise, finalize immediately.
622 * - In the timeout source: check for active I/O sources and finalize if none.
625 typedef struct _SpawnChannelData
627 GIOChannel
*channel
; /* NULL if not created / already destroyed */
634 /* stdout/stderr only */
635 GString
*buffer
; /* NULL if recursive */
636 GString
*line_buffer
; /* NULL if char buffered */
641 static void spawn_destroy_cb(gpointer data
)
643 SpawnChannelData
*sc
= (SpawnChannelData
*) data
;
645 g_io_channel_shutdown(sc
->channel
, FALSE
, NULL
);
649 g_string_free(sc
->buffer
, TRUE
);
652 g_string_free(sc
->line_buffer
, TRUE
);
656 static gboolean
spawn_write_cb(GIOChannel
*channel
, GIOCondition condition
, gpointer data
)
658 SpawnChannelData
*sc
= (SpawnChannelData
*) data
;
660 if (!sc
->cb
.write(channel
, condition
, sc
->cb_data
))
663 return !(condition
& G_IO_FAILURE
);
667 static gboolean
spawn_read_cb(GIOChannel
*channel
, GIOCondition condition
, gpointer data
)
669 SpawnChannelData
*sc
= (SpawnChannelData
*) data
;
670 GString
*line_buffer
= sc
->line_buffer
;
671 GString
*buffer
= sc
->buffer
? sc
->buffer
: g_string_sized_new(sc
->max_length
);
672 GIOCondition input_cond
= condition
& (G_IO_IN
| G_IO_PRI
);
673 GIOCondition failure_cond
= condition
& G_IO_FAILURE
;
675 * - Normally, read only once. With IO watches, our data processing must be immediate,
676 * which may give the child time to emit more data, and a read loop may combine it into
677 * large stdout and stderr portions. Under Windows, looping blocks.
678 * - On failure, read in a loop. It won't block now, there will be no more data, and the
679 * IO watch is not guaranteed to be called again (under Windows this is the last call).
688 gsize n
= line_buffer
->len
;
690 while ((status
= g_io_channel_read_chars(channel
, line_buffer
->str
+ n
,
691 DEFAULT_IO_LENGTH
, &chars_read
, NULL
)) == G_IO_STATUS_NORMAL
)
693 g_string_set_size(line_buffer
, n
+ chars_read
);
695 while (n
< line_buffer
->len
)
699 if (n
== sc
->max_length
)
701 else if (strchr("\n", line_buffer
->str
[n
])) /* '\n' or '\0' */
703 else if (n
< line_buffer
->len
- 1 && line_buffer
->str
[n
] == '\r')
704 line_len
= n
+ 1 + (line_buffer
->str
[n
+ 1] == '\n');
710 g_string_append_len(buffer
, line_buffer
->str
, line_len
);
711 g_string_erase(line_buffer
, 0, line_len
);
712 /* input only, failures are reported separately below */
713 sc
->cb
.read(buffer
, input_cond
, sc
->cb_data
);
714 g_string_truncate(buffer
, 0);
725 while ((status
= g_io_channel_read_chars(channel
, buffer
->str
, sc
->max_length
,
726 &chars_read
, NULL
)) == G_IO_STATUS_NORMAL
)
728 g_string_set_size(buffer
, chars_read
);
729 /* input only, failures are reported separately below */
730 sc
->cb
.read(buffer
, input_cond
, sc
->cb_data
);
737 /* Under OSX, after child death, the read watches receive input conditions instead
738 of error conditions, so we convert the termination statuses into conditions.
739 Should not hurt the other OS. */
740 if (status
== G_IO_STATUS_ERROR
)
741 failure_cond
|= G_IO_ERR
;
742 else if (status
== G_IO_STATUS_EOF
)
743 failure_cond
|= G_IO_HUP
;
746 if (failure_cond
) /* we must signal the callback */
748 if (line_buffer
&& line_buffer
->len
) /* flush the line buffer */
750 g_string_append_len(buffer
, line_buffer
->str
, line_buffer
->len
);
751 /* all data may be from a previous call */
753 input_cond
= G_IO_IN
;
758 g_string_truncate(buffer
, 0);
761 sc
->cb
.read(buffer
, input_cond
| failure_cond
, sc
->cb_data
);
764 if (buffer
!= sc
->buffer
)
765 g_string_free(buffer
, TRUE
);
767 return !failure_cond
;
771 typedef struct _SpawnWatcherData
773 SpawnChannelData sc
[3]; /* stdin, stdout, stderr */
774 GChildWatchFunc exit_cb
;
778 GMainContext
*main_context
; /* NULL if async execution */
779 GMainLoop
*main_loop
; /* NULL if async execution */
783 static void spawn_finalize(SpawnWatcherData
*sw
)
786 sw
->exit_cb(sw
->pid
, sw
->exit_status
, sw
->exit_data
);
790 g_main_loop_quit(sw
->main_loop
);
791 g_main_loop_unref(sw
->main_loop
);
794 g_spawn_close_pid(sw
->pid
);
795 g_slice_free(SpawnWatcherData
, sw
);
799 static gboolean
spawn_timeout_cb(gpointer data
)
801 SpawnWatcherData
*sw
= (SpawnWatcherData
*) data
;
804 for (i
= 0; i
< 3; i
++)
805 if (sw
->sc
[i
].channel
)
813 static void spawn_watch_cb(GPid pid
, gint status
, gpointer data
)
815 SpawnWatcherData
*sw
= (SpawnWatcherData
*) data
;
819 sw
->exit_status
= status
;
821 for (i
= 0; i
< 3; i
++)
823 if (sw
->sc
[i
].channel
)
825 GSource
*source
= g_timeout_source_new(50);
827 g_source_set_callback(source
, spawn_timeout_cb
, data
, NULL
);
828 g_source_attach(source
, sw
->main_context
);
829 g_source_unref(source
);
839 * Executes a child program and setups callbacks.
841 * A command line or an argument vector must be passed. If both are present, the argument
842 * vector is appended to the command line. An empty command line is not allowed.
844 * The synchronous execution may not be combined with recursive callbacks.
846 * In line buffered mode, the child input is broken on '\n', "\r\n", '\r', '\0' and max length.
848 * All I/O callbacks are guaranteed to be invoked at least once with @c G_IO_ERR, @c G_IO_HUP
849 * or @c G_IO_NVAL set (except for a @a stdin_cb which returns @c FALSE before that). For the
850 * non-recursive callbacks, this is guaranteed to be the last call, and may be used to free any
851 * resources associated with the callback.
853 * The @a stdin_cb may write to @c channel only once per invocation, only if @c G_IO_OUT is
854 * set, and only a non-zero number of characters.
856 * @c stdout_cb and @c stderr_cb may modify the received strings in any way, but must not
859 * The default max lengths are 24K for line buffered stdout, 8K for line buffered stderr,
860 * 4K for unbuffered input under Unix, and 2K for unbuffered input under Windows.
862 * @c exit_cb is always invoked last, after all I/O callbacks.
864 * The @a child_pid will be closed automatically, after @a exit_cb is invoked.
866 * @param working_directory child's current working directory, or @c NULL.
867 * @param command_line child program and arguments, or @c NULL.
868 * @param argv child's argument vector, or @c NULL.
869 * @param envp child's environment, or @c NULL.
870 * @param spawn_flags flags from SpawnFlags.
871 * @param stdin_cb callback to send data to childs's stdin, or @c NULL.
872 * @param stdin_data data to pass to @a stdin_cb.
873 * @param stdout_cb callback to receive child's stdout, or @c NULL.
874 * @param stdout_data data to pass to @a stdout_cb.
875 * @param stdout_max_length maximum data length to pass to stdout_cb, @c 0 = default.
876 * @param stderr_cb callback to receive child's stderr, or @c NULL.
877 * @param stderr_data data to pass to @a stderr_cb.
878 * @param stderr_max_length maximum data length to pass to stderr_cb, @c 0 = default.
879 * @param exit_cb callback to invoke when the child exits, or @c NULL.
880 * @param exit_data data to pass to @a exit_cb.
881 * @param child_pid return location for child process ID, or @c NULL.
882 * @param error return location for error.
884 * @return @c TRUE on success, @c FALSE on error.
889 gboolean
spawn_with_callbacks(const gchar
*working_directory
, const gchar
*command_line
,
890 gchar
**argv
, gchar
**envp
, SpawnFlags spawn_flags
, GIOFunc stdin_cb
, gpointer stdin_data
,
891 SpawnReadFunc stdout_cb
, gpointer stdout_data
, gsize stdout_max_length
,
892 SpawnReadFunc stderr_cb
, gpointer stderr_data
, gsize stderr_max_length
,
893 GChildWatchFunc exit_cb
, gpointer exit_data
, GPid
*child_pid
, GError
**error
)
896 int pipe
[3] = { -1, -1, -1 };
898 g_return_val_if_fail(!(spawn_flags
& SPAWN_RECURSIVE
) || !(spawn_flags
& SPAWN_SYNC
),
901 if (spawn_async_with_pipes(working_directory
, command_line
, argv
, envp
, &pid
,
902 stdin_cb
? &pipe
[0] : NULL
, stdout_cb
? &pipe
[1] : NULL
,
903 stderr_cb
? &pipe
[2] : NULL
, error
))
905 SpawnWatcherData
*sw
= g_slice_new0(SpawnWatcherData
);
906 gpointer cb_data
[3] = { stdin_data
, stdout_data
, stderr_data
};
910 sw
->main_context
= spawn_flags
& SPAWN_SYNC
? g_main_context_new() : NULL
;
915 for (i
= 0; i
< 3; i
++)
917 SpawnChannelData
*sc
= &sw
->sc
[i
];
918 GIOCondition condition
;
919 GSourceFunc callback
;
925 sc
->channel
= g_io_channel_win32_new_fd(pipe
[i
]);
927 sc
->channel
= g_io_channel_unix_new(pipe
[i
]);
928 g_io_channel_set_flags(sc
->channel
, G_IO_FLAG_NONBLOCK
, NULL
);
930 g_io_channel_set_encoding(sc
->channel
, NULL
, NULL
);
931 /* we have our own buffers, and GIO buffering blocks under Windows */
932 g_io_channel_set_buffered(sc
->channel
, FALSE
);
933 sc
->cb_data
= cb_data
[i
];
937 sc
->cb
.write
= stdin_cb
;
938 condition
= G_IO_OUT
| G_IO_FAILURE
;
939 callback
= (GSourceFunc
) spawn_write_cb
;
943 gboolean line_buffered
= !(spawn_flags
&
944 ((SPAWN_STDOUT_UNBUFFERED
>> 1) << i
));
946 condition
= G_IO_IN
| G_IO_PRI
| G_IO_FAILURE
;
947 callback
= (GSourceFunc
) spawn_read_cb
;
951 sc
->cb
.read
= stdout_cb
;
952 sc
->max_length
= stdout_max_length
? stdout_max_length
:
953 line_buffered
? 24576 : DEFAULT_IO_LENGTH
;
957 sc
->cb
.read
= stderr_cb
;
958 sc
->max_length
= stderr_max_length
? stderr_max_length
:
959 line_buffered
? 8192 : DEFAULT_IO_LENGTH
;
964 sc
->line_buffer
= g_string_sized_new(sc
->max_length
+
969 source
= g_io_create_watch(sc
->channel
, condition
);
970 g_io_channel_unref(sc
->channel
);
972 if (spawn_flags
& (SPAWN_STDIN_RECURSIVE
<< i
))
973 g_source_set_can_recurse(source
, TRUE
);
974 else if (i
) /* to avoid new string on each call */
975 sc
->buffer
= g_string_sized_new(sc
->max_length
);
977 g_source_set_callback(source
, callback
, sc
, spawn_destroy_cb
);
978 g_source_attach(source
, sw
->main_context
);
979 g_source_unref(source
);
982 sw
->exit_cb
= exit_cb
;
983 sw
->exit_data
= exit_data
;
984 source
= g_child_watch_source_new(pid
);
985 g_source_set_callback(source
, (GSourceFunc
) spawn_watch_cb
, sw
, NULL
);
986 g_source_attach(source
, sw
->main_context
);
987 g_source_unref(source
);
989 if (spawn_flags
& SPAWN_SYNC
)
991 sw
->main_loop
= g_main_loop_new(sw
->main_context
, FALSE
);
992 g_main_context_unref(sw
->main_context
);
993 g_main_loop_run(sw
->main_loop
);
1004 * Writes (a portion of) the data pointed by @a data->ptr to the @a channel.
1006 * If @c G_IO_OUT in @a condition is set, and the @a data->size is > 0, attempts to write
1007 * @a data->ptr (or a portion of it, depending on the size) to the @a channel. On success,
1008 * increases ptr and decreases size with the number of characters written.
1010 * This function may converted to @c GIOFunc and passed to @c spawn_with_callbacks() as
1011 * @c stdin_cb, together with a @c SpawnWriteData for @c stdin_data. As with any other
1012 * callback data, make sure that @c stdin_data exists while the child is being executed.
1013 * (For example, on asynchronous execution, you can allocate the data in the heap, and free
1014 * it in your @c spawn_with_callbacks() @c exit_cb callback.)
1016 * @return @c TRUE if the remaining size is > 0 and @a condition does not indicate any error,
1017 * @c FALSE otherwise.
1022 gboolean
spawn_write_data(GIOChannel
*channel
, GIOCondition condition
, SpawnWriteData
*data
)
1024 if ((condition
& G_IO_OUT
) && data
->size
)
1026 gsize chars_written
= 0;
1028 g_io_channel_write_chars(channel
, data
->ptr
, data
->size
< DEFAULT_IO_LENGTH
?
1029 data
->size
: DEFAULT_IO_LENGTH
, &chars_written
, NULL
);
1031 /* "This can be nonzero even if the return value is not G_IO_STATUS_NORMAL." */
1034 data
->ptr
+= chars_written
;
1035 data
->size
-= chars_written
;
1039 return data
->size
> 0 && !(condition
& G_IO_FAILURE
);
1043 static void spawn_append_gstring_cb(GString
*string
, GIOCondition condition
, gpointer data
)
1045 if (condition
& (G_IO_IN
| G_IO_PRI
))
1046 g_string_append_len((GString
*) data
, string
->str
, string
->len
);
1051 * Convinience @c GChildWatchFunc callback that copies the child exit status into a gint
1052 * pointed by @a exit_status.
1057 void spawn_get_exit_status_cb(G_GNUC_UNUSED GPid pid
, gint status
, gpointer exit_status
)
1059 *(gint
*) exit_status
= status
;
1064 * Executes a child synchronously.
1066 * A command line or an argument vector must be passed. If both are present, the argument
1067 * vector is appended to the command line. An empty command line is not allowed.
1069 * The @a stdin_data is sent to the child with @c spawn_write_data().
1071 * All output from the child, including the nul characters, is stored in @a stdout_data and
1072 * @a stderr_data (if non-NULL). Any existing data in these strings will be erased.
1074 * @param working_directory child's current working directory, or @c NULL.
1075 * @param command_line child program and arguments, or @c NULL.
1076 * @param argv child's argument vector, or @c NULL.
1077 * @param envp child's environment, or @c NULL.
1078 * @param stdin_data data to send to childs's stdin, or @c NULL.
1079 * @param stdout_data GString location to receive the child's stdout, or NULL.
1080 * @param stderr_data GString location to receive the child's stderr, or NULL.
1081 * @param exit_status return location for the child exit code, or NULL.
1082 * @param error return location for error.
1084 * @return @c TRUE on success, @c FALSE on error.
1089 gboolean
spawn_sync(const gchar
*working_directory
, const gchar
*command_line
, gchar
**argv
,
1090 gchar
**envp
, SpawnWriteData
*stdin_data
, GString
*stdout_data
, GString
*stderr_data
,
1091 gint
*exit_status
, GError
**error
)
1093 g_string_truncate(stdout_data
, 0);
1094 g_string_truncate(stderr_data
, 0);
1096 return spawn_with_callbacks(working_directory
, command_line
, argv
, envp
, SPAWN_SYNC
|
1097 SPAWN_UNBUFFERED
, stdin_data
? (GIOFunc
) spawn_write_data
: NULL
, stdin_data
,
1098 stdout_data
? spawn_append_gstring_cb
: NULL
, stdout_data
, 0,
1099 stderr_data
? spawn_append_gstring_cb
: NULL
, stderr_data
, 0,
1100 exit_status
? spawn_get_exit_status_cb
: NULL
, exit_status
, NULL
, error
);
1104 /* tests, not part of the API */
1109 static gboolean
read_line(const char *prompt
, char *buffer
, size_t size
)
1111 fputs(prompt
, stderr
);
1114 if (fgets(buffer
, size
, stdin
))
1116 char *s
= strchr(buffer
, '\n');
1126 static GString
*read_string(const char *prompt
)
1128 char buffer
[0x1000]; /* larger portions for spawn < file */
1129 GString
*string
= g_string_sized_new(sizeof buffer
);
1131 while (read_line(prompt
, buffer
, sizeof buffer
))
1134 g_string_append_c(string
, '\n');
1136 g_string_append(string
, buffer
);
1141 g_string_free(string
, TRUE
);
1149 static void print_cb(GString
*string
, GIOCondition condition
, gpointer data
)
1151 if (condition
& (G_IO_IN
| G_IO_PRI
))
1155 printf("%s: ", (const gchar
*) data
);
1156 /*fputs(string->str, stdout);*/
1157 for (i
= 0; i
< string
->len
; i
++)
1159 unsigned char c
= (unsigned char) string
->str
[i
];
1160 printf(c
>= ' ' && c
< 0x80 ? "%c" : "\\x%02x", c
);
1167 static void print_status(gint status
)
1169 fputs("finished, ", stderr
);
1171 if (WIFEXITED(status
))
1172 fprintf(stderr
, "exit code %d\n", WEXITSTATUS(status
));
1174 fputs("abnormal termination\n", stderr
);
1178 static void exit_cb(GPid pid
, gint status
, G_GNUC_UNUSED gpointer data
)
1180 fprintf(stderr
, "process %u ", (guint
) pid
);
1181 print_status(status
);
1185 static void watch_cb(GPid pid
, gint status
, gpointer data
)
1187 g_spawn_close_pid(pid
);
1188 exit_cb(pid
, status
, NULL
);
1189 g_main_loop_quit((GMainLoop
*) data
);
1193 int main(int argc
, char **argv
)
1199 fputs("usage: spawn <test-type>\n", stderr
);
1203 test_type
= argv
[1];
1205 if (!strcmp(test_type
, "syntax") || !strcmp(test_type
, "syntexec"))
1207 char command_line
[0x100];
1209 while (read_line("command line: ", command_line
, sizeof command_line
))
1211 GError
*error
= NULL
;
1213 if (spawn_check_command(command_line
, argv
[1][4] == 'e', &error
))
1214 fputs("valid\n", stderr
);
1217 fprintf(stderr
, "error: %s\n", error
->message
);
1218 g_error_free(error
);
1222 else if (!strcmp(test_type
, "execute"))
1224 char command_line
[0x100];
1226 while (read_line("command line: ", command_line
, sizeof command_line
))
1228 char working_directory
[0x100];
1229 char args
[4][0x100];
1230 char envs
[4][0x100];
1231 char *argv
[] = { args
[0], args
[1], args
[2], args
[3], NULL
};
1232 char *envp
[] = { envs
[0], envs
[1], envs
[2], envs
[3], NULL
};
1235 GError
*error
= NULL
;
1237 read_line("working directory: ", working_directory
, sizeof working_directory
);
1239 fputs("up to 4 arguments\n", stderr
);
1240 for (i
= 0; i
< 4 && read_line("argument: ", args
[i
], sizeof args
[i
]); i
++);
1243 fputs("up to 4 variables, or empty line for parent environment\n", stderr
);
1244 for (i
= 0; i
< 4 && read_line("variable: ", envs
[i
], sizeof envs
[i
]); i
++);
1247 if (spawn_async_with_pipes(*working_directory
? working_directory
: NULL
,
1248 *command_line
? command_line
: NULL
, argv
, i
? envp
: NULL
, &pid
, NULL
,
1249 NULL
, NULL
, &error
))
1251 GMainLoop
*loop
= g_main_loop_new(NULL
, TRUE
);
1253 g_child_watch_add(pid
, watch_cb
, loop
);
1254 g_main_loop_run(loop
);
1255 g_main_loop_unref(loop
);
1259 fprintf(stderr
, "error: %s\n", error
->message
);
1260 g_error_free(error
);
1264 else if (!strcmp(test_type
, "redirect") || !strcmp(test_type
, "redinput"))
1266 char command_line
[0x100];
1267 gboolean output
= test_type
[4] == 'r';
1269 while (read_line("command line: ", command_line
, sizeof command_line
))
1271 GString
*stdin_text
= read_string("text to send: ");
1272 SpawnWriteData stdin_data
;
1273 GError
*error
= NULL
;
1277 stdin_data
.ptr
= stdin_text
->str
;
1278 stdin_data
.size
= stdin_text
->len
;
1281 if (!spawn_with_callbacks(NULL
, command_line
, NULL
, NULL
, SPAWN_SYNC
,
1282 stdin_text
? (GIOFunc
) spawn_write_data
: NULL
, &stdin_data
,
1283 output
? print_cb
: NULL
, "stdout", 0, output
? print_cb
: NULL
,
1284 "stderr", 0, exit_cb
, NULL
, NULL
, &error
))
1286 fprintf(stderr
, "error: %s\n", error
->message
);
1287 g_error_free(error
);
1291 g_string_free(stdin_text
, TRUE
);
1294 else if (!strcmp(test_type
, "capture"))
1296 char command_line
[0x100];
1298 while (read_line("command line: ", command_line
, sizeof command_line
))
1300 GString
*stdin_text
= read_string("text to send: ");
1301 SpawnWriteData stdin_data
= { NULL
, 0 };
1302 GString
*stdout_data
= g_string_sized_new(0x10000); /* may grow */
1303 GString
*stderr_data
= g_string_sized_new(0x1000); /* may grow */
1305 GError
*error
= NULL
;
1309 stdin_data
.ptr
= stdin_text
->str
;
1310 stdin_data
.size
= stdin_text
->len
;
1313 if (spawn_sync(NULL
, command_line
, NULL
, NULL
, &stdin_data
, stdout_data
,
1314 stderr_data
, &exit_status
, &error
))
1316 printf("stdout: %s\n", stdout_data
->str
);
1317 printf("stderr: %s\n", stderr_data
->str
);
1318 print_status(exit_status
);
1322 fprintf(stderr
, "error: %s\n", error
->message
);
1323 g_error_free(error
);
1327 g_string_free(stdin_text
, TRUE
);
1329 g_string_free(stdout_data
, TRUE
);
1330 g_string_free(stderr_data
, TRUE
);
1335 fprintf(stderr
, "spawn: unknown test type '%s'", argv
[1]);
1341 #endif /* SPAWN_TEST */