/* 
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/
#ident "$Header: genlib.c 1.2 90/05/02 $@(#)genlib.c	1.2 89/12/06 "

#include <filehdr.h>
#include <aouthdr.h>
#include <scnhdr.h>
#include <stdio.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>

/*
 * Generate a coff format
 * shared library for this 
 * message catalog
 */

/*
 * default addreses for library
 * overridden by -p and -t
 * This is the start offfset , in the file, of the text segment
 * and the size of a text page in the library.
 * For Release 3.2 you need to specify 
 * that things begin in VM page 
 * boundaraies ie 2K
 */
#if u3b2
int text_page = 2048;
int text_start = 2048;
#endif
#if i386
int text_page = 4096;
int text_start = 4096;
#endif
#define TEXT_START text_start
#define TEXT_PAGE text_page
#define DATA_START TEXT_START+TEXT_PAGE

extern char *gettxt();

int
genlib(name,file_data)
char *name;
FILE * file_data;
{
int size;
int data,fd;
int nbytes;
int val,size_lib;
struct filehdr fhdr;
struct aouthdr ahdr;
struct scnhdr  shdr;
struct stat sbuf;
char buf[NBPG];

	/*
	 * I dont want to use
	 * stdio here sorry
	 */
	fflush(file_data);
	data = dup(fileno(file_data));
	fclose(file_data);
	/*
	 * get size of file
	 */
	if (fstat(data,&sbuf) < 0) {
		printf(gettxt("gencat:63","Can't stat input file %s\n"),name);
		fatal();
	}
	size = sbuf.st_size;
	fd=creat(name,0777);
	if (fd == -1) {
		fprintf(stderr,gettxt("gencat:64","Can't Open Shared Library File %s\n"),name);
		fatal();
	}

	/*
	 * Set header and
	 * write it out
	 */
#if u3b2
	fhdr.f_magic = WE32MAGIC;
#endif
#if i386
	fhdr.f_magic = I386MAGIC;
#endif
	fhdr.f_nscns = 4;
	fhdr.f_timdat = time(0L);
#if u3b2
	fhdr.f_symptr = 16432;
	fhdr.f_nsyms = 18;
#endif
#if i386
	fhdr.f_symptr = 8420;
	fhdr.f_nsyms = 24;
#endif
	fhdr.f_opthdr = sizeof(ahdr);
#if u3b2
	fhdr.f_flags = F_BM32RST | F_RELFLG | F_EXEC | F_AR32W ;
#endif
#if i386
	fhdr.f_flags =  F_RELFLG | F_EXEC | F_AR32WR ;
#endif
	if(write(fd,&fhdr,sizeof(fhdr)) != sizeof(fhdr)) {
		fprintf(stderr,gettxt("gencat:65","Can't write filehdr to %s\n"),name);
		fatal();
	}
	/*
	 * now do aouthdr
	 */
	ahdr.magic = 0443;
	ahdr.vstamp = 0;
	ahdr.tsize = size;
	ahdr.dsize = 4;
	ahdr.bsize = 0;
	ahdr.entry = 0;
	ahdr.text_start = 0x0;
	ahdr.data_start = 0x400000;
	if(write(fd,&ahdr,sizeof(ahdr)) != sizeof(ahdr)) {
		fprintf(stderr,gettxt("gencat:66","Can't write aouthdr to %s\n"),name);
		fatal();
	}
	/*
	 * Now text header
	 */
	strcpy(shdr.s_name,".text");
	shdr.s_paddr = 0x0;
	shdr.s_vaddr = 0x0;
	shdr.s_size = size;
	shdr.s_scnptr = TEXT_START;
	shdr.s_relptr = 0;
	shdr.s_lnnoptr = 0;
	shdr.s_nreloc= 0;
	shdr.s_nlnno= 0;
	shdr.s_flags = 0  | STYP_TEXT ;
	if(write(fd,&shdr,sizeof(shdr)) != sizeof(shdr)) {
		fprintf(stderr,gettxt("gencat:67","Can't write TEXT section header to %s\n"),name);
		fatal();
	}
	/*
	 * now data
	 */
	strcpy(shdr.s_name,".data");
	shdr.s_paddr = ahdr.data_start;
	shdr.s_vaddr = ahdr.data_start;
	shdr.s_size = 4;
	shdr.s_scnptr = DATA_START + ((size / TEXT_PAGE) * TEXT_PAGE);
	shdr.s_relptr = 0;
	shdr.s_lnnoptr = 0;
	shdr.s_nreloc= 0;
	shdr.s_nlnno= 0;
	shdr.s_flags = 0  | STYP_DATA ;
	if(write(fd,&shdr,sizeof(shdr)) != sizeof(shdr)) {
		fprintf(stderr,gettxt("gencat:68","Can't write DATA section header to %s\n"),name);
		fatal();
	}
	/* 
	 * now BSS
	 */
	strcpy(shdr.s_name,".bss");
	shdr.s_paddr += 4;
	shdr.s_vaddr += 4;
	shdr.s_size = 0;
	shdr.s_scnptr = 0;
	shdr.s_relptr = 0;
	shdr.s_lnnoptr = 0;
	shdr.s_nreloc= 0;
	shdr.s_nlnno= 0;
	shdr.s_flags = 0  | STYP_BSS ;
	if(write(fd,&shdr,sizeof(shdr)) != sizeof(shdr)) {
		fprintf(stderr,gettxt("gencat:69","Can't write BSS section header to %s\n"),name);
		fatal();
	}
	/* 
	 * now lib
	 */
	strcpy(shdr.s_name,".lib");
	shdr.s_paddr = 0x1;
	shdr.s_vaddr = 0x0;
	/*
	 * size of section
	 * is two ints + name
	 * alignment
	 */
	shdr.s_size = ( (strlen(name) / sizeof(int)) + 3) * sizeof (int);
	shdr.s_scnptr = DATA_START+4 + ((size / TEXT_PAGE) * TEXT_PAGE);
	shdr.s_relptr = 0;
	shdr.s_lnnoptr = 0;
	shdr.s_nreloc= 0;
	shdr.s_nlnno= 0;
	shdr.s_flags = 0  | STYP_LIB ;
	if(write(fd,&shdr,sizeof(shdr)) != sizeof(shdr)) {
		fprintf(stderr,gettxt("gencat:70","Can't write LIB section header to %s\n"),name);
		fatal();
	}
	/*
	 * write data
	 */
	lseek(fd,(long)TEXT_START,0);
	lseek(data,(long)0,0);
	while ((nbytes=read(data,buf,NBPG)) > 0) {
		size -= nbytes;
		if (write(fd,buf,nbytes) != nbytes) {
		    fprintf(stderr,gettxt("gencat:71","Can't write data to %s\n"),name);
		    fatal();
		}
	}
	if (size != 0) {
		fprintf(stderr,gettxt("gencat:72","Read error on %s\n"),name);
		fatal();
	}
	/*
	 * lets fix the  .lib section
	 */
	lseek(fd,(long)shdr.s_scnptr,0);
	/*
	 * total number of words
	 */
	val = shdr.s_size / sizeof(int);
	write(fd,&val,sizeof(int));
	/*
	 * onlt two words before name
	 */
	val = 2;
	write(fd,&val,sizeof(int));
	/*
	 * the name
	 */
	val = strlen(name);
	write(fd,name,val);
	/*
	 * fill to page boundary
	 */
	val = lseek(fd,0L,SEEK_CUR);
	val = NBPG - val % NBPG;
	if (val) {
	    memset(buf,'\0',val);
	    write(fd,buf,val);
	}
}
