[comp.sources.apple2] v001SRC003: AAF Tools

jac@paul.rutgers.edu (Jonathan A. Chandross) (11/19/90)

Submitted-by: gwyn@brl.mil
Posting-number: Volume 1, Source:3
Archive-name: archive/aaf_gwyn
Architecture: ANY_2
Version-number: 1.00

Enclosed is Doug Gwyn's version of the AAF tools.  These implement
the same functionality as my tools but may be more appropriate to
a different set of C compilers or to your view of how the AAF tools
should work.  

You can unpack this with the upaaf.c program I posted earlier.

Enjoy.

*************************************

=Read.Me
-
-Program:	apack
-Function:	pack text files into archive for convenient shipment
-Author:		Douglas A. Gwyn <Gwyn@BRL.MIL>
-Restrictions:	PUBLIC DOMAIN; no restrictions
-
-This program creates an Apple Archive Format (AAF) archive file that
-contains copies of any number of text files; the corresponding "aunpack"
-program may be used to unpack AAF archives back into a set of text files
-with the same contents as the originals.  AAF archives are suitable for
-transmission of collections of text files, including source code, among
-different computer systems, for example via electronic mail and USEnet
-newsgroups.  AAF is the official archive format for the USEnet
-comp.sources.apple2 newsgroup; the article having subject header
-"V001INF001:  Apple Archive Format" in that newsgroup contains the AAF
-specifications.  Note that AAF is not specific to Apple computers, and
-may be used for archiving text files on practically any computer system.
-AAF archives are intentionally not compressed, so that they may be read
-directly, edited, etc. without having to first be unpacked.
-
-See the "apack" source for instructions and further information.
-
=apack.c
-/*
-	apack -- pack text files into archive for convenient shipment
-
-	This source code is the original creation of Douglas A. Gwyn, who
-	has released it into the PUBLIC DOMAIN; there are no restrictions
-	whatever on its further use.  However, it would be unwise to make
-	altered versions that are incompatible with the AAF specification.
-
-	last edit:	31-Oct-1990	D A Gwyn
-
-	INSTRUCTIONS:	Compile this source using almost any hosted
-	implementation of C, and link with the standard C system library,
-	according to whatever procedures are necessary for your particular
-	environment.  To use this program, you must invoke it from an
-	environment that allows you to specify arguments and/or file
-	redirection.
-
-	Usage:	apack files... > archive
-
-	The specified text files are written into the archive, each file
-	preceded by a header line containing "=" followed by the filename.
-	Each line of file data is preceded by "-".  After all files are
-	written, an additional line consisting of "+END" is appended to
-	the archive.  This conforms to the Apple Archive Format (AAF)
-	used for postings to the USEnet comp.sources.apple2 newsgroup.
-
-	Since file contents are copied untranslated into the archive,
-	it is a good idea to not use control characters in the files,
-	as they may be mangled during transmission of the archive.
-	In particular, embedded carriage-returns might be mapped to
-	new-lines on the target system, resulting in incorrect unpacking
-	of the archive.  It is recommended that text lines not exceed 79
-	characters.  For filenames to be maximally portable, they should
-	each consist of an alphabetic character followed by no more than
-	five alphanumeric characters, optionally followed by a "." then
-	one to three additional alphanumeric characters.
-
-	The archive is printable as it stands; the companion program
-	"aunpack" may be used to unpack the archive into files having the
-	same names as the original files.  Because "aunpack" does not
-	check filenames for "funny" characters, but merely attempts to
-	open the named files for writing, if filenames that are not
-	suitable for the target environment were used, those files may
-	not be extracted; in particular, directory path syntax may not
-	be understood.  Fortunately, it is easy to edit an "apack"ed
-	archive to change the filenames when necessary before unpacking.
-
-	If "aunpack" is not available, an "apack"ed archive can fairly
-	easily be manually unpacked with a decent text editor.
-*/
-
-#include	<stdio.h>
-#ifdef __STDC__
-#include	<stdlib.h>
-#include	<string.h>
-#else
-extern void	exit();
-extern char	*strcat(), *strcpy();
-
-#define EXIT_SUCCESS	0
-#define EXIT_FAILURE	1
-#endif
-
-static char	buffer[BUFSIZ];
-
-int
-main( argc, argv )
-	int	argc;
-	char	*argv[];
-	{
-	register int	i;		/* file number */
-	register FILE	*fp = NULL;	/* input text stream */
-
-	for ( i = 1; i < argc; ++i )
-		if ( (fp = fopen( argv[i], "r" )) == NULL )
-			(void)fprintf( stderr, "apack: can't open \"%s\"\n",
-				       argv[i]
-				     );
-		else	{
-			buffer[0] = '=';
-			/*(void)*/strcpy( &buffer[1], argv[i] );
-			/*(void)*/strcat( &buffer[1], "\n" );
-
-			if ( fputs( buffer, stdout ) == EOF )
-				{
-				(void)fprintf( stderr, "apack: write error\n" );
-				exit( EXIT_FAILURE );
-				}
-
-			buffer[0] = '-';
-
-			while ( fgets( &buffer[1], BUFSIZ - 1, fp ) != NULL )
-				if ( fputs( buffer, stdout ) == EOF )
-					{
-					(void)fprintf( stderr,
-						       "apack: write error\n"
-						     );
-					exit( EXIT_FAILURE );
-					}
-
-			(void)fclose( fp );
-			}
-
-	(void)printf( "+END\n" );
-
-	if ( fflush( stdout ) != 0 )
-		{
-		(void)fprintf( stderr, "apack: write error\n" );
-		exit( EXIT_FAILURE );
-		}
-
-	return EXIT_SUCCESS;
-	}
=aunpack.c
-/*
-	aunpack -- unpack text files from archive for convenient shipment
-
-	This source code is the original creation of Douglas A. Gwyn, who
-	has released it into the PUBLIC DOMAIN; there are no restrictions
-	whatever on its further use.  However, it would be unwise to make
-	altered versions that are incompatible with the PAAF specification.
-
-	last edit:	31-Oct-1990	D A Gwyn
-
-	INSTRUCTIONS:	Save this article, minus the header information,
-	as "aunpack.c".  This particular source is not distributed in
-	PAAF (archived) format, because it is the program that unpacks
-	PAAF files, and if you didn't already have it you would have to
-	manually unpack it, which could be tedious.  Compile this source
-	using almost any hosted implementation of C, and link with the
-	standard C system library, according to whatever procedures are
-	necessary for your particular environment.  It , like the PAAF
-	format, is not Apple-specific, and indeed I use it on several
-	UNIX systems, as well as on my Apple II.  To use this program,
-	you must invoke it from an environment that allows you to specify
-	arguments and/or file redirection.
-
-	Usage:	aunpack [-c] [-r] [-v] < archive
-	or	aunpack [-c] [-r] [-v] archive
-
-	The archive must be in PAAF format, as created by the companion
-	program "apack".  Any line found in the archive that does not
-	start with one of the expected characters ("=", "-", or "+")
-	will be copied to the standard output; anything following a
-	filename header will be sent to that named file.  The -c option
-	permits the continued recognition of tagged lines after a "+"
-	line; the default is for the first "+" to end the archive.  (-c
-	is useful when you have concatenated several PAAF archives into
-	a single file.)  The -r option causes carriage-return characters
-	in the archive to be taken as line terminators; this is not
-	normally necessary, but may be helpful in some special situations.
-	The -v option causes each filename to be printed to the standard
-	error output immediately after successfully opening the file for
-	writing.
-
-	See the "apack" source for further information and the PAAF spec.
-*/
-
-#include	<stdio.h>
-#ifdef __STDC__
-#include	<stdlib.h>
-#include	<string.h>
-#else
-extern void	exit();
-/* #define strchr index	/* if necessary for your system */
-extern char	*strcat(), *strchr(), *strcpy(), *strncpy();
-extern int	strcmp();
-
-#define EXIT_SUCCESS	0
-#define EXIT_FAILURE	1
-#endif
-
-static char	buffer[BUFSIZ];
-static char	iname[BUFSIZ] = { "stdin" };	/* archive input filename */
-static char	oname[BUFSIZ - 1];	/* current output filename */
-static int	status = EXIT_SUCCESS;	/* EXIT_FAILURE if stdout write fails */
-
-int
-main( argc, argv )
-	int	argc;
-	char	*argv[];
-	{
-	register FILE	*ifp = stdin;	/* input stream */
-	register FILE	*ofp = NULL;	/* current output stream */
-	register char	*bp;
-	int		concat = 0;	/* indicates -c flag was specified */
-	int		map_crs = 0;	/* indicates -r flag was specified */
-	int		verbose = 0;	/* indicates -v flag was specified */
-	int		end_seen = 0;	/* indicates "+" record was seen */
-
-	for ( ; argc > 1; ++argv, --argc )
-		if ( strcmp( argv[1], "-v" ) == 0 )
-			verbose = 1;
-		else if ( strcmp( argv[1], "-c" ) == 0 )
-			concat = 1;
-		else if ( strcmp( argv[1], "-r" ) == 0 )
-			map_crs = 1;
-		else			/* not an option */
-			break;
-
-	if ( argc > 1 )
-		if ( (ifp = fopen( argv[1], "r" )) == NULL )
-			{
-			(void)fprintf( stderr, "aunpack: can't open \"%s\"\n",
-				       argv[1]
-				     );
-			exit( EXIT_FAILURE );
-			}
-		else	{
-			iname[0] = '"';
-			/*(void)*/strncpy( &iname[1], argv[1], BUFSIZ - 3 );
-			iname[BUFSIZ - 2] = '\0';	/* just in case */
-			/*(void)*/strcat( &iname[1], "\"" );
-			}
-
-	for ( ; ; )
-		{
-		if ( map_crs )
-			{
-			register int	c;
-
-			bp = buffer;
-
-			do	{
-				if ( (c = getc( ifp )) == EOF )
-					goto eof_or_error;
-
-				if ( c == '\r' )
-					c = '\n';
-
-				*bp++ = c;
-				}
-			while ( c != '\n' && bp < &buffer[BUFSIZ - 1] );
-
-			*bp = '\0';
-			}
-		else
-			if ( fgets( buffer, BUFSIZ, ifp ) == NULL )
-				goto eof_or_error;
-
-		if ( (bp = strchr( buffer, '\n' )) == NULL )
-			{
-			(void)fprintf( stderr,
-				  "aunpack: excessively long input line:\n%s\n",
-				       buffer
-				     );
-			goto look_out;
-			}
-
-		switch ( buffer[0] )
-			{
-		case '=':
-			if ( end_seen && !concat )
-				goto junk_line;
-
-			if ( ofp != NULL && fclose( ofp ) != 0 )
-				goto write_error;
-
-			*bp = '\0';	/* remove new-line */
-
-			/*(void)*/strcpy( oname, &buffer[1] );
-
-			if ( (ofp = fopen( oname, "w" )) == NULL )
-				{
-				(void)fprintf( stderr,
-					       "aunpack: can't create \"%s\"\n",
-					       oname
-					     );
-				exit( EXIT_FAILURE );
-				}
-
-			if ( verbose )
-				(void)fprintf( stderr, "%s\n", oname );
-
-			break;
-
-		case '-':
-			if ( end_seen && !concat )
-				goto junk_line;
-
-			if ( ofp == NULL )
-				{
-				(void)fprintf( stderr,
-					      "aunpack: data before filename\n",
-					       oname
-					     );
-				exit( EXIT_FAILURE );
-				}
-
-			if ( fputs( &buffer[1], ofp ) == EOF )
-				goto write_error;
-
-			break;
-
-		case '+':
-			end_seen = 1;
-
-			if ( ofp != NULL && fclose( ofp ) != 0 )
-				goto write_error;
-
-			ofp = NULL;
-
-			break;		/* keep going, in case of more stdout */
-
-		default:
-    junk_line:
-			if ( status == EXIT_SUCCESS
-			  && fputs( buffer, stdout ) == EOF
-			   )	{
-				(void)fprintf( stderr,
-					       "aunpack: error writing stdout\n"
-					     );
-
-				status = EXIT_FAILURE;	/* keep going, though */
-				}
-
-			break;
-			}
-		}
-
-    write_error:
-
-	(void)fprintf( stderr, "aunpack: error writing \"%s\"\n", oname );
-/*	goto look_out;	*/
-
-    look_out:
-
-	if ( ofp != NULL )
-		(void)fprintf( stderr, "aunpack: \"%s\" may be corrupted!\n",
-			       oname
-			     );
-
-	exit( EXIT_FAILURE );
-
-    eof_or_error:
-
-	if ( ferror( ifp ) )
-		{
-		(void)fprintf( stderr, "aunpack: error reading %s\n", iname );
-		goto look_out;
-		}
-
-	if ( !end_seen )
-		{
-		(void)fprintf( stderr, "aunpack: missing \"+\" record\n" );
-		goto look_out;
-		}
-
-	if ( ofp != NULL && fclose( ofp ) != 0 )
-		{
-		(void)fprintf( stderr, "aunpack: error writing \"%s\"\n", oname
-			     );
-		goto look_out;
-		}
-
-	return status;			/* failure is relatively unimportant */
-	}
-
+ END OF ARCHIVE