c family: Add support for digraphs
[geany-mirror.git] / src / spawn.c
blobd1ff510e446959a66a057f3fa5b67d04444e3461
1 /*
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.
22 * In particular:
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).
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
46 #include <errno.h>
47 #include <string.h>
49 #include "spawn.h"
51 #ifdef G_OS_WIN32
52 # include <ctype.h> /* isspace() */
53 # include <fcntl.h> /* _O_RDONLY, _O_WRONLY */
54 # include <io.h> /* _open_osfhandle, _close */
55 # include <windows.h>
56 #else /* G_OS_WIN32 */
57 # include <signal.h>
58 #endif /* G_OS_WIN32 */
60 #ifdef SPAWN_TEST
61 # define _
62 #else
63 # include "support.h"
64 #endif
66 #ifdef 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
70 #else
71 # define DEFAULT_IO_LENGTH 4096
72 #endif
74 #define G_IO_FAILURE (G_IO_ERR | G_IO_HUP | G_IO_NVAL) /* always used together */
77 /**
78 * Checks whether a command line is syntactically valid and extracts the program name from it.
80 * All OS:
81 * - any leading spaces, tabs and new lines are skipped
82 * - an empty command is invalid
83 * Unix:
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
86 * Windows:
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.
102 * @since 1.25
104 GEANY_API_SYMBOL
105 gchar *spawn_get_program_name(const gchar *command_line, GError **error)
107 gchar *program;
109 #ifdef G_OS_WIN32
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))
116 command_line++;
118 if (!*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)"));
123 return FALSE;
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 == '"')
131 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);
139 return FALSE;
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"));
146 return FALSE;
149 else
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"));
160 return FALSE;
164 program = g_strndup(command_line, s - command_line);
165 arguments = s + (*s == '"');
167 for (s = arguments; *s; s++)
169 if (*s == '"')
171 const char *slash;
173 for (slash = s; slash > arguments && slash[-1] == '\\'; slash--);
174 if ((s - slash) % 2 == 0)
175 open_quote ^= TRUE;
179 if (open_quote)
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);
185 g_free(program);
186 return FALSE;
188 #else /* G_OS_WIN32 */
189 int argc;
190 char **argv;
192 if (!g_shell_parse_argv(command_line, &argc, &argv, error))
193 return FALSE;
195 /* empty string results in parse error, so argv[0] is not NULL */
196 program = g_strdup(argv[0]);
197 g_strfreev(argv);
198 #endif /* G_OS_WIN32 */
200 return program;
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.
218 * @since 1.25
220 GEANY_API_SYMBOL
221 gboolean spawn_check_command(const gchar *command_line, gboolean execute, GError **error)
223 gchar *program = spawn_get_program_name(command_line, error);
225 if (!program)
226 return FALSE;
228 if (execute)
230 gchar *executable = g_find_program_in_path(program);
232 if (!executable)
234 g_set_error(error, G_SHELL_ERROR, G_SHELL_ERROR_FAILED, /* or SPAWN error? */
235 _("Program '%s' not found"), program);
236 g_free(program);
237 return FALSE;
240 g_free(executable);
243 g_free(program);
244 return TRUE;
249 * Kills a process.
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.
261 * @since 1.25
263 GEANY_API_SYMBOL
264 gboolean spawn_kill_process(GPid pid, GError **error)
266 #ifdef G_OS_WIN32
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);
273 g_free(message);
274 return FALSE;
276 #else
277 if (kill(pid, SIGTERM))
279 g_set_error(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, "%s", g_strerror(errno));
280 return FALSE;
282 #endif
283 return TRUE;
287 #ifdef G_OS_WIN32
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 };
292 STARTUPINFO startup;
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 */
299 gboolean pipe_io;
300 int i;
302 ZeroMemory(&startup, sizeof startup);
303 startup.cb = sizeof startup;
304 pipe_io = stdin_fd || stdout_fd || stderr_fd;
306 if (pipe_io)
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";
320 goto leave;
323 if (fd[i])
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));
331 goto leave;
334 else if (!CloseHandle(hpipe[i]))
336 failed = "CloseHandle";
337 goto leave;
340 if (!SetHandleInformation(hpipe[i + 3], HANDLE_FLAG_INHERIT,
341 HANDLE_FLAG_INHERIT))
343 failed = "SetHandleInformation";
344 goto leave;
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 */
359 else
361 failed = NULL;
362 CloseHandle(process.hThread); /* we don't need this */
363 *hprocess = process.hProcess;
366 leave:
367 if (failed)
369 if (!message)
370 message = g_win32_error_message(GetLastError());
372 failure = g_strdup_printf("%s() failed: %s", failed, message);
373 g_free(message);
376 if (pipe_io)
378 for (i = 0; i < 3; i++)
380 if (failed)
382 if (fd[i] && *fd[i] != -1)
383 _close(*fd[i]);
384 else if (hpipe[i])
385 CloseHandle(hpipe[i]);
388 if (hpipe[i + 3])
389 CloseHandle(hpipe[i + 3]);
393 return failure;
397 static void spawn_append_argument(GString *command, const char *text)
399 const char *s;
401 if (command->len)
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))
408 break;
411 if (*text && !*s)
412 g_string_append(command, text);
413 else
415 g_string_append_c(command, '"');
417 for (s = text; *s; s++)
419 const char *slash;
421 for (slash = s; *slash == '\\'; slash++);
423 if (slash > s)
425 g_string_append_len(command, s, slash - s);
427 if (!*slash || *slash == '"')
429 g_string_append_len(command, s, slash - s);
431 if (!*slash)
432 break;
435 s = slash;
438 if (*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.
482 * @since 1.25
484 GEANY_API_SYMBOL
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);
491 #ifdef G_OS_WIN32
492 GString *command;
493 GArray *environment;
494 GPid pid;
495 gchar *failure;
497 if (command_line)
499 gchar *program = spawn_get_program_name(command_line, error);
500 const gchar *arguments;
502 if (!program)
503 return FALSE;
505 command = g_string_new(NULL);
506 arguments = strstr(command_line, program) + strlen(program);
508 if (*arguments == '"')
510 g_string_append(command, program);
511 arguments++;
513 else
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);
521 g_free(program);
523 else
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++);
531 #ifdef SPAWN_TEST
532 g_message("full spawn command line: %s\n", command->str);
533 #endif
535 while (envp && *envp)
537 g_array_append_vals(environment, *envp, strlen(*envp) + 1);
538 envp++;
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);
548 if (failure)
550 g_set_error(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, "%s", failure);
551 g_free(failure);
552 return FALSE;
554 else if (!child_pid)
555 g_child_watch_add(pid, spawn_close_pid, NULL);
557 return TRUE;
558 #else /* G_OS_WIN32 */
559 int cl_argc;
560 char **full_argv;
561 gboolean spawned;
563 if (command_line)
565 int argc = 0;
566 char **cl_argv;
568 if (!g_shell_parse_argv(command_line, &cl_argc, &cl_argv, error))
569 return FALSE;
571 if (argv)
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;
578 else
579 full_argv = argv;
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);
591 return spawned;
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.
602 * @since 1.25
604 GEANY_API_SYMBOL
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 */
628 union
630 GIOFunc write;
631 SpawnReadFunc read;
632 } cb;
633 gpointer cb_data;
634 /* stdout/stderr only */
635 GString *buffer; /* NULL if recursive */
636 GString *line_buffer; /* NULL if char buffered */
637 gsize max_length;
638 } SpawnChannelData;
641 static void spawn_destroy_cb(gpointer data)
643 SpawnChannelData *sc = (SpawnChannelData *) data;
645 g_io_channel_shutdown(sc->channel, FALSE, NULL);
646 sc->channel = NULL;
648 if (sc->buffer)
649 g_string_free(sc->buffer, TRUE);
651 if (sc->line_buffer)
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))
661 return FALSE;
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).
681 if (input_cond)
683 gsize chars_read;
684 GIOStatus status;
686 if (line_buffer)
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)
697 gsize line_len = 0;
699 if (n == sc->max_length)
700 line_len = n;
701 else if (strchr("\n", line_buffer->str[n])) /* '\n' or '\0' */
702 line_len = n + 1;
703 else if (n < line_buffer->len - 1 && line_buffer->str[n] == '\r')
704 line_len = n + 1 + (line_buffer->str[n + 1] == '\n');
706 if (!line_len)
707 n++;
708 else
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);
715 n = 0;
719 if (!failure_cond)
720 break;
723 else
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);
732 if (!failure_cond)
733 break;
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 */
752 if (!input_cond)
753 input_cond = G_IO_IN;
755 else
757 input_cond = 0;
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;
775 gpointer exit_data;
776 GPid pid;
777 gint exit_status;
778 GMainContext *main_context; /* NULL if async execution */
779 GMainLoop *main_loop; /* NULL if async execution */
780 } SpawnWatcherData;
783 static void spawn_finalize(SpawnWatcherData *sw)
785 if (sw->exit_cb)
786 sw->exit_cb(sw->pid, sw->exit_status, sw->exit_data);
788 if (sw->main_loop)
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;
802 int i;
804 for (i = 0; i < 3; i++)
805 if (sw->sc[i].channel)
806 return TRUE;
808 spawn_finalize(sw);
809 return FALSE;
813 static void spawn_watch_cb(GPid pid, gint status, gpointer data)
815 SpawnWatcherData *sw = (SpawnWatcherData *) data;
816 int i;
818 sw->pid = pid;
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);
830 return;
834 spawn_finalize(sw);
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
857 * free them.
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.
886 * @since 1.25
888 GEANY_API_SYMBOL
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)
895 GPid pid;
896 int pipe[3] = { -1, -1, -1 };
898 g_return_val_if_fail(!(spawn_flags & SPAWN_RECURSIVE) || !(spawn_flags & SPAWN_SYNC),
899 FALSE);
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 };
907 GSource *source;
908 int i;
910 sw->main_context = spawn_flags & SPAWN_SYNC ? g_main_context_new() : NULL;
912 if (child_pid)
913 *child_pid = pid;
915 for (i = 0; i < 3; i++)
917 SpawnChannelData *sc = &sw->sc[i];
918 GIOCondition condition;
919 GSourceFunc callback;
921 if (pipe[i] == -1)
922 continue;
924 #ifdef G_OS_WIN32
925 sc->channel = g_io_channel_win32_new_fd(pipe[i]);
926 #else
927 sc->channel = g_io_channel_unix_new(pipe[i]);
928 g_io_channel_set_flags(sc->channel, G_IO_FLAG_NONBLOCK, NULL);
929 #endif
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];
935 if (i == 0)
937 sc->cb.write = stdin_cb;
938 condition = G_IO_OUT | G_IO_FAILURE;
939 callback = (GSourceFunc) spawn_write_cb;
941 else
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;
949 if (i == 1)
951 sc->cb.read = stdout_cb;
952 sc->max_length = stdout_max_length ? stdout_max_length :
953 line_buffered ? 24576 : DEFAULT_IO_LENGTH;
955 else
957 sc->cb.read = stderr_cb;
958 sc->max_length = stderr_max_length ? stderr_max_length :
959 line_buffered ? 8192 : DEFAULT_IO_LENGTH;
962 if (line_buffered)
964 sc->line_buffer = g_string_sized_new(sc->max_length +
965 DEFAULT_IO_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);
996 return TRUE;
999 return FALSE;
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.
1019 * @since 1.25
1021 GEANY_API_SYMBOL
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." */
1032 if (chars_written)
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.
1054 * @since 1.25
1056 GEANY_API_SYMBOL
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.
1086 * @since 1.25
1088 GEANY_API_SYMBOL
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 */
1105 #ifdef SPAWN_TEST
1106 #include <stdio.h>
1109 static gboolean read_line(const char *prompt, char *buffer, size_t size)
1111 fputs(prompt, stderr);
1112 *buffer = '\0';
1114 if (fgets(buffer, size, stdin))
1116 char *s = strchr(buffer, '\n');
1118 if (s)
1119 *s = '\0';
1122 return *buffer;
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))
1133 if (string->len)
1134 g_string_append_c(string, '\n');
1136 g_string_append(string, buffer);
1139 if (!string->len)
1141 g_string_free(string, TRUE);
1142 string = NULL;
1145 return string;
1149 static void print_cb(GString *string, GIOCondition condition, gpointer data)
1151 if (condition & (G_IO_IN | G_IO_PRI))
1153 gsize i;
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);
1162 putchar('\n');
1167 static void print_status(gint status)
1169 fputs("finished, ", stderr);
1171 if (WIFEXITED(status))
1172 fprintf(stderr, "exit code %d\n", WEXITSTATUS(status));
1173 else
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)
1195 char *test_type;
1197 if (argc != 2)
1199 fputs("usage: spawn <test-type>\n", stderr);
1200 return 1;
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);
1215 else
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 };
1233 int i;
1234 GPid pid;
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++);
1241 argv[i] = NULL;
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++);
1245 envp[i] = NULL;
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);
1257 else
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;
1275 if (stdin_text)
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);
1290 if (stdin_text)
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 */
1304 gint exit_status;
1305 GError *error = NULL;
1307 if (stdin_text)
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);
1320 else
1322 fprintf(stderr, "error: %s\n", error->message);
1323 g_error_free(error);
1326 if (stdin_text)
1327 g_string_free(stdin_text, TRUE);
1329 g_string_free(stdout_data, TRUE);
1330 g_string_free(stderr_data, TRUE);
1333 else
1335 fprintf(stderr, "spawn: unknown test type '%s'", argv[1]);
1336 return 1;
1339 return 0;
1341 #endif /* SPAWN_TEST */