1/* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GLib Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GLib at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25#undef G_DISABLE_ASSERT
26#undef G_LOG_DOMAIN
27
28#include <glib.h>
29#include <glib/gstdio.h>
30#include <stdio.h>
31#include <string.h>
32#include <stdlib.h>
33
34#ifdef G_OS_WIN32
35#include <fcntl.h>
36#include <io.h>
37#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
38#endif
39
40
41static void
42run_tests (const gchar* argv0)
43{
44 GError *err = NULL;
45 gchar *output = NULL;
46 gchar *erroutput = NULL;
47 gchar *dirname = g_path_get_dirname (file_name: argv0);
48#ifdef G_OS_WIN32
49 int pipedown[2], pipeup[2];
50 gchar **argv = 0;
51 gchar spawn_binary[1000] = {0};
52 gchar full_cmdline[1000] = {0};
53 g_snprintf (spawn_binary, sizeof (spawn_binary), "%s\\spawn-test-win32-gui.exe", dirname);
54#endif
55 g_free (mem: dirname);
56
57 err = NULL;
58 if (!g_spawn_command_line_sync (command_line: "nonexistent_application foo 'bar baz' blah blah",
59 NULL, NULL, NULL,
60 error: &err))
61 {
62 g_error_free (error: err);
63 }
64 else
65 {
66 g_warning ("no error for sync spawn of nonexistent application");
67 exit (status: 1);
68 }
69
70 err = NULL;
71 if (!g_spawn_command_line_async (command_line: "nonexistent_application foo bar baz \"blah blah\"",
72 error: &err))
73 {
74 g_error_free (error: err);
75 }
76 else
77 {
78 g_warning ("no error for async spawn of nonexistent application");
79 exit (status: 1);
80 }
81
82 err = NULL;
83#ifdef G_OS_UNIX
84 if (!g_spawn_command_line_sync (command_line: "/bin/sh -c 'echo hello'",
85 standard_output: &output, NULL, NULL,
86 error: &err))
87 {
88 fprintf (stderr, format: "Error: %s\n", err->message);
89 g_error_free (error: err);
90 exit (status: 1);
91 }
92 else
93 {
94 g_assert (output != NULL);
95
96 if (strcmp (s1: output, s2: "hello\n") != 0)
97 {
98 printf (format: "output was '%s', should have been 'hello'\n",
99 output);
100
101 exit (status: 1);
102 }
103
104 g_free (mem: output);
105 output = NULL;
106 }
107#endif
108 /* Running sort synchronously, collecting its output. 'sort' command is selected
109 * because it is non-builtin command on both unix and win32 with well-defined stdout behaviour.
110 */
111 g_file_set_contents (filename: "spawn-test-created-file.txt", contents: "line first\nline 2\nline last\n", length: -1, error: &err);
112 g_assert_no_error(err);
113 if (!g_spawn_command_line_sync (command_line: "sort spawn-test-created-file.txt",
114 standard_output: &output, standard_error: &erroutput, NULL,
115 error: &err))
116 {
117 fprintf (stderr, format: "Error: %s\n", err->message);
118 g_error_free (error: err);
119 exit (status: 1);
120 }
121 else
122 {
123 g_assert (output != NULL);
124 g_assert (erroutput != NULL);
125
126 if (strstr (haystack: output, needle: "\nline first") == 0)
127 {
128 printf (format: "output was '%s', should have contained 'line first' in second line\n",
129 output);
130
131 exit (status: 1);
132 }
133 if (erroutput[0] != '\0')
134 {
135 printf (format: "error output was '%s', should have been empty\n",
136 erroutput);
137 exit (status: 1);
138 }
139
140 g_free (mem: output);
141 output = NULL;
142 g_free (mem: erroutput);
143 erroutput = NULL;
144 g_unlink (filename: "spawn-test-created-file.txt");
145 }
146
147 if (!g_spawn_command_line_sync (command_line: "sort non-existing-file.txt",
148 NULL, standard_error: &erroutput, NULL,
149 error: &err))
150 {
151 fprintf (stderr, format: "Error: %s\n", err->message);
152 g_error_free (error: err);
153 exit (status: 1);
154 }
155 else
156 {
157 g_assert (erroutput != NULL);
158
159 if (erroutput[0] == '\0')
160 {
161 printf (format: "erroutput was empty, expected contain error message about non-existing-file.txt\n");
162 exit (status: 1);
163 }
164 g_free (mem: erroutput);
165 erroutput = NULL;
166 }
167
168#ifdef G_OS_WIN32
169 printf ("Running spawn-test-win32-gui in various ways.\n");
170
171 printf ("First asynchronously (without wait).\n");
172 g_snprintf (full_cmdline, sizeof (full_cmdline), "'%s' 1", spawn_binary);
173 if (!g_spawn_command_line_async (full_cmdline, &err))
174 {
175 fprintf (stderr, "Error: %s\n", err->message);
176 g_error_free (err);
177 exit (1);
178 }
179
180 printf ("Now synchronously, collecting its output.\n");
181 g_snprintf (full_cmdline, sizeof (full_cmdline), "'%s' 2", spawn_binary);
182 if (!g_spawn_command_line_sync (full_cmdline,
183 &output, &erroutput, NULL,
184 &err))
185 {
186 fprintf (stderr, "Error: %s\n", err->message);
187 g_error_free (err);
188 exit (1);
189 }
190 else
191 {
192 g_assert (output != NULL);
193 g_assert (erroutput != NULL);
194
195 if (strcmp (output, "This is stdout\r\n") != 0)
196 {
197 printf ("output was '%s', should have been 'This is stdout'\n",
198 g_strescape (output, NULL));
199
200 exit (1);
201 }
202 if (strcmp (erroutput, "This is stderr\r\n") != 0)
203 {
204 printf ("error output was '%s', should have been 'This is stderr'\n",
205 g_strescape (erroutput, NULL));
206 exit (1);
207 }
208
209 g_free (output);
210 output = NULL;
211 g_free (erroutput);
212 erroutput = NULL;
213 }
214
215 printf ("Now with G_SPAWN_FILE_AND_ARGV_ZERO.\n");
216 g_snprintf (full_cmdline, sizeof (full_cmdline), "'%s' this-should-be-argv-zero print_argv0", spawn_binary);
217 if (!g_shell_parse_argv (full_cmdline, NULL, &argv, &err))
218 {
219 fprintf (stderr, "Error parsing command line? %s\n", err->message);
220 g_error_free (err);
221 exit (1);
222 }
223
224 if (!g_spawn_sync (NULL, argv, NULL,
225 G_SPAWN_FILE_AND_ARGV_ZERO,
226 NULL, NULL, &output, NULL, NULL,
227 &err))
228 {
229 fprintf (stderr, "Error: %s\n", err->message);
230 g_error_free (err);
231 exit (1);
232 }
233 else
234 {
235 if (strcmp (output, "this-should-be-argv-zero") != 0)
236 {
237 printf ("output was '%s', should have been 'this-should-be-argv-zero'\n", output);
238 exit (1);
239 }
240 g_free (output);
241 output = NULL;
242 }
243
244 printf ("Now talking to it through pipes.\n");
245
246 if (pipe (pipedown) < 0 ||
247 pipe (pipeup) < 0)
248 {
249 fprintf (stderr, "Could not create pipes\n");
250 exit (1);
251 }
252
253 g_snprintf (full_cmdline, sizeof (full_cmdline), "'%s' pipes %d %d", spawn_binary, pipedown[0], pipeup[1]);
254 if (!g_shell_parse_argv (full_cmdline,
255 NULL, &argv,
256 &err))
257 {
258 fprintf (stderr, "Error parsing command line? %s\n", err->message);
259 g_error_free (err);
260 exit (1);
261 }
262
263 if (!g_spawn_async (NULL, argv, NULL,
264 G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
265 G_SPAWN_DO_NOT_REAP_CHILD,
266 NULL, NULL, NULL,
267 &err))
268 {
269 fprintf (stderr, "Error: %s\n", err->message);
270 g_error_free (err);
271 exit (1);
272 }
273 else
274 {
275 int k, n;
276 char buf[100];
277
278 if ((k = read (pipeup[0], &n, sizeof (n))) != sizeof (n))
279 {
280 int errsv = errno;
281 if (k == -1)
282 fprintf (stderr, "Read error: %s\n", g_strerror (errsv));
283 else
284 fprintf (stderr, "Wanted to read %d bytes, got %d\n",
285 (int)sizeof (n), k);
286 exit (1);
287 }
288
289 if ((k = read (pipeup[0], buf, n)) != n)
290 {
291 int errsv = errno;
292 if (k == -1)
293 fprintf (stderr, "Read error: %s\n", g_strerror (errsv));
294 else
295 fprintf (stderr, "Wanted to read %d bytes, got %d\n",
296 n, k);
297 exit (1);
298 }
299
300 n = strlen ("Bye then");
301 if (write (pipedown[1], &n, sizeof (n)) == -1 ||
302 write (pipedown[1], "Bye then", n) == -1)
303 {
304 int errsv = errno;
305 fprintf (stderr, "Write error: %s\n", g_strerror (errsv));
306 exit (1);
307 }
308
309 if ((k = read (pipeup[0], &n, sizeof (n))) != sizeof (n))
310 {
311 int errsv = errno;
312 if (k == -1)
313 fprintf (stderr, "Read error: %s\n", g_strerror (errsv));
314 else
315 fprintf (stderr, "Wanted to read %d bytes, got %d\n",
316 (int)sizeof (n), k);
317 exit (1);
318 }
319 if (n != strlen ("See ya"))
320 {
321 printf ("child wrote %d bytes, expected %d", n, (int) strlen ("See ya"));
322 exit (1);
323 }
324
325 if ((k = read (pipeup[0], buf, n)) != n)
326 {
327 int errsv = errno;
328 if (k == -1)
329 fprintf (stderr, "Read error: %s\n", g_strerror (errsv));
330 else
331 fprintf (stderr, "Wanted to read %d bytes, got %d\n",
332 n, k);
333 exit (1);
334 }
335 buf[n] = '\0';
336 if (strcmp (buf, "See ya") != 0)
337 {
338 printf ("output was '%s', should have been 'See ya'\n", buf);
339 exit (1);
340 }
341 }
342#endif
343}
344
345int
346main (int argc,
347 char *argv[])
348{
349 run_tests (argv0: argv[0]);
350
351 return 0;
352}
353

source code of gtk/subprojects/glib/tests/spawn-test.c