Path: seismo!harvard!husc6!panda!talcott!cbpavo.cbosgd.ATT:ulysses!mark (Mark Horton)
From: sources-request@panda.UUCP
Newsgroups: mod.sources
Subject: portable ar: suggested replacement for shar
Message-ID: <1770@panda.UUCP>
Date: 1 May 86 12:55:10 GMT
Sender: jpn@panda.UUCP
Lines: 270
Approved: jpn@panda.UUCP

Mod.sources:  Volume 4, Issue 81
Submitted by: talcott!cbpavo.cbosgd.ATT:ulysses!mark (Mark Horton)

[
  This is one of two submissions of programs that provide alternatives to
  "shar" as a source archive format.  This does not imply my support of
  one format over another.  Oh, I am distributing these in "shar" format
  to avoid the chicken-or-egg problem.
	- John Nelson - moderator, mod.sources
]

#!/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:
#	Makefile
#	README
#	arwrite.c
#	main.c
#	sample
#	unpar.c
# This archive created: Mon Apr 21 09:41:06 1986
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'

par:	arwrite.o main.o
	cc -o par main.o arwrite.o
unpar:	unpar.o
	cc -o unpar unpar.o
clean:
	rm par unpar *.o
SHAR_EOF
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
cat << \SHAR_EOF > 'README'
These programs pack and unpack files in the portable archive format.
This format is compatible with the ar command on 4BSD and System V
release 2.  These programs are available for use by anyone without
fee or license.

The par program packs into portable archive format.  The files to
write are named on the command line, the resulting archive is
written on stdout:
	par file1 file2 ... filen > files.a

The unpar program unpacks from stdin and writes the named files
out directly:
	unpar < files.a
SHAR_EOF
if test -f 'arwrite.c'
then
	echo shar: over-writing existing file "'arwrite.c'"
fi
cat << \SHAR_EOF > 'arwrite.c'
/*
 *		COPYRIGHT (c) HEWLETT-PACKARD COMPANY, 1984
 *
 *	Permission is granted for unlimited modification, use, and
 *	distribution except that this software may not be sold for
 *	profit.  No warranty is implied or expressed.
 *
 *Author:
 *	Paul Bame, HEWLETT-PACKARD LOGIC SYSTEMS DIVISION - Colorado Springs
 *	{ ihnp4!hpfcla | hplabs | harpo!hp-pcd }!hp-lsd!paul
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define ARFMAG "`\n"
#define ARMAG "!<arch>\n"

int
arwrite(filename,stream)
char *filename;
FILE *stream;
/*
 *	Write the file denoted by 'filename' to 'stream' in portable ar format.
 *	Any stream positioning is assumed to already be done.
 *
 *	arwrite() normally returns 0 but returns -1 in case of errors.  errno
 *	may be inspected to determine the cause of the error.
 *
 *	If necessary, the stream is padded with \n's to match the even boundary
 *	condition.
 */
{
	struct stat statbuf;
	FILE *instream;
	long i;

	/* stat() the file to get the stuff for the header */
	if( stat(filename,&statbuf) < 0 )
	{
		/* error! */
		return(-1);
	}

	/* Open file for reading */
	if( (instream = fopen(filename,"r")) == NULL )
	{
		/* error! */
		return(-1);
	}

	/* Now write the header */
	/* This information gleaned from ar(4) in V.2 */
	fprintf(stream,
		"%-16s%-12ld%-6d%-6d%-8o%-10ld%2s",
		filename,
		statbuf.st_mtime,
		statbuf.st_uid,
		statbuf.st_gid,
		statbuf.st_mode,
		statbuf.st_size,
		ARFMAG
		);

	/* And copy the file */
	/*   Note that there is no error recovery here! */
	for( i = 0 ; i < statbuf.st_size ; i++ )
	{
		fputc(fgetc(instream),stream);
	}

	/* and close */
	close(instream);

	/* and pad output stream */
	if( (ftell(stream) & 0x1) != 0 )
	{
		/* if offset is odd, pad with a nuline */
		fputc('\n',stream);
	}
	return(0);
}

arhdwrite(stream)
FILE *stream;
/*
 *	Write the archive header onto 'stream'
 */
{
	fprintf(stream,"%s",ARMAG);
}
SHAR_EOF
if test -f 'main.c'
then
	echo shar: over-writing existing file "'main.c'"
fi
cat << \SHAR_EOF > 'main.c'
/*
 *		COPYRIGHT (c) HEWLETT-PACKARD COMPANY, 1984
 *
 *	Permission is granted for unlimited modification, use, and
 *	distribution except that this software may not be sold for
 *	profit.  No warranty is implied or expressed.
 *
 *Author:
 *	Paul Bame, HEWLETT-PACKARD LOGIC SYSTEMS DIVISION - Colorado Springs
 *	{ ihnp4!hpfcla | hplabs | harpo!hp-pcd }!hp-lsd!paul
 */
#include <stdio.h>

extern	int	arwrite();
extern		arhdwrite();

main(argc,argv)
int argc;
char *argv[];
/*
 *	Write the named files (in argv) to stdout in portable ar format.
 */
{
	int i;

	if( argc < 2 )
	{
		fprintf(stderr,"Usage: %s file1 [file...]\n",argv[0]);
		exit(1);
	}

	/* Write the header */
	arhdwrite(stdout);

	/* and the files */
	for( i = 1 ; i < argc ; i++ )
	{
		if( arwrite(argv[i],stdout) < 0 )
		{
			perror(argv[i]);
			exit(1);
		}
	}
	exit(0);
}
SHAR_EOF
if test -f 'sample'
then
	echo shar: over-writing existing file "'sample'"
fi
cat << \SHAR_EOF > 'sample'
!<arch>
foo             458764309   12    0     100666  29        `
Sun Jul 15 14:31:49 EDT 1984

bar             458764313   12    0     100666  189       `
sarge    ttya    Jul 13 10:02
jgs      ttys1   Jul 15 10:45
mark     ttyp0   Jul 15 14:07	(cbosgd)
mark     ttyp1   Jul 13 09:36
mark     ttyp2   Jul 13 09:36
mark     ttyp3   Jul 13 16:57


SHAR_EOF
if test -f 'unpar.c'
then
	echo shar: over-writing existing file "'unpar.c'"
fi
cat << \SHAR_EOF > 'unpar.c'
/* unpack portable archives - written by Bill Welch */
#include <stdio.h>
#include <sys/types.h>

char buf[512];
main()
{
	char name[80];
	struct utimbuf {
		time_t actime;
		time_t modtime;
	} times;
	long mtime;
	int uid, gid, mode;
	long len, i;
	FILE *fp;

	while(gets(buf) != NULL){
		if (buf[strlen(buf) - 1] == '`') {
			printf("%s\n", buf);
			sscanf(buf, "%s %ld %d %d %o %ld", name,&mtime,&uid,&gid,
					&mode, &len);
			printf("%s %ld\n", name, len);
			fp = fopen(name, "w");
			for (i=0; i<len; i++) putc(getchar(), fp);
			fclose(fp);
			times.actime = times.modtime = mtime;
			/* If you don't have utime, just remove next 4 lines */
			if( utime(name,&times) < 0 )
			{
				perror("Can't modify date");
			}
			if( chmod(name,mode) < 0 )
			{
				perror("Can't modify mode");
			}
		}
	}
}
SHAR_EOF
#	End of shell archive
exit 0