xref: /netbsd-src/usr.sbin/mopd/common/file.c (revision f5d3fbbc6ff4a77159fb268d247bd94cb7d7e332)
1 /*	$NetBSD: file.c,v 1.4 1997/10/16 23:24:35 lukem Exp $	*/
2 
3 /*
4  * Copyright (c) 1995-96 Mats O Jansson.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Mats O Jansson.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: file.c,v 1.4 1997/10/16 23:24:35 lukem Exp $");
35 #endif
36 
37 #include "os.h"
38 #include "common.h"
39 #include "file.h"
40 #include "mopdef.h"
41 
42 #ifndef NOAOUT
43 #if defined(__NetBSD__) || defined(__OpenBSD__)
44 #include <sys/exec_aout.h>
45 #endif
46 #if defined(__bsdi__)
47 #define NOAOUT
48 #endif
49 #if defined(__FreeBSD__)
50 #include <sys/imgact_aout.h>
51 #endif
52 #if !defined(MID_VAX)
53 #define MID_VAX 140
54 #endif
55 #endif
56 
57 int	getCLBYTES __P((int));
58 int	getMID __P((int, int));
59 
60 void
61 mopFilePutLX(buf, index, value, cnt)
62 	u_char	       *buf;
63 	int		index, cnt;
64 	u_int32_t	value;
65 {
66 	int i;
67 	for (i = 0; i < cnt; i++) {
68 		buf[index+i] = value % 256;
69 		value = value / 256;
70 	}
71 }
72 
73 void
74 mopFilePutBX(buf, index, value, cnt)
75 	u_char	       *buf;
76 	int		index, cnt;
77 	u_int32_t	value;
78 {
79 	int i;
80 	for (i = 0; i < cnt; i++) {
81 		buf[index+cnt-1-i] = value % 256;
82 		value = value / 256;
83 	}
84 }
85 
86 u_int32_t
87 mopFileGetLX(buf, index, cnt)
88 	u_char	*buf;
89 	int	index, cnt;
90 {
91 	u_int32_t ret = 0;
92 	int i;
93 
94 	for (i = 0; i < cnt; i++) {
95 		ret = ret*256 + buf[index+cnt-1-i];
96 	}
97 
98 	return(ret);
99 }
100 
101 u_int32_t
102 mopFileGetBX(buf, index, cnt)
103 	u_char	*buf;
104 	int	index, cnt;
105 {
106 	u_int32_t ret = 0;
107 	int i;
108 
109 	for (i = 0; i < cnt; i++) {
110 		ret = ret*256 + buf[index+i];
111 	}
112 
113 	return(ret);
114 }
115 
116 void
117 mopFileSwapX(buf, index, cnt)
118 	u_char	*buf;
119 	int	index, cnt;
120 {
121 	int i;
122 	u_char c;
123 
124 	for (i = 0; i < (cnt / 2); i++) {
125 		c = buf[index+i];
126 		buf[index+i] = buf[index+cnt-1-i];
127 		buf[index+cnt-1-i] = c;
128 	}
129 
130 }
131 
132 int
133 CheckMopFile(fd)
134 	int	fd;
135 {
136 	u_char	header[512];
137 	short	image_type;
138 
139 	if (read(fd, header, 512) != 512)
140 		return(-1);
141 
142 	(void)lseek(fd, (off_t) 0, SEEK_SET);
143 
144 	image_type = (u_short)(header[IHD_W_ALIAS+1]*256 +
145 			       header[IHD_W_ALIAS]);
146 
147 	switch(image_type) {
148 		case IHD_C_NATIVE:		/* Native mode image (VAX)   */
149 		case IHD_C_RSX:			/* RSX image produced by TKB */
150 		case IHD_C_BPA:			/* BASIC plus analog         */
151 		case IHD_C_ALIAS:		/* Alias		     */
152 		case IHD_C_CLI:			/* Image is CLI		     */
153 		case IHD_C_PMAX:		/* PMAX system image	     */
154 		case IHD_C_ALPHA:		/* ALPHA system image	     */
155 			break;
156 		default:
157 			return(-1);
158 	}
159 
160 	return(0);
161 }
162 
163 int
164 GetMopFileInfo(fd, load, xfr)
165 	int		fd;
166 	u_int32_t      *load, *xfr;
167 {
168 	u_char		header[512];
169 	short		image_type;
170 	u_int32_t	load_addr, xfr_addr, isd, iha, hbcnt, isize;
171 
172 	if (read(fd, header, 512) != 512)
173 		return(-1);
174 
175 	image_type = (u_short)(header[IHD_W_ALIAS+1]*256 +
176 			       header[IHD_W_ALIAS]);
177 
178 	switch(image_type) {
179 		case IHD_C_NATIVE:		/* Native mode image (VAX)   */
180 			isd = (header[IHD_W_SIZE+1]*256 +
181 			       header[IHD_W_SIZE]);
182 			iha = (header[IHD_W_ACTIVOFF+1]*256 +
183 			       header[IHD_W_ACTIVOFF]);
184 			hbcnt = (header[IHD_B_HDRBLKCNT]);
185 			isize = (header[isd+ISD_W_PAGCNT+1]*256 +
186 				 header[isd+ISD_W_PAGCNT]) * 512;
187 			load_addr = ((header[isd+ISD_V_VPN+1]*256 +
188 				      header[isd+ISD_V_VPN]) & ISD_M_VPN)
189 					* 512;
190 			xfr_addr = (header[iha+IHA_L_TFRADR1+3]*0x1000000 +
191 				    header[iha+IHA_L_TFRADR1+2]*0x10000 +
192 				    header[iha+IHA_L_TFRADR1+1]*0x100 +
193 				    header[iha+IHA_L_TFRADR1]) & 0x7fffffff;
194 			printf("Native Image (VAX)\n");
195 			printf("Header Block Count: %d\n",hbcnt);
196 			printf("Image Size:         %08x\n",isize);
197 			printf("Load Address:       %08x\n",load_addr);
198 			printf("Transfer Address:   %08x\n",xfr_addr);
199 			break;
200 		case IHD_C_RSX:			/* RSX image produced by TKB */
201 			hbcnt = header[L_BBLK+1]*256 + header[L_BBLK];
202 			isize = (header[L_BLDZ+1]*256 + header[L_BLDZ]) * 64;
203 			load_addr = header[L_BSA+1]*256 + header[L_BSA];
204 			xfr_addr  = header[L_BXFR+1]*256 + header[L_BXFR];
205 			printf("RSX Image\n");
206 			printf("Header Block Count: %d\n",hbcnt);
207 			printf("Image Size:         %08x\n",isize);
208 			printf("Load Address:       %08x\n",load_addr);
209 			printf("Transfer Address:   %08x\n",xfr_addr);
210 			break;
211 		case IHD_C_BPA:			/* BASIC plus analog         */
212 			printf("BASIC-Plus Image, not supported\n");
213 			return(-1);
214 			break;
215 		case IHD_C_ALIAS:		/* Alias		     */
216 			printf("Alias, not supported\n");
217 			return(-1);
218 			break;
219 		case IHD_C_CLI:			/* Image is CLI		     */
220 			printf("CLI, not supported\n");
221 			return(-1);
222 			break;
223 		case IHD_C_PMAX:		/* PMAX system image	     */
224 			isd = (header[IHD_W_SIZE+1]*256 +
225 			       header[IHD_W_SIZE]);
226 			iha = (header[IHD_W_ACTIVOFF+1]*256 +
227 			       header[IHD_W_ACTIVOFF]);
228 			hbcnt = (header[IHD_B_HDRBLKCNT]);
229 			isize = (header[isd+ISD_W_PAGCNT+1]*256 +
230 				 header[isd+ISD_W_PAGCNT]) * 512;
231 			load_addr = (header[isd+ISD_V_VPN+1]*256 +
232 				     header[isd+ISD_V_VPN]) * 512;
233 			xfr_addr = (header[iha+IHA_L_TFRADR1+3]*0x1000000 +
234 				    header[iha+IHA_L_TFRADR1+2]*0x10000 +
235 				    header[iha+IHA_L_TFRADR1+1]*0x100 +
236 				    header[iha+IHA_L_TFRADR1]);
237 			printf("PMAX Image \n");
238 			printf("Header Block Count: %d\n",hbcnt);
239 			printf("Image Size:         %08x\n",isize);
240 			printf("Load Address:       %08x\n",load_addr);
241 			printf("Transfer Address:   %08x\n",xfr_addr);
242 			break;
243 		case IHD_C_ALPHA:		/* ALPHA system image	     */
244 			isd = (header[EIHD_L_ISDOFF+3]*0x1000000 +
245 			       header[EIHD_L_ISDOFF+2]*0x10000 +
246 			       header[EIHD_L_ISDOFF+1]*0x100 +
247 			       header[EIHD_L_ISDOFF]);
248 			hbcnt = (header[EIHD_L_HDRBLKCNT+3]*0x1000000 +
249 				 header[EIHD_L_HDRBLKCNT+2]*0x10000 +
250 				 header[EIHD_L_HDRBLKCNT+1]*0x100 +
251 				 header[EIHD_L_HDRBLKCNT]);
252 			isize = (header[isd+EISD_L_SECSIZE+3]*0x1000000 +
253 				 header[isd+EISD_L_SECSIZE+2]*0x10000 +
254 				 header[isd+EISD_L_SECSIZE+1]*0x100 +
255 				 header[isd+EISD_L_SECSIZE]);
256 			load_addr = 0;
257 			xfr_addr = 0;
258 			printf("Alpha Image \n");
259 			printf("Header Block Count: %d\n",hbcnt);
260 			printf("Image Size:         %08x\n",isize);
261 			printf("Load Address:       %08x\n",load_addr);
262 			printf("Transfer Address:   %08x\n",xfr_addr);
263 			break;
264 		default:
265 			printf("Unknown Image (%d)\n",image_type);
266 			return(-1);
267 	}
268 
269 	if (load != NULL) {
270 		*load = load_addr;
271 	}
272 
273 	if (xfr != NULL) {
274 		*xfr  = xfr_addr;
275 	}
276 
277 	return(0);
278 }
279 
280 #ifndef NOAOUT
281 int
282 getMID(old_mid,new_mid)
283 	int	old_mid, new_mid;
284 {
285 	int	mid;
286 
287 	mid = old_mid;
288 
289 	switch (new_mid) {
290 	case MID_I386:
291 		mid = MID_I386;
292 		break;
293 #ifdef MID_M68K
294 	case MID_M68K:
295 		mid = MID_M68K;
296 		break;
297 #endif
298 #ifdef MID_M68K4K
299 	case MID_M68K4K:
300 		mid = MID_M68K4K;
301 		break;
302 #endif
303 #ifdef MID_NS32532
304 	case MID_NS32532:
305 		mid = MID_NS32532;
306 		break;
307 #endif
308 	case MID_SPARC:
309 		mid = MID_SPARC;
310 		break;
311 #ifdef MID_PMAX
312 	case MID_PMAX:
313 		mid = MID_PMAX;
314 		break;
315 #endif
316 #ifdef MID_VAX
317 	case MID_VAX:
318 		mid = MID_VAX;
319 		break;
320 #endif
321 #ifdef MID_ALPHA
322 	case MID_ALPHA:
323 		mid = MID_ALPHA;
324 		break;
325 #endif
326 #ifdef MID_MIPS
327 	case MID_MIPS:
328 		mid = MID_MIPS;
329 		break;
330 #endif
331 #ifdef MID_ARM6
332 	case MID_ARM6:
333 		mid = MID_ARM6;
334 		break;
335 #endif
336 	default:
337 	}
338 
339 	return(mid);
340 }
341 
342 int
343 getCLBYTES(mid)
344 	int	mid;
345 {
346 	int	clbytes;
347 
348 	switch (mid) {
349 #ifdef MID_VAX
350 	case MID_VAX:
351 		clbytes = 1024;
352 		break;
353 #endif
354 	case MID_I386:
355 #ifdef MID_M68K4K
356 	case MID_M68K4K:
357 #endif
358 #ifdef MID_NS32532
359 	case MID_NS32532:
360 #endif
361 	case MID_SPARC:				/* It might be 8192 */
362 #ifdef MID_PMAX
363 	case MID_PMAX:
364 #endif
365 #ifdef MID_MIPS
366 	case MID_MIPS:
367 #endif
368 #ifdef MID_ARM6
369 	case MID_ARM6:
370 #endif
371 		clbytes = 4096;
372 		break;
373 #ifdef MID_M68K
374 	case MID_M68K:
375 #endif
376 #ifdef MID_ALPHA
377 	case MID_ALPHA:
378 #endif
379 #if defined(MID_M68K) || defined(MID_ALPHA)
380 		clbytes = 8192;
381 		break;
382 #endif
383 	default:
384 		clbytes = 0;
385 	}
386 
387 	return(clbytes);
388 }
389 #endif
390 
391 int
392 CheckAOutFile(fd)
393 	int	fd;
394 {
395 #ifdef NOAOUT
396 	return(-1);
397 #else
398 	struct exec ex, ex_swap;
399 	int	mid = -1;
400 
401 	if (read(fd, (char *)&ex, sizeof(ex)) != sizeof(ex))
402 		return(-1);
403 
404 	(void)lseek(fd, (off_t) 0, SEEK_SET);
405 
406 	if (read(fd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap))
407 		return(-1);
408 
409 	(void)lseek(fd, (off_t) 0, SEEK_SET);
410 
411 	mid = getMID(mid, N_GETMID (ex));
412 
413 	if (mid == -1) {
414 		mid = getMID(mid, N_GETMID (ex_swap));
415 	}
416 
417 	if (mid != -1) {
418 		return(0);
419 	} else {
420 		return(-1);
421 	}
422 #endif NOAOUT
423 }
424 
425 int
426 GetAOutFileInfo(fd, load, xfr, a_text, a_text_fill,
427 		a_data, a_data_fill, a_bss, a_bss_fill, aout)
428 	int		 fd;
429 	u_int32_t	*load, *xfr, *a_text, *a_text_fill;
430 	u_int32_t	*a_data, *a_data_fill, *a_bss, *a_bss_fill;
431 	int		 *aout;
432 {
433 #ifdef NOAOUT
434 	return(-1);
435 #else
436 	struct exec ex, ex_swap;
437 	u_int32_t	mid = -1;
438 	u_int32_t	magic, clbytes, clofset;
439 
440 	if (read(fd, (char *)&ex, sizeof(ex)) != sizeof(ex))
441 		return(-1);
442 
443 	(void)lseek(fd, (off_t) 0, SEEK_SET);
444 
445 	if (read(fd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap))
446 		return(-1);
447 
448 	mopFileSwapX((u_char *)&ex_swap, 0, 4);
449 
450 	mid = getMID(mid, N_GETMID (ex));
451 
452 	if (mid == -1) {
453 		mid = getMID(mid, N_GETMID (ex_swap));
454 		if (mid != -1) {
455 			mopFileSwapX((u_char *)&ex, 0, 4);
456 		}
457 	}
458 
459 	if (mid == -1) {
460 		return(-1);
461 	}
462 
463 	if (N_BADMAG (ex)) {
464 		return(-1);
465 	}
466 
467 	switch (mid) {
468 	case MID_I386:
469 #ifdef MID_NS32532
470 	case MID_NS32532:
471 #endif
472 #ifdef MID_PMAX
473 	case MID_PMAX:
474 #endif
475 #ifdef MID_VAX
476 	case MID_VAX:
477 #endif
478 #ifdef MID_ALPHA
479 	case MID_ALPHA:
480 #endif
481 #ifdef MID_ARM6
482 	case MID_ARM6:
483 #endif
484 		ex.a_text  = mopFileGetLX((u_char *)&ex_swap,  4, 4);
485 		ex.a_data  = mopFileGetLX((u_char *)&ex_swap,  8, 4);
486 		ex.a_bss   = mopFileGetLX((u_char *)&ex_swap, 12, 4);
487 		ex.a_syms  = mopFileGetLX((u_char *)&ex_swap, 16, 4);
488 		ex.a_entry = mopFileGetLX((u_char *)&ex_swap, 20, 4);
489 		ex.a_trsize= mopFileGetLX((u_char *)&ex_swap, 24, 4);
490 		ex.a_drsize= mopFileGetLX((u_char *)&ex_swap, 28, 4);
491 		break;
492 #ifdef MID_M68K
493 	case MID_M68K:
494 #endif
495 #ifdef MID_M68K4K
496 	case MID_M68K4K:
497 #endif
498 	case MID_SPARC:
499 #ifdef MID_MIPS
500 	case MID_MIPS:
501 #endif
502 		ex.a_text  = mopFileGetBX((u_char *)&ex_swap,  4, 4);
503 		ex.a_data  = mopFileGetBX((u_char *)&ex_swap,  8, 4);
504 		ex.a_bss   = mopFileGetBX((u_char *)&ex_swap, 12, 4);
505 		ex.a_syms  = mopFileGetBX((u_char *)&ex_swap, 16, 4);
506 		ex.a_entry = mopFileGetBX((u_char *)&ex_swap, 20, 4);
507 		ex.a_trsize= mopFileGetBX((u_char *)&ex_swap, 24, 4);
508 		ex.a_drsize= mopFileGetBX((u_char *)&ex_swap, 28, 4);
509 		break;
510 	default:
511 	}
512 
513 	printf("a.out image (");
514 	switch (N_GETMID (ex)) {
515 	case MID_I386:
516 		printf("i386");
517 		break;
518 #ifdef MID_M68K
519 	case MID_M68K:
520 		printf("m68k");
521 		break;
522 #endif
523 #ifdef MID_M68K4K
524 	case MID_M68K4K:
525 		printf("m68k 4k");
526 		break;
527 #endif
528 #ifdef MID_NS32532
529 	case MID_NS32532:
530 		printf("pc532");
531 		break;
532 #endif
533 	case MID_SPARC:
534 		printf("sparc");
535 		break;
536 #ifdef MID_PMAX
537 	case MID_PMAX:
538 		printf("pmax");
539 		break;
540 #endif
541 #ifdef MID_VAX
542 	case MID_VAX:
543 		printf("vax");
544 		break;
545 #endif
546 #ifdef MID_ALPHA
547 	case MID_ALPHA:
548 		printf("alpha");
549 		break;
550 #endif
551 #ifdef MID_MIPS
552 	case MID_MIPS:
553 		printf("mips");
554 		break;
555 #endif
556 #ifdef MID_ARM6
557 	case MID_ARM6:
558 		printf("arm32");
559 		break;
560 #endif
561 	default:
562 	}
563 	printf(") Magic: ");
564 	switch (N_GETMAGIC (ex)) {
565 	case OMAGIC:
566 		printf("OMAGIC");
567 		break;
568 	case NMAGIC:
569 		printf("NMAGIC");
570 		break;
571 	case ZMAGIC:
572 		printf("ZMAGIC");
573 		break;
574 	case QMAGIC:
575 		printf("QMAGIC");
576 		break;
577 	default:
578 		printf("Unknown %ld", (long) N_GETMAGIC (ex));
579 	}
580 	printf("\n");
581 	printf("Size of text:       %08lx\n", (long)ex.a_text);
582 	printf("Size of data:       %08lx\n", (long)ex.a_data);
583 	printf("Size of bss:        %08lx\n", (long)ex.a_bss);
584 	printf("Size of symbol tab: %08lx\n", (long)ex.a_syms);
585 	printf("Transfer Address:   %08lx\n", (long)ex.a_entry);
586 	printf("Size of reloc text: %08lx\n", (long)ex.a_trsize);
587 	printf("Size of reloc data: %08lx\n", (long)ex.a_drsize);
588 
589 	magic = N_GETMAGIC (ex);
590 	clbytes = getCLBYTES(mid);
591 	clofset = clbytes - 1;
592 
593 	if (load != NULL) {
594 		*load   = 0;
595 	}
596 
597 	if (xfr != NULL) {
598 		*xfr    = ex.a_entry;
599 	}
600 
601 	if (a_text != NULL) {
602 		*a_text = ex.a_text;
603 	}
604 
605 	if (a_text_fill != NULL) {
606 		if (magic == ZMAGIC || magic == NMAGIC) {
607 			*a_text_fill = clbytes - (ex.a_text & clofset);
608 			if (*a_text_fill == clbytes) {
609 				*a_text_fill = 0;
610 			}
611 		} else {
612 			*a_text_fill = 0;
613 	        }
614 	}
615 
616 	if (a_data != NULL) {
617 		*a_data = ex.a_data;
618 	}
619 
620 	if (a_data_fill != NULL) {
621 		if (magic == ZMAGIC || magic == NMAGIC) {
622 			*a_data_fill = clbytes - (ex.a_data & clofset);
623 			if (*a_data_fill == clbytes) {
624 				*a_data_fill = 0;
625 			}
626 		} else {
627 			*a_data_fill = 0;
628 	        }
629 	}
630 
631 	if (a_bss != NULL) {
632 		*a_bss  = ex.a_bss;
633 	}
634 
635 	if (a_bss_fill != NULL) {
636 		if (magic == ZMAGIC || magic == NMAGIC) {
637 			*a_bss_fill = clbytes - (ex.a_bss & clofset);
638 			if (*a_bss_fill == clbytes) {
639 				*a_bss_fill = 0;
640 			}
641 		} else {
642 			*a_bss_fill = clbytes -
643 				((ex.a_text+ex.a_data+ex.a_bss) & clofset);
644 			if (*a_text_fill == clbytes) {
645 				*a_text_fill = 0;
646 			}
647 	        }
648 	}
649 
650 	if (aout != NULL) {
651 		*aout = mid;
652 	}
653 
654 	return(0);
655 #endif NOAOUT
656 }
657 
658 int
659 GetFileInfo(fd, load, xfr, aout,
660 	    a_text, a_text_fill, a_data, a_data_fill, a_bss, a_bss_fill)
661 	int	fd, *aout;
662 	u_int32_t	*load, *xfr, *a_text, *a_text_fill;
663 	u_int32_t	*a_data, *a_data_fill, *a_bss, *a_bss_fill;
664 {
665 	int	err;
666 
667 	err = CheckAOutFile(fd);
668 
669 	if (err == 0) {
670 		err = GetAOutFileInfo(fd, load, xfr,
671 				      a_text, a_text_fill,
672 				      a_data, a_data_fill,
673 				      a_bss, a_bss_fill,
674 				      aout);
675 		if (err != 0) {
676 			return(-1);
677 		}
678 	} else {
679 		err = CheckMopFile(fd);
680 
681 		if (err == 0) {
682 			err = GetMopFileInfo(fd, load, xfr);
683 			if (err != 0) {
684 				return(-1);
685 			}
686 			*aout = -1;
687 		} else {
688 			return(-1);
689 		}
690 	}
691 
692 	return(0);
693 }
694 
695 ssize_t
696 mopFileRead(dlslot, buf)
697 	struct dllist *dlslot;
698 	u_char	*buf;
699 {
700 	ssize_t len, outlen;
701 	int	bsz;
702 	int32_t	pos, notdone, total;
703 
704 	if (dlslot->aout == -1) {
705 		len = read(dlslot->ldfd,buf,dlslot->dl_bsz);
706 	} else {
707 		bsz = dlslot->dl_bsz;
708 		pos = dlslot->a_lseek;
709 		len = 0;
710 
711 		total = dlslot->a_text;
712 
713 		if (pos < total) {
714 			notdone = total - pos;
715 			if (notdone <= bsz) {
716 				outlen = read(dlslot->ldfd,&buf[len],notdone);
717 			} else {
718 				outlen = read(dlslot->ldfd,&buf[len],bsz);
719 			}
720 			len = len + outlen;
721 			pos = pos + outlen;
722 			bsz = bsz - outlen;
723 		}
724 
725 		total = total + dlslot->a_text_fill;
726 
727 		if ((bsz > 0) && (pos < total)) {
728 			notdone = total - pos;
729 			if (notdone <= bsz) {
730 				outlen = notdone;
731 			} else {
732 				outlen = bsz;
733 			}
734 			memset(&buf[len], 0, outlen);
735 			len = len + outlen;
736 			pos = pos + outlen;
737 			bsz = bsz - outlen;
738 		}
739 
740 		total = total + dlslot->a_data;
741 
742 		if ((bsz > 0) && (pos < total)) {
743 			notdone = total - pos;
744 			if (notdone <= bsz) {
745 				outlen = read(dlslot->ldfd,&buf[len],notdone);
746 			} else {
747 				outlen = read(dlslot->ldfd,&buf[len],bsz);
748 			}
749 			len = len + outlen;
750 			pos = pos + outlen;
751 			bsz = bsz - outlen;
752 		}
753 
754 		total = total + dlslot->a_data_fill;
755 
756 		if ((bsz > 0) && (pos < total)) {
757 			notdone = total - pos;
758 			if (notdone <= bsz) {
759 				outlen = notdone;
760 			} else {
761 				outlen = bsz;
762 			}
763 			memset(&buf[len], 0, outlen);
764 			len = len + outlen;
765 			pos = pos + outlen;
766 			bsz = bsz - outlen;
767 		}
768 
769 		total = total + dlslot->a_bss;
770 
771 		if ((bsz > 0) && (pos < total)) {
772 			notdone = total - pos;
773 			if (notdone <= bsz) {
774 				outlen = notdone;
775 			} else {
776 				outlen = bsz;
777 			}
778 			memset(&buf[len], 0, outlen);
779 			len = len + outlen;
780 			pos = pos + outlen;
781 			bsz = bsz - outlen;
782 		}
783 
784 		total = total + dlslot->a_bss_fill;
785 
786 		if ((bsz > 0) && (pos < total)) {
787 			notdone = total - pos;
788 			if (notdone <= bsz) {
789 				outlen = notdone;
790 			} else {
791 				outlen = bsz;
792 			}
793 			memset(&buf[len], 0, outlen);
794 			len = len + outlen;
795 			pos = pos + outlen;
796 			bsz = bsz - outlen;
797 		}
798 
799 		dlslot->a_lseek = pos;
800 
801 	}
802 
803 	return(len);
804 }
805