/*
 * binhex -- binhex aufs files
 *
 * if called binhex handles aufs files, if called unxbin handles *.{rsrc,data,info} files
 * will process multiple files
 *
 * Nigel Perry, Aug 90, np@doc.ic.ac.uk
 *
 * This is a hacked version of...
 *
 * unxbin -- convert files generated by xbin or macget into BinHex 4.0 format.
 *
 * David Gentzel, Lexeme Corporation
 *
 * (c) 1985 David Gentzel
 * may be used but not sold without permission
 *
 * This is based on a Unix(tm) program with the same name and function written
 * by ????.  Original was a series of small programs (8to6, crc, etc.) piped
 * together and run by a shell script.  I completely rewrote the system as a
 * C program (speeding it up considerably, needless to say), added run-length
 * compression, and bullet-proofed (at least partly) the thing.  Unfortunately,
 * I have lost the name of the original poster (to net.sources.mac) without
 * whom this would never have appeared.
 *
 * created dbg 09/10/85 -- Version 1.0
 */

#include <stdio.h>
#include "aufs.h"

#ifdef VMS
# define PROGRAMNAME	"unxbin"
# define EXIT_ERROR	((1 << 28) | 2)
# ifndef MAXNAMLEN
#  define MAXNAMLEN	127
#  define MAXBASENAME	63
# endif
#else
# include <sys/types.h>
# include <sys/dir.h>
# define PROGRAMNAME	(argv[0])
# define AUFSNAME	"binhex"
# define EXIT_ERROR	1
# ifndef MAXNAMLEN
#  ifdef DIRSIZ
#   define MAXNAMLEN	DIRSIZ
#  else
#   define MAXNAMLEN	14
#  endif
# endif
# define MAXBASENAME	(MAXNAMLEN - 2)
#endif

extern char *sprintf(), *strrchr();
extern void aufs_gethead(), gethead(), fakehead(), make_buffer_crc(), make_file_crc(),
	    putchar_run();

main(argc, argv)
int argc;
register char *argv[];
{
    register FILE *rsrc, *data, *info;
    char fbuf[256], infobuf[128];
    register char *file;
    int aufs;
    int i;
    FinderInfo fndr_info;

    aufs = strcmp(PROGRAMNAME, AUFSNAME) == 0;

    if (argc < 2)
    {
	fprintf(stderr, "Usage: %s file(s)\n", PROGRAMNAME);
	exit(EXIT_ERROR);
    }

    for(i = 1; i < argc; i++)
    {
#ifdef VMS
	if ((file = strrchr(argv[i], ']')) == NULL)
	    file = strrchr(argv[i], ':');
#else
	file = strrchr(argv[i], '/');
#endif
	if (file)
	    file++;
	else
	    file = argv[i];
	if (strlen(file) > MAXBASENAME)
	    file[MAXBASENAME] = '\0';
	file = argv[i];
	(void) sprintf(fbuf, aufs ? ".resource/%s" : "%s.rsrc", file);
	fbuf[MAXNAMLEN] = '\0';
	rsrc = fopen(fbuf, "r");
	(void) sprintf(fbuf, aufs ? "%s" : "%s.data", file);
	fbuf[MAXNAMLEN] = '\0';
	data = fopen(fbuf, "r");
	if (rsrc == NULL && data == NULL)
	{
	    fprintf(stderr, "No resource or data forks for %s\n", argv[i]);
	    exit(EXIT_ERROR);
	}
	if (rsrc == NULL)
	    fprintf(stderr, "Warning: no resource file %s\n", fbuf);
	if (data == NULL)
	    fprintf(stderr, "Warning: no data file %s\n", fbuf);
	(void) sprintf(fbuf, aufs ? ".finderinfo/%s" : "%s.info", file);
	fbuf[MAXNAMLEN] = '\0';
	info = fopen(fbuf, "r");
	if (info == NULL)
	    fprintf(stderr, "Warning: no info file %s\n", fbuf);

	if(aufs)
	{    /* make the .finderinfo file */
	    FILE *oinfo;

	    sprintf(fbuf, ".finderinfo/%s.Hqx", file);
	    if((oinfo = fopen(fbuf, "w")) == NULL)
	    {   perror(fbuf);
		exit(1);
	    }
	    bzero(&fndr_info, sizeof(FinderInfo));
	    bcopy("TEXT", &fndr_info.fndr_type, 4);
	    bcopy("BnHq", &fndr_info.fndr_creator, 4);
	    fndr_info.fi_magic1 = FI_MAGIC1;
	    fndr_info.fi_version = FI_VERSION;
	    fndr_info.fi_magic = FI_MAGIC;
	    fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
	    strcpy(fndr_info.fi_macfilename, file);
	    fwrite(&fndr_info, sizeof(FinderInfo), 1, oinfo);
	    fclose(oinfo);
	}

	(void) sprintf(fbuf, "%s.Hqx", file);
	fbuf[MAXNAMLEN] = '\0';
	if (freopen(fbuf, "w", stdout) == NULL)
	{
	    fputs("Couldn't open output file.\n", stderr);
	    exit(EXIT_ERROR);
	}
	fputs("(This file must be converted with BinHex 4.0)\n:", stdout);
	if (info != NULL)
	{   if(aufs)
	    {   (void) fread(&fndr_info, sizeof(FinderInfo), 1, info);
		(void) fclose(info);
		aufs_gethead(&fndr_info, data, rsrc, infobuf);
	    }
	    else
	    {   (void) fread(fbuf, 128, 1, info);
		(void) fclose(info);
		gethead(fbuf, infobuf);
	    }
	}
	else
	    fakehead(file, rsrc, data, infobuf);
	make_buffer_crc(infobuf, 20 + infobuf[0]);
	make_file_crc(data);
	if (data != NULL)
	    (void) fclose(data);
	make_file_crc(rsrc);
	if (rsrc != NULL)
	    (void) fclose(rsrc);
	putchar_run(EOF);
	puts(":");
    }
    (void) fclose(stdout);
}
