[net.sources] fpack: plain file

perlman@wanginst.UUCP (Gary Perlman) (12/16/85)

The following program is similar to the shar archiver used to
send files over the net.  One thing I like about shar is that
the recipient only needs the Bourne shell to unpack a bunch of
files, making shell archives a great way to send files to UNIX
machines.  fpack was created to transfer files between machines
where one or both does not have sh.  It is like programs like
tar or cpio that pack and unpack their own archives, but fpack
is more portable, and not something I mind posting to the net,
because I wrote it.  The version here is very simple--it transfers
only plain text files, not directories--but it helped me transfer
100 files to MSDOS and unpack them there (ie, it simplified the
transfer because I could only transfer one file at a time and preferred
to transfer one huge file).  fpack can also be used to save space
because it can place several files in one file.  It is also pretty
safe because it does not code the files; if all else fails, you
can unpack an archive file using a text editor.

Example:
	fpack *.c > archive    -- creates the archive
	rm *.c                 -- get rid of the old files
	transfer archive       -- transfer archive
	fpack < archive        -- unpack archive and create files

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	fpack.1
#	makefile
#	fpack.c
#	fpack.test
# This archive created: Sun Dec 15 20:22:37 1985
# By:	Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'fpack.1'
then
	echo shar: "will not over-write existing file 'fpack.1'"
else
cat << \SHAR_EOF > 'fpack.1'
.TH FPACK 1WI "December 15, 1985" "Wang Institute" "Unix User's Manual"
.SH NAME
fpack \- pack and unpack ascii files with simple archiving scheme
.SH USAGE
.B fpack
[files]
.SH DESCRIPTION
.I fpack
is a simple plain text file archiving scheme to either
reduce the number of files or to package them together.
It is designed to be portable to systems between which
files may be transferred, such as between UNIX and MSDOS.
It can save space on systems that use disk blocks for files that occupy
a small part of a block.
One of the program's requirements is that it does not alter the format
of its input, so files like documents or human readable data files
are not converted to a special format.
.PP
Files are delimited by a special string at the start of a line:
.br
	fpack:!@#$%^&*():	<filename>
.br
.SH NOTES
.PP
Text outside file delimiters in an archive will be ignored.
.PP
If a file does not end with a newline character,
one will be silently added.
.PP
If a file to be unpacked exists,
then it will not be overwritten.
Instead, the contents of the file(s) being unpacked will be discarded.
.SH EXAMPLES
.nf
Pack up some C source files.
	fpack a.c b.c c.c > archive
Unpack all files.
	fpack < archive
.fi
.SH "SEE ALSO"
shar(1), sh(1) make a more flexible archiving scheme for UNIX.
.SH AUTHOR
Gary Perlman
SHAR_EOF
fi
if test -f 'makefile'
then
	echo shar: "will not over-write existing file 'makefile'"
else
cat << \SHAR_EOF > 'makefile'
C=$(CC) $(CFLAGS) -DVERBOSE

fpack: fpack.c
	$C -o fpack fpack.c

test: fpack
	fpack.test

lint:
	lint -hp fpack.c

archive: fpack.1 makefile fpack.c fpack.test
	shar fpack.1 makefile fpack.c fpack.test > archive

fpack.1: fpack.c
	seec -t MANUAL fpack.c > fpack.1

gprof:
	$C -pg -o fpack fpack.c

.PRECIOUS: fpack.c
SHAR_EOF
fi
if test -f 'fpack.c'
then
	echo shar: "will not over-write existing file 'fpack.c'"
else
cat << \SHAR_EOF > 'fpack.c'
/*MANUAL.TH FPACK 1WI "December 15, 1985" "Wang Institute" "Unix User's Manual"
*/

/*MANUAL.SH NAME
fpack \- pack and unpack ascii files with simple archiving scheme
*/

/*MANUAL.SH USAGE
.B fpack
[files]
*/

/*MANUAL.SH DESCRIPTION
.I fpack
is a simple plain text file archiving scheme to either
reduce the number of files or to package them together.
It is designed to be portable to systems between which
files may be transferred, such as between UNIX and MSDOS.
It can save space on systems that use disk blocks for files that occupy
a small part of a block.
One of the program's requirements is that it does not alter the format
of its input, so files like documents or human readable data files
are not converted to a special format.
.PP
Files are delimited by a special string at the start of a line:
.br
	fpack:!@#$%^&*():	<filename>
.br
*/

/*MANUAL.SH NOTES
.PP
Text outside file delimiters in an archive will be ignored.
.PP
If a file does not end with a newline character,
one will be silently added.
.PP
If a file to be unpacked exists,
then it will not be overwritten.
Instead, the contents of the file(s) being unpacked will be discarded.
*/

/*MANUAL.SH EXAMPLES
.nf
Pack up some C source files.
	fpack a.c b.c c.c > archive
Unpack all files.
	fpack < archive
.fi
*/

/*MANUAL.SH "SEE ALSO"
shar(1), sh(1) make a more flexible archiving scheme for UNIX.
*/

/*MANUAL.SH AUTHOR
Gary Perlman
*/


#include <stdio.h>

#ifndef lint
static	char	sccsid[] = "@(#)fpack.c 1.1 (WangInst) 12/15/85";
#endif

#define	MAGIC	"fpack:!@#$%^&*(): " /* default file delimiter */

#ifdef	VERBOSE
#define	blabber(fun,file) fprintf (stderr, "fpack: %s '%s'\n", fun, file)
#else
#define	blabber(fun,file)
#endif

typedef	int       Status;      /* return/exit status of functions */
#define	SUCCESS   ((Status) 0)
#define	FAILURE   ((Status) 1)

/*FUNCTION main */
main (argc, argv)
int 	argc;     /* argument count */
char	**argv;   /* argument vector */
	{
	Status	result = SUCCESS;

	if (argc == 1) /* no files, unpack stdin */
		result = funpack ();
	else
		{
		while (--argc)
			if (fpack (*++argv) == FAILURE)
				result = FAILURE;
		printf ("%s\n", MAGIC); /* end of files */
		}

	exit (result);
	}

/*FUNCTION fpack:	pack files for later extraction by funpack */
Status
fpack (file)
char	*file;
	{
	FILE	*ioptr;
	char	line[BUFSIZ];
	char	*ptr;
	
	if (ioptr = fopen (file, "r"))
		{
		blabber ("packing", file);
		printf ("%s%s%s\n", MAGIC, file);
		while (fgets (line, BUFSIZ, ioptr))
			fputs (line, stdout);
		for (ptr = line; *ptr; ptr++);
		if (ptr > line && *(ptr-1) != '\n') /* incomplete last line */
			putc ('\n', stdout);
		fclose (ioptr);
		return (SUCCESS);
		}
	fprintf (stderr, "fpack: Can't open '%s' for reading\n", file);
	return (FAILURE);
	}

/*FUNCTION funpack:	unpack and create files packed by fpack */
Status
funpack ()
	{
	FILE	*ioptr = NULL;
	char	line[BUFSIZ];
	int 	maglen = strlen (MAGIC);
	char	*ptr;

	while (gets (line))
		{
		if (!strncmp (MAGIC, line, maglen))
			{
			if (ioptr)
				{
				fclose (ioptr);
				ioptr = NULL;
				}
			ptr = line + maglen;
			if (*ptr == '\0') /* done */
				ioptr = NULL;
			else if (access (ptr, 4) == 0) /* file exists */
				{
				fprintf (stderr, "fpack: '%s' exists (not unpacked)\n", ptr);
				ioptr = NULL;
				}
			else if ((ioptr = fopen (ptr, "w")) == NULL)
				{
				fprintf (stderr, "fpack: Can't create '%s'\n", ptr);
				return (FAILURE);
				}
			if (ioptr != NULL)
				blabber ("unpacking", ptr);
			}
		else if (ioptr != NULL)
			{
			fputs (line, ioptr);
			putc ('\n', ioptr);
			}
		}
	return (SUCCESS);
	}

/*FUNCTION access:	determine if a file exists */
#ifdef MSDOS /* fake a version of the access(2) function */
access (file, mode)
char	*file;
int 	mode;     /* this is ignored in MSDOS version */
	{
	FILE	*ioptr;
	if (ioptr = fopen (file, "r"))
		fclose (ioptr);
	return (ioptr == NULL);
	}
#endif
SHAR_EOF
fi
if test -f 'fpack.test'
then
	echo shar: "will not over-write existing file 'fpack.test'"
else
cat << \SHAR_EOF > 'fpack.test'
TMP="fpack$$"
trap "rm -f $TMP.* /tmp/$TMP; exit 1" 2

/bin/echo -n Oops > $TMP.echo
date > $TMP.date
ls > $TMP.ls

ls -l $TMP.*
echo Howdy from the fpack test > /tmp/$TMP
fpack $TMP.* >> /tmp/$TMP
echo Happy trails from fpack test >> /tmp/$TMP
rm -f $TMP.*
fpack < /tmp/$TMP
ls -l $TMP.*

rm -f $TMP.* /tmp/$TMP
SHAR_EOF
chmod +x 'fpack.test'
fi
exit 0
#	End of shell archive
-- 
Gary Perlman  Wang Institute  Tyngsboro, MA 01879  (617) 649-9731
UUCP: decvax!wanginst!perlman             CSNET: perlman@wanginst