a4f094dd |
1 | /* |
2 | * hcommon.c |
3 | * - complex test harness, routines used for both record and playback |
4 | */ |
5 | /* |
6 | * This file is part of adns, which is Copyright (C) 1997, 1998 Ian Jackson |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2, or (at your option) |
11 | * any later version. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software Foundation, |
20 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 | */ |
22 | |
7d251914 |
23 | #include <fcntl.h> |
24 | #include <string.h> |
25 | #include <errno.h> |
26 | |
27 | #include <sys/socket.h> |
28 | #include <netinet/in.h> |
29 | #include <arpa/inet.h> |
30 | |
a4f094dd |
31 | #include "harness.h" |
32 | #include "internal.h" |
33 | |
7d251914 |
34 | vbuf vb; |
35 | FILE *Toutputfile= 0; |
36 | |
37 | const struct Terrno Terrnos[]= { |
38 | { "EAGAIN", EAGAIN }, |
39 | { "EINPROGRESS", EINPROGRESS }, |
40 | { "EINTR", EINTR }, |
41 | { "EINVAL", EINVAL }, |
42 | { "EMSGSIZE", EMSGSIZE }, |
43 | { "ENOBUFS", ENOBUFS }, |
44 | { "ENOENT", ENOENT }, |
45 | { "ENOPROTOOPT", ENOPROTOOPT }, |
46 | { "ENOSPC", ENOSPC }, |
47 | { "EWOULDBLOCK", EWOULDBLOCK }, |
48 | { 0, 0 } |
49 | }; |
a4f094dd |
50 | |
51 | void Qgettimeofday(void) { |
7d251914 |
52 | Q_str("gettimeofday()"); |
a4f094dd |
53 | } |
54 | |
7d251914 |
55 | void Qselect(int n, const fd_set *rfds, const fd_set *wfds, const fd_set *efds, |
56 | const struct timeval *to) { |
a4f094dd |
57 | vb.used= 0; |
7d251914 |
58 | Tvbf("select(%d,",n); |
59 | Tvbfdset(n,rfds); |
60 | Tvba(","); |
61 | Tvbfdset(n,wfds); |
62 | Tvba(","); |
63 | Tvbfdset(n,efds); |
64 | if (to) { |
65 | Tvbf(", %ld.%06ld)",to->tv_sec,to->tv_usec); |
a4f094dd |
66 | } else { |
7d251914 |
67 | Tvba(", NULL)"); |
a4f094dd |
68 | } |
7d251914 |
69 | Q_vb(); |
a4f094dd |
70 | } |
71 | |
72 | void Qsocket(int type) { |
73 | switch (type) { |
7d251914 |
74 | case SOCK_STREAM: Q_str("socket(,SOCK_STREAM,)"); break; |
75 | case SOCK_DGRAM: Q_str("socket(,SOCK_DGRAM,)"); break; |
a4f094dd |
76 | default: abort(); |
77 | } |
78 | } |
79 | |
7d251914 |
80 | void Qfcntl_setfl(int fd, int cmd, long arg) { |
81 | vb.used= 0; |
82 | Tvbf("fcntl(%d, F_SETFL, %ld)",fd,arg); |
83 | Q_vb(); |
84 | } |
85 | |
86 | void Qfcntl_other(int fd, int cmd) { |
87 | assert(cmd==F_GETFL); |
88 | vb.used= 0; |
89 | Tvbf("fcntl(%d, F_GETFL)",fd); |
90 | Q_vb(); |
91 | } |
92 | |
93 | void Qconnect(int fd, struct sockaddr *addr, int addrlen) { |
94 | vb.used= 0; |
95 | Tvbf("connect(%d, ",fd); |
96 | Tvbaddr(addr,addrlen); |
97 | Tvba(")"); |
98 | Q_vb(); |
99 | } |
100 | |
101 | void Qclose(int fd) { |
102 | vb.used= 0; |
103 | Tvbf("close(%d)",fd); |
104 | Q_vb(); |
105 | } |
106 | |
107 | void Qsendto(int fd, const void *msg, int msglen, |
108 | const struct sockaddr *addr, int addrlen) { |
109 | vb.used= 0; |
110 | Tvbf("sendto(%d,,,, ",fd); |
111 | Tvbaddr(addr,addrlen); |
112 | Tvba(")"); |
113 | Tvbbytes(msg,msglen); |
114 | Q_vb(); |
115 | } |
116 | |
117 | void Qrecvfrom(int fd, int buflen, int addrlen) { |
118 | vb.used= 0; |
119 | Tvbf("recvfrom(%d,,%d,,,%d)",fd,buflen,addrlen); |
120 | Q_vb(); |
121 | } |
122 | |
123 | void Qread(int fd, size_t len) { |
124 | vb.used= 0; |
125 | Tvbf("read(%d,,%lu)",fd,(unsigned long)len); |
126 | Q_vb(); |
127 | } |
128 | |
129 | void Qwrite(int fd, const void *buf, size_t len) { |
130 | vb.used= 0; |
131 | Tvbf("write(%d,,)",fd); |
132 | Tvbbytes(buf,len); |
133 | Q_vb(); |
134 | } |
135 | |
136 | |
137 | void Tvbaddr(const struct sockaddr *addr, int len) { |
138 | const struct sockaddr_in *ai= (const struct sockaddr_in*)addr; |
139 | |
140 | assert(len==sizeof(struct sockaddr_in)); |
141 | assert(ai->sin_family==AF_INET); |
142 | Tvbf(" %s:%u",inet_ntoa(ai->sin_addr),htons(ai->sin_port)); |
143 | } |
144 | |
145 | void Tvbbytes(const void *buf, int len) { |
146 | const byte *bp; |
147 | int i; |
148 | |
149 | if (!len) { Tvba(" empty"); return; } |
150 | for (i=0, bp=buf; i<len; i++, bp++) { |
151 | if (!(i&31)) Tvba("\n "); |
152 | else if (!(i&3)) Tvba(" "); |
153 | Tvbf("%02x",*bp); |
154 | } |
155 | } |
156 | |
157 | void Tvbfdset(int max, const fd_set *fds) { |
158 | int i; |
159 | const char *comma= ""; |
160 | |
161 | Tvba(" ["); |
162 | for (i=0; i<max; i++) { |
163 | if (!FD_ISSET(i,fds)) continue; |
164 | Tvba(comma); |
165 | Tvbf("%d",i); |
166 | comma= ","; |
167 | } |
168 | Tvba("]"); |
169 | } |
170 | |
171 | void Tvberrno(int e) { |
172 | const struct Terrno *te; |
a4f094dd |
173 | |
7d251914 |
174 | for (te= Terrnos; te->n && te->v != e; te++); |
175 | if (te->n) Tvba(te->n); |
176 | else Tvbf("E#%d",e); |
a4f094dd |
177 | } |
178 | |
7d251914 |
179 | void Tvba(const char *str) { |
180 | if (!adns__vbuf_appendstr(&vb,str)) Tnomem(); |
181 | } |
a4f094dd |
182 | |
7d251914 |
183 | void Tvbvf(const char *fmt, va_list al) { |
184 | char buf[1000]; |
185 | buf[sizeof(buf)-2]= '\t'; |
186 | vsnprintf(buf,sizeof(buf),fmt,al); |
187 | assert(buf[sizeof(buf)-2] == '\t'); |
a4f094dd |
188 | |
7d251914 |
189 | Tvba(buf); |
190 | } |
191 | |
192 | void Tvbf(const char *fmt, ...) { |
193 | va_list al; |
194 | va_start(al,fmt); |
195 | Tvbvf(fmt,al); |
196 | va_end(al); |
197 | } |
198 | |
199 | |
200 | void Tfailed(const char *why) { |
201 | fprintf(stderr,"adns test harness: failure: %s: %s\n",why,strerror(errno)); |
202 | exit(-1); |
203 | } |
204 | |
205 | void Tnomem(void) { |
206 | Tfailed("unable to malloc/realloc"); |
207 | } |
208 | |
209 | void Toutputerr(void) { |
210 | Tfailed("write error on test harness output"); |
211 | } |
212 | |
213 | void Tensureoutputfile(void) { |
214 | /* fixme: allow sending it elsewhere */ |
215 | Toutputfile= stdout; |
216 | } |