[comp.sources.apple2] v001ADM21: Repost of AAF Unpacker

jac@yoko.rutgers.edu (Jonathan A. Chandross) (05/02/91)

Posting-number: Volume 1, Administrivia: 21

This posting is a repost of V1 #1 intended for those of you lacking a
mechanism to unpack AAF (Apple Archive Format) files.

THIS POSTING SHOULD *NOT* BE ARCHIVED.

IT CONTAINS NO NEW SOURCE.

Enjoy.
#################

/*
 *******************************************************************************
 *
 * upaaf.c
 *
 * Unpack an archive in apple format.
 *
 * Another quality product handcrafted with loving care by:
 *	Jonathan A. Chandross
 *	jac@paul.rutgers.edu
 *	November 1990
 *
 * COPYRIGHT 1990 by Jonathan A. Chandross
 * All rights reserved.
 *
 * Use "cc -D SHELL" to compile for use with a shell.
 *
 *******************************************************************************
 */

#include <stdio.h>

/*
 *******************************************************************************
 *
 * Defines
 *
 * EXPORT		function is visible outside this module
 * IMPORT		function is defined outside this module
 * STATIC		function is invisible outside this module
 *
 * LENGTH		length of strings
 *
 *******************************************************************************
 */
#define EXPORT
#define IMPORT	extern
#define LOCAL	static

#define LENGTH	255

/*
 *******************************************************************************
 *
 * main
 *
 * Unpacks a file in Apple Archive Format
 * 
 * Parameters:
 *	argc			number of command line arguments if compiled
 *				for a shell
 *	argv			command line argument vector
 * Locals:
 *	archive_name		name of archive to unpack if not using a
 *				shell
 * Returns:
 *
 * If this program is compiled for use with a shell, the first command line
 * argument is considered to contain the name of the archive to unpack.  If
 * this program is compiled stand-alone, i.e. not for use with a shell, it
 * prompts for the archive to unpack.
 *
 * The SHELL define is an unsightly way to do things, but there is little
 * choice if this program is to be used on an Apple lacking some sort of
 * shell.
 *
 *******************************************************************************
 */
#ifdef SHELL
EXPORT int main(argc, argv)
int		argc;
char		*argv[];
#else
EXPORT int main()
#endif
{
IMPORT	void	unpack();
#ifdef SHELL
IMPORT	void	usage();
#else
char		archive_name[LENGTH];
#endif

#ifdef SHELL
	/*
	 * If we are using a shell, then argv[1] will be the name of the
	 * archive to unpack.
	 */
	if(argc == 2)
		unpack(argv[1]);
	else {
		usage(argv[0]);
		exit(1);
		}
#else
	(void) fputs("Enter name of archive to unpack:", stdout);
	(void) scanf("%s", archive_name);
	unpack(archive_name);
#endif

	return(0);
}

/*
 *******************************************************************************
 *
 * usage
 *
 * Print out a message on how to use this program
 * 
 * Parameters:
 *	object_name		name of object file storing this program
 * Locals:
 * Returns:
 *
 *******************************************************************************
 */
#ifdef SHELL
LOCAL void usage(object_name)
char		*object_name;
{
	(void) fprintf(stderr, "Usage: %s archive-name\n", object_name);
}
#endif

/*
 *******************************************************************************
 *
 * unpack
 *
 * Unpack an archive
 * 
 * Parameters:
 *	archive_file_name	name of archive file to unpack
 * Locals:
 *	buffer			holds each line as it is read out of archive
 *	archive_file		archive file
 *	output_file		current file being unpacked from archive
 * Returns:
 *
 *******************************************************************************
 */
LOCAL void unpack(archive_file_name)
char		*archive_file_name;
{
IMPORT	char	*fgets();
IMPORT	int	fput();
IMPORT	int	strlen();
IMPORT	int	fclose();
IMPORT	FILE	*fopen();
char		buffer[LENGTH];
FILE		*archive_file;
FILE		*output_file = (FILE *)NULL;

	/*
	 * Open the archive file and make sure it exists.
	 */
	if((archive_file = fopen(archive_file_name, "r")) == (FILE *)NULL) {
		(void) fprintf(stderr, "Error: could not open archive '%s'\n",
			archive_file_name);
		exit(1);
		}
	
	/*
	 * As long as the file is not empty, process lines
	 */
	while(fgets(buffer, LENGTH, archive_file) != (char *)NULL) {
		/*
		 * What kind of line do we have? 
		 */
		switch(buffer[0]) {
		     case '=':
			/*
			 * Have a file name.  Remove the trailing newline
			 * from the file-name (left by fgets) by overwriting
			 * with a Null.  Then open the file and verify that
			 * we can write to it.  Skip over the first character
			 * in the file-name (it is an '=') 
			 */
			buffer[strlen(buffer) - 1] = '\0';
			(void) fprintf(stdout, "Unpacking '%s'\n", &buffer[1]);

			/*
			 * If we have an open output file, close it.
			 */
			if(output_file != (FILE *)NULL)
				(void) fclose(output_file);

			if((output_file = fopen(&buffer[1], "w")) ==
			   (FILE *)EOF) {
				(void) fprintf(stderr,
					"Error: could not open '%s'\n", buffer);
				exit(1);
				}
			break;
		     case '-':
			/*
			 * Have a line of source.  Add the line to the output
			 * file without the leading "-".
			 */
			if(output_file == (FILE *)NULL) {
				fputs("Error: no file specified.\n", stderr);
				exit(1);
				}
			else
				(void) fputs(&buffer[1], output_file);
			break;
		     case '+':
			/*
			 * End of archive.  Exit.
			 */
			exit(0);
			break;
		     default:
			/*
			 * Have some other type of line (mail header,
			 * signature, comment, etc.)  Output it.
			 */
			(void) fputs(&buffer[0], stdout);
			break;
		     }
		}
}