chiark / gitweb /
@@ -11,6 +11,11 @@
[adns] / regress / hplayback.c
CommitLineData
c7340170 1#include <assert.h>
2#include <string.h>
3#include <errno.h>
4#include <stdlib.h>
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <netinet/in.h>
8#include <arpa/inet.h>
4b30caad 9#include <sys/time.h>
c7340170 10#include <unistd.h>
11#include <fcntl.h>
12#include "harness.h"
13static FILE *Tinputfile, *Treportfile;
14static vbuf vb2;
15extern void Tshutdown(void) {
16 adns__vbuf_free(&vb2);
17}
18static void Tensurereportfile(void) {
19 const char *fdstr;
20 int fd;
21 if (Treportfile) return;
22 Treportfile= stderr;
23 fdstr= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr) return;
24 fd= atoi(fdstr);
25 Treportfile= fdopen(fd,"a"); if (!Treportfile) Tfailed("fdopen ADNS_TEST_REPORT_FD");
26}
27static void Psyntax(const char *where) {
28 fprintf(stderr,"adns test harness: syntax error in test log input file: %s\n",where);
29 exit(-1);
30}
31static void Pcheckinput(void) {
32 if (ferror(Tinputfile)) Tfailed("read test log input file");
33 if (feof(Tinputfile)) Psyntax("eof at syscall reply");
34}
0366bd10 35void Tensurerecordfile(void) {
c7340170 36 const char *fdstr;
37 int fd;
38 int chars;
39 unsigned long sec, usec;
40 if (Tinputfile) return;
41 Tinputfile= stdin;
42 fdstr= getenv("ADNS_TEST_IN_FD");
43 if (fdstr) {
44 fd= atoi(fdstr);
45 Tinputfile= fdopen(fd,"r"); if (!Tinputfile) Tfailed("fdopen ADNS_TEST_IN_FD");
46 }
47 setvbuf(Tinputfile,0,_IONBF,0);
48 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
49 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
50 chars= -1;
51 sscanf(vb2.buf," start %lu.%lu%n",&sec,&usec,&chars);
52 if (chars==-1) Psyntax("start time invalid");
53 currenttime.tv_sec= sec;
54 currenttime.tv_usec= usec;
55 if (vb2.buf[chars] != '\n') Psyntax("not newline after start time");
56}
57static void Parg(const char *argname) {
58 int l;
59 if (vb2.buf[vb2.used++] != ' ') Psyntax("not a space before argument");
60 l= strlen(argname);
61 if (memcmp(vb2.buf+vb2.used,argname,l)) Psyntax("argument name wrong");
62 vb2.used+= l;
63 if (vb2.buf[vb2.used++] != '=') Psyntax("not = after argument name");
64}
65static int Pstring_maybe(const char *string) {
66 int l;
67 l= strlen(string);
68 if (memcmp(vb2.buf+vb2.used,string,l)) return 0;
69 vb2.used+= l;
70 return 1;
71}
72static void Pstring(const char *string, const char *emsg) {
73 if (Pstring_maybe(string)) return;
74 Psyntax(emsg);
75}
76static int Perrno(const char *stuff) {
77 const struct Terrno *te;
78 int r;
79 char *ep;
80 for (te= Terrnos; te->n && strcmp(te->n,stuff); te++);
81 if (te->n) return te->v;
82 r= strtoul(stuff+2,&ep,10);
83 if (*ep) Psyntax("errno value not recognised, not numeric");
84 return r;
85}
86static void P_updatetime(void) {
87 int chars;
88 unsigned long sec, usec;
89 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
90 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
91 chars= -1;
92 sscanf(vb2.buf," +%lu.%lu%n",&sec,&usec,&chars);
93 if (chars==-1) Psyntax("update time invalid");
94 currenttime.tv_sec+= sec;
95 currenttime.tv_usec+= usec;
96 if (currenttime.tv_usec > 1000000) {
97 currenttime.tv_sec++;
98 currenttime.tv_usec -= 1000000;
99 }
100 if (vb2.buf[chars] != '\n') Psyntax("not newline after update time");
101}
102static void Pfdset(fd_set *set, int max) {
103 int r, c;
104 char *ep;
105 if (vb2.buf[vb2.used++] != '[') Psyntax("fd set start not [");
106 FD_ZERO(set);
107 if (vb2.buf[vb2.used] == ']') { vb2.used++; return; }
108 for (;;) {
109 r= strtoul(vb2.buf+vb2.used,&ep,10);
110 if (r>=max) Psyntax("fd set member > max");
111 if (ep == (char*)vb2.buf+vb2.used) Psyntax("empty entry in fd set");
112 FD_SET(r,set);
113 vb2.used= ep - (char*)vb2.buf;
114 c= vb2.buf[vb2.used++];
115 if (c == ']') break;
116 if (c != ',') Psyntax("fd set separator not ,");
117 }
118}
119#ifdef HAVE_POLL
120static int Ppollfdevents(void) {
121 int events;
122 if (Pstring_maybe("0")) return 0;
123 events= 0;
124 if (Pstring_maybe("POLLIN")) {
125 events |= POLLIN;
126 if (!Pstring_maybe("|")) return events;
127 }
128 if (Pstring_maybe("POLLOUT")) {
129 events |= POLLOUT;
130 if (!Pstring_maybe("|")) return events;
131 }
132 Pstring("POLLPRI","pollfdevents PRI?");
133 return events;
134}
135static void Ppollfds(struct pollfd *fds, int nfds) {
136 int i;
137 char *ep;
138 const char *comma= "";
139 if (vb2.buf[vb2.used++] != '[') Psyntax("pollfds start not [");
140 for (i=0; i<nfds; i++) {
141 Pstring("{fd=","{fd= in pollfds");
142 fds->fd= strtoul(vb2.buf+vb2.used,&ep,10);
143 vb2.used= ep - (char*)vb2.buf;
144 Pstring(", events=",", events= in pollfds");
145 fds->events= Ppollfdevents();
146 Pstring(", revents=",", revents= in pollfds");
147 fds->revents= Ppollfdevents();
148 Pstring("}","} in pollfds");
149 Pstring(comma,"separator in pollfds");
150 comma= ", ";
151 }
152 if (vb2.buf[vb2.used++] != ']') Psyntax("pollfds end not ]");
153}
154#endif
155static void Paddr(struct sockaddr *addr, int *lenr) {
156 struct sockaddr_in *sa= (struct sockaddr_in*)addr;
157 char *p, *ep;
158 long ul;
159 assert(*lenr >= sizeof(*sa));
160 p= strchr(vb2.buf+vb2.used,':');
161 if (!p) Psyntax("no port on address");
162 *p++= 0;
163 memset(sa,0,sizeof(*sa));
164 sa->sin_family= AF_INET;
165 if (!inet_aton(vb2.buf+vb2.used,&sa->sin_addr)) Psyntax("invalid address");
166 ul= strtoul(p,&ep,10);
167 if (*ep && *ep != ' ') Psyntax("invalid port (bad syntax)");
168 if (ul >= 65536) Psyntax("port too large");
169 sa->sin_port= htons(ul);
170 *lenr= sizeof(*sa);
171 vb2.used= ep - (char*)vb2.buf;
172}
173static int Pbytes(byte *buf, int maxlen) {
174 static const char hexdigits[]= "0123456789abcdef";
175 int c, v, done;
176 const char *pf;
177 done= 0;
178 for (;;) {
179 c= getc(Tinputfile); Pcheckinput();
180 if (c=='\n' || c==' ' || c=='\t') continue;
181 if (c=='.') break;
182 pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid first hex digit");
183 v= (pf-hexdigits)<<4;
184 c= getc(Tinputfile); Pcheckinput();
185 pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid second hex digit");
186 v |= (pf-hexdigits);
187 if (maxlen<=0) Psyntax("buffer overflow in bytes");
188 *buf++= v;
189 maxlen--; done++;
190 }
191 for (;;) {
192 c= getc(Tinputfile); Pcheckinput();
193 if (c=='\n') return done;
194 }
195}
196void Q_vb(void) {
197 int r;
198 const char *nl;
0366bd10 199 Tensurerecordfile();
c7340170 200 if (!adns__vbuf_ensure(&vb2,vb.used+2)) Tnomem();
201 r= fread(vb2.buf,1,vb.used+2,Tinputfile);
202 if (feof(Tinputfile)) {
203 fprintf(stderr,"adns test harness: input ends prematurely; program did:\n %.*s\n",
204 vb.used,vb.buf);
205 exit(-1);
206 }
207 Pcheckinput();
208 if (vb2.buf[0] != ' ') Psyntax("not space before call");
209 if (memcmp(vb.buf,vb2.buf+1,vb.used) ||
210 vb2.buf[vb.used+1] != '\n') {
211 fprintf(stderr,
212 "adns test harness: program did unexpected:\n %.*s\n"
213 "was expecting:\n %.*s\n",
214 vb.used,vb.buf, vb.used,vb2.buf+1);
215 exit(1);
216 }
217 Tensurereportfile();
218 nl= memchr(vb.buf,'\n',vb.used);
219 fprintf(Treportfile," %.*s\n", (int)(nl ? nl - (const char*)vb.buf : vb.used), vb.buf);
220}
221int Hselect( int max , fd_set *rfds , fd_set *wfds , fd_set *efds , struct timeval *to ) {
222 int r, amtread;
223 char *ep;
224 Qselect( max , rfds , wfds , efds , to );
225 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
226 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
227 Tensurereportfile();
228 fprintf(Treportfile,"%s",vb2.buf);
229 amtread= strlen(vb2.buf);
230 if (amtread<=0 || vb2.buf[--amtread]!='\n')
231 Psyntax("badly formed line");
232 vb2.buf[amtread]= 0;
233 if (memcmp(vb2.buf," select=",8)) Psyntax("syscall reply mismatch");
234 if (vb2.buf[8] == 'E') {
235 int e;
236 e= Perrno(vb2.buf+8);
237 P_updatetime();
238 errno= e;
239 return -1;
240 }
241 r= strtoul(vb2.buf+8,&ep,10);
242 if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
243 vb2.used= ep - (char*)vb2.buf;
244 Parg("rfds"); Pfdset(rfds,max);
245 Parg("wfds"); Pfdset(wfds,max);
246 Parg("efds"); Pfdset(efds,max);
247 assert(vb2.used <= amtread);
248 if (vb2.used != amtread) Psyntax("junk at end of line");
249 P_updatetime();
250 return r;
251}
252#ifdef HAVE_POLL
253int Hpoll( struct pollfd *fds , int nfds , int timeout ) {
254 int r, amtread;
255 char *ep;
256 Qpoll( fds , nfds , timeout );
257 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
258 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
259 Tensurereportfile();
260 fprintf(Treportfile,"%s",vb2.buf);
261 amtread= strlen(vb2.buf);
262 if (amtread<=0 || vb2.buf[--amtread]!='\n')
263 Psyntax("badly formed line");
264 vb2.buf[amtread]= 0;
265 if (memcmp(vb2.buf," poll=",6)) Psyntax("syscall reply mismatch");
266 if (vb2.buf[6] == 'E') {
267 int e;
268 e= Perrno(vb2.buf+6);
269 P_updatetime();
270 errno= e;
271 return -1;
272 }
273 r= strtoul(vb2.buf+6,&ep,10);
274 if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
275 vb2.used= ep - (char*)vb2.buf;
276 Parg("fds"); Ppollfds(fds,nfds);
277 assert(vb2.used <= amtread);
278 if (vb2.used != amtread) Psyntax("junk at end of line");
279 P_updatetime();
280 return r;
281}
282#endif
283int Hsocket( int domain , int type , int protocol ) {
284 int r, amtread;
285 char *ep;
286 Tmust("socket","domain",domain==AF_INET);
287 Tmust("socket","type",type==SOCK_STREAM || type==SOCK_DGRAM);
288 Qsocket( type );
289 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
290 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
291 Tensurereportfile();
292 fprintf(Treportfile,"%s",vb2.buf);
293 amtread= strlen(vb2.buf);
294 if (amtread<=0 || vb2.buf[--amtread]!='\n')
295 Psyntax("badly formed line");
296 vb2.buf[amtread]= 0;
297 if (memcmp(vb2.buf," socket=",8)) Psyntax("syscall reply mismatch");
298 if (vb2.buf[8] == 'E') {
299 int e;
300 e= Perrno(vb2.buf+8);
301 P_updatetime();
302 errno= e;
303 return -1;
304 }
305 r= strtoul(vb2.buf+8,&ep,10);
306 if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
307 vb2.used= ep - (char*)vb2.buf;
308 assert(vb2.used <= amtread);
309 if (vb2.used != amtread) Psyntax("junk at end of line");
310 P_updatetime();
311 return r;
312}
313int Hfcntl( int fd , int cmd , ... ) {
314 int r, amtread;
315 va_list al; long arg;
316 Tmust("fcntl","cmd",cmd==F_SETFL || cmd==F_GETFL);
317 if (cmd == F_SETFL) {
318 va_start(al,cmd); arg= va_arg(al,long); va_end(al);
319 } else {
320 arg= 0;
321 }
322 Qfcntl( fd , cmd , arg );
323 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
324 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
325 Tensurereportfile();
326 fprintf(Treportfile,"%s",vb2.buf);
327 amtread= strlen(vb2.buf);
328 if (amtread<=0 || vb2.buf[--amtread]!='\n')
329 Psyntax("badly formed line");
330 vb2.buf[amtread]= 0;
331 if (memcmp(vb2.buf," fcntl=",7)) Psyntax("syscall reply mismatch");
332 if (vb2.buf[7] == 'E') {
333 int e;
334 e= Perrno(vb2.buf+7);
335 P_updatetime();
336 errno= e;
337 return -1;
338 }
339 r= 0;
340 if (cmd == F_GETFL) {
341 if (!memcmp(vb2.buf+7,"O_NONBLOCK|...",14)) {
342 r= O_NONBLOCK;
343 vb2.used= 7+14;
344 } else if (!memcmp(vb2.buf+7,"~O_NONBLOCK&...",15)) {
345 vb2.used= 7+15;
346 } else {
347 Psyntax("fcntl flags not O_NONBLOCK|... or ~O_NONBLOCK&...");
348 }
349 } else if (cmd == F_SETFL) {
350 if (memcmp(vb2.buf+7,"OK",2)) Psyntax("success/fail not E* or OK");
351 vb2.used= 7+2;
352 r= 0;
353 } else {
354 Psyntax("fcntl not F_GETFL or F_SETFL");
355 }
356 assert(vb2.used <= amtread);
357 if (vb2.used != amtread) Psyntax("junk at end of line");
358 P_updatetime();
359 return r;
360}
361int Hconnect( int fd , const struct sockaddr *addr , int addrlen ) {
362 int r, amtread;
363 Qconnect( fd , addr , addrlen );
364 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
365 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
366 Tensurereportfile();
367 fprintf(Treportfile,"%s",vb2.buf);
368 amtread= strlen(vb2.buf);
369 if (amtread<=0 || vb2.buf[--amtread]!='\n')
370 Psyntax("badly formed line");
371 vb2.buf[amtread]= 0;
372 if (memcmp(vb2.buf," connect=",9)) Psyntax("syscall reply mismatch");
373 if (vb2.buf[9] == 'E') {
374 int e;
375 e= Perrno(vb2.buf+9);
376 P_updatetime();
377 errno= e;
378 return -1;
379 }
380 if (memcmp(vb2.buf+9,"OK",2)) Psyntax("success/fail not E* or OK");
381 vb2.used= 9+2;
382 r= 0;
383 assert(vb2.used <= amtread);
384 if (vb2.used != amtread) Psyntax("junk at end of line");
385 P_updatetime();
386 return r;
387}
0366bd10 388int Hbind( int fd , const struct sockaddr *addr , int addrlen ) {
389 int r, amtread;
390 Qbind( fd , addr , addrlen );
391 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
392 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
393 Tensurereportfile();
394 fprintf(Treportfile,"%s",vb2.buf);
395 amtread= strlen(vb2.buf);
396 if (amtread<=0 || vb2.buf[--amtread]!='\n')
397 Psyntax("badly formed line");
398 vb2.buf[amtread]= 0;
399 if (memcmp(vb2.buf," bind=",6)) Psyntax("syscall reply mismatch");
400 if (vb2.buf[6] == 'E') {
401 int e;
402 e= Perrno(vb2.buf+6);
403 P_updatetime();
404 errno= e;
405 return -1;
406 }
407 if (memcmp(vb2.buf+6,"OK",2)) Psyntax("success/fail not E* or OK");
408 vb2.used= 6+2;
409 r= 0;
410 assert(vb2.used <= amtread);
411 if (vb2.used != amtread) Psyntax("junk at end of line");
412 P_updatetime();
413 return r;
414}
415int Hlisten( int fd , int backlog ) {
416 int r, amtread;
417 Qlisten( fd , backlog );
418 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
419 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
420 Tensurereportfile();
421 fprintf(Treportfile,"%s",vb2.buf);
422 amtread= strlen(vb2.buf);
423 if (amtread<=0 || vb2.buf[--amtread]!='\n')
424 Psyntax("badly formed line");
425 vb2.buf[amtread]= 0;
426 if (memcmp(vb2.buf," listen=",8)) Psyntax("syscall reply mismatch");
427 if (vb2.buf[8] == 'E') {
428 int e;
429 e= Perrno(vb2.buf+8);
430 P_updatetime();
431 errno= e;
432 return -1;
433 }
434 if (memcmp(vb2.buf+8,"OK",2)) Psyntax("success/fail not E* or OK");
435 vb2.used= 8+2;
436 r= 0;
437 assert(vb2.used <= amtread);
438 if (vb2.used != amtread) Psyntax("junk at end of line");
439 P_updatetime();
440 return r;
441}
c7340170 442int Hclose( int fd ) {
443 int r, amtread;
444 Qclose( fd );
445 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
446 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
447 Tensurereportfile();
448 fprintf(Treportfile,"%s",vb2.buf);
449 amtread= strlen(vb2.buf);
450 if (amtread<=0 || vb2.buf[--amtread]!='\n')
451 Psyntax("badly formed line");
452 vb2.buf[amtread]= 0;
453 if (memcmp(vb2.buf," close=",7)) Psyntax("syscall reply mismatch");
454 if (vb2.buf[7] == 'E') {
455 int e;
456 e= Perrno(vb2.buf+7);
457 P_updatetime();
458 errno= e;
459 return -1;
460 }
461 if (memcmp(vb2.buf+7,"OK",2)) Psyntax("success/fail not E* or OK");
462 vb2.used= 7+2;
463 r= 0;
464 assert(vb2.used <= amtread);
465 if (vb2.used != amtread) Psyntax("junk at end of line");
466 P_updatetime();
467 return r;
468}
469int Hsendto( int fd , const void *msg , int msglen , unsigned int flags , const struct sockaddr *addr , int addrlen ) {
470 int r, amtread;
471 char *ep;
472 Tmust("sendto","flags",flags==0);
473 Qsendto( fd , msg , msglen , addr , addrlen );
474 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
475 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
476 Tensurereportfile();
477 fprintf(Treportfile,"%s",vb2.buf);
478 amtread= strlen(vb2.buf);
479 if (amtread<=0 || vb2.buf[--amtread]!='\n')
480 Psyntax("badly formed line");
481 vb2.buf[amtread]= 0;
482 if (memcmp(vb2.buf," sendto=",8)) Psyntax("syscall reply mismatch");
483 if (vb2.buf[8] == 'E') {
484 int e;
485 e= Perrno(vb2.buf+8);
486 P_updatetime();
487 errno= e;
488 return -1;
489 }
490 r= strtoul(vb2.buf+8,&ep,10);
491 if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
492 vb2.used= ep - (char*)vb2.buf;
493 assert(vb2.used <= amtread);
494 if (vb2.used != amtread) Psyntax("junk at end of line");
495 P_updatetime();
496 return r;
497}
498int Hrecvfrom( int fd , void *buf , int buflen , unsigned int flags , struct sockaddr *addr , int *addrlen ) {
499 int r, amtread;
500 Tmust("recvfrom","flags",flags==0);
501 Tmust("recvfrom","*addrlen",*addrlen>=sizeof(struct sockaddr_in));
502 Qrecvfrom( fd , buflen , *addrlen );
503 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
504 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
505 Tensurereportfile();
506 fprintf(Treportfile,"%s",vb2.buf);
507 amtread= strlen(vb2.buf);
508 if (amtread<=0 || vb2.buf[--amtread]!='\n')
509 Psyntax("badly formed line");
510 vb2.buf[amtread]= 0;
511 if (memcmp(vb2.buf," recvfrom=",10)) Psyntax("syscall reply mismatch");
512 if (vb2.buf[10] == 'E') {
513 int e;
514 e= Perrno(vb2.buf+10);
515 P_updatetime();
516 errno= e;
517 return -1;
518 }
519 if (memcmp(vb2.buf+10,"OK",2)) Psyntax("success/fail not E* or OK");
520 vb2.used= 10+2;
521 r= 0;
522 Parg("addr"); Paddr(addr,addrlen);
523 assert(vb2.used <= amtread);
524 if (vb2.used != amtread) Psyntax("junk at end of line");
525 r= Pbytes(buf,buflen);
526 P_updatetime();
527 return r;
528}
529int Hread( int fd , void *buf , size_t buflen ) {
530 int r, amtread;
531 Qread( fd , buflen );
532 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
533 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
534 Tensurereportfile();
535 fprintf(Treportfile,"%s",vb2.buf);
536 amtread= strlen(vb2.buf);
537 if (amtread<=0 || vb2.buf[--amtread]!='\n')
538 Psyntax("badly formed line");
539 vb2.buf[amtread]= 0;
540 if (memcmp(vb2.buf," read=",6)) Psyntax("syscall reply mismatch");
541 if (vb2.buf[6] == 'E') {
542 int e;
543 e= Perrno(vb2.buf+6);
544 P_updatetime();
545 errno= e;
546 return -1;
547 }
548 if (memcmp(vb2.buf+6,"OK",2)) Psyntax("success/fail not E* or OK");
549 vb2.used= 6+2;
550 r= 0;
551 assert(vb2.used <= amtread);
552 if (vb2.used != amtread) Psyntax("junk at end of line");
553 r= Pbytes(buf,buflen);
554 P_updatetime();
555 return r;
556}
557int Hwrite( int fd , const void *buf , size_t len ) {
558 int r, amtread;
559 char *ep;
560 Qwrite( fd , buf , len );
561 if (!adns__vbuf_ensure(&vb2,1000)) Tnomem();
562 fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput();
563 Tensurereportfile();
564 fprintf(Treportfile,"%s",vb2.buf);
565 amtread= strlen(vb2.buf);
566 if (amtread<=0 || vb2.buf[--amtread]!='\n')
567 Psyntax("badly formed line");
568 vb2.buf[amtread]= 0;
569 if (memcmp(vb2.buf," write=",7)) Psyntax("syscall reply mismatch");
570 if (vb2.buf[7] == 'E') {
571 int e;
572 e= Perrno(vb2.buf+7);
573 P_updatetime();
574 errno= e;
575 return -1;
576 }
577 r= strtoul(vb2.buf+7,&ep,10);
578 if (*ep && *ep!=' ') Psyntax("return value not E* or positive number");
579 vb2.used= ep - (char*)vb2.buf;
580 assert(vb2.used <= amtread);
581 if (vb2.used != amtread) Psyntax("junk at end of line");
582 P_updatetime();
583 return r;
584}