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 -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 -#ifdef __STDC__ -#include -#include -#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 -#ifdef __STDC__ -#include -#include -#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