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 
41 static void
run_tests(const gchar * argv0)42 run_tests (const gchar* argv0)
43 {
44   GError *err = NULL;
45   gchar *output = NULL;
46   gchar *erroutput = NULL;
47   gchar *dirname = g_path_get_dirname (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 (dirname);
56 
57   err = NULL;
58   if (!g_spawn_command_line_sync ("nonexistent_application foo 'bar baz' blah blah",
59                                   NULL, NULL, NULL,
60                                   &err))
61     {
62       g_error_free (err);
63     }
64   else
65     {
66       g_warning ("no error for sync spawn of nonexistent application");
67       exit (1);
68     }
69 
70   err = NULL;
71   if (!g_spawn_command_line_async ("nonexistent_application foo bar baz \"blah blah\"",
72                                    &err))
73     {
74       g_error_free (err);
75     }
76   else
77     {
78       g_warning ("no error for async spawn of nonexistent application");
79       exit (1);
80     }
81 
82   err = NULL;
83 #ifdef G_OS_UNIX
84   if (!g_spawn_command_line_sync ("/bin/sh -c 'echo hello'",
85                                   &output, NULL, NULL,
86                                   &err))
87     {
88       fprintf (stderr, "Error: %s\n", err->message);
89       g_error_free (err);
90       exit (1);
91     }
92   else
93     {
94       g_assert (output != NULL);
95 
96       if (strcmp (output, "hello\n") != 0)
97         {
98           printf ("output was '%s', should have been 'hello'\n",
99                   output);
100 
101           exit (1);
102         }
103 
104       g_free (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 ("spawn-test-created-file.txt", "line first\nline 2\nline last\n", -1, &err);
112   g_assert_no_error(err);
113   if (!g_spawn_command_line_sync ("sort spawn-test-created-file.txt",
114                                   &output, &erroutput, NULL,
115                                   &err))
116     {
117       fprintf (stderr, "Error: %s\n", err->message);
118       g_error_free (err);
119       exit (1);
120     }
121   else
122     {
123       g_assert (output != NULL);
124       g_assert (erroutput != NULL);
125 
126       if (strstr (output, "\nline first") == 0)
127         {
128           printf ("output was '%s', should have contained 'line first' in second line\n",
129                   output);
130 
131           exit (1);
132         }
133       if (erroutput[0] != '\0')
134 	{
135 	  printf ("error output was '%s', should have been empty\n",
136 		  erroutput);
137 	  exit (1);
138 	}
139 
140       g_free (output);
141       output = NULL;
142       g_free (erroutput);
143       erroutput = NULL;
144       g_unlink ("spawn-test-created-file.txt");
145     }
146 
147   if (!g_spawn_command_line_sync ("sort non-existing-file.txt",
148                                   NULL, &erroutput, NULL,
149                                   &err))
150     {
151       fprintf (stderr, "Error: %s\n", err->message);
152       g_error_free (err);
153       exit (1);
154     }
155   else
156     {
157       g_assert (erroutput != NULL);
158 
159       if (erroutput[0] == '\0')
160         {
161           printf ("erroutput was empty, expected contain error message about non-existing-file.txt\n");
162           exit (1);
163         }
164       g_free (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 
345 int
main(int argc,char * argv[])346 main (int   argc,
347       char *argv[])
348 {
349   run_tests (argv[0]);
350 
351   return 0;
352 }
353