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