1#include <gio/gio.h>
2#include <string.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <errno.h>
6#ifdef G_OS_UNIX
7#include <unistd.h>
8#include <gio/gunixinputstream.h>
9#include <gio/gunixoutputstream.h>
10#else
11#include <io.h>
12#endif
13
14static GOptionEntry options[] = {
15 {NULL}
16};
17
18static void
19write_all (int fd,
20 const guint8* buf,
21 gsize len)
22{
23 while (len > 0)
24 {
25 gssize bytes_written = write (fd: fd, buf: buf, n: len);
26 int errsv = errno;
27 if (bytes_written < 0)
28 g_error ("Failed to write to fd %d: %s",
29 fd, g_strerror (errsv));
30 buf += bytes_written;
31 len -= bytes_written;
32 }
33}
34
35static int
36echo_mode (int argc,
37 char **argv)
38{
39 int i;
40
41 for (i = 2; i < argc; i++)
42 {
43 write_all (fd: 1, buf: (guint8*)argv[i], len: strlen (s: argv[i]));
44 write_all (fd: 1, buf: (guint8*)"\n", len: 1);
45 }
46
47 return 0;
48}
49
50static int
51echo_stdout_and_stderr_mode (int argc,
52 char **argv)
53{
54 int i;
55
56 for (i = 2; i < argc; i++)
57 {
58 write_all (fd: 1, buf: (guint8*)argv[i], len: strlen (s: argv[i]));
59 write_all (fd: 1, buf: (guint8*)"\n", len: 1);
60 write_all (fd: 2, buf: (guint8*)argv[i], len: strlen (s: argv[i]));
61 write_all (fd: 2, buf: (guint8*)"\n", len: 1);
62 }
63
64 return 0;
65}
66
67static int
68cat_mode (int argc,
69 char **argv)
70{
71 GIOChannel *chan_stdin;
72 GIOChannel *chan_stdout;
73 GIOStatus status;
74 char buf[1024];
75 gsize bytes_read, bytes_written;
76 GError *local_error = NULL;
77 GError **error = &local_error;
78
79 chan_stdin = g_io_channel_unix_new (fd: 0);
80 g_io_channel_set_encoding (channel: chan_stdin, NULL, error);
81 g_assert_no_error (local_error);
82 chan_stdout = g_io_channel_unix_new (fd: 1);
83 g_io_channel_set_encoding (channel: chan_stdout, NULL, error);
84 g_assert_no_error (local_error);
85
86 while (TRUE)
87 {
88 do
89 status = g_io_channel_read_chars (channel: chan_stdin, buf, count: sizeof (buf),
90 bytes_read: &bytes_read, error);
91 while (status == G_IO_STATUS_AGAIN);
92
93 if (status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
94 break;
95
96 do
97 status = g_io_channel_write_chars (channel: chan_stdout, buf, count: bytes_read,
98 bytes_written: &bytes_written, error);
99 while (status == G_IO_STATUS_AGAIN);
100
101 if (status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
102 break;
103 }
104
105 g_io_channel_unref (channel: chan_stdin);
106 g_io_channel_unref (channel: chan_stdout);
107
108 if (local_error)
109 {
110 g_printerr (format: "I/O error: %s\n", local_error->message);
111 g_clear_error (err: &local_error);
112 return 1;
113 }
114 return 0;
115}
116
117static gint
118sleep_forever_mode (int argc,
119 char **argv)
120{
121 GMainLoop *loop;
122
123 loop = g_main_loop_new (NULL, TRUE);
124 g_main_loop_run (loop);
125
126 return 0;
127}
128
129static int
130write_to_fds (int argc, char **argv)
131{
132 int i;
133
134 for (i = 2; i < argc; i++)
135 {
136 int fd = atoi (nptr: argv[i]);
137 FILE *f = fdopen (fd: fd, modes: "w");
138 const char buf[] = "hello world\n";
139 size_t bytes_written;
140
141 g_assert (f != NULL);
142
143 bytes_written = fwrite (ptr: buf, size: 1, n: sizeof (buf), s: f);
144 g_assert (bytes_written == sizeof (buf));
145
146 if (fclose (stream: f) == -1)
147 g_assert_not_reached ();
148 }
149
150 return 0;
151}
152
153static int
154env_mode (int argc, char **argv)
155{
156 char **env;
157 int i;
158
159 env = g_get_environ ();
160
161 for (i = 0; env[i]; i++)
162 g_print (format: "%s\n", env[i]);
163
164 g_strfreev (str_array: env);
165
166 return 0;
167}
168
169static int
170cwd_mode (int argc, char **argv)
171{
172 char *cwd;
173
174 cwd = g_get_current_dir ();
175 g_print (format: "%s\n", cwd);
176 g_free (mem: cwd);
177
178 return 0;
179}
180
181static int
182printenv_mode (int argc, char **argv)
183{
184 gint i;
185
186 for (i = 2; i < argc; i++)
187 {
188 const gchar *value = g_getenv (variable: argv[i]);
189
190 if (value != NULL)
191 g_print (format: "%s=%s\n", argv[i], value);
192 }
193
194 return 0;
195}
196
197int
198main (int argc, char **argv)
199{
200 GOptionContext *context;
201 GError *error = NULL;
202 const char *mode;
203 gboolean ret;
204
205 context = g_option_context_new (parameter_string: "MODE - Test GSubprocess stuff");
206 g_option_context_add_main_entries (context, entries: options, NULL);
207 ret = g_option_context_parse (context, argc: &argc, argv: &argv, error: &error);
208 g_option_context_free (context);
209
210 if (!ret)
211 {
212 g_printerr (format: "%s: %s\n", argv[0], error->message);
213 g_error_free (error);
214 return 1;
215 }
216
217 if (argc < 2)
218 {
219 g_printerr (format: "MODE argument required\n");
220 return 1;
221 }
222
223 mode = argv[1];
224 if (strcmp (s1: mode, s2: "noop") == 0)
225 return 0;
226 else if (strcmp (s1: mode, s2: "exit1") == 0)
227 return 1;
228 else if (strcmp (s1: mode, s2: "assert-argv0") == 0)
229 {
230 if (strcmp (s1: argv[0], s2: "moocow") == 0)
231 return 0;
232 g_printerr (format: "argv0=%s != moocow\n", argv[0]);
233 return 1;
234 }
235 else if (strcmp (s1: mode, s2: "echo") == 0)
236 return echo_mode (argc, argv);
237 else if (strcmp (s1: mode, s2: "echo-stdout-and-stderr") == 0)
238 return echo_stdout_and_stderr_mode (argc, argv);
239 else if (strcmp (s1: mode, s2: "cat") == 0)
240 return cat_mode (argc, argv);
241 else if (strcmp (s1: mode, s2: "sleep-forever") == 0)
242 return sleep_forever_mode (argc, argv);
243 else if (strcmp (s1: mode, s2: "write-to-fds") == 0)
244 return write_to_fds (argc, argv);
245 else if (strcmp (s1: mode, s2: "env") == 0)
246 return env_mode (argc, argv);
247 else if (strcmp (s1: mode, s2: "cwd") == 0)
248 return cwd_mode (argc, argv);
249 else if (strcmp (s1: mode, s2: "printenv") == 0)
250 return printenv_mode (argc, argv);
251 else
252 {
253 g_printerr (format: "Unknown MODE %s\n", argv[1]);
254 return 1;
255 }
256
257 return TRUE;
258}
259

source code of gtk/subprojects/glib/gio/tests/gsubprocess-testprog.c