/*
 * mktsk [-b] infile [outfile]
 *
 *	- convert UNIX a.out file into OS/32 MT task
 *      - '-b' flag means make a bootstrap program
 */

#include <a.out.h>
#include <stdio.h>

struct os_lib {		/* OS/32 Loader Information Block */
	char	l_segt,		/* segment type */
		l_nlib,		/* number of LIBs */
		l_nlu,		/* max number of logical units */
		l_nasn,		/* max number of assigns */
		l_mpri,		/* max priority */
		l_ipri,		/* initial priority */
		l_preg,		/* pure segmentation register */
		l_ncom,		/* number of task common segs */
		l_nlsg,		/* number of library segs */
		l_tatr;		/* task common attributes */
	short	l_opt;		/* task options */
	int	l_segs,		/* size of impure (sectors) */
		l_fw2,		/* num entries ?? */
		l_fw3,		/* max system space ?? */
		l_itsw[2],	/* initial TSW */
		l_psiz,		/* size of pure (sectors) */
		l_prn,		/* sector offset of pure */
		l_segn;		/* last word of segment name ?? */
	char	l_dumn[16];	/* dump file or dummy name ?? */
	int	l_his,		/* patch history pointer */
		l_fill0[4];	/*	-	*/
	char	l_date[8],	/* TET date */
		l_time[8];	/* TET time */
	short	l_nioq,		/* max queued I/O requests */
		l_fill1;	/*	-	*/
	int	l_ctop,		/* last halfword in partition */
		l_utop;		/* impure size (bytes) */
};

struct exec	hdr;		/* a.out header of input file */
struct os_lib	lib;		/* loader information block for output file */
char		buff[256];	/* sector buffer */
int		bootflg;	/* make a bootstrap image */

main(argc, argv)
char **argv;
{
	register len, n;

	if (argc > 1 && argv[1][0] == '-') {
		bootflg++;
		argc--;
		argv++;
	}
	if (argc < 2)
		error("Usage: mktsk [ -b ] infile [ outfile ]");
	close(0);
	if (open(argv[1], 0) != 0)
		error("Can't open %s", argv[1]);
	if (argc > 2) {
		close(1);
		if(creat(argv[2], 0666) != 1)
			error("Can't create %s", argv[2]);
	}
	/*
	 * Read a.out header
	 */
	if (read(0, &hdr, sizeof(hdr)) != sizeof(hdr))
		error("a.out header read error");
	if (hdr.a_magic != A_MAGIC1)
		error("Bad a.out format");
	/*
	 * Make loader information block
	 */
	lib.l_segt = 1;
	lib.l_nlib = 1;
	lib.l_nlu = 15;
	lib.l_mpri = lib.l_ipri = 128;
	lib.l_segs = (hdr.a_text + hdr.a_data + 255) >> 8;
	/* Make sure size is at least 32 sectors, because of bug in P-E LSU */
	if (bootflg && lib.l_segs < 32)
		lib.l_segs = 32;
	lib.l_fw3 = 0xfffff;
	lib.l_itsw[1] = (bootflg? 0x60 : hdr.a_entry);
	lib.l_utop = hdr.a_text + hdr.a_data;
	lib.l_ctop = ((lib.l_utop + (hdr.a_stack? hdr.a_stack: 4096)) & ~255)
			+ 254;

	if (wrsec(1, &lib, sizeof lib))
		error("Loader information block write error");
	/*
	 * Copy text and data
	 */
	for (n = lib.l_segs; n; n--) {
		if ((len = read(0, buff, 256)) > 0) {
			if (wrsec(1, buff, len))
				error("Write error");
		} else if (len < 0)
			error("Read error");
		else
			break;
	}
	/*
	 * Pad with zeroes for bootstrap image
	 */
	for (; n; n--)
		if (wrsec(1, buff, 0))
			error("Write error");
}

/*
 * Write len bytes from addr to fd, null-padding to 256-byte sector
 */
wrsec(fd, addr, len)
char *addr;
{
	register n;
	static char zeroes[256];

	if (len > 0)
		if (write(fd, addr, len) != len)
			return(1);
	if ((n = 256-len) > 0)
		if (write(fd, zeroes, n) != n)
			return(1);
	return(0);
}

error(s, x)
{
	fprintf(stderr, s, x);
	fprintf(stderr, "\n");
	exit(1);
}
