Windows: Convert working directory into locale encoding before spawning commands
[geany-mirror.git] / src / spawn.c
blob627d42958e8b3b55f8d135123a9258f127c68a6c
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 /** @file spawn.h
43 * Portable and convenient process spawning and communication.
46 #ifdef HAVE_CONFIG_H
47 # include "config.h"
48 #endif
50 #include <errno.h>
51 #include <string.h>
53 #include "spawn.h"
55 #ifdef G_OS_WIN32
56 # include <ctype.h> /* isspace() */
57 # include <fcntl.h> /* _O_RDONLY, _O_WRONLY */
58 # include <io.h> /* _open_osfhandle, _close */
59 # include <windows.h>
60 #else /* G_OS_WIN32 */
61 # include <signal.h>
62 #endif /* G_OS_WIN32 */
64 #ifdef SPAWN_TEST
65 # define _
66 # define GEANY_API_SYMBOL
67 #else
68 # include "support.h"
69 #endif
71 #if ! GLIB_CHECK_VERSION(2, 31, 20) && ! defined(G_SPAWN_ERROR_TOO_BIG)
72 # define G_SPAWN_ERROR_TOO_BIG G_SPAWN_ERROR_2BIG
73 #endif
75 #ifdef G_OS_WIN32
76 /* Each 4KB under Windows seem to come in 2 portions, so 2K + 2K is more
77 balanced than 4095 + 1. May be different on the latest Windows/glib? */
78 # define DEFAULT_IO_LENGTH 2048
79 #else
80 # define DEFAULT_IO_LENGTH 4096
82 /* helper function that cuts glib citing of the original text on bad quoting: it may be long,
83 and only the caller knows whether it's UTF-8. Thought we lose the ' or " failed info. */
84 static gboolean spawn_parse_argv(const gchar *command_line, gint *argcp, gchar ***argvp,
85 GError **error)
87 GError *gerror = NULL;
89 if (g_shell_parse_argv(command_line, argcp, argvp, &gerror))
90 return TRUE;
92 g_set_error_literal(error, gerror->domain, gerror->code,
93 gerror->code == G_SHELL_ERROR_BAD_QUOTING ?
94 _("Text ended before matching quote was found") : gerror->message);
95 g_error_free(gerror);
96 return FALSE;
98 #endif
100 #define G_IO_FAILURE (G_IO_ERR | G_IO_HUP | G_IO_NVAL) /* always used together */
104 * Checks whether a command line is syntactically valid and extracts the program name from it.
106 * See @c spawn_check_command() for details.
108 * @param command_line the command line to check and get the program name from.
109 * @param error return location for error.
111 * @return allocated string with the program name on success, @c NULL on error.
113 static gchar *spawn_get_program_name(const gchar *command_line, GError **error)
115 gchar *program;
117 #ifdef G_OS_WIN32
118 gboolean open_quote = FALSE;
119 const gchar *s, *arguments;
121 g_return_val_if_fail(command_line != NULL, FALSE);
123 while (*command_line && strchr(" \t\r\n", *command_line))
124 command_line++;
126 if (!*command_line)
128 g_set_error_literal(error, G_SHELL_ERROR, G_SHELL_ERROR_EMPTY_STRING,
129 /* TL note: from glib */
130 _("Text was empty (or contained only whitespace)"));
131 return FALSE;
134 /* To prevent Windows from doing something weird, we want to be 100% sure that the
135 character after the program name is a delimiter, so we allow space and tab only. */
137 if (*command_line == '"')
139 command_line++;
140 /* Windows allows "foo.exe, but we may have extra arguments */
141 if ((s = strchr(command_line, '"')) == NULL)
143 g_set_error_literal(error, G_SHELL_ERROR, G_SHELL_ERROR_BAD_QUOTING,
144 _("Text ended before matching quote was found"));
145 return FALSE;
148 if (!strchr(" \t", s[1])) /* strchr() catches s[1] == '\0' */
150 g_set_error_literal(error, G_SHELL_ERROR, G_SHELL_ERROR_BAD_QUOTING,
151 _("A quoted Windows program name must be entirely inside the quotes"));
152 return FALSE;
155 else
157 const gchar *quote = strchr(command_line, '"');
159 /* strchr() catches *s == '\0', and the for body is empty */
160 for (s = command_line; !strchr(" \t", *s); s++);
162 if (quote && quote < s)
164 g_set_error_literal(error, G_SHELL_ERROR, G_SHELL_ERROR_BAD_QUOTING,
165 _("A quoted Windows program name must be entirely inside the quotes"));
166 return FALSE;
170 program = g_strndup(command_line, s - command_line);
171 arguments = s + (*s == '"');
173 for (s = arguments; *s; s++)
175 if (*s == '"')
177 const char *slash;
179 for (slash = s; slash > arguments && slash[-1] == '\\'; slash--);
180 if ((s - slash) % 2 == 0)
181 open_quote ^= TRUE;
185 if (open_quote)
187 g_set_error_literal(error, G_SHELL_ERROR, G_SHELL_ERROR_BAD_QUOTING,
188 _("Text ended before matching quote was found"));
189 g_free(program);
190 return FALSE;
192 #else /* G_OS_WIN32 */
193 int argc;
194 char **argv;
196 if (!spawn_parse_argv(command_line, &argc, &argv, error))
197 return FALSE;
199 /* empty string results in parse error, so argv[0] is not NULL */
200 program = g_strdup(argv[0]);
201 g_strfreev(argv);
202 #endif /* G_OS_WIN32 */
204 return program;
209 * Checks whether a command line is valid.
211 * Checks if @a command_line is syntactically valid.
213 * All OS:
214 * - any leading spaces, tabs and new lines are skipped
215 * - an empty command is invalid
217 * Unix:
218 * - the standard shell quoting and escaping rules are used, see @c g_shell_parse_argv()
219 * - as a consequence, an unqouted # at the start of an argument comments to the end of line
221 * Windows:
222 * - leading carriage returns are skipped too
223 * - a quoted program name must be entirely inside the quotes. No "C:\Foo\Bar".pdf or
224 * "C:\Foo\Bar".bat, which would be executed by Windows as `C:\Foo\Bar.exe`
225 * - an unquoted program name may not contain spaces. `Foo Bar Qux` will not be considered
226 * `"Foo Bar.exe" Qux` or `"Foo Bar Qux.exe"`, depending on what executables exist, as
227 * Windows normally does.
228 * - the program name must be separated from the arguments by at least one space or tab
229 * - the standard Windows quoting and escaping rules are used: double quote is escaped with
230 * backslash, and any literal backslashes before a double quote must be duplicated.
232 * If @a execute is TRUE, also checks, using @c g_find_program_in_path(), if the program
233 * specified in @a command_line exists and is executable.
235 * @param command_line the command line to check.
236 * @param execute whether to check if the command line is really executable.
237 * @param error return location for error.
239 * @return @c TRUE on success, @c FALSE on error.
241 * @since 1.25
243 GEANY_API_SYMBOL
244 gboolean spawn_check_command(const gchar *command_line, gboolean execute, GError **error)
246 gchar *program = spawn_get_program_name(command_line, error);
248 if (!program)
249 return FALSE;
251 if (execute)
253 gchar *executable = g_find_program_in_path(program);
255 if (!executable)
257 g_set_error_literal(error, G_SHELL_ERROR, G_SHELL_ERROR_FAILED,
258 _("Program not found"));
259 g_free(program);
260 return FALSE;
263 g_free(executable);
266 g_free(program);
267 return TRUE;
272 * Kills a process.
274 * @param pid id of the process to kill.
275 * @param error return location for error.
277 * On Unix, sends a SIGTERM to the process.
279 * On Windows, terminates the process with exit code 255 (used sometimes as "generic"
280 * error code, or for programs terminated with Ctrl+C / Ctrl+Break).
282 * @return @c TRUE on success, @c FALSE on error.
284 * @since 1.25
286 GEANY_API_SYMBOL
287 gboolean spawn_kill_process(GPid pid, GError **error)
289 #ifdef G_OS_WIN32
290 if (!TerminateProcess(pid, 255))
292 gchar *message = g_win32_error_message(GetLastError());
294 g_set_error_literal(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, message);
295 g_free(message);
296 return FALSE;
298 #else
299 if (kill(pid, SIGTERM))
301 g_set_error_literal(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, g_strerror(errno));
302 return FALSE;
304 #endif
305 return TRUE;
309 #ifdef G_OS_WIN32
310 static gchar *spawn_create_process_with_pipes(char *command_line, const char *working_directory,
311 void *environment, HANDLE *hprocess, int *stdin_fd, int *stdout_fd, int *stderr_fd)
313 enum { WRITE_STDIN, READ_STDOUT, READ_STDERR, READ_STDIN, WRITE_STDOUT, WRITE_STDERR };
314 STARTUPINFO startup;
315 PROCESS_INFORMATION process;
316 HANDLE hpipe[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
317 int *fd[3] = { stdin_fd, stdout_fd, stderr_fd };
318 const char *failed; /* failed WIN32/CRTL function, if any */
319 gchar *message = NULL; /* glib WIN32/CTRL error message */
320 gchar *failure = NULL; /* full error text */
321 gboolean pipe_io;
322 int i;
324 ZeroMemory(&startup, sizeof startup);
325 startup.cb = sizeof startup;
326 pipe_io = stdin_fd || stdout_fd || stderr_fd;
328 if (pipe_io)
330 startup.dwFlags |= STARTF_USESTDHANDLES;
332 /* not all programs accept mixed NULL and non-NULL hStd*, so we create all */
333 for (i = 0; i < 3; i++)
335 static int pindex[3][2] = { { READ_STDIN, WRITE_STDIN },
336 { READ_STDOUT, WRITE_STDOUT }, { READ_STDERR, WRITE_STDERR } };
338 if (!CreatePipe(&hpipe[pindex[i][0]], &hpipe[pindex[i][1]], NULL, 0))
340 hpipe[pindex[i][0]] = hpipe[pindex[i][1]] = NULL;
341 failed = "create pipe";
342 goto leave;
345 if (fd[i])
347 static int mode[3] = { _O_WRONLY, _O_RDONLY, _O_RDONLY };
349 if ((*fd[i] = _open_osfhandle((intptr_t) hpipe[i], mode[i])) == -1)
351 failed = "convert pipe handle to file descriptor";
352 message = g_strdup(g_strerror(errno));
353 goto leave;
356 else if (!CloseHandle(hpipe[i]))
358 failed = "close pipe";
359 goto leave;
362 if (!SetHandleInformation(hpipe[i + 3], HANDLE_FLAG_INHERIT,
363 HANDLE_FLAG_INHERIT))
365 failed = "set pipe handle to inheritable";
366 goto leave;
371 startup.hStdInput = hpipe[READ_STDIN];
372 startup.hStdOutput = hpipe[WRITE_STDOUT];
373 startup.hStdError = hpipe[WRITE_STDERR];
375 if (!CreateProcess(NULL, command_line, NULL, NULL, TRUE, pipe_io ? CREATE_NO_WINDOW : 0,
376 environment, working_directory, &startup, &process))
378 failed = ""; /* report the message only */
379 /* further errors will not be reported */
381 else
383 failed = NULL;
384 CloseHandle(process.hThread); /* we don't need this */
386 if (hprocess)
387 *hprocess = process.hProcess;
388 else
389 CloseHandle(process.hProcess);
392 leave:
393 if (failed)
395 if (!message)
397 size_t len;
399 message = g_win32_error_message(GetLastError());
400 len = strlen(message);
402 /* unlike g_strerror(), the g_win32_error messages may include a final '.' */
403 if (len > 0 && message[len - 1] == '.')
404 message[len - 1] = '\0';
407 if (*failed == '\0')
408 failure = message;
409 else
411 failure = g_strdup_printf("Failed to %s (%s)", failed, message);
412 g_free(message);
416 if (pipe_io)
418 for (i = 0; i < 3; i++)
420 if (failed)
422 if (fd[i] && *fd[i] != -1)
423 _close(*fd[i]);
424 else if (hpipe[i])
425 CloseHandle(hpipe[i]);
428 if (hpipe[i + 3])
429 CloseHandle(hpipe[i + 3]);
433 return failure;
437 static void spawn_append_argument(GString *command, const char *text)
439 const char *s;
441 if (command->len)
442 g_string_append_c(command, ' ');
444 for (s = text; *s; s++)
446 /* g_ascii_isspace() fails for '\v', and locale spaces (if any) will do no harm */
447 if (*s == '"' || isspace(*s))
448 break;
451 if (*text && !*s)
452 g_string_append(command, text);
453 else
455 g_string_append_c(command, '"');
457 for (s = text; *s; s++)
459 const char *slash;
461 for (slash = s; *slash == '\\'; slash++);
463 if (slash > s)
465 g_string_append_len(command, s, slash - s);
467 if (!*slash || *slash == '"')
469 g_string_append_len(command, s, slash - s);
471 if (!*slash)
472 break;
475 s = slash;
478 if (*s == '"')
479 g_string_append_c(command, '\\');
481 g_string_append_c(command, *s);
484 g_string_append_c(command, '"');
487 #endif /* G_OS_WIN32 */
491 * Executes a child program asynchronously and setups pipes.
493 * This is the low-level spawning function. Please use @c spawn_with_callbacks() unless
494 * you need to setup specific event source(s).
496 * A command line or an argument vector must be passed. If both are present, the argument
497 * vector is appended to the command line. An empty command line is not allowed.
499 * Under Windows, if the child is a console application, and at least one file descriptor is
500 * specified, the new child console (if any) will be hidden.
502 * If a @a child_pid is passed, it's your responsibility to invoke @c g_spawn_close_pid().
504 * @param working_directory child's current working directory, or @c NULL.
505 * @param command_line child program and arguments, or @c NULL.
506 * @param argv child's argument vector, or @c NULL.
507 * @param envp child's environment, or @c NULL.
508 * @param child_pid return location for child process ID, or @c NULL.
509 * @param stdin_fd return location for file descriptor to write to child's stdin, or @c NULL.
510 * @param stdout_fd return location for file descriptor to read child's stdout, or @c NULL.
511 * @param stderr_fd return location for file descriptor to read child's stderr, or @c NULL.
512 * @param error return location for error.
514 * @return @c TRUE on success, @c FALSE on error.
516 static gboolean spawn_async_with_pipes(const gchar *working_directory, const gchar *command_line,
517 gchar **argv, gchar **envp, GPid *child_pid, gint *stdin_fd, gint *stdout_fd,
518 gint *stderr_fd, GError **error)
520 g_return_val_if_fail(command_line != NULL || argv != NULL, FALSE);
522 #ifdef G_OS_WIN32
523 GString *command;
524 GArray *environment;
525 GError *gerror = NULL;
526 gchar *locale_working_directory;
527 gchar *locale_command;
528 gchar *failure;
530 if (command_line)
532 gchar *program = spawn_get_program_name(command_line, error);
533 const gchar *arguments;
535 if (!program)
536 return FALSE;
538 command = g_string_new(NULL);
539 arguments = strstr(command_line, program) + strlen(program);
541 if (*arguments == '"')
543 g_string_append(command, program);
544 arguments++;
546 else
548 /* quote the first token, to avoid Windows attemps to run two or more
549 unquoted tokens as a program until an existing file name is found */
550 g_string_printf(command, "\"%s\"", program);
553 g_string_append(command, arguments);
554 g_free(program);
556 else
557 command = g_string_new(NULL);
559 environment = g_array_new(TRUE, FALSE, sizeof(char));
561 while (argv && *argv)
562 spawn_append_argument(command, *argv++);
564 #if defined(SPAWN_TEST) || defined(GEANY_DEBUG)
565 g_message("full spawn command line: %s", command->str);
566 #endif
568 while (envp && *envp)
570 g_array_append_vals(environment, *envp, strlen(*envp) + 1);
571 envp++;
574 // convert working directory into locale encoding
575 if (g_utf8_validate(working_directory, -1, NULL))
577 locale_working_directory = g_locale_from_utf8(working_directory, -1, NULL, NULL, &gerror);
578 if (gerror) {
579 /* TODO use the code below post-1.28 as it introduces a new string
580 gchar *msg = g_strdup_printf(
581 _("Failed to convert working directory into locale encoding: %s"), gerror->message);
582 g_set_error_literal(error, gerror->domain, gerror->code, msg);
584 g_set_error_literal(error, gerror->domain, gerror->code, gerror->message);
585 g_error_free(gerror);
586 g_string_free(command, TRUE);
587 g_array_free(environment, TRUE);
588 g_free(locale_working_directory);
589 /*g_free(msg);*/
590 return FALSE;
593 // convert command into locale encoding
594 if (g_utf8_validate(command->str, -1, NULL))
596 locale_command = g_locale_from_utf8(command->str, -1, NULL, NULL, &gerror);
597 if (gerror) {
598 /* TODO use the code below post-1.28 as it introduces a new string
599 gchar *msg = g_strdup_printf(
600 _("Failed to convert command into locale encoding: %s"), gerror->message);
601 g_set_error_literal(error, gerror->domain, gerror->code, msg);
603 g_set_error_literal(error, gerror->domain, gerror->code, gerror->message);
604 g_error_free(gerror);
605 g_string_free(command, TRUE);
606 g_array_free(environment, TRUE);
607 g_free(locale_working_directory);
608 g_free(locale_command);
609 /*g_free(msg);*/
610 return FALSE;
613 failure = spawn_create_process_with_pipes(locale_command, locale_working_directory,
614 envp ? environment->data : NULL, child_pid, stdin_fd, stdout_fd, stderr_fd);
616 g_string_free(command, TRUE);
617 g_array_free(environment, TRUE);
618 g_free(locale_working_directory);
619 g_free(locale_command);
621 if (failure)
623 g_set_error_literal(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, failure);
624 g_free(failure);
625 return FALSE;
628 return TRUE;
629 #else /* G_OS_WIN32 */
630 int cl_argc;
631 char **full_argv;
632 gboolean spawned;
633 GError *gerror = NULL;
635 if (command_line)
637 int argc = 0;
638 char **cl_argv;
640 if (!spawn_parse_argv(command_line, &cl_argc, &cl_argv, error))
641 return FALSE;
643 if (argv)
644 for (argc = 0; argv[argc]; argc++);
646 full_argv = g_renew(gchar *, cl_argv, cl_argc + argc + 1);
647 memcpy(full_argv + cl_argc, argv, argc * sizeof(gchar *));
648 full_argv[cl_argc + argc] = NULL;
650 else
651 full_argv = argv;
653 spawned = g_spawn_async_with_pipes(working_directory, full_argv, envp,
654 G_SPAWN_SEARCH_PATH | (child_pid ? G_SPAWN_DO_NOT_REAP_CHILD : 0), NULL, NULL,
655 child_pid, stdin_fd, stdout_fd, stderr_fd, &gerror);
657 if (!spawned)
659 gint en = 0;
660 const gchar *message = gerror->message;
662 /* try to cut glib citing of the program name or working directory: they may be long,
663 and only the caller knows whether they're UTF-8. We lose the exact chdir error. */
664 switch (gerror->code)
666 #ifdef EACCES
667 case G_SPAWN_ERROR_ACCES : en = EACCES; break;
668 #endif
669 #ifdef EPERM
670 case G_SPAWN_ERROR_PERM : en = EPERM; break;
671 #endif
672 #ifdef E2BIG
673 case G_SPAWN_ERROR_TOO_BIG : en = E2BIG; break;
674 #endif
675 #ifdef ENOEXEC
676 case G_SPAWN_ERROR_NOEXEC : en = ENOEXEC; break;
677 #endif
678 #ifdef ENAMETOOLONG
679 case G_SPAWN_ERROR_NAMETOOLONG : en = ENAMETOOLONG; break;
680 #endif
681 #ifdef ENOENT
682 case G_SPAWN_ERROR_NOENT : en = ENOENT; break;
683 #endif
684 #ifdef ENOMEM
685 case G_SPAWN_ERROR_NOMEM : en = ENOMEM; break;
686 #endif
687 #ifdef ENOTDIR
688 case G_SPAWN_ERROR_NOTDIR : en = ENOTDIR; break;
689 #endif
690 #ifdef ELOOP
691 case G_SPAWN_ERROR_LOOP : en = ELOOP; break;
692 #endif
693 #ifdef ETXTBUSY
694 case G_SPAWN_ERROR_TXTBUSY : en = ETXTBUSY; break;
695 #endif
696 #ifdef EIO
697 case G_SPAWN_ERROR_IO : en = EIO; break;
698 #endif
699 #ifdef ENFILE
700 case G_SPAWN_ERROR_NFILE : en = ENFILE; break;
701 #endif
702 #ifdef EMFILE
703 case G_SPAWN_ERROR_MFILE : en = EMFILE; break;
704 #endif
705 #ifdef EINVAL
706 case G_SPAWN_ERROR_INVAL : en = EINVAL; break;
707 #endif
708 #ifdef EISDIR
709 case G_SPAWN_ERROR_ISDIR : en = EISDIR; break;
710 #endif
711 #ifdef ELIBBAD
712 case G_SPAWN_ERROR_LIBBAD : en = ELIBBAD; break;
713 #endif
714 case G_SPAWN_ERROR_CHDIR :
716 message = _("Failed to change to the working directory");
717 break;
719 case G_SPAWN_ERROR_FAILED :
721 message = _("Unknown error executing child process");
722 break;
726 if (en)
727 message = g_strerror(en);
729 g_set_error_literal(error, gerror->domain, gerror->code, message);
730 g_error_free(gerror);
733 if (full_argv != argv)
735 full_argv[cl_argc] = NULL;
736 g_strfreev(full_argv);
739 return spawned;
740 #endif /* G_OS_WIN32 */
745 * Executes a child asynchronously.
747 * A command line or an argument vector must be passed. If both are present, the argument
748 * vector is appended to the command line. An empty command line is not allowed.
750 * If a @a child_pid is passed, it's your responsibility to invoke @c g_spawn_close_pid().
752 * @param working_directory @nullable child's current working directory, or @c NULL.
753 * @param command_line @nullable child program and arguments, or @c NULL.
754 * @param argv @nullable child's argument vector, or @c NULL.
755 * @param envp @nullable child's environment, or @c NULL.
756 * @param child_pid @out @optional return location for child process ID, or @c NULL.
757 * @param error return location for error.
759 * @return @c TRUE on success, @c FALSE on error.
761 * @since 1.25
763 GEANY_API_SYMBOL
764 gboolean spawn_async(const gchar *working_directory, const gchar *command_line, gchar **argv,
765 gchar **envp, GPid *child_pid, GError **error)
767 return spawn_async_with_pipes(working_directory, command_line, argv, envp, child_pid,
768 NULL, NULL, NULL, error);
773 * Spawn with callbacks - general event sequence:
775 * - Launch the child.
776 * - Setup any I/O callbacks and a child watch callback.
777 * - On sync execution, run a main loop.
778 * - Wait for the child to terminate.
779 * - Check for active I/O sources. If any, add a timeout source to watch them, they should
780 * become inactive real soon now that the child is dead. Otherwise, finalize immediately.
781 * - In the timeout source: check for active I/O sources and finalize if none.
784 typedef struct _SpawnChannelData
786 GIOChannel *channel; /* NULL if not created / already destroyed */
787 union
789 GIOFunc write;
790 SpawnReadFunc read;
791 } cb;
792 gpointer cb_data;
793 /* stdout/stderr only */
794 GString *buffer; /* NULL if recursive */
795 GString *line_buffer; /* NULL if char buffered */
796 gsize max_length;
797 } SpawnChannelData;
800 static void spawn_destroy_cb(gpointer data)
802 SpawnChannelData *sc = (SpawnChannelData *) data;
804 g_io_channel_shutdown(sc->channel, FALSE, NULL);
805 sc->channel = NULL;
807 if (sc->buffer)
808 g_string_free(sc->buffer, TRUE);
810 if (sc->line_buffer)
811 g_string_free(sc->line_buffer, TRUE);
815 static gboolean spawn_write_cb(GIOChannel *channel, GIOCondition condition, gpointer data)
817 SpawnChannelData *sc = (SpawnChannelData *) data;
819 if (!sc->cb.write(channel, condition, sc->cb_data))
820 return FALSE;
822 return !(condition & G_IO_FAILURE);
826 static gboolean spawn_read_cb(GIOChannel *channel, GIOCondition condition, gpointer data)
828 SpawnChannelData *sc = (SpawnChannelData *) data;
829 GString *line_buffer = sc->line_buffer;
830 GString *buffer = sc->buffer ? sc->buffer : g_string_sized_new(sc->max_length);
831 GIOCondition input_cond = condition & (G_IO_IN | G_IO_PRI);
832 GIOCondition failure_cond = condition & G_IO_FAILURE;
834 * - Normally, read only once. With IO watches, our data processing must be immediate,
835 * which may give the child time to emit more data, and a read loop may combine it into
836 * large stdout and stderr portions. Under Windows, looping blocks.
837 * - On failure, read in a loop. It won't block now, there will be no more data, and the
838 * IO watch is not guaranteed to be called again (under Windows this is the last call).
840 if (input_cond)
842 gsize chars_read;
843 GIOStatus status;
845 if (line_buffer)
847 gsize n = line_buffer->len;
849 while ((status = g_io_channel_read_chars(channel, line_buffer->str + n,
850 DEFAULT_IO_LENGTH, &chars_read, NULL)) == G_IO_STATUS_NORMAL)
852 g_string_set_size(line_buffer, n + chars_read);
854 while (n < line_buffer->len)
856 gsize line_len = 0;
858 if (n == sc->max_length)
859 line_len = n;
860 else if (strchr("\n", line_buffer->str[n])) /* '\n' or '\0' */
861 line_len = n + 1;
862 else if (n < line_buffer->len - 1 && line_buffer->str[n] == '\r')
863 line_len = n + 1 + (line_buffer->str[n + 1] == '\n');
865 if (!line_len)
866 n++;
867 else
869 g_string_append_len(buffer, line_buffer->str, line_len);
870 g_string_erase(line_buffer, 0, line_len);
871 /* input only, failures are reported separately below */
872 sc->cb.read(buffer, input_cond, sc->cb_data);
873 g_string_truncate(buffer, 0);
874 n = 0;
878 if (!failure_cond)
879 break;
882 else
884 while ((status = g_io_channel_read_chars(channel, buffer->str, sc->max_length,
885 &chars_read, NULL)) == G_IO_STATUS_NORMAL)
887 g_string_set_size(buffer, chars_read);
888 /* input only, failures are reported separately below */
889 sc->cb.read(buffer, input_cond, sc->cb_data);
891 if (!failure_cond)
892 break;
896 /* Under OSX, after child death, the read watches receive input conditions instead
897 of error conditions, so we convert the termination statuses into conditions.
898 Should not hurt the other OS. */
899 if (status == G_IO_STATUS_ERROR)
900 failure_cond |= G_IO_ERR;
901 else if (status == G_IO_STATUS_EOF)
902 failure_cond |= G_IO_HUP;
905 if (failure_cond) /* we must signal the callback */
907 if (line_buffer && line_buffer->len) /* flush the line buffer */
909 g_string_append_len(buffer, line_buffer->str, line_buffer->len);
910 /* all data may be from a previous call */
911 if (!input_cond)
912 input_cond = G_IO_IN;
914 else
916 input_cond = 0;
917 g_string_truncate(buffer, 0);
920 sc->cb.read(buffer, input_cond | failure_cond, sc->cb_data);
923 if (buffer != sc->buffer)
924 g_string_free(buffer, TRUE);
926 return !failure_cond;
930 typedef struct _SpawnWatcherData
932 SpawnChannelData sc[3]; /* stdin, stdout, stderr */
933 GChildWatchFunc exit_cb;
934 gpointer exit_data;
935 GPid pid;
936 gint exit_status;
937 GMainContext *main_context; /* NULL if async execution */
938 GMainLoop *main_loop; /* NULL if async execution */
939 } SpawnWatcherData;
942 static void spawn_finalize(SpawnWatcherData *sw)
944 if (sw->exit_cb)
945 sw->exit_cb(sw->pid, sw->exit_status, sw->exit_data);
947 if (sw->main_loop)
949 g_main_loop_quit(sw->main_loop);
950 g_main_loop_unref(sw->main_loop);
953 g_spawn_close_pid(sw->pid);
954 g_slice_free(SpawnWatcherData, sw);
958 static gboolean spawn_timeout_cb(gpointer data)
960 SpawnWatcherData *sw = (SpawnWatcherData *) data;
961 int i;
963 for (i = 0; i < 3; i++)
964 if (sw->sc[i].channel)
965 return TRUE;
967 spawn_finalize(sw);
968 return FALSE;
972 static void spawn_watch_cb(GPid pid, gint status, gpointer data)
974 SpawnWatcherData *sw = (SpawnWatcherData *) data;
975 int i;
977 sw->pid = pid;
978 sw->exit_status = status;
980 for (i = 0; i < 3; i++)
982 if (sw->sc[i].channel)
984 GSource *source = g_timeout_source_new(50);
986 g_source_set_callback(source, spawn_timeout_cb, data, NULL);
987 g_source_attach(source, sw->main_context);
988 g_source_unref(source);
989 return;
993 spawn_finalize(sw);
997 /** @girskip
998 * Executes a child program and setups callbacks.
1000 * A command line or an argument vector must be passed. If both are present, the argument
1001 * vector is appended to the command line. An empty command line is not allowed.
1003 * The synchronous execution may not be combined with recursive callbacks.
1005 * In line buffered mode, the child input is broken on `\n`, `\r\n`, `\r`, `\0` and max length.
1007 * All I/O callbacks are guaranteed to be invoked at least once with @c G_IO_ERR, @c G_IO_HUP
1008 * or @c G_IO_NVAL set (except for a @a stdin_cb which returns @c FALSE before that). For the
1009 * non-recursive callbacks, this is guaranteed to be the last call, and may be used to free any
1010 * resources associated with the callback.
1012 * The @a stdin_cb may write to @c channel only once per invocation, only if @c G_IO_OUT is
1013 * set, and only a non-zero number of characters.
1015 * @c stdout_cb and @c stderr_cb may modify the received strings in any way, but must not
1016 * free them.
1018 * The default max lengths are 24K for line buffered stdout, 8K for line buffered stderr,
1019 * 4K for unbuffered input under Unix, and 2K for unbuffered input under Windows.
1021 * @c exit_cb is always invoked last, after all I/O callbacks.
1023 * The @a child_pid will be closed automatically, after @a exit_cb is invoked.
1025 * @param working_directory @nullable child's current working directory, or @c NULL.
1026 * @param command_line @nullable child program and arguments, or @c NULL.
1027 * @param argv @nullable child's argument vector, or @c NULL.
1028 * @param envp @nullable child's environment, or @c NULL.
1029 * @param spawn_flags flags from SpawnFlags.
1030 * @param stdin_cb @nullable callback to send data to childs's stdin, or @c NULL.
1031 * @param stdin_data data to pass to @a stdin_cb.
1032 * @param stdout_cb @nullable callback to receive child's stdout, or @c NULL.
1033 * @param stdout_data data to pass to @a stdout_cb.
1034 * @param stdout_max_length maximum data length to pass to stdout_cb, @c 0 = default.
1035 * @param stderr_cb @nullable callback to receive child's stderr, or @c NULL.
1036 * @param stderr_data data to pass to @a stderr_cb.
1037 * @param stderr_max_length maximum data length to pass to stderr_cb, @c 0 = default.
1038 * @param exit_cb @nullable callback to invoke when the child exits, or @c NULL.
1039 * @param exit_data data to pass to @a exit_cb.
1040 * @param child_pid @out @optional return location for child process ID, or @c NULL.
1041 * @param error return location for error.
1043 * @return @c TRUE on success, @c FALSE on error.
1045 * @since 1.25
1047 GEANY_API_SYMBOL
1048 gboolean spawn_with_callbacks(const gchar *working_directory, const gchar *command_line,
1049 gchar **argv, gchar **envp, SpawnFlags spawn_flags, GIOFunc stdin_cb, gpointer stdin_data,
1050 SpawnReadFunc stdout_cb, gpointer stdout_data, gsize stdout_max_length,
1051 SpawnReadFunc stderr_cb, gpointer stderr_data, gsize stderr_max_length,
1052 GChildWatchFunc exit_cb, gpointer exit_data, GPid *child_pid, GError **error)
1054 GPid pid;
1055 int pipe[3] = { -1, -1, -1 };
1057 g_return_val_if_fail(!(spawn_flags & SPAWN_RECURSIVE) || !(spawn_flags & SPAWN_SYNC),
1058 FALSE);
1060 if (spawn_async_with_pipes(working_directory, command_line, argv, envp, &pid,
1061 stdin_cb ? &pipe[0] : NULL, stdout_cb ? &pipe[1] : NULL,
1062 stderr_cb ? &pipe[2] : NULL, error))
1064 SpawnWatcherData *sw = g_slice_new0(SpawnWatcherData);
1065 gpointer cb_data[3] = { stdin_data, stdout_data, stderr_data };
1066 GSource *source;
1067 int i;
1069 sw->main_context = spawn_flags & SPAWN_SYNC ? g_main_context_new() : NULL;
1071 if (child_pid)
1072 *child_pid = pid;
1074 for (i = 0; i < 3; i++)
1076 SpawnChannelData *sc = &sw->sc[i];
1077 GIOCondition condition;
1078 GSourceFunc callback;
1080 if (pipe[i] == -1)
1081 continue;
1083 #ifdef G_OS_WIN32
1084 sc->channel = g_io_channel_win32_new_fd(pipe[i]);
1085 #else
1086 sc->channel = g_io_channel_unix_new(pipe[i]);
1087 g_io_channel_set_flags(sc->channel, G_IO_FLAG_NONBLOCK, NULL);
1088 #endif
1089 g_io_channel_set_encoding(sc->channel, NULL, NULL);
1090 /* we have our own buffers, and GIO buffering blocks under Windows */
1091 g_io_channel_set_buffered(sc->channel, FALSE);
1092 sc->cb_data = cb_data[i];
1094 if (i == 0)
1096 sc->cb.write = stdin_cb;
1097 condition = G_IO_OUT | G_IO_FAILURE;
1098 callback = (GSourceFunc) spawn_write_cb;
1100 else
1102 gboolean line_buffered = !(spawn_flags &
1103 ((SPAWN_STDOUT_UNBUFFERED >> 1) << i));
1105 condition = G_IO_IN | G_IO_PRI | G_IO_FAILURE;
1106 callback = (GSourceFunc) spawn_read_cb;
1108 if (i == 1)
1110 sc->cb.read = stdout_cb;
1111 sc->max_length = stdout_max_length ? stdout_max_length :
1112 line_buffered ? 24576 : DEFAULT_IO_LENGTH;
1114 else
1116 sc->cb.read = stderr_cb;
1117 sc->max_length = stderr_max_length ? stderr_max_length :
1118 line_buffered ? 8192 : DEFAULT_IO_LENGTH;
1121 if (line_buffered)
1123 sc->line_buffer = g_string_sized_new(sc->max_length +
1124 DEFAULT_IO_LENGTH);
1128 source = g_io_create_watch(sc->channel, condition);
1129 g_io_channel_unref(sc->channel);
1131 if (spawn_flags & (SPAWN_STDIN_RECURSIVE << i))
1132 g_source_set_can_recurse(source, TRUE);
1133 else if (i) /* to avoid new string on each call */
1134 sc->buffer = g_string_sized_new(sc->max_length);
1136 g_source_set_callback(source, callback, sc, spawn_destroy_cb);
1137 g_source_attach(source, sw->main_context);
1138 g_source_unref(source);
1141 sw->exit_cb = exit_cb;
1142 sw->exit_data = exit_data;
1143 source = g_child_watch_source_new(pid);
1144 g_source_set_callback(source, (GSourceFunc) spawn_watch_cb, sw, NULL);
1145 g_source_attach(source, sw->main_context);
1146 g_source_unref(source);
1148 if (spawn_flags & SPAWN_SYNC)
1150 sw->main_loop = g_main_loop_new(sw->main_context, FALSE);
1151 g_main_context_unref(sw->main_context);
1152 g_main_loop_run(sw->main_loop);
1155 return TRUE;
1158 return FALSE;
1163 * Writes (a portion of) the data pointed by @a data->ptr to the @a channel.
1165 * If @c G_IO_OUT in @a condition is set, and the @a data->size is > 0, attempts to write
1166 * @a data->ptr (or a portion of it, depending on the size) to the @a channel. On success,
1167 * increases ptr and decreases size with the number of characters written.
1169 * This function may converted to @c GIOFunc and passed to @c spawn_with_callbacks() as
1170 * @c stdin_cb, together with a @c SpawnWriteData for @c stdin_data. As with any other
1171 * callback data, make sure that @c stdin_data exists while the child is being executed.
1172 * (For example, on asynchronous execution, you can allocate the data in the heap, and free
1173 * it in your @c spawn_with_callbacks() @c exit_cb callback.)
1175 * @param channel the channel to write data to.
1176 * @param condition condition to check for @c G_IO_OUT.
1177 * @param data @c SpawnWriteData to write to @a channel.
1179 * @return @c TRUE if the remaining size is > 0 and @a condition does not indicate any error,
1180 * @c FALSE otherwise.
1182 * @since 1.25
1184 GEANY_API_SYMBOL
1185 gboolean spawn_write_data(GIOChannel *channel, GIOCondition condition, SpawnWriteData *data)
1187 if ((condition & G_IO_OUT) && data->size)
1189 gsize chars_written = 0;
1191 g_io_channel_write_chars(channel, data->ptr, data->size < DEFAULT_IO_LENGTH ?
1192 data->size : DEFAULT_IO_LENGTH, &chars_written, NULL);
1194 /* "This can be nonzero even if the return value is not G_IO_STATUS_NORMAL." */
1195 if (chars_written)
1197 data->ptr += chars_written;
1198 data->size -= chars_written;
1202 return data->size > 0 && !(condition & G_IO_FAILURE);
1206 static void spawn_append_gstring_cb(GString *string, GIOCondition condition, gpointer data)
1208 if (condition & (G_IO_IN | G_IO_PRI))
1209 g_string_append_len((GString *) data, string->str, string->len);
1213 static void spawn_get_exit_status_cb(G_GNUC_UNUSED GPid pid, gint status, gpointer exit_status)
1215 *(gint *) exit_status = status;
1220 * Executes a child synchronously.
1222 * A command line or an argument vector must be passed. If both are present, the argument
1223 * vector is appended to the command line. An empty command line is not allowed.
1225 * The @a stdin_data is sent to the child with @c spawn_write_data().
1227 * All output from the child, including the nul characters, is stored in @a stdout_data and
1228 * @a stderr_data (if non-NULL). Any existing data in these strings will be erased.
1230 * @param working_directory @nullable child's current working directory, or @c NULL.
1231 * @param command_line @nullable child program and arguments, or @c NULL.
1232 * @param argv @nullable child's argument vector, or @c NULL.
1233 * @param envp @nullable child's environment, or @c NULL.
1234 * @param stdin_data @nullable data to send to childs's stdin, or @c NULL.
1235 * @param stdout_data @nullable GString location to receive the child's stdout, or @c NULL.
1236 * @param stderr_data @nullable GString location to receive the child's stderr, or @c NULL.
1237 * @param exit_status @out @optional return location for the child exit code, or @c NULL.
1238 * @param error return location for error.
1240 * @return @c TRUE on success, @c FALSE on error.
1242 * @since 1.25
1244 GEANY_API_SYMBOL
1245 gboolean spawn_sync(const gchar *working_directory, const gchar *command_line, gchar **argv,
1246 gchar **envp, SpawnWriteData *stdin_data, GString *stdout_data, GString *stderr_data,
1247 gint *exit_status, GError **error)
1249 if (stdout_data)
1250 g_string_truncate(stdout_data, 0);
1251 if (stderr_data)
1252 g_string_truncate(stderr_data, 0);
1254 return spawn_with_callbacks(working_directory, command_line, argv, envp, SPAWN_SYNC |
1255 SPAWN_UNBUFFERED, stdin_data ? (GIOFunc) spawn_write_data : NULL, stdin_data,
1256 stdout_data ? spawn_append_gstring_cb : NULL, stdout_data, 0,
1257 stderr_data ? spawn_append_gstring_cb : NULL, stderr_data, 0,
1258 exit_status ? spawn_get_exit_status_cb : NULL, exit_status, NULL, error);
1262 /* tests, not part of the API */
1263 #ifdef SPAWN_TEST
1264 #include <stdio.h>
1267 static gboolean read_line(const char *prompt, char *buffer, size_t size)
1269 fputs(prompt, stderr);
1270 *buffer = '\0';
1272 if (fgets(buffer, size, stdin))
1274 char *s = strchr(buffer, '\n');
1276 if (s)
1277 *s = '\0';
1280 return *buffer;
1284 static GString *read_string(const char *prompt)
1286 char buffer[0x1000]; /* larger portions for spawn < file */
1287 GString *string = g_string_sized_new(sizeof buffer);
1289 while (read_line(prompt, buffer, sizeof buffer))
1291 if (string->len)
1292 g_string_append_c(string, '\n');
1294 g_string_append(string, buffer);
1297 if (!string->len)
1299 g_string_free(string, TRUE);
1300 string = NULL;
1303 return string;
1307 static void print_cb(GString *string, GIOCondition condition, gpointer data)
1309 if (condition & (G_IO_IN | G_IO_PRI))
1311 gsize i;
1313 printf("%s: ", (const gchar *) data);
1314 /*fputs(string->str, stdout);*/
1315 for (i = 0; i < string->len; i++)
1317 unsigned char c = (unsigned char) string->str[i];
1318 printf(c >= ' ' && c < 0x80 ? "%c" : "\\x%02x", c);
1320 putchar('\n');
1325 static void print_status(gint status)
1327 fputs("finished, ", stderr);
1329 if (SPAWN_WIFEXITED(status))
1330 fprintf(stderr, "exit code %d\n", SPAWN_WEXITSTATUS(status));
1331 else
1332 fputs("abnormal termination\n", stderr);
1336 static void exit_cb(GPid pid, gint status, G_GNUC_UNUSED gpointer data)
1338 fprintf(stderr, "process %u ", (guint) pid);
1339 print_status(status);
1343 static void watch_cb(GPid pid, gint status, gpointer data)
1345 g_spawn_close_pid(pid);
1346 exit_cb(pid, status, NULL);
1347 g_main_loop_quit((GMainLoop *) data);
1351 int main(int argc, char **argv)
1353 char *test_type;
1355 if (argc != 2)
1357 fputs("usage: spawn <test-type>\n", stderr);
1358 return 1;
1361 test_type = argv[1];
1363 if (!strcmp(test_type, "syntax") || !strcmp(test_type, "syntexec"))
1365 char command_line[0x100];
1367 while (read_line("command line: ", command_line, sizeof command_line))
1369 GError *error = NULL;
1371 if (spawn_check_command(command_line, argv[1][4] == 'e', &error))
1372 fputs("valid\n", stderr);
1373 else
1375 fprintf(stderr, "error: %s\n", error->message);
1376 g_error_free(error);
1380 else if (!strcmp(test_type, "execute"))
1382 char command_line[0x100];
1384 while (read_line("command line: ", command_line, sizeof command_line))
1386 char working_directory[0x100];
1387 char args[4][0x100];
1388 char envs[4][0x100];
1389 char *argv[] = { args[0], args[1], args[2], args[3], NULL };
1390 char *envp[] = { envs[0], envs[1], envs[2], envs[3], NULL };
1391 int i;
1392 GPid pid;
1393 GError *error = NULL;
1395 read_line("working directory: ", working_directory, sizeof working_directory);
1397 fputs("up to 4 arguments\n", stderr);
1398 for (i = 0; i < 4 && read_line("argument: ", args[i], sizeof args[i]); i++);
1399 argv[i] = NULL;
1401 fputs("up to 4 variables, or empty line for parent environment\n", stderr);
1402 for (i = 0; i < 4 && read_line("variable: ", envs[i], sizeof envs[i]); i++);
1403 envp[i] = NULL;
1405 if (spawn_async_with_pipes(*working_directory ? working_directory : NULL,
1406 *command_line ? command_line : NULL, argv, i ? envp : NULL, &pid, NULL,
1407 NULL, NULL, &error))
1409 GMainLoop *loop = g_main_loop_new(NULL, TRUE);
1411 g_child_watch_add(pid, watch_cb, loop);
1412 g_main_loop_run(loop);
1413 g_main_loop_unref(loop);
1415 else
1417 fprintf(stderr, "error: %s\n", error->message);
1418 g_error_free(error);
1422 else if (!strcmp(test_type, "redirect") || !strcmp(test_type, "redinput"))
1424 char command_line[0x100];
1425 gboolean output = test_type[4] == 'r';
1427 while (read_line("command line: ", command_line, sizeof command_line))
1429 GString *stdin_text = read_string("text to send: ");
1430 SpawnWriteData stdin_data;
1431 GError *error = NULL;
1433 if (stdin_text)
1435 stdin_data.ptr = stdin_text->str;
1436 stdin_data.size = stdin_text->len;
1439 if (!spawn_with_callbacks(NULL, command_line, NULL, NULL, SPAWN_SYNC,
1440 stdin_text ? (GIOFunc) spawn_write_data : NULL, &stdin_data,
1441 output ? print_cb : NULL, "stdout", 0, output ? print_cb : NULL,
1442 "stderr", 0, exit_cb, NULL, NULL, &error))
1444 fprintf(stderr, "error: %s\n", error->message);
1445 g_error_free(error);
1448 if (stdin_text)
1449 g_string_free(stdin_text, TRUE);
1452 else if (!strcmp(test_type, "capture"))
1454 char command_line[0x100];
1456 while (read_line("command line: ", command_line, sizeof command_line))
1458 GString *stdin_text = read_string("text to send: ");
1459 SpawnWriteData stdin_data = { NULL, 0 };
1460 GString *stdout_data = g_string_sized_new(0x10000); /* may grow */
1461 GString *stderr_data = g_string_sized_new(0x1000); /* may grow */
1462 gint exit_status;
1463 GError *error = NULL;
1465 if (stdin_text)
1467 stdin_data.ptr = stdin_text->str;
1468 stdin_data.size = stdin_text->len;
1471 if (spawn_sync(NULL, command_line, NULL, NULL, &stdin_data, stdout_data,
1472 stderr_data, &exit_status, &error))
1474 printf("stdout: %s\n", stdout_data->str);
1475 printf("stderr: %s\n", stderr_data->str);
1476 print_status(exit_status);
1478 else
1480 fprintf(stderr, "error: %s\n", error->message);
1481 g_error_free(error);
1484 if (stdin_text)
1485 g_string_free(stdin_text, TRUE);
1487 g_string_free(stdout_data, TRUE);
1488 g_string_free(stderr_data, TRUE);
1491 else
1493 fprintf(stderr, "spawn: unknown test type '%s'", argv[1]);
1494 return 1;
1497 return 0;
1499 #endif /* SPAWN_TEST */