Line data Source code
1 : /* t-support.h - Helper routines for regression tests.
2 : Copyright (C) 2000 Werner Koch (dd9jn)
3 : Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
4 :
5 : This file is part of GPGME.
6 :
7 : GPGME is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU Lesser General Public License as
9 : published by the Free Software Foundation; either version 2.1 of
10 : the License, or (at your option) any later version.
11 :
12 : GPGME is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : Lesser General Public License for more details.
16 :
17 : You should have received a copy of the GNU Lesser General Public
18 : License along with this program; if not, write to the Free Software
19 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 : 02111-1307, USA. */
21 :
22 : #include <unistd.h>
23 : #include <errno.h>
24 : #include <stdlib.h>
25 : #include <locale.h>
26 : #include <limits.h>
27 : #include <ctype.h>
28 :
29 : #ifdef HAVE_W32_SYSTEM
30 : #include <windows.h>
31 : #endif
32 :
33 : #include <gpgme.h>
34 :
35 : #ifndef DIM
36 : #define DIM(v) (sizeof(v)/sizeof((v)[0]))
37 : #endif
38 :
39 : #define fail_if_err(err) \
40 : do \
41 : { \
42 : if (err) \
43 : { \
44 : fprintf (stderr, "%s:%d: %s: %s\n", \
45 : __FILE__, __LINE__, gpgme_strsource (err), \
46 : gpgme_strerror (err)); \
47 : exit (1); \
48 : } \
49 : } \
50 : while (0)
51 :
52 :
53 : #ifdef GPGRT_HAVE_MACRO_FUNCTION
54 : void GPGRT_ATTR_NORETURN
55 0 : _test (const char *expr, const char *file, int line,
56 : const char *func)
57 : {
58 0 : fprintf (stderr, "Test \"%s\" in %s failed (%s:%d)\n",
59 : expr, func, file, line);
60 0 : exit (1);
61 : }
62 : # define test(expr) \
63 : ((expr) \
64 : ? (void) 0 \
65 : : _test (#expr, __FILE__, __LINE__, __FUNCTION__))
66 : #else /*!GPGRT_HAVE_MACRO_FUNCTION*/
67 : void
68 : _test (const char *expr, const char *file, int line)
69 : {
70 : fprintf (stderr, "Test \"%s\" failed (%s:%d)\n",
71 : expr, file, line);
72 : exit (1);
73 : }
74 : # define test(expr) \
75 : ((expr) \
76 : ? (void) 0 \
77 : : _test (#expr, __FILE__, __LINE__))
78 : #endif /*!GPGRT_HAVE_MACRO_FUNCTION*/
79 :
80 :
81 : static const char *
82 0 : nonnull (const char *s)
83 : {
84 0 : return s? s :"[none]";
85 : }
86 :
87 :
88 : void
89 18 : print_data (gpgme_data_t dh)
90 : {
91 : #define BUF_SIZE 512
92 : char buf[BUF_SIZE + 1];
93 : int ret;
94 :
95 18 : ret = gpgme_data_seek (dh, 0, SEEK_SET);
96 18 : if (ret)
97 0 : fail_if_err (gpgme_err_code_from_errno (errno));
98 71 : while ((ret = gpgme_data_read (dh, buf, BUF_SIZE)) > 0)
99 35 : fwrite (buf, ret, 1, stdout);
100 18 : if (ret < 0)
101 0 : fail_if_err (gpgme_err_code_from_errno (errno));
102 18 : }
103 :
104 :
105 : gpgme_error_t
106 0 : passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info,
107 : int last_was_bad, int fd)
108 : {
109 : int res;
110 0 : char pass[] = "abc\n";
111 0 : int passlen = strlen (pass);
112 0 : int off = 0;
113 :
114 : (void)opaque;
115 : (void)uid_hint;
116 : (void)passphrase_info;
117 : (void)last_was_bad;
118 :
119 : do
120 : {
121 0 : res = gpgme_io_write (fd, &pass[off], passlen - off);
122 0 : if (res > 0)
123 0 : off += res;
124 : }
125 0 : while (res > 0 && off != passlen);
126 :
127 0 : return off == passlen ? 0 : gpgme_error_from_errno (errno);
128 : }
129 :
130 :
131 : char *
132 5 : make_filename (const char *fname)
133 : {
134 5 : const char *srcdir = getenv ("srcdir");
135 : char *buf;
136 :
137 5 : if (!srcdir)
138 0 : srcdir = ".";
139 5 : buf = malloc (strlen(srcdir) + strlen(fname) + 2);
140 5 : if (!buf)
141 0 : exit (8);
142 5 : strcpy (buf, srcdir);
143 5 : strcat (buf, "/");
144 5 : strcat (buf, fname);
145 5 : return buf;
146 : }
147 :
148 :
149 : void
150 46 : init_gpgme (gpgme_protocol_t proto)
151 : {
152 : gpgme_error_t err;
153 :
154 46 : gpgme_check_version (NULL);
155 46 : setlocale (LC_ALL, "");
156 46 : gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
157 : #ifndef HAVE_W32_SYSTEM
158 46 : gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
159 : #endif
160 :
161 46 : err = gpgme_engine_check_version (proto);
162 46 : fail_if_err (err);
163 46 : }
164 :
165 :
166 : void
167 0 : print_import_result (gpgme_import_result_t r)
168 : {
169 : gpgme_import_status_t st;
170 :
171 0 : for (st=r->imports; st; st = st->next)
172 : {
173 0 : printf (" fpr: %s err: %d (%s) status:", nonnull (st->fpr),
174 : st->result, gpgme_strerror (st->result));
175 0 : if (st->status & GPGME_IMPORT_NEW)
176 0 : fputs (" new", stdout);
177 0 : if (st->status & GPGME_IMPORT_UID)
178 0 : fputs (" uid", stdout);
179 0 : if (st->status & GPGME_IMPORT_SIG)
180 0 : fputs (" sig", stdout);
181 0 : if (st->status & GPGME_IMPORT_SUBKEY)
182 0 : fputs (" subkey", stdout);
183 0 : if (st->status & GPGME_IMPORT_SECRET)
184 0 : fputs (" secret", stdout);
185 0 : putchar ('\n');
186 : }
187 0 : printf ("key import summary:\n"
188 : " considered: %d\n"
189 : " no user id: %d\n"
190 : " imported: %d\n"
191 : " imported_rsa: %d\n"
192 : " unchanged: %d\n"
193 : " new user ids: %d\n"
194 : " new subkeys: %d\n"
195 : " new signatures: %d\n"
196 : " new revocations: %d\n"
197 : " secret read: %d\n"
198 : " secret imported: %d\n"
199 : " secret unchanged: %d\n"
200 : " skipped new keys: %d\n"
201 : " not imported: %d\n"
202 : " skipped v3 keys: %d\n",
203 : r->considered,
204 : r->no_user_id,
205 : r->imported,
206 : r->imported_rsa,
207 : r->unchanged,
208 : r->new_user_ids,
209 : r->new_sub_keys,
210 : r->new_signatures,
211 : r->new_revocations,
212 : r->secret_read,
213 : r->secret_imported,
214 : r->secret_unchanged,
215 : r->skipped_new_keys,
216 : r->not_imported,
217 : r->skipped_v3_keys);
218 0 : }
219 :
220 :
221 : /* Read the next number in the version string STR and return it in
222 : *NUMBER. Return a pointer to the tail of STR after parsing, or
223 : *NULL if the version string was invalid. */
224 : static const char *
225 6 : parse_version_number (const char *str, int *number)
226 : {
227 : #define MAXVAL ((INT_MAX - 10) / 10)
228 6 : int val = 0;
229 :
230 : /* Leading zeros are not allowed. */
231 6 : if (*str == '0' && isdigit(str[1]))
232 0 : return NULL;
233 :
234 19 : while (isdigit (*str) && val <= MAXVAL)
235 : {
236 7 : val *= 10;
237 7 : val += *(str++) - '0';
238 : }
239 6 : *number = val;
240 6 : return val > MAXVAL ? NULL : str;
241 : }
242 :
243 :
244 : /* Parse the version string STR in the format MAJOR.MINOR.MICRO (for
245 : example, 9.3.2) and return the components in MAJOR, MINOR and MICRO
246 : as integers. The function returns the tail of the string that
247 : follows the version number. This might be the empty string if there
248 : is nothing following the version number, or a patchlevel. The
249 : function returns NULL if the version string is not valid. */
250 : static const char *
251 2 : parse_version_string (const char *str, int *major, int *minor, int *micro)
252 : {
253 2 : str = parse_version_number (str, major);
254 2 : if (!str || *str != '.')
255 0 : return NULL;
256 2 : str++;
257 :
258 2 : str = parse_version_number (str, minor);
259 2 : if (!str || *str != '.')
260 0 : return NULL;
261 2 : str++;
262 :
263 2 : str = parse_version_number (str, micro);
264 2 : if (!str)
265 0 : return NULL;
266 :
267 : /* A patchlevel might follow. */
268 2 : return str;
269 : }
270 :
271 :
272 : /* Return true if MY_VERSION is at least REQ_VERSION, and false
273 : otherwise. */
274 : static int
275 1 : compare_versions (const char *my_version,
276 : const char *rq_version)
277 : {
278 : int my_major, my_minor, my_micro;
279 : int rq_major, rq_minor, rq_micro;
280 : const char *my_plvl, *rq_plvl;
281 :
282 1 : if (!rq_version)
283 0 : return 1;
284 1 : if (!my_version)
285 0 : return 0;
286 :
287 1 : my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
288 1 : if (!my_plvl)
289 0 : return 0;
290 :
291 1 : rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro);
292 1 : if (!rq_plvl)
293 0 : return 0;
294 :
295 1 : if (my_major > rq_major
296 1 : || (my_major == rq_major && my_minor > rq_minor)
297 1 : || (my_major == rq_major && my_minor == rq_minor
298 1 : && my_micro > rq_micro)
299 0 : || (my_major == rq_major && my_minor == rq_minor
300 0 : && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0))
301 1 : return 1;
302 :
303 0 : return 0;
304 : }
305 :
306 : /* Return true if we have the required gpg version. */
307 : static int
308 1 : check_gpg_version (const char *req_version)
309 : {
310 : gpgme_engine_info_t engine_info;
311 1 : init_gpgme (GPGME_PROTOCOL_OpenPGP);
312 :
313 1 : fail_if_err (gpgme_get_engine_info (&engine_info));
314 1 : for (; engine_info; engine_info = engine_info->next)
315 1 : if (engine_info->protocol == GPGME_PROTOCOL_OpenPGP)
316 1 : break;
317 :
318 1 : test (engine_info);
319 :
320 1 : return compare_versions (engine_info->version, req_version);
321 : }
|