chiark / gitweb /
gpg agent threading bugs: Add some `xxx' comments.
[gnupg2.git] / common / t-exectool.c
1 /* t-exectool.c - Module test for exectool.c
2  * Copyright (C) 2016 g10 Code GmbH
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG 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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <https://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <assert.h>
25 #include <unistd.h>
26
27 #include "util.h"
28 #include "exectool.h"
29
30 static int verbose;
31
32 #define fail(msg, err)                                           \
33   do { fprintf (stderr, "%s:%d: %s failed: %s\n",                \
34                 __FILE__,__LINE__, (msg), gpg_strerror (err));   \
35     exit (1);                                                    \
36   } while(0)
37
38 static void
39 test_executing_true (void)
40 {
41   gpg_error_t err;
42   const char *argv[] = { "/bin/true", NULL };
43   char *result;
44   size_t len;
45
46   if (access (argv[0], X_OK))
47     {
48       fprintf (stderr, "skipping test: %s not executable: %s",
49                argv[0], strerror (errno));
50       return;
51     }
52
53   if (verbose)
54     fprintf (stderr, "Executing %s...\n", argv[0]);
55
56   err = gnupg_exec_tool (argv[0], &argv[1], "", &result, &len);
57   if (err)
58     fail ("gnupg_exec_tool", err);
59
60   assert (result);
61   assert (len == 0);
62   free (result);
63 }
64
65 static void
66 test_executing_false (void)
67 {
68   gpg_error_t err;
69   const char *argv[] = { "/bin/false", NULL };
70   char *result;
71   size_t len;
72
73   if (access (argv[0], X_OK))
74     {
75       fprintf (stderr, "skipping test: %s not executable: %s",
76                argv[0], strerror (errno));
77       return;
78     }
79
80   if (verbose)
81     fprintf (stderr, "Executing %s...\n", argv[0]);
82
83   err = gnupg_exec_tool (argv[0], &argv[1], "", &result, &len);
84   assert (err == GPG_ERR_GENERAL);
85 }
86
87 static void
88 test_executing_cat (const char *vector)
89 {
90   gpg_error_t err;
91   const char *argv[] = { "/bin/cat", NULL };
92   char *result;
93   size_t len;
94
95   if (access (argv[0], X_OK))
96     {
97       fprintf (stderr, "skipping test: %s not executable: %s",
98                argv[0], strerror (errno));
99       return;
100     }
101
102   if (verbose)
103     fprintf (stderr, "Executing %s...\n", argv[0]);
104
105   err = gnupg_exec_tool (argv[0], &argv[1], vector, &result, &len);
106   if (err)
107     fail ("gnupg_exec_tool", err);
108
109   assert (result);
110
111   /* gnupg_exec_tool returns the correct length... */
112   assert (len == strlen (vector));
113   /* ... but 0-terminates data for ease of use.  */
114   assert (result[len] == 0);
115
116   assert (strcmp (result, vector) == 0);
117   free (result);
118 }
119
120
121 static void
122 test_catting_cat (void)
123 {
124   gpg_error_t err;
125   const char *argv[] = { "/bin/cat", "/bin/cat", NULL };
126   char *result;
127   size_t len;
128   estream_t in;
129   char *reference, *p;
130   size_t reference_len;
131
132   if (access (argv[0], X_OK))
133     {
134       fprintf (stderr, "skipping test: %s not executable: %s",
135                argv[0], strerror (errno));
136       return;
137     }
138
139   in = es_fopen (argv[1], "r");
140   if (in == NULL)
141     {
142       fprintf (stderr, "skipping test: could not open %s: %s",
143                argv[1], strerror (errno));
144       return;
145     }
146
147   err = es_fseek (in, 0L, SEEK_END);
148   if (err)
149     {
150       fprintf (stderr, "skipping test: could not seek in %s: %s",
151                argv[1], gpg_strerror (err));
152       return;
153     }
154
155   reference_len = es_ftell (in);
156   err = es_fseek (in, 0L, SEEK_SET);
157   assert (!err || !"rewinding failed");
158
159   reference = malloc (reference_len);
160   assert (reference || !"allocating reference buffer failed");
161
162   for (p = reference; p - reference < reference_len; )
163     {
164       size_t bytes_read, left;
165       left = reference_len - (p - reference);
166       if (left > 4096)
167         left = 4096;
168       err = es_read (in, p, left, &bytes_read);
169       if (err)
170         {
171           fprintf (stderr, "error reading %s: %s",
172                    argv[1], gpg_strerror (err));
173           exit (1);
174         }
175
176       p += bytes_read;
177     }
178   es_fclose (in);
179
180   if (verbose)
181     fprintf (stderr, "Executing %s %s...\n", argv[0], argv[1]);
182
183   err = gnupg_exec_tool (argv[0], &argv[1], "", &result, &len);
184   if (err)
185     fail ("gnupg_exec_tool", err);
186
187   assert (result);
188
189   /* gnupg_exec_tool returns the correct length... */
190   assert (len == reference_len);
191   assert (memcmp (result, reference, reference_len) == 0);
192   free (reference);
193   free (result);
194 }
195
196
197 int
198 main (int argc, char **argv)
199 {
200   int i;
201   char binjunk[256];
202
203   if (argc)
204     { argc--; argv++; }
205   if (argc && !strcmp (argv[0], "--verbose"))
206     {
207       verbose = 1;
208       argc--; argv++;
209     }
210
211   test_executing_true ();
212   test_executing_false ();
213   test_executing_cat ("Talking to myself here...");
214
215   for (i = 0; i < 255 /* one less */; i++)
216     binjunk[i] = i + 1; /* avoid 0 */
217   binjunk[255] = 0;
218
219   test_executing_cat (binjunk);
220   test_catting_cat ();
221
222   return 0;
223 }