1 /* Copyright 1988, 1996 by the Massachusetts Institute of Technology.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 *
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 *
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26 * OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* This file is a test driver for the Hesiod library. */
30
31 static const char rcsid[] = "$Id: hestest.c,v 1.3 1999-10-23 19:29:16 danw Exp $";
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include <netdb.h>
38 #include <errno.h>
39 #include <pwd.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <stdarg.h>
43 #include "hesiod.h"
44
45 static char *word_end(char *s);
46 static char *find_word(char *s);
47 static char *get_word(char *p, char *buf);
48 static char *get_field(char *p, int delim, char *buf);
49 static int compare_vector(char **vector, char *spec);
50 static int compare_pwnam(struct passwd *pw, char *spec);
51 static int compare_serv(struct servent *serv, char *spec);
52 static int compare_office(struct hesiod_postoffice *office, char *spec);
53 static int compare_compat_office(struct hes_postoffice *office, char *spec);
54 static void free_ptrs(char **ptrs);
55 static void failure(const char *fmt, ...);
56
57 int saw_failure = 0;
58
main(int argc,char ** argv)59 int main(int argc, char **argv)
60 {
61 FILE *fp;
62 char buf[1024], *p, *q, name[128], type[128], proto[128], **list;
63 int line, errval;
64 struct passwd *pw;
65 struct servent *serv;
66 struct hesiod_postoffice *po;
67 struct hes_postoffice *compatpo;
68 void *context;
69
70 if (argc != 2)
71 {
72 fprintf(stderr, "Usage: %s filename\n", argv[0]);
73 return 1;
74 }
75
76 fp = fopen(argv[1], "r");
77 if (!fp)
78 {
79 fprintf(stderr, "Couldn't open %s for reading.\n", argv[1]);
80 return 1;
81 }
82
83 if (hesiod_init(&context) < 0)
84 {
85 fprintf(stderr, "Can't initialize hesiod library.\n");
86 return 1;
87 }
88
89 line = 0;
90 while (fgets(buf, sizeof(buf), fp))
91 {
92 line++;
93
94 /* Strip off trailing spaces (inefficiently). */
95 while (isspace((unsigned char)buf[strlen(buf) - 1]))
96 buf[strlen(buf) - 1] = 0;
97
98 /* Get the first word, discard comment lines and invalid lines. */
99 q = word_end(p = find_word(buf));
100 if (*p == '#' || !*p)
101 continue;
102
103 if (*q && q - p == 7 && strncmp(p, "resolve", 7) == 0)
104 {
105 /* Test for hesiod_resolve and hes_resolve. */
106 q = get_word(find_word(q), name);
107 q = get_word(find_word(q), type);
108 p = find_word(q);
109 list = hesiod_resolve(context, name, type);
110 errval = errno;
111 if (!list && !(*p == 'E' && p[1] == 0))
112 {
113 failure("Line %d failed (hesiod_resolve error %d).\n", line,
114 errval);
115 continue;
116 }
117 if (list && compare_vector(list, p) < 0)
118 {
119 failure("Line %d failed in hesiod_resolve().\n", line);
120 hesiod_free_list(context, list);
121 continue;
122 }
123 if (list)
124 hesiod_free_list(context, list);
125 list = hes_resolve(name, type);
126 if (!list)
127 {
128 if (*p == 'E' && p[1] == 0)
129 printf("Line %d passed (%d, %d).\n", line, errval,
130 hes_error());
131 else
132 failure("Line %d failed (hes_resolve error %d).\n", line,
133 hes_error());
134 continue;
135 }
136 if (compare_vector(list, p) < 0)
137 failure("Line %d failed in hes_resolve().\n", line);
138 else
139 printf("Line %d passed.\n", line);
140 free_ptrs(list);
141 }
142 else if (*q && q - p == 8 && strncmp(p, "getpwnam", 8) == 0)
143 {
144 /* Test for hesiod_getpwnam and hes_getpwnam. */
145 q = get_word(find_word(q), name);
146 p = find_word(q);
147 pw = hesiod_getpwnam(context, name);
148 errval = errno;
149 if (!pw && !(*p == 'E' && p[1] == 0))
150 {
151 failure("Line %d failed (hesiod_getpwnam error %d).\n", line,
152 errval);
153 continue;
154 }
155 if (pw && compare_pwnam(pw, p) < 0)
156 {
157 failure("Line %d failed in hesiod_getpwnam().\n", line);
158 continue;
159 }
160 if (pw)
161 hesiod_free_passwd(context, pw);
162 pw = hes_getpwnam(name);
163 if (!pw)
164 {
165 if (*p == 'E' && p[1] == 0)
166 printf("Line %d passed (%d, %d).\n", line, errval,
167 hes_error());
168 else
169 failure("Line %d failed (hes_getpwnam error %d).\n", line,
170 hes_error());
171 continue;
172 }
173 if (compare_pwnam(pw, p) < 0)
174 failure("Line %d failed in hes_getpwnam().\n", line);
175 else
176 printf("Line %d passed.\n", line);
177 }
178 else if (*q && q - p == 8 && strncmp(p, "getpwuid", 8) == 0)
179 {
180 /* Test for hesiod_getpwuid and hes_getpwuid. */
181 q = get_word(find_word(q), name);
182 p = find_word(q);
183 pw = hesiod_getpwuid(context, atoi(name));
184 errval = errno;
185 if (!pw && !(*p == 'E' && p[1] == 0))
186 {
187 failure("Line %d failed (hesiod_getpwuid error %d).\n", line,
188 errval);
189 continue;
190 }
191 if (pw && compare_pwnam(pw, p) < 0)
192 {
193 failure("Line %d failed in hesiod_getpwuid().\n", line);
194 continue;
195 }
196 if (pw)
197 hesiod_free_passwd(context, pw);
198 pw = hes_getpwuid(atoi(name));
199 if (!pw)
200 {
201 if (*p == 'E' && p[1] == 0)
202 printf("Line %d passed (%d, %d).\n", line, errval,
203 hes_error());
204 else
205 failure("Line %d failed (hes_getpwuid error %d).\n", line,
206 hes_error());
207 continue;
208 }
209 if (compare_pwnam(pw, p) < 0)
210 failure("Line %d failed in hes_getpwuid().\n", line);
211 else
212 printf("Line %d passed.\n", line);
213 }
214 else if (*q && q - p == 13 && strncmp(p, "getservbyname", 13) == 0)
215 {
216 /* Test for hesiod_getservbyname and hes_getservbyname. */
217 q = get_word(find_word(q), name);
218 q = get_word(find_word(q), proto);
219 p = find_word(q);
220 serv = hesiod_getservbyname(context, name, proto);
221 errval = errno;
222 if (!serv && !(*p == 'E' && p[1] == 0))
223 {
224 failure("Line %d failed (hesiod_getservbyname error %d).\n",
225 line, errno);
226 continue;
227 }
228 if (serv && compare_serv(serv, p) < 0)
229 {
230 failure("Line %d failed in hesiod_getservbyname.\n", line);
231 continue;
232 }
233 if (serv)
234 hesiod_free_servent(context, serv);
235 serv = hes_getservbyname(name, proto);
236 if (!serv)
237 {
238 if (*p == 'E' && p[1] == 0)
239 printf("Line %d passed (%d, %d).\n", line, errval,
240 hes_error());
241 else
242 failure("Line %d failed (hes_getservbyname error %d).\n", line,
243 hes_error());
244 continue;
245 }
246 if (compare_serv(serv, p) < 0)
247 failure("Line %d failed in hes_getservbyname().\n", line);
248 else
249 printf("Line %d passed.\n", line);
250 }
251 else if (*q && q - p == 11 && strncmp(p, "getmailhost", 11) == 0)
252 {
253 /* Test for hesiod_getmailhost and hes_getmailhost. */
254 q = get_word(find_word(q), name);
255 p = find_word(q);
256 po = hesiod_getmailhost(context, name);
257 errval = errno;
258 if (!po && !(*p == 'E' && p[1] == 0))
259 {
260 failure("Line %d failed (hesiod_getmailhost error %d).\n",
261 line, errval);
262 continue;
263 }
264 if (po && compare_office(po, p) < 0)
265 {
266 failure("Line %d failed in hesiod_getmailhost.\n", line);
267 continue;
268 }
269 if (po)
270 hesiod_free_postoffice(context, po);
271 compatpo = hes_getmailhost(name);
272 if (!compatpo)
273 {
274 if (*p == 'E' && p[1] == 0)
275 printf("Line %d passed (%d, %d).\n", line, errval,
276 hes_error());
277 else
278 failure("Line %d failed (hes_getmailhost error %d).\n", line,
279 hes_error());
280 continue;
281 }
282 if (compare_compat_office(compatpo, p) < 0)
283 failure("Line %d failed in hes_getmailhost().\n", line);
284 else
285 printf("Line %d passed.\n", line);
286
287 }
288 else
289 {
290 fprintf(stderr, "Line %d invalid: %s\n", line, buf);
291 return 2;
292 }
293 }
294
295 return saw_failure;
296 }
297
word_end(char * s)298 static char *word_end(char *s)
299 {
300 while (*s && !isspace((unsigned char)*s))
301 s++;
302 return s;
303 }
304
find_word(char * s)305 static char *find_word(char *s)
306 {
307 while (isspace((unsigned char)*s))
308 s++;
309 return s;
310 }
311
get_word(char * p,char * buf)312 static char *get_word(char *p, char *buf)
313 {
314 char *q = word_end(p);
315
316 strncpy(buf, p, q - p);
317 buf[q - p] = 0;
318 return q;
319 }
320
get_field(char * p,int delim,char * buf)321 static char *get_field(char *p, int delim, char *buf)
322 {
323 char *q = strchr(p, delim);
324
325 if (q) {
326 strncpy(buf, p, q - p);
327 buf[q - p] = 0;
328 return q + 1;
329 } else {
330 strcpy(buf, p);
331 return NULL;
332 }
333 }
334
compare_vector(char ** vector,char * spec)335 static int compare_vector(char **vector, char *spec)
336 {
337 char field[100];
338
339 for (; *vector; vector++) {
340 spec = get_field(spec, '\\', field);
341 if ((!spec && vector[1]) || strcmp(*vector, field) != 0)
342 return -1;
343 }
344 return (spec) ? -1 : 0;
345 }
346
compare_pwnam(struct passwd * pw,char * spec)347 static int compare_pwnam(struct passwd *pw, char *spec)
348 {
349 char field[100];
350
351 spec = get_field(spec, ':', field);
352 if (!spec || strcmp(pw->pw_name, field) != 0)
353 return -1;
354 spec = get_field(spec, ':', field);
355 if (!spec || strcmp(pw->pw_passwd, field) != 0)
356 return -1;
357 spec = get_field(spec, ':', field);
358 if (pw->pw_uid != atoi(field))
359 return -1;
360 spec = get_field(spec, ':', field);
361 if (pw->pw_gid != atoi(field))
362 return -1;
363 spec = get_field(spec, ':', field);
364 if (!spec || strcmp(pw->pw_gecos, field) != 0)
365 return -1;
366 spec = get_field(spec, ':', field);
367 if (!spec || strcmp(pw->pw_dir, field) != 0)
368 return -1;
369 spec = get_field(spec, ':', field);
370 if (spec || strcmp(pw->pw_shell, field) != 0)
371 return -1;
372 return 0;
373 }
374
compare_serv(struct servent * serv,char * spec)375 static int compare_serv(struct servent *serv, char *spec)
376 {
377 char field[100], **aliases;
378
379 spec = get_field(spec, ':', field);
380 if (!spec || strcmp(serv->s_name, field) != 0)
381 return -1;
382 spec = get_field(spec, ':', field);
383 if (!spec || strcmp(serv->s_proto, field) != 0)
384 return -1;
385 spec = get_field(spec, ':', field);
386 if (serv->s_port != htons(atoi(field)))
387 return -1;
388 for (aliases = serv->s_aliases; *aliases; aliases++)
389 {
390 if (!spec)
391 return -1;
392 spec = get_field(spec, '\\', field);
393 if (strcmp(*aliases, field) != 0)
394 return -1;
395 }
396 return (spec) ? -1 : 0;
397 }
398
compare_office(struct hesiod_postoffice * office,char * spec)399 static int compare_office(struct hesiod_postoffice *office, char *spec)
400 {
401 char field[100];
402
403 spec = get_field(spec, ':', field);
404 if (!spec || strcmp(office->hesiod_po_type, field) != 0)
405 return -1;
406 spec = get_field(spec, ':', field);
407 if (!spec || strcmp(office->hesiod_po_host, field) != 0)
408 return -1;
409 spec = get_field(spec, ':', field);
410 if (spec || strcmp(office->hesiod_po_name, field) != 0)
411 return -1;
412 return 0;
413 }
414
compare_compat_office(struct hes_postoffice * office,char * spec)415 static int compare_compat_office(struct hes_postoffice *office, char *spec)
416 {
417 char field[100];
418
419 spec = get_field(spec, ':', field);
420 if (!spec || strcmp(office->po_type, field) != 0)
421 return -1;
422 spec = get_field(spec, ':', field);
423 if (!spec || strcmp(office->po_host, field) != 0)
424 return -1;
425 spec = get_field(spec, ':', field);
426 if (spec || strcmp(office->po_name, field) != 0)
427 return -1;
428 return 0;
429 }
430
free_ptrs(char ** ptrs)431 static void free_ptrs(char **ptrs)
432 {
433 for (; *ptrs; ptrs++)
434 free(*ptrs);
435 }
436
failure(const char * fmt,...)437 static void failure(const char *fmt, ...)
438 {
439 va_list ap;
440
441 saw_failure = 1;
442 va_start(ap, fmt);
443 vprintf(fmt, ap);
444 va_end(ap);
445 }
446