diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-02-16 14:02:23 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-02-16 14:02:23 +0000 |
commit | 17c88acd603c4f8ee1805c0db851cc9ce112f75f (patch) | |
tree | 5dc387f78a67ccffed8d546124ece2702fd1265e | |
parent | aee82888eabdaee16aa78529f78361afcf8b2b01 (diff) | |
download | gnunet-17c88acd603c4f8ee1805c0db851cc9ce112f75f.tar.gz gnunet-17c88acd603c4f8ee1805c0db851cc9ce112f75f.zip |
actually add test case, and added proper stdin support to os_start_process function...
-rw-r--r-- | src/util/os_priority.c | 21 | ||||
-rw-r--r-- | src/util/test_os_start_process.c | 114 |
2 files changed, 130 insertions, 5 deletions
diff --git a/src/util/os_priority.c b/src/util/os_priority.c index 26c76483c..4c9a449b1 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c | |||
@@ -127,7 +127,6 @@ pid_t | |||
127 | GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, const char *filename, ...) | 127 | GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, const char *filename, ...) |
128 | { | 128 | { |
129 | /* FIXME: Make this work on windows!!! */ | 129 | /* FIXME: Make this work on windows!!! */ |
130 | /* FIXME: Make this work with stdin as well as stdout! */ | ||
131 | va_list ap; | 130 | va_list ap; |
132 | 131 | ||
133 | #ifndef MINGW | 132 | #ifndef MINGW |
@@ -135,7 +134,9 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNE | |||
135 | char **argv; | 134 | char **argv; |
136 | int argc; | 135 | int argc; |
137 | int fd_stdout_write; | 136 | int fd_stdout_write; |
137 | int fd_stdout_read; | ||
138 | int fd_stdin_read; | 138 | int fd_stdin_read; |
139 | int fd_stdin_write; | ||
139 | 140 | ||
140 | argc = 0; | 141 | argc = 0; |
141 | va_start (ap, filename); | 142 | va_start (ap, filename); |
@@ -149,9 +150,15 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNE | |||
149 | argc++; | 150 | argc++; |
150 | va_end (ap); | 151 | va_end (ap); |
151 | if (pipe_stdout != NULL) | 152 | if (pipe_stdout != NULL) |
152 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), &fd_stdout_write, sizeof (int)); | 153 | { |
154 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), &fd_stdout_write, sizeof (int)); | ||
155 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_READ), &fd_stdout_read, sizeof (int)); | ||
156 | } | ||
153 | if (pipe_stdin != NULL) | 157 | if (pipe_stdin != NULL) |
154 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_READ), &fd_stdin_read, sizeof (int)); | 158 | { |
159 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdin, GNUNET_DISK_PIPE_END_READ), &fd_stdin_read, sizeof (int)); | ||
160 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdin, GNUNET_DISK_PIPE_END_WRITE), &fd_stdin_write, sizeof (int)); | ||
161 | } | ||
155 | 162 | ||
156 | #if HAVE_WORKING_VFORK | 163 | #if HAVE_WORKING_VFORK |
157 | ret = vfork (); | 164 | ret = vfork (); |
@@ -166,6 +173,7 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNE | |||
166 | } | 173 | } |
167 | else | 174 | else |
168 | { | 175 | { |
176 | |||
169 | #if HAVE_WORKING_VFORK | 177 | #if HAVE_WORKING_VFORK |
170 | /* let's hope vfork actually works; for some extreme cases (including | 178 | /* let's hope vfork actually works; for some extreme cases (including |
171 | a testcase) we need 'execvp' to have run before we return, since | 179 | a testcase) we need 'execvp' to have run before we return, since |
@@ -175,11 +183,11 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNE | |||
175 | #else | 183 | #else |
176 | /* let's give the child process a chance to run execvp, 1s should | 184 | /* let's give the child process a chance to run execvp, 1s should |
177 | be plenty in practice */ | 185 | be plenty in practice */ |
178 | sleep (1); | ||
179 | if (pipe_stdout != NULL) | 186 | if (pipe_stdout != NULL) |
180 | GNUNET_DISK_pipe_close_end(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); | 187 | GNUNET_DISK_pipe_close_end(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); |
181 | if (pipe_stdin != NULL) | 188 | if (pipe_stdin != NULL) |
182 | GNUNET_DISK_pipe_close_end(pipe_stdin, GNUNET_DISK_PIPE_END_READ); | 189 | GNUNET_DISK_pipe_close_end(pipe_stdin, GNUNET_DISK_PIPE_END_READ); |
190 | sleep (1); | ||
183 | #endif | 191 | #endif |
184 | } | 192 | } |
185 | GNUNET_free (argv); | 193 | GNUNET_free (argv); |
@@ -190,12 +198,15 @@ GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNE | |||
190 | { | 198 | { |
191 | dup2(fd_stdout_write, 1); | 199 | dup2(fd_stdout_write, 1); |
192 | close (fd_stdout_write); | 200 | close (fd_stdout_write); |
201 | close (fd_stdout_read); | ||
193 | } | 202 | } |
194 | 203 | ||
195 | if (pipe_stdout != NULL) | 204 | if (pipe_stdin != NULL) |
196 | { | 205 | { |
206 | |||
197 | dup2(fd_stdin_read, 0); | 207 | dup2(fd_stdin_read, 0); |
198 | close (fd_stdin_read); | 208 | close (fd_stdin_read); |
209 | close (fd_stdin_write); | ||
199 | } | 210 | } |
200 | 211 | ||
201 | execvp (filename, argv); | 212 | execvp (filename, argv); |
diff --git a/src/util/test_os_start_process.c b/src/util/test_os_start_process.c new file mode 100644 index 000000000..8114f399f --- /dev/null +++ b/src/util/test_os_start_process.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file util/test_os_start_process.c | ||
22 | * @brief testcase for os start process code | ||
23 | * | ||
24 | * This testcase simply calls the os start process code | ||
25 | * giving a file descriptor to write stdout to. If the | ||
26 | * correct data "HELLO" is read then all is well. | ||
27 | * | ||
28 | */ | ||
29 | #include "platform.h" | ||
30 | #include "gnunet_common.h" | ||
31 | #include "gnunet_getopt_lib.h" | ||
32 | #include "gnunet_os_lib.h" | ||
33 | #include "gnunet_program_lib.h" | ||
34 | #include "gnunet_scheduler_lib.h" | ||
35 | #include "disk.h" | ||
36 | |||
37 | #define VERBOSE GNUNET_NO | ||
38 | |||
39 | static int | ||
40 | check () | ||
41 | { | ||
42 | char *fn; | ||
43 | pid_t pid; | ||
44 | char *buf; | ||
45 | int fd_stdout; | ||
46 | int fd_stdin; | ||
47 | int ret; | ||
48 | static char *test_phrase = "HELLO WORLD"; | ||
49 | /* Pipe to write to started processes stdin (on write end) */ | ||
50 | struct GNUNET_DISK_PipeHandle *hello_pipe_stdin; | ||
51 | /* Pipe to read from started processes stdout (on read end) */ | ||
52 | struct GNUNET_DISK_PipeHandle *hello_pipe_stdout; | ||
53 | |||
54 | buf = GNUNET_malloc(strlen(test_phrase) + 1); | ||
55 | GNUNET_asprintf(&fn, "cat"); | ||
56 | |||
57 | hello_pipe_stdin = GNUNET_DISK_pipe(GNUNET_YES); | ||
58 | hello_pipe_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
59 | |||
60 | if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) | ||
61 | return GNUNET_SYSERR; | ||
62 | |||
63 | pid = GNUNET_OS_start_process (hello_pipe_stdin, hello_pipe_stdout, fn, | ||
64 | "test_gnunet_echo_hello", NULL); | ||
65 | |||
66 | /* Close the write end of the read pipe */ | ||
67 | GNUNET_DISK_pipe_close_end(hello_pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); | ||
68 | /* Close the read end of the write pipe */ | ||
69 | GNUNET_DISK_pipe_close_end(hello_pipe_stdin, GNUNET_DISK_PIPE_END_READ); | ||
70 | /* Get the FD to read from */ | ||
71 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(hello_pipe_stdout, GNUNET_DISK_PIPE_END_READ), &fd_stdout, sizeof (int)); | ||
72 | /* Get the FD to write to */ | ||
73 | GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE), &fd_stdin, sizeof (int)); | ||
74 | |||
75 | /* Write the test_phrase to the cat process */ | ||
76 | ret = write(fd_stdin, test_phrase, strlen(test_phrase) + 1); | ||
77 | |||
78 | /* Close the write end to end the cycle! */ | ||
79 | GNUNET_DISK_pipe_close_end(hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE); | ||
80 | |||
81 | ret = 0; | ||
82 | /* Read from the cat process, hopefully get the phrase we wrote to it! */ | ||
83 | while (read(fd_stdout, buf, strlen(test_phrase) + 1) > 0) | ||
84 | { | ||
85 | ret = strncmp(buf, test_phrase, strlen(test_phrase)); | ||
86 | } | ||
87 | |||
88 | if (0 != PLIBC_KILL (pid, SIGTERM)) | ||
89 | { | ||
90 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
91 | } | ||
92 | GNUNET_OS_process_wait (pid); | ||
93 | GNUNET_DISK_pipe_close(hello_pipe_stdout); | ||
94 | GNUNET_DISK_pipe_close(hello_pipe_stdin); | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | int | ||
100 | main (int argc, char *argv[]) | ||
101 | { | ||
102 | int ret; | ||
103 | |||
104 | GNUNET_log_setup ("test-start-process", | ||
105 | #if VERBOSE | ||
106 | "DEBUG", | ||
107 | #else | ||
108 | "WARNING", | ||
109 | #endif | ||
110 | NULL); | ||
111 | ret = check (); | ||
112 | |||
113 | return ret; | ||
114 | } | ||