/* dc42wrap: wrap a "raw" floppy image as an Apple DiskCopy 4.2 file */
/* Eric P. Scott, ana-systems, June 1998 */
/* MacBinary III support added September 1998 */
/* AppleSingle support added November 1998 */

/*
 * Copyright 1998 by Eric P. Scott.  All rights reserved.
 *
 * This software is "freeware" but is not in the public domain.
 *
 * The author grants you a nonexclusive royalty-free license to copy,
 * redistribute, and use this software for any purpose provided that
 * source distributions retain this entire copyright and license.
 * You may not sublicense or distribute modified versions to anyone else
 * except as part of another product or program, and modified versions
 * must be so labeled.
 *
 * You are encouraged to give proper credit to the author in binary
 * distributions and associated documentation.
 *
 * This software is provided "as is" with no warranties of any kind,
 * including the warranties of merchantability and fitness for a
 * particular purpose.
 */

/* On some platforms, you can make "smaller" executables */
/* SunOS 4.1.x: cc -o dc42wrap -s -n -Bdynamic -O dc42wrap.c */
/* NEXTSTEP 3.x: cc -o dc42wrap -s -object -O2 -g dc42wrap.c */

/* Compile with -DGENERATE_MACBINARY_III if you really want MacBinary III */
/* (I don't recommend it.) */
/* See <URL:http://www.lazerware.com/formats/macbinary.html> */

#ifdef __SVR4
#define USE_MEMSET 1
#else
#ifdef linux
/* Linux has bzero(); the man page advocates a less efficient replacement */
#define USE_MEMSET 1
#endif
#ifndef hpux
/* "should" be HAVE_TM_GMTOFF, but autoconf set this confusing precedent */
#define HAVE_TM_ZONE 1
#endif
#endif

#ifdef NeXT
#include <bsd/libc.h>
#else
#include <stdio.h>
#ifdef __STRICT_BSD__
#include <strings.h>
#else
#include <string.h>
#endif
#ifndef __tm_gmtoff
/* compensate for GNU/Linux lossage */
#define __tm_gmtoff tm_gmtoff
#endif
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif

#ifndef lint
static char sccsid[]="@(#)dc42wrap.c	0.4.2 (ana-systems) 11/23/98";
#endif

#ifndef AUX
#ifdef NeXT
/* NEXTSTEP Encoding to Mac Roman Encoding */
#ifdef __STDC__
const
#endif
unsigned char nsetomac[]={
	  0,   1,   2,   3,   4,   5,   6,   7,
	  8,   9,  10,  11,  12,  13,  14,  15,
	 16,  17,  18,  19,  20,  21,  22,  23,
	 24,  25,  26,  27,  28,  29,  30,  31,
	 32,  33,  34,  35,  36,  37,  38,  39,
	 40,  41,  42,  43,  44,  45,  46,  47,
	 48,  49,  50,  51,  52,  53,  54,  55,
	 56,  57,  58,  59,  60,  61,  62,  63,
	 64,  65,  66,  67,  68,  69,  70,  71,
	 72,  73,  74,  75,  76,  77,  78,  79,
	 80,  81,  82,  83,  84,  85,  86,  87,
	 88,  89,  90,  91,  92,  93,  94,  95,
	 96,  97,  98,  99, 100, 101, 102, 103,
	104, 105, 106, 107, 108, 109, 110, 111,
	112, 113, 114, 115, 116, 117, 118, 119,
	120, 121, 122, 123, 124, 125, 126, 127,
	202, 203, 231, 229, 204, 128, 129, 130,
	233, 131, 230, 232, 237, 234, 235, 236,
	 32, 132, 241, 238, 239, 205, 133, 244,
	242, 243, 134,  32,  32, 181,  32, 214,
	169, 193, 162, 163, 218, 180, 196, 164,
	219,  32, 210, 199, 220, 221, 222, 223,
	168, 208, 160, 224, 225,  32, 166, 165,
	226, 227, 211, 200, 201, 228, 194, 192,
	 32, 212, 171, 246, 247, 248, 249, 250,
	172,  32, 251, 252,  32, 253, 254, 255,
	209, 177,  32,  32,  32, 136, 135, 137,
	139, 138, 140, 141, 143, 142, 144, 145,
	147, 174, 146, 187, 148, 149,  32, 150,
	 32, 175, 206, 188, 152, 151, 153, 155,
	154, 190, 157, 156, 158, 245, 159,  32,
	 32, 191, 207, 167,  32, 216,  32,  32
};
#else
/* ISO Latin 1 Encoding to Mac Roman Encoding */
#ifdef __STDC__
const
#endif
unsigned char iso1tomac[]={
	  0,   1,   2,   3,   4,   5,   6,   7,
	  8,   9,  10,  11,  12,  13,  14,  15,
	 16,  17,  18,  19,  20,  21,  22,  23,
	 24,  25,  26,  27,  28,  29,  30,  31,
	 32,  33,  34,  35,  36,  37,  38,  39,
	 40,  41,  42,  43,  44,  45,  46,  47,
	 48,  49,  50,  51,  52,  53,  54,  55,
	 56,  57,  58,  59,  60,  61,  62,  63,
	 64,  65,  66,  67,  68,  69,  70,  71,
	 72,  73,  74,  75,  76,  77,  78,  79,
	 80,  81,  82,  83,  84,  85,  86,  87,
	 88,  89,  90,  91,  92,  93,  94,  95,
	 96,  97,  98,  99, 100, 101, 102, 103,
	104, 105, 106, 107, 108, 109, 110, 111,
	112, 113, 114, 115, 116, 117, 118, 119,
	120, 121, 122, 123, 124, 125, 126, 127,
	 32,  32,  32,  32,  32,  32,  32,  32,
	 32,  32,  32,  32,  32,  32,  32,  32,
	245, 212, 171, 246, 247, 248, 249, 250,
	172,  32, 251, 252,  32, 253, 254, 255,
	202, 193, 162, 163, 219, 180,  32, 164,
	172, 169, 187, 199, 194, 208, 168, 248,
	161, 177,  32,  32, 171, 181, 166, 225,
	252,  32, 188, 200,  32,  32,  32, 192,
	203, 231, 229, 204, 128, 129, 174, 130,
	233, 131, 230, 232, 237, 234, 235, 236,
	 32, 132, 241, 238, 239, 205, 133,  32,
	175, 244, 242, 243, 134,  32,  32, 167,
	136, 135, 137, 139, 138, 140, 190, 141,
	143, 142, 144, 145, 147, 146, 148, 149,
	 32, 150, 152, 151, 153, 155, 154, 214,
	191, 157, 156, 158, 159,  32,  32, 216
};
#endif
#endif

/* See <URL:ftp://ftp.apple.com/dts/aii/ftn/ftn-e0-0005>
 *
 *     DiskCopy 4.2 Image Header
 *    +---------------+---------------+---------------+---------------+
 *  0 | name                                                          |
 *    ~                                                               ~
 *    |                                                               |
 *    +---------------------------------------------------------------+
 * 64 | dataSize=1474560L (1440K) : 737280L (720K)                    |
 *    +---------------------------------------------------------------+
 * 68 | tagSize=0L                                                    |
 *    +---------------------------------------------------------------+
 * 72 | dataChecksum                                                  |
 *    +---------------------------------------------------------------+
 * 76 | tagChecksum=0L                                                |
 *    +---------------+---------------+-------------------------------+
 * 80 | diskFormat=3:2|formatByte=0x22| private=0x100                 |
 *    +---------------+---------------+-------------------------------+
 * 84
 */

static unsigned char imgh[84]={
	/* name */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	/* dataSize */
	0x00, 0x16, 0x80, 0x00,
	/* tagSize */
	0x00, 0x00, 0x00, 0x00,
	/* dataChecksum */
	0x00, 0x00, 0x00, 0x00,
	/* tagChecksum */
	0x00, 0x00, 0x00, 0x00,
	/* diskFormat */
	0x03,
	/* formatByte */
	0x22,
	/* private */
	0x01, 0x00
};

/* 359-byte resource fork template */
/* padded to 128-byte multiple for MacBinary II */
static unsigned char rsrcfork[384]={
	/* resource header */
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x35,
	0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x32,
	/* next 240 bytes reserved for resource manager */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	/* resource data */
	0x00, 0x00, 0x00, 0x31,   48,  '4',  '.',  '2',
	 ',',  ' ',  't',  'a',  'g',  ' ',  'c',  'h',
	 'k',  's',  'u',  'm',  '=',  '$',  '0',  '0',
	 '0',  '0',  '0',  '0',  '0',  '0',  ',',  ' ',
	 'd',  'a',  't',  'a',  ' ',  'c',  'h',  'k',
	 's',  'u',  'm',  '=',  '$',  '?',  '?',  '?',
	 '?',  '?',  '?',  '?',  '?', 0x00, 0x00, 0x01,
	0x00, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x00,
	0x35, 0x00, 0x00, 0x00, 0x32, 0xde, 0xad, 0xbe,
	0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x1c, 0x00,
	0x32, 0x00, 0x00,  'd',  'C',  'p',  'y', 0x00,
	0x00, 0x00, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x00,
	0x00, 0x00, 0x00, 0xfe, 0xed, 0xfa, 0xce
};

#ifdef __STDC__
int
main(int argc, char *argv[])
#else
main(argc, argv)
int argc;
char *argv[];
#endif
{
#ifdef __STDC__
	void writembh(FILE *, const char *,
		unsigned long, unsigned long, long),
	writeash(FILE *, const char *,
		unsigned long, unsigned long, long, long);
#else
	void writembh(), writeash();
#endif
	extern int optind;
	extern char *optarg;
	register char *p, *b;
	register int c;
	register unsigned long s, n;
	int fmt, named;
	struct stat st;
	char *hname, hbuf[64];

	hname=(char *)NULL;
	fmt=0;
	named=0;
	while ((c=getopt(argc, argv, "H:mn:rs"))!=EOF) switch (c) {
	case 'm':
		if (fmt) {
		fmt1:
			(void)fprintf(stderr,
"%s: only one -r, -m, or -s may be specified\n", *argv);
			exit(1);
		}
		fmt=2;
		break;
	case 'r':
		if (fmt) goto fmt1;
		fmt=1;
		break;
	case 's':
		if (fmt) goto fmt1;
		fmt=3;
		break;
	case 'n':
		if (named) {
			(void)fprintf(stderr,
				"%s: only one -n may be specified\n", *argv);
			exit(1);
		}
		b=optarg;
		if ((c=strlen(b))>63) {
			(void)fprintf(stderr,
				"%s: name limited to 63 characters\n", *argv);
			exit(1);
		}
#ifdef __STRICT_BSD__
		p=index(b, ':');
#else
		p=strchr(b, ':');
#endif
		if (p) {
			(void)fprintf(stderr,
				"%s: name may not contain colons\n", *argv);
			exit(1);
		}
		p=(char *)imgh;
		*p++=c;
		while (c>0) {
			if (*b=='.') {
				b++;
				*p++='\245';
				if (--c<=0) break;
			}
			do {
#ifdef AUX
				*p++= *b++;
#else
				*(unsigned char *)p++=
#ifdef NeXT
					nsetomac[*(unsigned char *)b++];
#else
					iso1tomac[*(unsigned char *)b++];
#endif
#endif
			} while (--c>0);
			break;
			/*NOTREACHED*/
		}
		named++;
		break;
	case 'H':
		if (hname) {
			(void)fprintf(stderr,
				"%s: only one -H may be specified\n", *argv);
			exit(1);
		}
		if (strlen(optarg)>63) {
			(void)fprintf(stderr,
				"%s: file name limited to 63 characters\n",
				*argv);
			exit(1);
		}
#ifdef __STRICT_BSD__
		p=index(optarg, ':');
#else
		p=strchr(optarg, ':');
#endif
		if (p) {
			(void)fprintf(stderr,
				"%s: file name may not contain colons\n",
				*argv);
			exit(1);
		}
#ifndef AUX
		for (p=optarg;(c=(int)*(unsigned char *)p++)!=0;)
#ifdef NeXT
			if ((c&~0x7f)!=0&&nsetomac[c]==32)
#else
			if ((c&~0x7f)!=0&&iso1tomac[c]==32)
#endif
			{
				(void)fprintf(stderr,
"%s: invalid character(s) in file name\n", *argv);
				exit(1);
			}
#endif
		hname=optarg;
		break;
	default:
		goto usage;
	}
	if (argc-optind!=2) {
	usage:
		(void)fprintf(stderr,
			"Usage:\n\t%s -r [-n name] in.flp out.image\n", *argv);
		(void)fprintf(stderr,
"\t%s -m [-H out.image] [-n name] in.flp out.image.bin\n", *argv);
		(void)fprintf(stderr,
"\t%s -s [-H out.image] [-n name] in.flp out.image.sgl\n", *argv);
#ifdef GENERATE_MACBINARY_III
		(void)fputs("\t\t-r  [Raw] Data Fork only\n\
\t\t\t(implied type='dImg' creator='dCpy')\n\
\t\t-m  MacBinary III\n\
\t\t-s  AppleSingle\n\
\t\t-H  MacBinary/AppleSingle file name\n\
\t\t-n  Name in disk image header\n", stderr);
#else
		(void)fputs("\t\t-r  [Raw] Data Fork only\n\
\t\t\t(implied type='dImg' creator='dCpy')\n\
\t\t-m  MacBinary II\n\
\t\t-s  AppleSingle\n\
\t\t-H  MacBinary/AppleSingle file name\n\
\t\t-n  Name in disk image header\n", stderr);
#endif
		exit(1);
	}
	if (fmt<=0) {
		(void)fprintf(stderr, "%s: specify one of -m, -r, or -s\n",
			*argv);
		exit(1);
	}
	if (hname&&fmt<2) {
		(void)fprintf(stderr,
			"%s: -H can't be specified with -r\n", *argv);
		exit(1);
	}
	if (!named) {
#ifdef __STRICT_BSD__
		b=rindex(argv[optind], '/');
#else
		b=strrchr(argv[optind], '/');
#endif
		if (!b) b=argv[optind];
		else b++;
		if ((c=strlen(b))>63) c=63;
		p=(char *)imgh;
		*p++=c;
		while (c>0) {
			if (*b=='.') {
				b++;
				*p++='\245';
				if (--c<=0) break;
			}
			do {
				if (*b==':') {
					b++;
					*p++='/';
				}
				else
#ifdef AUX
					*p++= *b++;
#else
					*(unsigned char *)p++=
#ifdef NeXT
					nsetomac[*(unsigned char *)b++];
#else
					iso1tomac[*(unsigned char *)b++];
#endif
#endif
			} while (--c>0);
			break;
			/*NOTREACHED*/
		}
	}
	if (!hname) {
#ifdef __STRICT_BSD__
		b=rindex(argv[argc-1], '/');
#else
		b=strrchr(argv[argc-1], '/');
#endif
		if (!b) b=argv[argc-1];
		else b++;
		p=hbuf;
		if ((c=strlen(b))>0) {
			if (c>4&&((!strcmp(&b[c-4], ".bin"))||
				!strcmp(&b[c-4], ".sgl"))) c-=4;
			if (c>63) c=63;
			do {
				if (*b==':') {
					b++;
					*p++='/';
				}
				else *p++=*b++;
			} while (--c>0);
		}
		*p='\0';
		hname=hbuf;
	}
	p=argv[optind];
	if ((*p!='-'||p[1]!='\0')&&!freopen(p, "r", stdin)) {
		perror(p);
		exit(1);
	}
	(void)fstat(fileno(stdin), &st);
	if ((st.st_mode&S_IFMT)==S_IFDIR) {
		(void)fprintf(stderr, "%s: input can't be a directory\n",
			*argv);
		exit(1);
	}
#ifdef __STDC__
	b=(char *)malloc(1474560u);
#else
	b=(char *)malloc(1474560);
#endif
	if (!b) {
		(void)fprintf(stderr, "%s: malloc() failed!\n", *argv);
		exit(1);
	}
	p=argv[argc-1];
	if ((*p!='-'||p[1]!='\0')&&!freopen(p, "w", stdout)) {
		perror(p);
		exit(1);
	}
	s=0L;
	n=0L;
	p=b;
	while ((c=getchar())!=EOF) {
		if (n>=1474560L) break;
		*p++=c;
		n++;
		s+=(unsigned long)c<<8;
		if ((c=getchar())==EOF) break;
		*p++=c;
		n++;
		s+=(unsigned long)c;
		if (s&1) {
			s>>=1;
			s|=0x80000000L;
		}
		else {
			s>>=1;
			s&=0x7fffffffL;
		}
	}
	imgh[72]=(s>>24)&0xff;	/* dataChecksum */
	imgh[73]=(s>>16)&0xff;
	imgh[74]=(s>>8)&0xff;
	imgh[75]=s&0xff;
	switch ((long)n) {
	case 1474560L:	/* 1440K */
#ifdef NOTDEF
		imgh[65]=0x16;	/* dataSize+1 */
		imgh[66]=0x80;	/* dataSize+2 */
		imgh[80]=0x03;	/* diskFormat */
#endif
		break;
	case 737280L:	/* 720K */
		imgh[65]=0x0b;	/* dataSize+1 */
		imgh[66]=0x40;	/* dataSize+2 */
		imgh[80]=0x02;	/* diskFormat */
		break;
	default:
		(void)fprintf(stderr, "%s: input not 1440K or 720K\n", *argv);
		exit(1);
		break;
	}
	if (fmt>1) (void)sprintf((char *)&rsrcfork[301], "%08lX", s);
	if (fmt==2) writembh(stdout, hname, sizeof imgh+n, 359L, st.st_mtime);
	else if (fmt==3) {
		writeash(stdout, hname, sizeof imgh+n, 359L,
			st.st_mtime, st.st_atime);
#ifdef PACK1
		(void)fwrite((char *)rsrcfork, 1, 359, stdout);
#else
		(void)fwrite((char *)rsrcfork, 1, 360, stdout);
#endif
	}
	(void)fwrite((char *)imgh, sizeof imgh, 1, stdout);
	(void)fwrite(b, 1, n, stdout);
	if (fmt==2) {
		c=128-sizeof imgh; do {
			putc('\0', stdout);
		} while (--c>0);
		(void)fwrite((char *)rsrcfork, 1, 384, stdout);
	}
	(void)fflush(stdout);
	if (ferror(stdout)) {
		(void)fprintf(stderr, "%s: error writing output\n", *argv);
		(void)fflush(stderr);
		p=argv[argc-1];
		if (*p!='-'||p[1]!='\0') (void)ftruncate(fileno(stdout), 0L);
		exit(1);
	}
	exit(0);
}

/* Return offset from GMT */
#ifdef __STDC__
long gmtoff(long when)
#else
long gmtoff(when)
long when;
#endif
{
	register struct tm *tm;

	tm=localtime(&when);
#ifdef CUPERTINO_CENTRIC
	return((tm->tm_isdst>0) ? -25200L : -28800L);
#else
#ifdef HAVE_TM_ZONE
	return(tm->tm_gmtoff);	/* BSD */
#else
#ifdef hpux
	if (tm->tm_isdst<=0) return(-timezone);
	/* the following is technically wrong, but works in the U.S. */
	return(3600L-timezone);
#else /* !hpux */
	return((tm->tm_isdst>0) ? -altzone : -timezone);	/* SVR4 */
#endif /* !hpux */
#endif /* !HAVE_TM_ZONE */
#endif /* !CUPERTINO_CENTRIC */
}

/* See <URL:ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt> */
#ifdef __STDC__
const
#endif
unsigned short crc_ccitt[256]={
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};

/* write MacBinary II header */
/* this is really a structure with misaligned elements, grr */
#ifdef __STDC__
void writembh(FILE *outf, const char *fname,
	unsigned long dlen, unsigned long rlen, long mtime)
#else
void writembh(outf, fname, dlen, rlen, mtime)
FILE *outf;
char *fname;
unsigned long dlen, rlen;
long mtime;
#endif
{
	register unsigned char *p;
	register unsigned short crc;
	register unsigned long when;
	register unsigned char *e;
	register int c;
#ifdef __STDC__
	register const char *b;
#else
	register char *b;
#endif
	unsigned char mbh[128];

#ifdef USE_MEMSET
	memset((void *)mbh, 0, sizeof mbh);
#else
	bzero((char *)mbh, sizeof mbh);
#endif
	b=fname;
	if ((c=strlen(b))>63) c=63;
	p= &mbh[1];
	*p++=c;
	while (c>0) {
		if (*b=='.') {
			b++;
			*p++='\245';
			if (--c<=0) break;
		}
		do {
#ifdef AUX
			*p++= *b++;
#else
			*(unsigned char *)p++=
#ifdef NeXT
				nsetomac[*(unsigned char *)b++];
#else
				iso1tomac[*(unsigned char *)b++];
#endif
#endif
		} while (--c>0);
		break;
		/*NOTREACHED*/
	}
	p=mbh;
	(void)strncpy((char *)&p[65], "dImgdCpy", 8);
#ifdef NOTDEF
	/* my data fork is <16M */
	p[83]=(dlen>>24)&255;	/* data fork length */
#endif
	p[84]=(dlen>>16)&255;
	p[85]=(dlen>>8)&255;
	p[86]=dlen&255;
#ifdef NOTDEF
	/* my resource fork is <64K */
	p[87]=(rlen>>24)&255;	/* resource fork length */
#endif
	p[88]=(rlen>>16)&255;
	p[89]=(rlen>>8)&255;
	p[90]=rlen&255;
	when=(unsigned long)(mtime+2082844800L+gmtoff(mtime));
	p[91]=(when>>24)&255;	/* creation */
	p[92]=(when>>16)&255;
	p[93]=(when>>8)&255;
	p[94]=when&255;
	p[95]=(when>>24)&255;	/* modification */
	p[96]=(when>>16)&255;
	p[97]=(when>>8)&255;
	p[98]=when&255;
#ifdef GENERATE_MACBINARY_III
	p[102]='m'; p[103]='B'; p[104]='I'; p[105]='N';
	p[122]='\202';
#else
	p[122]='\201';
#endif
	p[123]='\201';
	e=p+124;
	/* crc computation adapted from mcvert */
	crc=0;
	do {
		crc^=*p++<<8;
		crc=((crc&255)<<8)^crc_ccitt[(crc>>8)&255];
	} while (p<e);
	*e++=(crc>>8)&255;
	*e=crc&255;
	(void)fwrite((char *)mbh, 1, sizeof mbh, outf);
}

static unsigned char asgl0[98]={
	0x00, 0x05, 0x16, 0x00,		/* magic */
	0x00, 0x02, 0x00, 0x00,		/* version */
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    6,			/* entries */

	   0,    0,    0,    3,		/* entryid=3L (Real Name) */
	0x00, 0x00, 0x00, 0x62,		/* offset */
	   0,    0,    0,    0,		/* length */
	   0,    0,    0,    9,		/* entryid=9L (Finder Info) */
	0x00, 0x00, 0x00, 0x62,		/* offset */
	   0,    0,    0,   32,		/* length=32L */
	   0,    0,    0,    8,		/* entryid=8L (File Dates Info) */
	0x00, 0x00, 0x00, 0x82,		/* offset */
	   0,    0,    0,   16,		/* length=16L */
	   0,    0,    0,    4,		/* entryid=4L (Comment) */
	0x00, 0x00, 0x00, 0x92,		/* offset */
	   0,    0,    0,    0,		/* length */
	   0,    0,    0,    2,		/* entryid=2L (Resource Fork) */
	0x00, 0x00, 0x00, 0x92,		/* offset */
	   0,    0,    0,    0,		/* length */
	   0,    0,    0,    1,		/* entryid=1L (Data Fork) */
	0x00, 0x00, 0x00, 0x92,		/* offset */
	   0,    0,    0,    0		/* length */
}, asgl1[48]={
	 'd',  'I',  'm',  'g',		/* fdType */
	 'd',  'C',  'p',  'y',		/* fdCreator */
	0x01, 0x00,			/* fdFlags */
	   0,    0,			/* fdLocation.v */
	   0,    0,			/* fdLocation.h */
	   0,    0,			/* fdFldr */
	   0,    0,			/* fdIconID */
	   0,    0,    0,    0,    0,    0,	/* fdUnused */
	0x80,				/* fdScript */
	0x00,				/* fdXFlags */
	   0,    0,			/* fdComment */
	   0,    0,    0,    0,		/* fdPutAway */

	0x4b, 0x6d, 0x0c, 0x00,		/* creation */
	0x4b, 0x6d, 0x0c, 0x00,		/* modification */
	0x4b, 0x6d, 0x0c, 0x00,		/* backup */
	0x4b, 0x6d, 0x0c, 0x00		/* access */
};

/* write AppleSingle header */
#ifdef __STDC__
void writeash(FILE *outf, const char *fname,
	unsigned long dlen, unsigned long rlen, long mtime, long atime)
#else
void writeash(outf, fname, dlen, rlen, mtime, atime)
FILE *outf;
char *fname;
unsigned long dlen, rlen;
long mtime, atime;
#endif
{
#ifdef __STDC__
	register const char *p;
#else
	register char *p;
#endif
	register int c;
	register long off;
	
	if ((c=strlen(fname))>63) c=63;
	asgl0[37]=c;
#ifdef PACK1
	off=(long)(98+c);
#else
	/* not required, but not forbidden either */
	off=(long)((101+c)&~3);
#endif
	asgl0[44]=(unsigned char)((off>>8)&0xff);
	asgl0[45]=(unsigned char)(off&0xff);
	off+=32L;
	asgl0[56]=(unsigned char)((off>>8)&0xff);
	asgl0[57]=(unsigned char)(off&0xff);
	off+=16L;
	asgl0[68]=(unsigned char)((off>>8)&0xff);
	asgl0[69]=(unsigned char)(off&0xff);
	asgl0[80]=(unsigned char)((off>>8)&0xff);
	asgl0[81]=(unsigned char)(off&0xff);
#ifdef NOTDEF
	/* my resource fork is <64K */
	asgl0[83]=(unsigned char)((rlen>>16)&0xff);
#endif
	asgl0[84]=(unsigned char)((rlen>>8)&0xff);
	asgl0[85]=(unsigned char)(rlen&0xff);
#ifdef PACK1
	off+=rlen;
#else
#ifdef NOTDEF
	off+=rlen+3L;
	off&=~3L;
#else
	off+=(rlen+3L)&~3L;
#endif
#endif
	asgl0[92]=(unsigned char)((off>>8)&0xff);
	asgl0[93]=(unsigned char)(off&0xff);
#ifdef NOTDEF
	/* my data fork is <16M */
	asgl0[94]=(unsigned char)((dlen>>24)&0xff);
#endif
	asgl0[95]=(unsigned char)((dlen>>16)&0xff);
	asgl0[96]=(unsigned char)((dlen>>8)&0xff);
	asgl0[97]=(unsigned char)(dlen&0xff);
	(void)fwrite((char *)asgl0, 1, sizeof asgl0, outf);
	p=fname;
	while (c>0) {
		if (*p=='.') {
			p++;
			(void)fputc('\245', outf);
			if (--c<=0) break;
		}
		do {
#ifdef AUX
			(void)fputc(*p++, outf);
#else
#ifdef NeXT
			(void)fputc((int)nsetomac[*(unsigned char *)p++],
				outf);
#else
			(void)fputc((int)iso1tomac[*(unsigned char *)p++],
				outf);
#endif
#endif
		} while (--c>0);
		break;
		/*NOTREACHED*/
	}
#ifndef PACK1
	switch (asgl0[37]&3) {
	case 3:
		(void)fputc('\0', outf);
		/*FALL THROUGH*/
	case 0:
		(void)fputc('\0', outf);
		/*FALL THROUGH*/
	case 1:
		(void)fputc('\0', outf);
		/*FALL THROUGH*/
	default:
		break;
	}
#endif
	/* time offsets intended to be compatible with Dartmouth Fetch */
	off=(unsigned long)(mtime-946684800L+gmtoff(mtime));
	asgl1[36]=asgl1[32]=(unsigned char)((off>>24)&0xff);
	asgl1[37]=asgl1[33]=(unsigned char)((off>>16)&0xff);
	asgl1[38]=asgl1[34]=(unsigned char)((off>>8)&0xff);
	asgl1[39]=asgl1[35]=(unsigned char)(off&0xff);
	off=(unsigned long)(atime-946684800L+gmtoff(atime));
	asgl1[44]=(unsigned char)((off>>24)&0xff);
	asgl1[45]=(unsigned char)((off>>16)&0xff);
	asgl1[46]=(unsigned char)((off>>8)&0xff);
	asgl1[47]=(unsigned char)(off&0xff);
	(void)fwrite((char *)asgl1, 1, sizeof asgl1, outf);
}


syntax highlighted by Code2HTML, v. 0.9.1