Mercurial > illumos > onarm
annotate usr/src/cmd/bnu/eio.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
5 * Common Development and Distribution License (the "License"). | |
6 * You may not use this file except in compliance with the License. | |
7 * | |
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 * or http://www.opensolaris.org/os/licensing. | |
10 * See the License for the specific language governing permissions | |
11 * and limitations under the License. | |
12 * | |
13 * When distributing Covered Code, include this CDDL HEADER in each | |
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 * If applicable, add the following below this CDDL HEADER, with the | |
16 * fields enclosed by brackets "[]" replaced with your own identifying | |
17 * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 * | |
19 * CDDL HEADER END | |
20 */ | |
21 /* | |
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
23 * Use is subject to license terms. | |
24 */ | |
25 | |
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ | |
27 /* All Rights Reserved */ | |
28 | |
29 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
30 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 31 |
32 #include "uucp.h" | |
33 | |
34 #ifdef E_PROTOCOL | |
35 | |
36 #ifndef MIN | |
37 #define MIN(a,b) (((a)<(b))?(a):(b)) | |
38 #endif | |
39 | |
40 #if defined(BSD4_2) || defined (ATTSVR4) | |
41 #include <netinet/in.h> | |
42 #endif /* BSD4_2 || ATTSVR4 */ | |
43 | |
44 #define EBUFSIZ 1024 | |
45 #define EMESGLEN 20 | |
46 | |
47 #define TBUFSIZE 1024 | |
48 #define TPACKSIZE 512 | |
49 | |
50 extern long lseek(); /* Find offset into the file. */ | |
51 static jmp_buf Failbuf; | |
52 extern int erdblk(); | |
53 extern unsigned msgtime; | |
54 | |
55 static char Erdstash[EBUFSIZ]; | |
56 static int Erdlen; | |
57 | |
58 /* | |
59 * error-free channel protocol | |
60 */ | |
61 /* ARGSUSED */ | |
62 static void | |
63 ealarm(sig) | |
64 int sig; | |
65 { | |
66 longjmp(Failbuf, 1); | |
67 } | |
68 static void (*esig)(); | |
69 | |
70 /* | |
71 * turn on protocol timer | |
72 */ | |
73 int | |
74 eturnon() | |
75 { | |
76 esig=signal(SIGALRM, ealarm); | |
77 return(0); | |
78 } | |
79 | |
80 int | |
81 eturnoff() | |
82 { | |
83 signal(SIGALRM, esig); | |
84 return(0); | |
85 } | |
86 | |
87 /* | |
88 * write message across link | |
89 * type -> message type | |
90 * str -> message body (ascii string) | |
91 * fn -> link file descriptor | |
92 * return | |
93 * FAIL -> write failed | |
94 * SUCCESS -> write succeeded | |
95 */ | |
96 int | |
97 ewrmsg(type, str, fn) | |
98 char *str; | |
99 int fn; | |
100 char type; | |
101 { | |
102 return(etwrmsg(type, str, fn, 0)); | |
103 } | |
104 | |
105 /* | |
106 * read message from link | |
107 * str -> message buffer | |
108 * fn -> file descriptor | |
109 * return | |
110 * FAIL -> read timed out | |
111 * SUCCESS -> ok message in str | |
112 */ | |
113 int | |
114 erdmsg(str, fn) | |
115 char *str; | |
116 { | |
117 return(etrdmsg(str, fn, 0)); | |
118 } | |
119 | |
120 /* | |
121 * read data from file fp1 and write | |
122 * on link | |
123 * fp1 -> file descriptor | |
124 * fn -> link descriptor | |
125 * returns: | |
126 * FAIL ->failure in link | |
127 * SUCCESS -> ok | |
128 */ | |
129 int | |
130 ewrdata(fp1, fn) | |
131 FILE *fp1; | |
132 int fn; | |
133 { | |
134 int ret; | |
135 int fd1; | |
136 int len; | |
137 unsigned long bytes; | |
138 char bufr[EBUFSIZ]; | |
139 struct stat statbuf; | |
140 off_t msglen; | |
141 char cmsglen[EMESGLEN]; | |
142 off_t startPoint; /* Offset from begining of the file in | |
143 * case we are restarting from a check | |
144 * point. | |
145 */ | |
146 | |
147 if (setjmp(Failbuf)) { | |
148 DEBUG(7, "ewrdata failed\n%s", ""); | |
149 return(FAIL); | |
150 } | |
151 bytes = 0L; | |
152 fd1 = fileno(fp1); | |
153 fstat(fd1, &statbuf); | |
154 startPoint = lseek(fd1, 0L, 1); | |
155 if (startPoint < 0) | |
156 { | |
157 DEBUG(7, "ewrdata lseek failed. Errno=%d\n", errno); | |
158 return(FAIL); | |
159 } | |
160 msglen = statbuf.st_size - startPoint; | |
161 if (msglen < 0) | |
162 { | |
163 DEBUG(7, "ewrdata: startPoint past end of file.\n%s", ""); | |
164 return(FAIL); | |
165 } | |
166 sprintf(cmsglen, "%ld", (long) msglen); | |
167 DEBUG(9, "ewrdata writing %d ...", sizeof(cmsglen)); | |
168 alarm(msgtime); | |
169 ret = (*Write)(fn, cmsglen, sizeof(cmsglen)); | |
170 alarm(0); | |
171 DEBUG(9, "ret %d\n", ret); | |
172 if (ret != sizeof(cmsglen)) | |
173 return(FAIL); | |
174 DEBUG(7, "ewrdata planning to send %ld bytes to remote.\n", msglen); | |
175 while ((len = read( fd1, bufr, EBUFSIZ )) > 0) { | |
176 DEBUG(9, "ewrdata writing %d ...", len); | |
177 alarm(msgtime); | |
178 bytes += len; | |
179 putfilesize(bytes); | |
180 ret = (*Write)(fn, bufr, (unsigned) len); | |
181 alarm(0); | |
182 DEBUG(9, "ewrdata ret %d\n", ret); | |
183 if (ret != len) | |
184 return(FAIL); | |
185 if ((msglen -= len) <= 0) | |
186 break; | |
187 } | |
188 if (len < 0 || (len == 0 && msglen != 0)) return(FAIL); | |
189 return(SUCCESS); | |
190 } | |
191 | |
192 /* | |
193 * read data from link and | |
194 * write into file | |
195 * fp2 -> file descriptor | |
196 * fn -> link descriptor | |
197 * returns: | |
198 * SUCCESS -> ok | |
199 * FAIL -> failure on link | |
200 */ | |
201 int | |
202 erddata(fn, fp2) | |
203 FILE *fp2; | |
204 { | |
205 int ret; | |
206 int fd2; | |
207 char bufr[EBUFSIZ]; | |
208 int len; | |
209 long msglen, bytes; | |
210 char cmsglen[EMESGLEN], *cptr, *erdptr = Erdstash; | |
211 | |
212 DEBUG(9, "erddata wants %d\n", sizeof(cmsglen)); | |
213 if (Erdlen > 0) { | |
214 DEBUG(9, "%d bytes stashed\n", Erdlen); | |
215 if (Erdlen >= sizeof(cmsglen)) { | |
216 memcpy(cmsglen, erdptr, sizeof(cmsglen)); | |
217 Erdlen -= sizeof(cmsglen); | |
218 erdptr += sizeof(cmsglen); | |
219 ret = len = 0; | |
220 } else { | |
221 memcpy(cmsglen, Erdstash, Erdlen); | |
222 cptr = cmsglen + Erdlen; | |
223 len = sizeof(cmsglen) - Erdlen; | |
224 ret = erdblk(cptr, len, fn); | |
225 Erdlen = 0; | |
226 } | |
227 } else { | |
228 len = sizeof(cmsglen); | |
229 ret = erdblk(cmsglen, sizeof(cmsglen), fn); | |
230 } | |
231 if (ret != len) | |
232 return(FAIL); | |
233 ret = SUCCESS; | |
234 sscanf(cmsglen, "%ld", &msglen); | |
235 if ( ((msglen-1)/512 +1) > Ulimit ) | |
236 ret = EFBIG; | |
237 DEBUG(7, "erddata file is %ld bytes\n", msglen); | |
238 fd2 = fileno( fp2 ); | |
239 | |
240 if (Erdlen > 0) { | |
241 DEBUG(9, "%d bytes stashed\n", Erdlen); | |
242 if (write(fileno(fp2), erdptr, Erdlen) != Erdlen) | |
243 return(FAIL); | |
244 msglen -= Erdlen; | |
245 Erdlen = 0; | |
246 DEBUG(7, "erddata remainder is %ld bytes\n", msglen); | |
247 } | |
248 | |
249 for (;;) { | |
250 len = erdblk(bufr, (int) MIN(msglen, EBUFSIZ), fn); | |
251 DEBUG(9, "erdblk ret %d\n", len); | |
252 if (len < 0) { | |
253 DEBUG(7, "erdblk failed\n%s", ""); | |
254 return(FAIL); | |
255 } | |
256 | |
257 /* | |
258 * handle the case for remote socket close. | |
259 */ | |
260 if (len == 0) { | |
261 ret = errno; | |
262 DEBUG(7, "erddata: remote socket closed, errno %d\n", | |
263 ret); | |
264 break; | |
265 } | |
266 bytes += len; | |
267 putfilesize(bytes); | |
268 if ((msglen -= len) < 0) { | |
269 DEBUG(7, "erdblk read too much\n%s", ""); | |
270 return(FAIL); | |
271 } | |
272 /* this write is to file -- use write(2), not (*Write) */ | |
273 if ( ret == SUCCESS && write( fd2, bufr, len ) != len ) { | |
274 ret = errno; | |
275 DEBUG(7, "erddata: write to file failed, errno %d\n", ret); | |
276 } | |
277 if (msglen == 0) | |
278 break; | |
279 } | |
280 return(ret); | |
281 } | |
282 | |
283 /* | |
284 * read block from link | |
285 * reads are timed | |
286 * blk -> address of buffer | |
287 * len -> size to read | |
288 * fn -> link descriptor | |
289 * returns: | |
290 * FAIL -> link error timeout on link | |
291 * i -> # of bytes read (must not be 0) | |
292 */ | |
293 int | |
294 erdblk(blk, len, fn) | |
295 char *blk; | |
296 { | |
297 int i, ret; | |
298 | |
299 if(setjmp(Failbuf)) { | |
300 DEBUG(7, "timeout (%d sec)\n", msgtime); | |
301 return(FAIL); | |
302 } | |
303 | |
304 alarm(msgtime); | |
305 for (i = 0; i < len; i += ret) { | |
306 DEBUG(9, "erdblk ask %d ", len - i); | |
307 if ((ret = (*Read)(fn, blk, (unsigned) len - i)) < 0) { | |
308 alarm(0); | |
309 DEBUG(7, "erdblk read failed\n%s", ""); | |
310 return(FAIL); | |
311 } | |
312 DEBUG(9, "erdblk got %d\n", ret); | |
313 if (ret == 0) | |
314 break; | |
315 blk += ret; | |
316 } | |
317 alarm(0); | |
318 return(i); | |
319 } | |
320 | |
321 struct tbuf { | |
322 long t_nbytes; | |
323 char t_data[TBUFSIZE]; | |
324 }; | |
325 | |
326 /* | |
327 * read message from link | |
328 * str -> message buffer | |
329 * fn -> file descriptor | |
330 * return | |
331 * FAIL -> read timed out | |
332 * SUCCESS -> ok message in str | |
333 */ | |
334 int | |
335 trdmsg(str, fn) | |
336 char *str; | |
337 { | |
338 return(etrdmsg(str, fn, TPACKSIZE)); | |
339 } | |
340 | |
341 /* | |
342 * write message across link | |
343 * type -> message type | |
344 * str -> message body (ascii string) | |
345 * fn -> link file descriptor | |
346 * return | |
347 * FAIL -> write failed | |
348 * SUCCESS -> write succeeded | |
349 */ | |
350 int | |
351 twrmsg(type, str, fn) | |
352 char type; | |
353 char *str; | |
354 { | |
355 return(etwrmsg(type, str, fn, TPACKSIZE)); | |
356 } | |
357 | |
358 /* | |
359 * read data from file fp1 and write on link | |
360 * fp1 -> file descriptor | |
361 * fn -> link descriptor | |
362 * returns: | |
363 * FAIL ->failure in link | |
364 * SUCCESS -> ok | |
365 */ | |
366 int | |
367 twrdata(fp1, fn) | |
368 FILE *fp1; | |
369 int fn; | |
370 { | |
371 int ret; | |
372 int len; | |
373 unsigned long bytes; | |
374 struct tbuf bufr; | |
375 struct stat statbuf; | |
376 | |
377 if (setjmp(Failbuf)) { | |
378 DEBUG(7, "twrdata failed\n", 0); | |
379 return(FAIL); | |
380 } | |
381 fstat(fileno(fp1), &statbuf); | |
382 bytes = 0L; | |
383 while ((len = read(fileno(fp1), bufr.t_data, TBUFSIZE)) > 0) { | |
384 bufr.t_nbytes = htonl((long)len); | |
385 DEBUG(7, "twrdata writing %d ...", len); | |
386 bytes += len; | |
387 putfilesize(bytes); | |
388 len += sizeof(long); | |
389 alarm(msgtime); | |
390 ret = (*Write)(fn, (char *)&bufr, (unsigned) len); | |
391 alarm(0); | |
392 DEBUG(7, "ret %d\n", ret); | |
393 if (ret != len) | |
394 return(FAIL); | |
395 if (len != TBUFSIZE+sizeof(long)) | |
396 break; | |
397 } | |
398 bufr.t_nbytes = 0; | |
399 alarm(msgtime); | |
400 ret = write(fn, (char *)&bufr, sizeof(long)); | |
401 alarm(0); | |
402 if (ret != sizeof(long)) | |
403 return FAIL; | |
404 return(SUCCESS); | |
405 } | |
406 | |
407 /* | |
408 * read data from link and write into file | |
409 * fp2 -> file descriptor | |
410 * fn -> link descriptor | |
411 * returns: | |
412 * SUCCESS -> ok | |
413 * FAIL -> failure on link | |
414 */ | |
415 int | |
416 trddata(fn, fp2) | |
417 FILE *fp2; | |
418 { | |
419 int len, nread; | |
420 long Nbytes; | |
421 unsigned long bytes = 0L; | |
422 char bufr[TBUFSIZE]; | |
423 | |
424 for (;;) { | |
425 len = erdblk((char *)&Nbytes, sizeof(Nbytes), fn); | |
426 DEBUG(7, "trddata ret %d\n", len); | |
427 if (len != sizeof(Nbytes)) | |
428 return(FAIL); | |
429 Nbytes = ntohl(Nbytes); | |
430 DEBUG(7,"trddata expecting %ld bytes\n", Nbytes); | |
431 nread = Nbytes; | |
432 if (nread == 0) | |
433 break; | |
434 len = erdblk(bufr, nread, fn); | |
435 if (len != Nbytes) | |
436 return(FAIL); | |
437 bytes += len; | |
438 putfilesize(bytes); | |
439 if (write(fileno(fp2), bufr, len) != len) | |
440 return(FAIL); | |
441 } | |
442 return(SUCCESS); | |
443 } | |
444 | |
445 /* | |
446 * read message from link | |
447 * str -> message buffer | |
448 * fn -> file descriptor | |
449 * i -> if non-zero, amount to read; o.w., read up to '\0' | |
450 * return | |
451 * FAIL -> read timed out | |
452 * SUCCESS -> ok message in str | |
453 * | |
454 * 'e' is fatally flawed -- in a byte stream world, rdmsg can pick up | |
455 * the cmsglen on a R request. if this happens, we stash the excess | |
456 * where rddata can pick it up. | |
457 */ | |
458 | |
459 int | |
460 etrdmsg(str, fn, i) | |
461 char *str; | |
462 int i; | |
463 { | |
464 int len; | |
465 int nullterm = 0; | |
466 char *null, *argstr; | |
467 | |
468 | |
469 if (i == 0) { | |
470 DEBUG(9, "etrdmsg looking for null terminator\n", 0); | |
471 nullterm++; | |
472 i = EBUFSIZ; | |
473 argstr = str; | |
474 } | |
475 | |
476 if(setjmp(Failbuf)) { | |
477 DEBUG(7, "timeout (%d sec)\n", msgtime); | |
478 return(FAIL); | |
479 } | |
480 | |
481 alarm(msgtime); | |
482 for (;;) { | |
483 DEBUG(9, "etrdmsg want %d ...", i); | |
484 len = (*Read)(fn, str, i); | |
485 DEBUG(9, "got %d\n", len); | |
486 if (len == 0) | |
487 continue; /* timeout will get this */ | |
488 if (len < 0) { | |
489 alarm(0); | |
490 return(FAIL); | |
491 } | |
492 str += len; | |
493 i -= len; | |
494 if (nullterm) { | |
495 /* no way can a msg be as long as EBUFSIZ-1 ... */ | |
496 *str = 0; | |
497 null = strchr(argstr, '\0'); | |
498 if (null != str) { | |
499 null++; /* start of stash */ | |
500 memcpy(Erdstash + Erdlen, null, str - null); | |
501 Erdlen += str - null; | |
502 break; | |
503 } else | |
504 argstr = str; | |
505 } else { | |
506 if (i == 0) | |
507 break; | |
508 } | |
509 } | |
510 alarm(0); | |
511 return(SUCCESS); | |
512 } | |
513 | |
514 /* | |
515 * write message across link | |
516 * type -> message type | |
517 * str -> message body (ascii string) | |
518 * fn -> link file descriptor | |
519 * len -> if non-zero, amount to write; | |
520 o.w., write up to '\0' (inclusive) | |
521 * return | |
522 * FAIL -> write failed | |
523 * SUCCESS -> write succeeded | |
524 */ | |
525 int | |
526 etwrmsg(type, str, fn, len) | |
527 char type; | |
528 char *str; | |
529 int fn, len; | |
530 { | |
531 char bufr[EBUFSIZ], *endstr; | |
532 int ret; | |
533 | |
534 bufr[0] = type; | |
535 | |
536 /* point endstr to last character to be sent */ | |
537 if ((endstr = strchr(str, '\n')) != 0) | |
538 *endstr = 0; | |
539 else | |
540 endstr = str + strlen(str); | |
541 | |
542 memcpy(bufr+1, str, (endstr - str) + 1); /* include '\0' */ | |
543 if (len == 0) | |
544 len = (endstr - str) + 2; /* include bufr[0] and '\0' */ | |
545 else | |
546 bufr[len-1] = 0; /* 't' needs this terminator */ | |
547 | |
548 | |
549 if (setjmp(Failbuf)) { | |
550 DEBUG(7, "etwrmsg write failed\n", 0); | |
551 return(FAIL); | |
552 } | |
553 DEBUG(9, "etwrmsg want %d ... ", len); | |
554 alarm(msgtime); | |
555 ret = (*Write)(fn, bufr, (unsigned) len); | |
556 alarm(0); | |
557 DEBUG(9, "sent %d\n", ret); | |
558 if (ret != len) | |
559 return(FAIL); | |
560 return(SUCCESS); | |
561 } | |
562 #endif /* E_PROTOCOL */ |