AUSAM/source/S/lked.c

Compare this file to the similar file:
Show the results in this format:

#

/*
 * A program to enable shared-data programs to be linked
 */ 

char tmpfile[]	"tmpfile";
char ld[]	"/bin/ld";
char aout[]	"a.out";

main(argc, argv)
int argc;
char *argv[];
{
	register int k;
	register int j;
	register int i;
	int fidi;
	int fido;
	int hdri[8];
	int zero;
	int bsssize;
	int datsize;
	int txtsize;
	int totsize;
	int iobuf[12000];
	int ioleng;
	int textid;


	zero = 0;
	if(argc < 3)
		error("Usage: lked id text.o data.o [ld args]\n");

	/* i.d. */ 
	textid = *argv[1];

	/* get at text file */ 
	if((fidi = open(argv[2], 0)) < 0)
	{
		perror(argv[2]);
		exit(1);
	}
	read(fidi, hdri, sizeof hdri);
	if(hdri[0] != 0407 || hdri[7] != 0)
	{
		prints(2, argv[2]);
		error(" not relocatable\n");
	}
	if((fido = creat(tmpfile, 0600)) < 0)
	{
		perror(tmpfile);
		exit(1);
	}
	txtsize = hdri[1];
	datsize = hdri[2];
	bsssize = hdri[3];
	hdri[1] =+ hdri[3]+hdri[2];	/* merge text, data and bss */ 
	hdri[2] = hdri[3] = 0;
	write(fido, &hdri, sizeof hdri);
	totsize = txtsize+datsize;
	/* copy text */ 
	for(i = totsize; i >= 0; )
	{
		i =- 512;
		ioleng = read(fidi, iobuf, i < 0?i+512:512);
		write(fido, iobuf, ioleng);
	}
	/* make bss look real */ 
	for(i = 0; i < bsssize; i =+ 2)
		write(fido, &zero, 2);

	/* adjust relocation factor */ 
	for(i = totsize; i >= 0; )
	{
		i =- 512;
		ioleng = read(fidi, iobuf, i < 0?i+512:512);
		if(j = ioleng/2)
		{
			do
			{
				if(iobuf[j-1] == 006 || iobuf[j-1] == 004)
					iobuf[j-1] = 002;
				else if(iobuf[j-1] == 007 || iobuf[j-1] == 005)
					iobuf[j-1] = 003;
			}
			while(--j);
		}
		write(fido, iobuf, ioleng);
	}
	/* fix bss relocation */ 
	for(i = 0; i < bsssize; i =+ 2)
		write(fido, &zero, 2);

	/* copy and adjust symbol table */ 
	while(read(fidi, iobuf, 12) == 12)
	{
		if(iobuf[4] == 004 || iobuf[4] == 003)
			iobuf[4] = 002;
		else if(iobuf[4] == 044 || iobuf[4] == 043)
			iobuf[4] = 042;
		write(fido, iobuf, 12);
	}
	close(fidi);
	close(fido);

	if(fork() == 0)
	{
		argv[0] = ld + 5;
		argv[1] = "-rX";
		argv[2] = "tmpfile";
		argv[argc] = 0;
		execv(ld, argv);
		perror(ld);
		exit(1);
	}
	waitx(iobuf);
	if(unlink(tmpfile) < 0)
	{
		perror(tmpfile);
		exit(1);
	}

	if((fidi = open(aout, 2)) < 0)
		error("Can't open a.out\n");
	read(fidi, &hdri, 16);
	if(hdri[0] != 0407 || hdri[7] != 0)
		error("ld output incorrect\n");
	hdri[2] =+ hdri[1]-txtsize;
	hdri[1] = txtsize;
	seek(fidi, 0, 0);
	write(fidi, &hdri, 16);
	totsize = 2*(hdri[1]+hdri[2]);
	if((totsize > sizeof iobuf) || read(fidi, iobuf, totsize) != totsize)
		error("resultant text and data unsuitable\n");
	totsize =/ 4;
	for(k = 0; k < totsize; k++)
	{
		if(iobuf[totsize+k] == 2 && iobuf[k] >= txtsize)
			iobuf[totsize+k] = 4;
		else if(iobuf[totsize+k] == 3)
		{
			if((iobuf[k]+2*k+2) >= txtsize)
				iobuf[k+totsize] = 5;
		}
	}
	seek(fidi, 16, 0);
	totsize =* 4;
	if(write(fidi, iobuf, totsize) != totsize)
		error("write error a.out\n");
	/*
	 * fix up those symbols we changed before
	 */
	while(read(fidi, iobuf, 12) == 12)
	{
		if((iobuf[4] == 002 || iobuf[4] == 042) && iobuf[5] >= txtsize)
		{
			iobuf[4] =+ 1;
			seek(fidi, -12, 1);
			write(fidi, iobuf, 12);
		}
	}
	close(fidi);
	if(fork() == 0)
	{
		argv[0] = ld + 5;
		argv[1] = "-n";
		argv[2] = aout;
		argv[3] = 0;
		execv(ld, argv);
		perror(ld);
		exit(1);
	}
	waitx(iobuf);
	if((fidi = open(aout, 2)) < 0)
	{
		perror(aout);
		exit(1);
	}
	read(fidi, &hdri, 16);
	if(hdri[0] != 0410)
		error("a.out not suitable\n");
	hdri[6] = textid;
	hdri[0] = 0412;
	seek(fidi, 0, 0);
	write(fidi, &hdri, 16);
	close(fidi);
	return(0);
}

error(arg)
{
	prints(2, arg);
	exit(1);
}