home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume9
/
brkdig
< prev
next >
Wrap
Text File
|
1989-12-27
|
64KB
|
2,289 lines
Newsgroups: comp.sources.misc
organization: Unicom Systems Development, Dallas
subject: v09i091: brkdig - break mailing list digest into USENET messages
From: chip@chinacat.Lonestar.ORG (Chip Rosenthal)
Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
Posting-number: Volume 9, Issue 91
Submitted-by: chip@chinacat.Lonestar.ORG (Chip Rosenthal)
Archive-name: brkdig
"brkdig" takes a mailing list digest, breaks it into individual messages,
and provides headers appropriate for direct posting into USENET. I developed
"brkdig" when I administered the [TELECOM Digest]->comp.dcom.telecom gateway.
It has been well tested under SCO XENIX.
There is one major portability issue: "brkdig" uses the System V regex(3)
routine, and takes advantage of its ability to extract information from the
string. I don't believe there is a direct BSD analog for this function.
#! /bin/sh
# this is a "shar" archive - run through "/bin/sh" to extract 12 files:
# README Defs-example brkdig.h brkdig.c loaddefs.c block.c header.c cleanhdr.c fixfrom.c getdate.y Makefile testaddr
# Wrapped by news@chinacat on Mon Dec 25 09:51:44 CST 1989
# Unpacking this archive requires: sed test wc (possibly mkdir)
# Existing files will not be clobbered unless "-c" is specified on the cmd line.
if test -f README -a "$1" != "-c" ; then
echo "README: file exists - will not be overwritten"
else
echo "x - README (file 1 of 12, 2546 chars)"
sed -e 's/^X//' << 'END_OF_FILE_README' > README
X
X"brkdig" processes a mailing list digest into individual messages suitable
Xfor posting to USENET. There are two parts to this task: slicing the
Xdigest and generating the USENET headers. The usage is:
X
X brkdig [ -d max_days ] [ -f defs_file ] [ -I ] [ file ]
X
X -d max_days The "Date" of all messages is compared to a threshold,
X is stripped if too old. This prevents inews from
X rejecting articles for being too old. This switch
X overrides the default given in "brkdig.h". A zero
X "max_days" value may be used to suppress the check.
X
X -f defs_file The digest definitions file which directs the
X gateway procedure. This switch overrides the default
X given in "brkdig.h".
X
X -I This switch inhibits the creation of the messages, for
X debugging purposes.
X
X file Pathname to the digest to process. If not specified,
X the standard input is processed.
X
X"brkdig" will generate a set of files, each containing an individual message
Xfrom the digest, with headers ready to pass to "inews". A log of the gateway
Xprocessing is written to the standard error. At successful conclusion, a
Xsingle line is written to the standard output in the following format:
X
X volume_num issue_num num_mssgs mssg_1_file ... mssg_N_file
X
X volume_num Volume number of the digest, padded to two digits
X with leading zeros.
X
X issue_num Issue number of the digest, padded to three digits
X with leading zeros.
X
X num_mssgs Number of messages in the digest, padded to two
X digits with leading zeros.
X
X mssg_1_file Pathname to the first message extracted from the
X digest -- all prepared for posting.
X
X .
X .
X .
X
X mssg_N_file Pathname to the last message extracted.
X
XTherefore, to process and post the messages you could use a command
Xsequence such as:
X
X if set -- `brkdig $digest_file` ; then
X : brkdig worked
X else
X exit 1
X fi
X shift ; shift ; shift # throw away first three fields
X for file in $* ; do
X /usr/lib/news/inews -h < $file
X rm $file
X done
X
XThe key to the digest processing is the definitions file. Definitions
Xin this file are generally a keyword, followed by a parameter. Comments
Xare introduced with a "#" and are ignored. The "Defs-example" file
X(included in this distribution) is an example definitions file. It also
Xcontains comments which describe the required format.
X
X
XChip Rosenthal
X<chip@vector.Dallas.TX.US>
X@(#) README 1.2 89/12/25 09:48:05
X
END_OF_FILE_README
size="`wc -c < README`"
if test 2546 -ne "$size" ; then
echo "README: extraction error - got $size chars"
fi
fi
if test -f Defs-example -a "$1" != "-c" ; then
echo "Defs-example: file exists - will not be overwritten"
else
echo "x - Defs-example (file 2 of 12, 7240 chars)"
sed -e 's/^X//' << 'END_OF_FILE_Defs-example' > Defs-example
X##############################################################################
X#
X# @(#) Defs-example 1.1 89/12/25 09:45:30
X#
X# Defs-example - Sample "brkdig" definitions file.
X#
X# This example file is configured for the TELECOM Digest. It is based
X# on the actual file used when I gatewayed the TELECOM Digest into
X# comp.dcom.telecom.
X#
X# Mon Dec 4 08:40:23 1989 - Chip Rosenthal <chip@chinacat.Lonestar.ORG>
X# Commented for inclusion in "brkdig" release.
X#
X##############################################################################
X
X
X##############################################################################
X#
X# DIGEST_NAME - Name displayed on log output.
X# The parameter is a name displayed in the log output just to identify
X# the type of digest processed, and not is used anywhere else.
X
XDIGEST_NAME TELECOM
X
X
X##############################################################################
X#
X# TEMP_NAME - Pattern for creating temporary file names.
X# The parameter is a sprintf(3) pattern for generating names for the
X# individual message files. The parameter will be formatted with
X# three numeric arguments - the digest volume number, issue number,
X# and message number.
X
XTEMP_NAME /tmp/msg-v%02di%03dm%02d
X
X
X##############################################################################
X#
X# ADDR_CHECK - Command to check e-mail addresses.
X# The parameter is a command which verifies whether an e-mail address
X# is valid. This is used *only* when the From: address in a messaage
X# is a bang path rather than an RFC-822 address. "brkdig" will attempt
X# to build a valid address from the path and use this command to check
X# it out. This is important because inews will step on bad addresses.
X# The command must return a zero result on a valid address and a nonzero
X# result on a bad address. The parameter is a sprintf(3) pattern and
X# will be formatted with one argument - the address to check.
X
XADDR_CHECK smail -bv '%s' </dev/null >/dev/null 2>&1 # smail3.1
X#ADDR_CHECK /usenet/telecom-digest/work/testaddr '%s' # smail2.5
X
X
X##############################################################################
X#
X# Patterns within the digest, specified as regex(3) regular expressions.
X#
X# PAT_TITLE The parameter is a regex(3) format regular expression which
X# identifies the title line in the digest. This line must
X# include the digest volume and issue numbers, and the parameter
X# must include the commands to extract these two parameters.
X# The volume number will be extracted as "$0" and the issue
X# number will be extracted as "$1". Please refer to the
X# regex(3) manual page for information on forming such regular
X# expressions.
X#
X# PAT_HDRSEP This parameter is a regular expression which describes the
X# line which seperates the digest header from the first message
X# in the digest.
X#
X# PAT_MSSGSEP This parameter is a regular expression which describes the
X# line which seperates messages in the digest.
X#
X# PAT_DIGEND This parameter is a regular expression which describes any
X# line in the digest trailer. This is used to confirm that an
X# entire, untruncated digest was received and processed
X# correctly. Note that an actual telecom digest ends with a
X# line something like: "End of TELECOM Digest V9 #183", but we
X# have to use '.' instead of '#' in the pattern because '#' is
X# the comment character within this file.
X
X
XPAT_TITLE ^TELECOM Digest .* Volume ([0-9]{1,6})$0 : Issue ([0-9]{1,6})$1
X
XPAT_HDRSEP ^------------------------------------------------------------------{1,9}$
X
XPAT_MSSGSEP ^----------------------------{1,5}$
X
XPAT_DIGEND ^End of TELECOM Digest V[0-9]* .[0-9]*$
X
X
X##############################################################################
X#
X# Message header definitions.
X#
X# The USENET headers are generated according to the table specified
X# below. Headers are generated in the order given, and are controlled
X# by the "flag" type. Some header types need a value to be specified
X# in the definition. The flags, whether they need a value, and a
X# description are as follows:
X#
X# flag value? description
X# -------- ------ ----------------------------------------------------
X# HDR_REQ yes Must appear - use our value if user doesn't give one.
X# HDR_OPT no Optional - generate only if the user provided one.
X# HDR_IGN no Silently ignore this if the user provided one.
X# HDR_ADD yes Ignore any user-supplied value and insert our own.
X# HDR_FMT yes Like "HDR_ADD", but format value with vol/iss/mssg no.
X# HDR_FROM yes Like "HDR_REQ", but perform special "From:" checks.
X# HDR_DATE no Like "HDR_OPT", but perform special "Date:" checks.
X#
X# More detailed explainations of the header flags are as follows:
X#
X# HDR_REQ This header must appear in the news article header. If
X# the original message contains this header, then its value
X# will be used. Otherwise, we will fill in a default value.
X#
X# HDR_OPT This header may appear in the news article header. If
X# the original message contains this header, then its value
X# will be used. Otherwise, this header will not appear in
X# the news article.
X#
X# HDR_ADD The news article will contain this header with the value
X# we specify. If the original message contains this header
X# then it will be silently ignored.
X#
X# HDR_IGN This header will never be placed in the news article.
X# If the original message contains this header then it will
X# be silently ignored.
X#
X# HDR_FMT This is similar to a "HDR_ADD" field, except the header
X# value given in the specifications file should be a
X# sprintf(3) pattern The pattern will be formatted with
X# four numeric fields: the digest volume number, the digest
X# issue number, a message number, and the total number of
X# messages in the digest. The message number starts at 1
X# and increments with each message in the digest.
X#
X# HDR_FROM This is similar to a "HDR_REQ" field, except the header
X# value is subject to special address processing. That is,
X# the value used will be guaranteed to be an RFC822ish
X# looking address.
X#
X# HDR_DATE This is similar to a "HDR_OPT" field, except the header
X# value is subject to special date processing. That is,
X# the value will be compared to a threshold, and if found
X# to be too old will be suppressed. The threshold is defined
X# by MAX_AGE in the "brkdig.h" file, and may be changed
X# with the "-d" command line option.
X#
X# NOTE: In the following, I replaced "vector.dallas.tx.us", the site
X# upon which this definitions file was used with "BOGUS.ADDRESS".
X
X# type header value
X#------ --------------------- ---------------------------------------------
XHDR_ADD Path telecom-gateway
XHDR_FROM From nobody@nowhere.UUCP (this is a bogus address)
XHDR_ADD Newsgroups comp.dcom.telecom
XHDR_REQ Subject (none)
XHDR_FMT Message-ID <telecom-v%02di%04dm%02d@BOGUS.ADDRESS>
XHDR_DATE Date
XHDR_OPT References
XHDR_OPT Keywords
XHDR_OPT Summary
XHDR_OPT Reply-To
XHDR_OPT Followup-To
XHDR_OPT Organization
XHDR_ADD Approved telecom-request@BOGUS.ADDRESS
XHDR_ADD X-Submissions-To telecom@eecs.nwu.edu
XHDR_ADD X-Administrivia-To telecom-request@BOGUS.ADDRESS
XHDR_FMT X-TELECOM-Digest volume %d, issue %d, message %d of %d
XHDR_IGN To
XHDR_IGN Cc
XHDR_IGN CC
XHDR_IGN Lines
X
END_OF_FILE_Defs-example
size="`wc -c < Defs-example`"
if test 7240 -ne "$size" ; then
echo "Defs-example: extraction error - got $size chars"
fi
fi
if test -f brkdig.h -a "$1" != "-c" ; then
echo "brkdig.h: file exists - will not be overwritten"
else
echo "x - brkdig.h (file 3 of 12, 3331 chars)"
sed -e 's/^X//' << 'END_OF_FILE_brkdig.h' > brkdig.h
X/* @(#) brkdig.h 1.2 89/09/21 20:25:59
X *
X * Module: brkdig.h - global definitions
X * Package: brkdig - digest processor
X *
X * Thu Sep 21 20:16:47 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Added "clean_header()".
X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Cleanup and beta release.
X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Original composition.
X */
X
X
X/*
X * DEFS_FILE - Default file with digest configuration definitions. May be
X * overridden with "-f" command line option.
X */
X#define DEFS_FILE "Defs"
X
X
X/*
X * MAX_AGE - Maximum message age in seconds. The "Date" field will be
X * stripped from messages if they are over this value to prevent inews
X * from rejecting the message. A non-positive (e.g. zero) value suppresses
X * this check. May be overriden by "-d".
X */
X#define MAX_AGE ( 7 * (24*60*60) )
X
X
X#define BUFLEN 1024 /* input line buffer sizes */
X#define MAXMSSGS 128 /* maximum messages in a digest */
X#define MAXHDRS 64 /* maximum number of headers defined */
X#define TRUE 1
X#define FALSE 0
X
X
X/*
X * USENET header types - used in (struct header_definitions)
X */
X#define HDR_REQ 1 /* this header must be in the message */
X#define HDR_FROM 2 /* special handling of "From:" header */
X#define HDR_DATE 3 /* special handling of "Date:" header */
X#define HDR_ADD 4 /* add this header; ignore user's value */
X#define HDR_FMT 5 /* like HDR_ADD, but format it first */
X#define HDR_OPT 6 /* this header may be used if present */
X#define HDR_IGN 7 /* this header should be suppressed */
X
X
X#ifndef LINT
X# define SCCSID(STR) static char sccsid[] = STR;
X#else
X# define SCCSID(STR)
X#endif
X
X
X#ifdef M_XENIX
X# ifdef NULL
X# undef NULL
X# define NULL 0
X# endif
X#endif
X
X
X#ifdef INTERN
X# define EXTERN
X# define INIT(X) = X
X#else
X# define EXTERN extern
X# define INIT(X)
X#endif
X
X
X/*
X * Structure of a block of text.
X */
Xstruct text_block {
X char **line; /* dynamically allocated list of lines */
X int nlines; /* number of lines in the list */
X int max; /* list will hold this many lines */
X};
X
Xstruct header_definition {
X int type; /* code to define header processing */
X char *name; /* name of this header */
X char *value; /* value we will supply */
X};
X
X
X/*
X * Globals
X */
XEXTERN int Inhibit INIT(FALSE); /* inhibit file creation */
XEXTERN int Max_age INIT(MAX_AGE); /* limit on "Date" acceptance */
XEXTERN int Num_hdrs INIT(0); /* num "Hdr_defs[]" defined */
XEXTERN char *Defs_file INIT(DEFS_FILE);/* file with header defs */
XEXTERN char *Dig_name INIT(NULL); /* name of this digest */
XEXTERN char *Tmp_name INIT(NULL); /* pattern for temp files */
XEXTERN char *Addrchk_cmd INIT(NULL); /* cmd to check email addr */
XEXTERN char *Pat_title INIT(NULL); /* regex for digest header */
XEXTERN char *Pat_hdrsep INIT(NULL); /* re for end of header */
XEXTERN char *Pat_mssgsep INIT(NULL); /* re for message seperator */
XEXTERN char *Pat_digend INIT(NULL); /* re for end of digest */
XEXTERN struct header_definition Hdr_defs[MAXHDRS]; /* hdr generation specs */
X
X
X/*
X * Global procedures.
X */
Xint block_load();
Xint block_extract();
Xint block_find();
Xvoid clean_header();
Xvoid output_header();
Xchar *fix_bang_from();
Xchar *Sstrdup();
Xchar *Smalloc();
Xchar *Srealloc();
X
END_OF_FILE_brkdig.h
size="`wc -c < brkdig.h`"
if test 3331 -ne "$size" ; then
echo "brkdig.h: extraction error - got $size chars"
fi
fi
if test -f brkdig.c -a "$1" != "-c" ; then
echo "brkdig.c: file exists - will not be overwritten"
else
echo "x - brkdig.c (file 4 of 12, 6458 chars)"
sed -e 's/^X//' << 'END_OF_FILE_brkdig.c' > brkdig.c
X/* @(#) brkdig.c 1.2 89/09/21 20:25:58
X *
X * Module: brkdig.c - digest processor main program
X * Package: brkdig - digest processor
X *
X * Thu Sep 21 20:16:47 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Added "clean_header()".
X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Cleanup and beta release.
X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Original composition.
X */
X
X#include <stdio.h>
X#include <errno.h>
X#define INTERN
X#include "brkdig.h"
X
XSCCSID("@(#) brkdig.c 1.2 89/09/21 20:25:58")
X
X#define USAGE "usage: %s [-d max_days] [-f defs_file] [-I] [file]\n"
X
X/*
X * There are two phases to the digest processor. In the first phase, we
X * break up the digest into all of its individual pieces, specifically the
X * digest header, all of the message headers, and all of the message bodies.
X * In the second phase, we run through all of the message headers and bodies
X * and generate news articles.
X *
X * The digest text is manipulated in a (struct text_block). We start by
X * loading the entire digest into a "Digest" block, and then pull out the
X * pieces. Two procedures, block_find() and block_extract() are used. The
X * block_find() procedure takes a (struct text_block) and a regular expression,
X * and returns the index of the first line in the block containing the RE.
X * the block_extract() procedure pulls a range of lines out of one block,
X * and places them into another.
X */
X
Xstruct text_block Digest; /* entire digest loaded here */
Xstruct text_block Digheader; /* the digest header */
Xstruct text_block Mssgheader[MAXMSSGS]; /* all the message headers */
Xstruct text_block Mssgbody[MAXMSSGS]; /* all the message bodies */
X
Xextern int errno;
Xextern char *sys_errlist[];
X
X
X/*VARARGS*/
Xstatic void abort(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
Xchar *fmt, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9;
X{
X fputs(" ", stderr);
X fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X fputs("\n ABORTING - please process digest manually\n", stderr);
X (void) exit(1);
X /*NOTREACHED*/
X}
X
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X char volno_str[8], issno_str[8], *fname;
X int volno, issno, nmssgs, n, i;
X FILE *fp;
X static char tmpfname[BUFLEN];
X extern char *optarg;
X extern int optind;
X extern char *regcmp();
X
X /*
X * Process command line arguments.
X */
X while ( (i=getopt(argc,argv,"d:f:I")) != EOF ) {
X switch ( i ) {
X case 'd':
X Max_age = atoi(optarg) * (24*60*60);
X break;
X case 'f':
X Defs_file = optarg;
X break;
X case 'I':
X Inhibit = TRUE;
X break;
X default:
X fprintf(stderr, USAGE, argv[0]);
X (void) exit(1);
X }
X }
X switch ( argc-optind ) {
X case 0: fname = NULL; break;
X case 1: fname = argv[optind]; break;
X default: fprintf(stderr, USAGE, argv[0]); (void) exit(1);
X }
X
X /*
X * Load the definitions.
X */
X (void) load_defs(Defs_file);
X fprintf(stderr, "%s: receiving %s digest...\n", argv[0], Dig_name);
X
X /*
X * Load in the digest.
X */
X if ( block_load(&Digest, fname) != 0 )
X abort("couldn't read file \"%s\" (%s)", fname, sys_errlist[errno]);
X
X /*
X * Locate the end of the digest header.
X */
X if ( ( i = block_find(&Digest, Pat_hdrsep, (char *)0) ) < 0 )
X abort("couldn't locate end of digest header");
X
X /*
X * Pull the header out of the digest.
X */
X if ( block_extract(&Digheader, &Digest, 0, i) < 0 )
X abort("couldn't extract header from digest");
X
X /*
X * Locate the digest title within the header.
X */
X if (block_find(&Digheader, Pat_title, volno_str, issno_str, (char *)0) < 0)
X abort("couldn't locate digest title line");
X volno = atoi(volno_str);
X issno = atoi(issno_str);
X fprintf(stderr," processing volume %d issue %d\n",volno,issno);
X
X /*
X * Extract all of the mesasges.
X */
X for (
X nmssgs = 0 ;
X ( i=block_find(&Digest, Pat_mssgsep, (char *)0) ) >= 0 ;
X ++nmssgs
X ) {
X if ( block_extract(&Mssgbody[nmssgs], &Digest, 0, i) < 0 )
X abort("mssg %d - couldn't extract from digest", nmssgs+1);
X (void) block_extract((struct text_block *)0, &Mssgbody[nmssgs], i, i);
X }
X fprintf(stderr, " extracted %d messages from digest\n", nmssgs);
X
X /*
X * Perform some sanity checks on the message extraction.
X */
X if ( nmssgs == 0 )
X abort("didn't extract any messages");
X if ( block_find(&Digest, Pat_digend, (char *)0) < 0 )
X abort("couldn't locate digest trailer");
X if ( block_find(&Digest, "^From ", (char *)0) >= 0 )
X abort("looks like unextracted messages remain");
X
X /*
X * Split up the message headers and bodies.
X */
X for ( n = 0 ; n < nmssgs ; ++n ) {
X if ( ( i = block_find(&Mssgbody[n], "^$", (char *)0) ) < 0 )
X abort("mssg %d - couldn't find end of header", n+1);
X if ( block_extract(&Mssgheader[n], &Mssgbody[n], 0, i) < 0 )
X abort("mssg %d - couldn't extract message header", n+1);
X clean_header(&Mssgheader[n], n+1);
X }
X
X /*
X * Process the messages.
X */
X for ( n = 0 ; n < nmssgs ; ++n ) {
X
X /*
X * Open message file.
X */
X (void) sprintf(tmpfname, Tmp_name, volno, issno, n+1);
X if ( (fp=fopen((Inhibit ? "/dev/null" : tmpfname), "w")) == NULL ) {
X abort("mssg %d - couldn't create \"%s\" (%s)",
X n+1, tmpfname, sys_errlist[errno]);
X }
X
X /*
X * Dump the article.
X */
X output_header(fp, &Mssgheader[n], volno, issno, n+1, nmssgs);
X putc('\n', fp);
X for ( i = 0 ; i < Mssgbody[n].nlines ; ++i ) {
X fputs(Mssgbody[n].line[i], fp);
X putc('\n', fp);
X }
X
X (void) fclose(fp);
X
X }
X
X fprintf(stderr, " extraction complete.\n");
X
X /*
X * Output information for poster.
X */
X (void) printf("%02d %03d %02d", volno, issno, nmssgs);
X for ( i = 0 ; i < nmssgs ; ++i ) {
X (void) putchar(' ');
X (void) printf(Tmp_name, volno, issno, i+1);
X }
X (void) putchar('\n');
X
X (void) exit(0);
X /*NOTREACHED*/
X}
X
X
Xstatic char malloc_error[] = "malloc: out of space\n";
X
Xchar *Sstrdup(s)
Xchar *s;
X{
X extern char *strcpy();
X return strcpy( Smalloc((unsigned)strlen(s)+1), s );
X}
X
Xchar *Smalloc(n)
Xunsigned n;
X{
X char *s;
X extern char *malloc();
X if ( (s=malloc(n)) == NULL ) {
X fputs(malloc_error,stderr);
X (void) exit(2);
X }
X return s;
X}
X
Xchar *Srealloc(s,n)
Xchar *s;
Xunsigned n;
X{
X extern char *realloc();
X if ( s == NULL )
X return Smalloc(n);
X if ( (s=realloc(s,n)) == NULL ) {
X fputs(malloc_error,stderr);
X (void) exit(2);
X }
X return s;
X}
X
X
END_OF_FILE_brkdig.c
size="`wc -c < brkdig.c`"
if test 6458 -ne "$size" ; then
echo "brkdig.c: extraction error - got $size chars"
fi
fi
if test -f loaddefs.c -a "$1" != "-c" ; then
echo "loaddefs.c: file exists - will not be overwritten"
else
echo "x - loaddefs.c (file 5 of 12, 3732 chars)"
sed -e 's/^X//' << 'END_OF_FILE_loaddefs.c' > loaddefs.c
X/* @(#) loaddefs.c 1.1 89/08/25 20:47:41
X *
X * Module: loaddefs.c - definitions file processing
X * Package: brkdig - digest processor
X *
X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Original composition.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include "brkdig.h"
X
X#define Strmatch(S1,S2) ( strcmp((S1),(S2)) == 0 )
X
X
Xvoid load_defs(fname)
Xchar *fname;
X{
X char **defp, *cmd, *arg, *s;
X int lineno, htype;
X FILE *fp;
X static char buf[BUFLEN];
X
X if ( (fp=fopen(fname,"r")) == NULL ) {
X perror(fname);
X (void) exit(1);
X }
X
X for ( lineno = 1 ; fgets(buf,sizeof(buf),fp) != NULL ; ++lineno ) {
X
X /*
X * Trim comments, trailing spaces.
X */
X if ( (s=strchr(buf,'#')) != NULL )
X *s = '\0';
X for ( s = buf+strlen(buf)-1 ; s >= buf && isspace(*s) ; --s ) ;
X *(s+1) = '\0';
X if ( buf[0] == '\0' )
X continue;
X
X /*
X * Split the line into a command and argument.
X */
X for ( cmd = buf ; isspace(*cmd) ; ++cmd ) ;
X for ( arg = cmd ; *arg != '\0' && !isspace(*arg) ; ++arg ) ;
X if ( *arg == '\0' ) {
X fprintf(stderr,"%s(%d): missing argument to '%s'\n",
X fname,lineno,cmd);
X (void) exit(1);
X }
X for ( *arg++ = '\0' ; isspace(*arg) ; ++arg ) ;
X
X /*
X * Process the command.
X */
X defp = NULL;
X htype = -1;
X if ( Strmatch(cmd,"DIGEST_NAME") ) defp = &Dig_name;
X else if ( Strmatch(cmd,"TEMP_NAME") ) defp = &Tmp_name;
X else if ( Strmatch(cmd,"ADDR_CHECK") ) defp = &Addrchk_cmd;
X else if ( Strmatch(cmd,"PAT_TITLE") ) defp = &Pat_title;
X else if ( Strmatch(cmd,"PAT_HDRSEP") ) defp = &Pat_hdrsep;
X else if ( Strmatch(cmd,"PAT_MSSGSEP") ) defp = &Pat_mssgsep;
X else if ( Strmatch(cmd,"PAT_DIGEND") ) defp = &Pat_digend;
X else if ( Strmatch(cmd,"HDR_ADD") ) htype = HDR_ADD;
X else if ( Strmatch(cmd,"HDR_DATE") ) htype = HDR_DATE;
X else if ( Strmatch(cmd,"HDR_FMT") ) htype = HDR_FMT;
X else if ( Strmatch(cmd,"HDR_FROM") ) htype = HDR_FROM;
X else if ( Strmatch(cmd,"HDR_IGN") ) htype = HDR_IGN;
X else if ( Strmatch(cmd,"HDR_OPT") ) htype = HDR_OPT;
X else if ( Strmatch(cmd,"HDR_REQ") ) htype = HDR_REQ;
X else {
X fprintf(stderr,"%s(%d): unknown command '%s'\n",
X fname,lineno,cmd);
X (void) exit(1);
X }
X
X if ( defp != NULL ) {
X if ( *defp != NULL ) {
X fprintf(stderr,"%s(%d): duplicate definition of '%s'\n",
X fname,lineno,cmd);
X (void) exit(1);
X }
X *defp = Sstrdup(arg);
X }
X
X if ( htype >= 0 ) {
X if ( Num_hdrs >= MAXHDRS ) {
X fprintf(stderr,"%s(%d): too many header specifications\n",
X fname,lineno);
X (void) exit(1);
X }
X Hdr_defs[Num_hdrs].type = htype;
X for ( s = arg ; *s != '\0' && !isspace(*s) ; ++s ) ;
X if ( *s == '\0' ) {
X Hdr_defs[Num_hdrs].value = NULL;
X } else {
X for ( *s++ = '\0' ; isspace(*s) ; ++s ) ;
X Hdr_defs[Num_hdrs].value = Sstrdup(s);
X }
X Hdr_defs[Num_hdrs].name = Sstrdup(arg);
X ++Num_hdrs;
X }
X
X }
X
X if ( Dig_name == NULL ) {
X fprintf(stderr,"%s: parameter 'DIG_NAME' unspecified\n", fname);
X (void) exit(1);
X }
X if ( Tmp_name == NULL ) {
X fprintf(stderr,"%s: parameter 'TMP_NAME' unspecified\n", fname);
X (void) exit(1);
X }
X if ( Addrchk_cmd == NULL ) {
X fprintf(stderr,"%s: parameter 'ADDRCHK_CMD' unspecified\n", fname);
X (void) exit(1);
X }
X if ( Pat_title == NULL ) {
X fprintf(stderr,"%s: parameter 'PAT_TITLE' unspecified\n", fname);
X (void) exit(1);
X }
X if ( Pat_hdrsep == NULL ) {
X fprintf(stderr,"%s: parameter 'PAT_HDRSEP' unspecified\n", fname);
X (void) exit(1);
X }
X if ( Pat_mssgsep == NULL ) {
X fprintf(stderr,"%s: parameter 'PAT_MSSGSEP' unspecified\n", fname);
X (void) exit(1);
X }
X if ( Pat_digend == NULL ) {
X fprintf(stderr,"%s: parameter 'PAT_DIGEND' unspecified\n", fname);
X (void) exit(1);
X }
X
X}
X
END_OF_FILE_loaddefs.c
size="`wc -c < loaddefs.c`"
if test 3732 -ne "$size" ; then
echo "loaddefs.c: extraction error - got $size chars"
fi
fi
if test -f block.c -a "$1" != "-c" ; then
echo "block.c: file exists - will not be overwritten"
else
echo "x - block.c (file 6 of 12, 4263 chars)"
sed -e 's/^X//' << 'END_OF_FILE_block.c' > block.c
X/* @(#) block.c 1.1 89/08/25 20:47:39
X *
X * Module: block.c - text block manipulation routines
X * Package: brkdig - digest processor
X *
X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Cleanup and beta release.
X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Original composition.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include "brkdig.h"
X
XSCCSID("@(#) block.c 1.1 89/08/25 20:47:39")
X
Xstatic struct text_block *block_clean();
X
X
X/*
X * block_load() - load the contents of a file into a block.
X * The block will be initialized prior to loading. Any information
X * currently in the block prior to the load will be lost.
X */
Xint block_load(b,fname)
Xstruct text_block *b;
Xchar *fname;
X{
X FILE *fp;
X char *s;
X static char buf[1024];
X
X if ( fname == NULL )
X fp = stdin;
X else if ( (fp=fopen(fname,"r")) == NULL )
X return -1;
X
X b->nlines = b->max = 0;
X b->line = NULL;
X
X while ( fgets(buf,sizeof(buf),fp) != NULL ) {
X
X /*
X * Expand block if more space is needed.
X */
X if ( b->nlines >= b->max ) {
X b->max = ( b->max == 0 ? 128 : b->max << 1 ) ;
X b->line =
X (char **)Srealloc( (char *)b->line, b->max*sizeof(char *) );
X }
X
X /*
X * Trim trailing space.
X */
X for ( s = buf+strlen(buf)-1 ; s >= buf && isspace(*s) ; --s ) ;
X *(s+1) = '\0';
X
X /*
X * Append line to block.
X */
X b->line[b->nlines++] = Sstrdup(buf);
X
X }
X
X if ( fname != NULL )
X (void) fclose(fp);
X (void) block_clean(b);
X return 0;
X}
X
X
X/*
X * block_extract() - move a group of lines from one block to another
X * Lines are numbered "0" through "nlines-1". The inclusive range
X * of lines is deleted from the "b_old" block. The "b_new" block is
X * initialized, and the deleted lines are placed there. If there was
X * any information in the "b_new" block prior to extraction then it
X * will be lost. If the "b_new" block is NULL, then this procedure
X * just deletes the range of lines from the "b_old" block.
X */
Xint block_extract(b_new,b_old,nstart,nend)
Xstruct text_block *b_new;
Xstruct text_block *b_old;
Xint nstart;
Xint nend;
X{
X int nlines, i;
X
X if ( nstart < 0 || nend >= b_old->nlines || nstart > nend )
X return -1;
X
X nlines = nend-nstart+1;
X
X if ( b_new != NULL ) {
X b_new->max = b_new->nlines = nlines;
X b_new->line = (char **) Smalloc( b_new->max * sizeof(char *) );
X for ( i = 0 ; i < nlines ; ++i )
X b_new->line[i] = b_old->line[nstart+i];
X (void) block_clean(b_new);
X }
X
X for ( i = nend+1 ; i < b_old->nlines ; ++i )
X b_old->line[i-nlines] = b_old->line[i];
X b_old->nlines -= nlines;
X (void) block_clean(b_old);
X
X return 0;
X}
X
X
X/*
X * block_find() - find the first instance of a pattern in a block.
X * The "pattern" is a regular expression. The arguments allow up
X * to five sections of the line to be extracted (c.f. regexp(3)).
X * The index (between "0" and "nlines-1") of the first line in the
X * block which matches the pattern is returned. A "-1" is returned
X * upon search failure or error.
X */
X/*VARARGS*/
Xint block_find(b,pattern,a0,a1,a2,a3,a4)
Xstruct text_block *b;
Xchar *pattern, *a0, *a1, *a2, *a3, *a4;
X{
X char *re;
X int i;
X extern char *regcmp(), *regex();
X extern void free();
X
X if ( (re=regcmp(pattern,(char *)0)) == NULL ) {
X fputs("malloc: out of space\n",stderr);
X (void) exit(2);
X }
X
X for ( i = 0 ; i < b->nlines ; ++i ) {
X if ( regex(re,b->line[i],a0,a1,a2,a3,a4,(char *)0) != NULL )
X break;
X }
X
X (void) free(re);
X return ( i < b->nlines ? i : -1 );
X}
X
X
X/*
X * block_clean() - trim leading and trailing blank lines from a block.
X * The "nlines" count is updated to reflect any changes.
X */
Xstatic struct text_block *block_clean(b)
Xstruct text_block *b;
X{
X int i, j;
X char *s;
X
X /*
X * Trim leading blank lines.
X */
X for ( i = 0 ; i < b->nlines ; ++i ) {
X for ( s = b->line[i] ; isspace(*s) ; ++s ) ;
X if ( *s != '\0' )
X break;
X }
X if ( i > 0 ) {
X for ( j = i ; j < b->nlines ; ++j )
X b->line[j-i] = b->line[j];
X b->nlines -= i;
X }
X
X /*
X * Trim trailing blank lines.
X */
X for ( i = b->nlines-1 ; i >= 0 ; --i ) {
X for ( s = b->line[i] ; isspace(*s) ; ++s ) ;
X if ( *s != '\0' )
X break;
X }
X b->nlines = i+1;
X
X return b;
X}
X
X
END_OF_FILE_block.c
size="`wc -c < block.c`"
if test 4263 -ne "$size" ; then
echo "block.c: extraction error - got $size chars"
fi
fi
if test -f header.c -a "$1" != "-c" ; then
echo "header.c: file exists - will not be overwritten"
else
echo "x - header.c (file 7 of 12, 6640 chars)"
sed -e 's/^X//' << 'END_OF_FILE_header.c' > header.c
X/* @(#) header.c 1.1 89/08/25 20:47:41
X *
X * Module: header.c - news article header generation
X * Package: brkdig - digest processor
X *
X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Cleanup and beta release.
X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Original composition.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include "brkdig.h"
X
XSCCSID("@(#) header.c 1.1 89/08/25 20:47:41")
X
X
Xstatic char *find_header();
Xstatic char *append_header();
X
X
Xstatic void hdr_error(mssgno,hdr_name,problem,old_value,new_value)
Xint mssgno;
Xchar *hdr_name;
Xchar *problem;
Xchar *old_value;
Xchar *new_value;
X{
X fprintf(stderr," message %d - \"%s\" header problem - %s\n",
X mssgno, hdr_name, problem);
X if ( old_value != NULL )
X fprintf(stderr," ..removing \"%s: %s\"\n", hdr_name, old_value);
X if ( new_value != NULL )
X fprintf(stderr," ....adding \"%s: %s\"\n", hdr_name, new_value);
X}
X
X
Xvoid output_header(fp,b,volno,issno,mssgno,nummssgs)
XFILE *fp;
Xstruct text_block *b;
Xint volno, issno, mssgno, nummssgs;
X{
X int hdrno, i;
X long time_now, time_post;
X char *appendhdr, *name, *value, *new_value;
X static char fmtbuf[BUFLEN];
X extern long time(), getdate();
X extern void free();
X
X (void) time(&time_now);
X appendhdr = NULL;
X
X /*
X * Go through all of the header items.
X */
X for ( hdrno = 0 ; hdrno < Num_hdrs ; ++hdrno ) {
X
X name = Hdr_defs[hdrno].name;
X
X /*
X * Process the header.
X */
X switch ( Hdr_defs[hdrno].type ) {
X
X case HDR_REQ:
X if ( (value=find_header(b,name,mssgno)) == NULL ) {
X value = Hdr_defs[hdrno].value;
X hdr_error(mssgno, name, "required header not in message",
X (char *)NULL, value);
X }
X break;
X
X case HDR_ADD:
X (void) find_header(b,name,mssgno);
X value = Hdr_defs[hdrno].value;
X break;
X
X case HDR_FMT:
X (void) find_header(b,name,mssgno);
X (void) sprintf(fmtbuf,
X Hdr_defs[hdrno].value, volno, issno, mssgno, nummssgs);
X value = fmtbuf;
X break;
X
X case HDR_OPT:
X value = find_header(b,name,mssgno);
X break;
X
X case HDR_IGN:
X (void) find_header(b,name,mssgno);
X value = NULL;
X break;
X
X case HDR_FROM:
X
X /*
X * Make sure the user gave us an address.
X */
X if ( (value=find_header(b,name,mssgno)) == NULL ) {
X value = Hdr_defs[hdrno].value;
X hdr_error(mssgno, name, "required header not in message",
X (char *)NULL, value);
X appendhdr = append_header(appendhdr,
X "message missing 'From' field - bogus address added",
X (char *)NULL, (char *)NULL
X );
X break;
X }
X
X /*
X * If there is a '@' in it, then assume it is OK.
X */
X if ( strchr(value,'@') != NULL )
X break;
X
X /*
X * Try to munge bang-paths into an address. If that doesn't
X * work then use a bogus default.
X */
X if ( (new_value=fix_bang_from(value)) == NULL )
X new_value = Hdr_defs[hdrno].value;
X hdr_error(mssgno, name, "address is not valid USENET syntax",
X value, new_value);
X appendhdr = append_header(appendhdr,
X "original 'From' address is not valid USENET syntax",
X "X-Originally-From", value
X );
X value = new_value;
X break;
X
X
X case HDR_DATE:
X
X /*
X * If the user didn't specify a date, that's OK.
X */
X if ( (value=find_header(b,name,mssgno)) == NULL )
X break;
X
X /*
X * Verify that the syntax is correct.
X */
X if ( (time_post=getdate(value,(char *)NULL)) <= 0 ) {
X hdr_error(mssgno, name, "date is not valid USENET syntax",
X value, (char *)NULL);
X appendhdr = append_header(appendhdr,
X "original 'Date' value is not valid USENET syntax",
X "X-Original-Date", value
X );
X value = NULL;
X break;
X }
X
X /*
X * Verify that it isn't too old - otherwise inews might reject it.
X */
X if ( Max_age > 0 && time_now-time_post > Max_age ) {
X hdr_error(mssgno, name, "date is too old for posting",
X value, (char *)NULL);
X appendhdr = append_header(appendhdr,
X "original 'Date' value is too old for posting",
X "X-Original-Date", value
X );
X value = NULL;
X break;
X }
X
X /*
X * The date looks good.
X */
X break;
X
X default:
X hdr_error(mssgno, name, "INTERNAL ERROR - bad header code",
X (char *)NULL, (char *)NULL);
X (void) exit(1);
X
X }
X
X if ( value != NULL )
X fprintf(fp, "%s: %s\n", name, value);
X
X }
X
X for ( i = 0 ; i < b->nlines ; ++i ) {
X if ( b->line[i] != NULL ) {
X name = b->line[i];
X for ( value = name ; *value != ':' && *value != '\0' ; ++value ) ;
X if ( *value != '\0' )
X for ( *value++ = '\0' ; isspace(*value) ; ++value ) ;
X hdr_error(mssgno, name, "unknown or unsupported header",
X value, (char *)NULL);
X }
X }
X
X if ( appendhdr != NULL ) {
X fputs(appendhdr,fp);
X (void) free(appendhdr);
X }
X
X}
X
X
Xstatic char *find_header(b,name,mssgno)
Xstruct text_block *b;
Xchar *name;
Xint mssgno;
X{
X int count, len, i;
X char *value, *s;
X static char valbuf[BUFLEN];
X extern void free();
X extern char *strcpy();
X
X len = strlen(name);
X value = NULL;
X count = 0;
X
X for ( i = 0 ; i < b->nlines ; ++i ) {
X
X /*
X * See if this is a header line we want.
X */
X if ( b->line[i] == NULL )
X continue;
X if ( strncmp(b->line[i],name,len) != 0 )
X continue;
X if ( b->line[i][len] != ':' || !isspace(b->line[i][len+1]) )
X continue;
X
X /*
X * Locate and save off the value.
X */
X for ( s = b->line[i]+len+1 ; isspace(*s) ; ++s ) ;
X if ( *s != '\0' ) {
X if ( ++count > 1 ) {
X hdr_error(mssgno, name, "duplicate header value",
X s, (char *)NULL);
X } else {
X value = strcpy(valbuf,s);
X }
X }
X
X /*
X * Erase and free up the header.
X */
X (void) free(b->line[i]);
X b->line[i] = NULL;
X
X }
X
X return value;
X}
X
X
Xstatic char *append_header(h,problem,add_hdr,add_value)
Xchar *h, *problem, *add_hdr, *add_value;
X{
X unsigned len;
X char *newh;
X static char warning_mssg[] = "X-GATEWAY-WARNING: ";
X extern char *malloc(), *realloc();
X
X len =
X sizeof(warning_mssg)-1
X + strlen(problem)
X + sizeof("\n")-1
X + strlen(add_hdr)
X + sizeof(": ")-1
X + strlen(add_value)
X + sizeof("\n")-1
X ;
X
X newh = ( h == NULL ? malloc(len+1) : realloc(h,strlen(h)+len+1) );
X if ( newh == NULL ) {
X fputs("malloc: out of space\n",stderr);
X (void) exit(1);
X }
X if ( h == NULL )
X *newh = '\0';
X
X (void) strcat(newh,warning_mssg);
X (void) strcat(newh,problem);
X (void) strcat(newh,"\n");
X if ( add_hdr != NULL && add_value != NULL ) {
X (void) strcat(newh,add_hdr);
X (void) strcat(newh,": ");
X (void) strcat(newh,add_value);
X (void) strcat(newh,"\n");
X }
X
X return newh;
X}
X
END_OF_FILE_header.c
size="`wc -c < header.c`"
if test 6640 -ne "$size" ; then
echo "header.c: extraction error - got $size chars"
fi
fi
if test -f cleanhdr.c -a "$1" != "-c" ; then
echo "cleanhdr.c: file exists - will not be overwritten"
else
echo "x - cleanhdr.c (file 8 of 12, 1686 chars)"
sed -e 's/^X//' << 'END_OF_FILE_cleanhdr.c' > cleanhdr.c
X/* @(#) cleanhdr.c 1.1 89/09/21 20:26:07
X *
X * Module: cleanhdr.c - header block cleanups
X * Package: brkdig - digest processor
X *
X * Thu Sep 21 20:00:31 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Original composition.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include "brkdig.h"
X
XSCCSID("@(#) cleanhdr.c 1.1 89/09/21 20:26:07")
X
X/*
X * clean_header() - perform various header cleanups.
X * This procedure attempts to work around various limitations and
X * glitches which occur to headers when passed through mail.
X */
Xvoid clean_header(h,mssgno)
Xstruct text_block *h;
Xint mssgno;
X{
X char *s;
X int i, j;
X
X for ( i = 0 ; i < h->nlines ; ++i ) {
X
X /*
X * Assume a line starting with whitespace is a continuation line.
X */
X if ( i > 0 && isspace(*h->line[i]) ) {
X for ( s = h->line[i] ; isspace(*s) ; ++s ) ;
X *--s = ' ';
X j = strlen(h->line[i-1]) + strlen(s) + 1;
X h->line[i-1] = Srealloc( h->line[i-1], j );
X (void) strcat(h->line[i-1],s);
X (void) free(h->line[i]);
X for ( j = i+1 ; j < h->nlines ; ++j )
X h->line[j-1] = h->line[j];
X --h->nlines;
X --i;
X continue;
X }
X
X /*
X * Convert ">From" to "From".
X */
X if ( strncmp( h->line[i], ">From:", sizeof(">From:")-1 ) == 0 ) {
X for ( s = h->line[i] ; *s != '\0' ; ++s )
X *s = *(s+1);
X }
X
X /*
X * Verify that this looks like a header.
X */
X for ( s = h->line[i] ; *s != '\0' && *s != ':' && !isspace(*s) ; ++s ) ;
X if ( *s != ':' ) {
X fprintf(stderr," message %d - illegal header removed \"%s\"\n",
X mssgno, h->line[i]);
X for ( j = i+1 ; j < h->nlines ; ++j )
X h->line[j-1] = h->line[j];
X --h->nlines;
X --i;
X continue;
X }
X
X }
X
X}
END_OF_FILE_cleanhdr.c
size="`wc -c < cleanhdr.c`"
if test 1686 -ne "$size" ; then
echo "cleanhdr.c: extraction error - got $size chars"
fi
fi
if test -f fixfrom.c -a "$1" != "-c" ; then
echo "fixfrom.c: file exists - will not be overwritten"
else
echo "x - fixfrom.c (file 9 of 12, 3936 chars)"
sed -e 's/^X//' << 'END_OF_FILE_fixfrom.c' > fixfrom.c
X/* @(#) fixfrom.c 1.1 89/08/25 20:47:40
X *
X * Module: fixfrom.c - fix bang-path style from lines
X * Package: brkdig - digest processor
X *
X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Cleanup and beta release.
X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
X * Original composition.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include "brkdig.h"
X
XSCCSID("@(#) fixfrom.c 1.1 89/08/25 20:47:40")
X
Xstatic int checkaddr();
X
X/*
X * fix_bang_from() - convert "From" field to an RFC822 address
X *
X * The "from" argument is a "from" field which contains a bang-path rather
X * than a valid address. The path is converted to a legal (and hopefully
X * valid) address. If the field doesn't contain a bang path or the conversion
X * fails, then NULL is returned.
X *
X * Two attempts are performed at translation. In the first attempt, we
X * look for a fully qualified domain name, and build an address from there.
X * If several such qualified names exist, then the rightmost is taken. For
X * example, we would convert "cs.utech.edu!bigvax!moscvax.krem.org!ihnp4!fred"
X * to "inhp4!fred@moscvax.krem.org".
X *
X * In the second attempt, we try to build addresses until we find one our
X * router program understands. For example, given "utech!bigvax!ihnp4!fred",
X * we would try (in order) "fred@ihnp4.UUCP", "ihnp4!fred@bigvax.UUCP", and
X * "bigvax!ihnp4!fred@utech.UUCP".
X *
X * If neither of these approaches work we give up and return NULL.
X */
Xchar *fix_bang_from(from)
Xchar *from;
X{
X static char pathbuf[BUFLEN], addrbuf[BUFLEN];
X char *pathelem[64], *s1, *s2;
X int nelem, n, i;
X
X (void) strcpy(pathbuf,from);
X
X /*
X * Extract anything enclosed in '<' angle brackets '>'
X */
X if ( (s1=strchr(pathbuf,'<')) != NULL && (s2=strchr(s1,'>')) != NULL ) {
X *s2 = '\0';
X (void) strcpy(pathbuf,s1+1);
X }
X
X /*
X * Throw out anything enclosed in '(' parens ')'
X */
X if ( (s1=strchr(pathbuf,'(')) != NULL && (s2=strchr(s1,')')) != NULL )
X (void) strcpy(s1,s2+1);
X
X /*
X * Trim leading space.
X */
X for ( s1 = pathbuf ; isspace(*s1) ; ++s1 ) ;
X if ( s1 != pathbuf )
X (void) strcpy(pathbuf,s1);
X
X /*
X * Terminate the line after the first word.
X */
X for ( s1 = pathbuf ; *s1 != '\0' && !isspace(*s1) ; ++s1 ) ;
X *s1 = '\0';
X
X /*
X * We are only dealing with bang paths here.
X */
X if ( strchr(pathbuf,'!') == NULL )
X return NULL;
X
X /*
X * Break the path at the '!' bangs.
X */
X for (
X s1 = pathbuf, nelem = 0 ;
X (pathelem[nelem]=strtok(s1,"!")) != NULL ;
X s1 = NULL, ++nelem
X ) ;
X
X /*
X * Search for an element which is a fully qualified domain name.
X */
X for ( n = nelem-2 ; n >= 0 ; --n ) {
X if ( strchr(pathelem[n],'.') == NULL )
X continue;
X addrbuf[0] = '\0';
X for ( i = n+1 ; i < nelem ; ++i ) {
X if ( i > n+1 )
X (void) strcat(addrbuf,"!");
X (void) strcat(addrbuf,pathelem[i]);
X }
X (void) strcat(addrbuf,"@");
X (void) strcat(addrbuf,pathelem[n]);
X return addrbuf;
X }
X
X /*
X * Search for an element which we can build an address from.
X */
X for ( n = nelem-2 ; n >= 0 ; --n ) {
X addrbuf[0] = '\0';
X for ( i = n+1 ; i < nelem ; ++i ) {
X if ( i > n+1 )
X (void) strcat(addrbuf,"!");
X (void) strcat(addrbuf,pathelem[i]);
X }
X (void) strcat(addrbuf,"@");
X (void) strcat(addrbuf,pathelem[n]);
X (void) strcat(addrbuf,".UUCP");
X if ( checkaddr(addrbuf) )
X return addrbuf;
X }
X
X return NULL;
X}
X
X
X
Xstatic int checkaddr(addr)
Xchar *addr;
X{
X static char cmdbuf[BUFLEN];
X int status, pid;
X
X (void) sprintf(cmdbuf,Addrchk_cmd,addr);
X switch ( (pid=fork()) ) {
X case -1: /* fork error */
X perror("fork");
X (void) exit(1);
X case 0: /* child */
X (void) execl( "/bin/sh", "sh", "-c", cmdbuf, (char *)NULL );
X perror("exec");
X (void) exit(1);
X default:
X while ( wait(&status) != pid ) ;
X return ( status == 0 );
X }
X}
X
END_OF_FILE_fixfrom.c
size="`wc -c < fixfrom.c`"
if test 3936 -ne "$size" ; then
echo "fixfrom.c: extraction error - got $size chars"
fi
fi
if test -f getdate.y -a "$1" != "-c" ; then
echo "getdate.y: file exists - will not be overwritten"
else
echo "x - getdate.y (file 10 of 12, 13345 chars)"
sed -e 's/^X//' << 'END_OF_FILE_getdate.y' > getdate.y
X%token ID MONTH DAY MERIDIAN SNUMBER UNUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
X%{
X /* Originally from: Steven M. Bellovin (unc!smb) */
X /* Dept. of Computer Science */
X /* University of North Carolina at Chapel Hill */
X /* @(#)getdate.y 2.19 1/17/89 */
X
X/*
X * Fri Mar 24 22:57:24 1989 - Chip Rosenthal <chip@vector.UUCP>
X * Added new "tspec" to handle HH:MM:SS.mm type times.
X * Added new "dtspec" to handle DD-MMM-YYYY type dates.
X * Yep...it ain't RFC822...but what does VMS care?
X */
X
X/*****
X#include "defs.h"
X******/
X#include <sys/types.h>
X#ifdef USG
Xstruct timeb
X{
X time_t time;
X unsigned short millitm;
X short timezone;
X short dstflag;
X};
X#else
X#include <sys/timeb.h>
X#endif
X#include <ctype.h>
X
X#if defined(BSD4_2)
X#include <sys/time.h>
X#else /* sane */
X#include <time.h>
X#endif /* sane */
X
X#define NULL 0
X#define daysec (24L*60L*60L)
X static int timeflag, zoneflag, dateflag, dayflag, relflag;
X static time_t relsec, relmonth;
X static int hh, mm, ss, merid, daylight;
X static int dayord, dayreq;
X static int month, day, year;
X static int ourzone;
X#define AM 1
X#define PM 2
X#define DAYLIGHT 1
X#define STANDARD 2
X#define MAYBE 3
X%}
X
X%%
Xtimedate: /* empty */
X | timedate item;
X
Xitem: tspec =
X {timeflag++;}
X | zone =
X {zoneflag++;}
X | dtspec =
X {dateflag++;}
X | dyspec =
X {dayflag++;}
X | rspec =
X {relflag++;}
X | nspec;
X
Xnspec: UNUMBER =
X {if (timeflag && dateflag && !relflag) year = $1;
X else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
X
Xtspec: UNUMBER MERIDIAN =
X {hh = $1; mm = 0; ss = 0; merid = $2;}
X | UNUMBER ':' UNUMBER =
X {hh = $1; mm = $3; merid = 24;}
X | UNUMBER ':' UNUMBER MERIDIAN =
X {hh = $1; mm = $3; merid = $4;}
X | UNUMBER ':' UNUMBER SNUMBER =
X {hh = $1; mm = $3; merid = 24;
X daylight = STANDARD; ourzone = -($4%100 + 60*($4/100));}
X | UNUMBER ':' UNUMBER ':' UNUMBER =
X {hh = $1; mm = $3; ss = $5; merid = 24;}
X | UNUMBER ':' UNUMBER ':' UNUMBER '.' UNUMBER =
X {hh = $1; mm = $3; ss = $5; merid = 24; /* added 3/24/89 CR */ }
X | UNUMBER ':' UNUMBER ':' UNUMBER MERIDIAN =
X {hh = $1; mm = $3; ss = $5; merid = $6;}
X | UNUMBER ':' UNUMBER ':' UNUMBER SNUMBER =
X {hh = $1; mm = $3; ss = $5; merid = 24;
X daylight = STANDARD; ourzone = -($6%100 + 60*($6/100));};
X
Xzone: ZONE =
X {ourzone = $1; daylight = STANDARD;}
X | DAYZONE =
X {ourzone = $1; daylight = DAYLIGHT;};
X
Xdyspec: DAY =
X {dayord = 1; dayreq = $1;}
X | DAY ',' =
X {dayord = 1; dayreq = $1;}
X | UNUMBER DAY =
X {dayord = $1; dayreq = $2;};
X
Xdtspec: UNUMBER '/' UNUMBER =
X {month = $1; day = $3;}
X | UNUMBER '/' UNUMBER '/' UNUMBER =
X {month = $1; day = $3; year = $5;}
X | UNUMBER MONTH SNUMBER =
X {month = $2; day = $1; year = -$3; /* added 3/24/89 CR */ }
X | MONTH UNUMBER =
X {month = $1; day = $2;}
X | MONTH UNUMBER ',' UNUMBER =
X {month = $1; day = $2; year = $4;}
X | UNUMBER MONTH =
X {month = $2; day = $1;}
X | UNUMBER MONTH UNUMBER =
X {month = $2; day = $1; year = $3;};
X
X
Xrspec: SNUMBER UNIT =
X {relsec += 60L * $1 * $2;}
X | SNUMBER MUNIT =
X {relmonth += $1 * $2;}
X | SNUMBER SUNIT =
X {relsec += $1;}
X | UNIT =
X {relsec += 60L * $1;}
X | MUNIT =
X {relmonth += $1;}
X | SUNIT =
X {relsec++;}
X | rspec AGO =
X {relsec = -relsec; relmonth = -relmonth;};
X%%
X
Xstatic int mdays[12] =
X {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
X#define epoch 1970
X
Xextern struct tm *localtime();
X
Xtime_t
Xdateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
Xint mm, dd, yy, h, m, s, mer, zone, dayflag;
X{
X time_t tod, jdate;
X register int i;
X time_t timeconv();
X
X if (yy < 0) yy = -yy;
X if (yy < 100) yy += 1900;
X mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
X if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
X dd < 1 || dd > mdays[--mm]) return (-1);
X jdate = dd-1;
X for (i=0; i<mm; i++) jdate += mdays[i];
X for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
X jdate *= daysec;
X jdate += zone * 60L;
X if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
X jdate += tod;
X if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
X jdate += -1*60*60;
X return (jdate);
X}
X
Xtime_t
Xdayconv(ord, day, now)
Xint ord, day; time_t now;
X{
X register struct tm *loctime;
X time_t tod;
X time_t daylcorr();
X
X tod = now;
X loctime = localtime(&tod);
X tod += daysec * ((day - loctime->tm_wday + 7) % 7);
X tod += 7*daysec*(ord<=0?ord:ord-1);
X return daylcorr(tod, now);
X}
X
Xtime_t
Xtimeconv(hh, mm, ss, mer)
Xregister int hh, mm, ss, mer;
X{
X if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
X switch (mer) {
X case AM: if (hh < 1 || hh > 12) return(-1);
X return (60L * ((hh%12)*60L + mm)+ss);
X case PM: if (hh < 1 || hh > 12) return(-1);
X return (60L * ((hh%12 +12)*60L + mm)+ss);
X case 24: if (hh < 0 || hh > 23) return (-1);
X return (60L * (hh*60L + mm)+ss);
X default: return (-1);
X }
X}
Xtime_t
Xmonthadd(sdate, relmonth)
Xtime_t sdate, relmonth;
X{
X struct tm *ltime;
X time_t dateconv();
X time_t daylcorr();
X int mm, yy;
X
X if (relmonth == 0) return 0;
X ltime = localtime(&sdate);
X mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
X yy = mm/12;
X mm = mm%12 + 1;
X return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
X ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
X}
X
Xtime_t
Xdaylcorr(future, now)
Xtime_t future, now;
X{
X int fdayl, nowdayl;
X
X nowdayl = (localtime(&now)->tm_hour+1) % 24;
X fdayl = (localtime(&future)->tm_hour+1) % 24;
X return (future-now) + 60L*60L*(nowdayl-fdayl);
X}
X
Xstatic char *lptr;
X
Xyylex()
X{
X extern int yylval;
X int sign = 0;
X register char c;
X register char *p;
X char idbuf[20];
X int pcnt;
X
X for (;;) {
X while (isspace(*lptr))
X lptr++;
X
X if (isdigit(c = *lptr) || c == '-' || c == '+') {
X if (c== '-' || c == '+') {
X if (c=='-') sign = -1;
X else sign = 1;
X if (!isdigit(*++lptr)) {
X /* yylval = sign; return (UNUMBER); */
X return yylex(); /* skip the '-' sign */
X }
X }
X yylval = 0;
X while (isdigit(c = *lptr++))
X yylval = 10*yylval + c - '0';
X lptr--;
X if (sign < 0)
X yylval = -yylval;
X if (sign != 0)
X return SNUMBER;
X else
X return UNUMBER;
X
X } else if (isalpha(c)) {
X p = idbuf;
X while (isalpha(c = *lptr++) || c=='.')
X if (p < &idbuf[sizeof(idbuf)-1]) *p++ = c;
X *p = '\0';
X lptr--;
X return (lookup(idbuf));
X }
X
X else if (c == '(') {
X pcnt = 0;
X do {
X c = *lptr++;
X if (c == '\0') return(c);
X else if (c == '(') pcnt++;
X else if (c == ')') pcnt--;
X } while (pcnt > 0);
X }
X
X else return (*lptr++);
X }
X}
X
Xstruct table {
X char *name;
X int type, value;
X};
X
Xstruct table mdtab[] = {
X {"january", MONTH, 1},
X {"february", MONTH, 2},
X {"march", MONTH, 3},
X {"april", MONTH, 4},
X {"may", MONTH, 5},
X {"june", MONTH, 6},
X {"july", MONTH, 7},
X {"august", MONTH, 8},
X {"september", MONTH, 9},
X {"sept", MONTH, 9},
X {"october", MONTH, 10},
X {"november", MONTH, 11},
X {"december", MONTH, 12},
X
X {"sunday", DAY, 0},
X {"monday", DAY, 1},
X {"tuesday", DAY, 2},
X {"tues", DAY, 2},
X {"wednesday", DAY, 3},
X {"wednes", DAY, 3},
X {"thursday", DAY, 4},
X {"thur", DAY, 4},
X {"thurs", DAY, 4},
X {"friday", DAY, 5},
X {"saturday", DAY, 6},
X {0, 0, 0}};
X
X#define HRS *60
X#define HALFHR 30
Xstruct table mztab[] = {
X {"a.m.", MERIDIAN, AM},
X {"am", MERIDIAN, AM},
X {"p.m.", MERIDIAN, PM},
X {"pm", MERIDIAN, PM},
X {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
X {"n.s.t.", ZONE, 3 HRS + HALFHR},
X {"ast", ZONE, 4 HRS}, /* Atlantic */
X {"a.s.t.", ZONE, 4 HRS},
X {"adt", DAYZONE, 4 HRS},
X {"a.d.t.", DAYZONE, 4 HRS},
X {"est", ZONE, 5 HRS}, /* Eastern */
X {"e.s.t.", ZONE, 5 HRS},
X {"edt", DAYZONE, 5 HRS},
X {"e.d.t.", DAYZONE, 5 HRS},
X {"cst", ZONE, 6 HRS}, /* Central */
X {"c.s.t.", ZONE, 6 HRS},
X {"cdt", DAYZONE, 6 HRS},
X {"c.d.t.", DAYZONE, 6 HRS},
X {"mst", ZONE, 7 HRS}, /* Mountain */
X {"m.s.t.", ZONE, 7 HRS},
X {"mdt", DAYZONE, 7 HRS},
X {"m.d.t.", DAYZONE, 7 HRS},
X {"pst", ZONE, 8 HRS}, /* Pacific */
X {"p.s.t.", ZONE, 8 HRS},
X {"pdt", DAYZONE, 8 HRS},
X {"p.d.t.", DAYZONE, 8 HRS},
X {"yst", ZONE, 9 HRS}, /* Yukon */
X {"y.s.t.", ZONE, 9 HRS},
X {"ydt", DAYZONE, 9 HRS},
X {"y.d.t.", DAYZONE, 9 HRS},
X {"hst", ZONE, 10 HRS}, /* Hawaii */
X {"h.s.t.", ZONE, 10 HRS},
X {"hdt", DAYZONE, 10 HRS},
X {"h.d.t.", DAYZONE, 10 HRS},
X
X {"gmt", ZONE, 0 HRS},
X {"g.m.t.", ZONE, 0 HRS},
X {"bst", DAYZONE, 0 HRS}, /* British Summer Time */
X {"b.s.t.", DAYZONE, 0 HRS},
X {"eet", ZONE, 0 HRS}, /* European Eastern Time */
X {"e.e.t.", ZONE, 0 HRS},
X {"eest", DAYZONE, 0 HRS}, /* European Eastern Summer Time */
X {"e.e.s.t.", DAYZONE, 0 HRS},
X {"met", ZONE, -1 HRS}, /* Middle European Time */
X {"m.e.t.", ZONE, -1 HRS},
X {"mest", DAYZONE, -1 HRS}, /* Middle European Summer Time */
X {"m.e.s.t.", DAYZONE, -1 HRS},
X {"wet", ZONE, -2 HRS }, /* Western European Time */
X {"w.e.t.", ZONE, -2 HRS },
X {"west", DAYZONE, -2 HRS}, /* Western European Summer Time */
X {"w.e.s.t.", DAYZONE, -2 HRS},
X
X {"jst", ZONE, -9 HRS}, /* Japan Standard Time */
X {"j.s.t.", ZONE, -9 HRS}, /* Japan Standard Time */
X /* No daylight savings time */
X
X {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
X {"a.e.s.t.", ZONE, -10 HRS},
X {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
X {"a.e.s.s.t.", DAYZONE, -10 HRS},
X {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
X {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
X {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
X {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
X {"awst", ZONE, -8 HRS}, /* Australian Western Time */
X {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */
X {0, 0, 0}};
X
Xstruct table unittb[] = {
X {"year", MUNIT, 12},
X {"month", MUNIT, 1},
X {"fortnight", UNIT, 14*24*60},
X {"week", UNIT, 7*24*60},
X {"day", UNIT, 1*24*60},
X {"hour", UNIT, 60},
X {"minute", UNIT, 1},
X {"min", UNIT, 1},
X {"second", SUNIT, 1},
X {"sec", SUNIT, 1},
X {0, 0, 0}};
X
Xstruct table othertb[] = {
X {"tomorrow", UNIT, 1*24*60},
X {"yesterday", UNIT, -1*24*60},
X {"today", UNIT, 0},
X {"now", UNIT, 0},
X {"last", UNUMBER, -1},
X {"this", UNIT, 0},
X {"next", UNUMBER, 2},
X {"first", UNUMBER, 1},
X /* {"second", UNUMBER, 2}, */
X {"third", UNUMBER, 3},
X {"fourth", UNUMBER, 4},
X {"fifth", UNUMBER, 5},
X {"sixth", UNUMBER, 6},
X {"seventh", UNUMBER, 7},
X {"eighth", UNUMBER, 8},
X {"ninth", UNUMBER, 9},
X {"tenth", UNUMBER, 10},
X {"eleventh", UNUMBER, 11},
X {"twelfth", UNUMBER, 12},
X {"ago", AGO, 1},
X {0, 0, 0}};
X
Xstruct table milzone[] = {
X {"a", ZONE, 1 HRS},
X {"b", ZONE, 2 HRS},
X {"c", ZONE, 3 HRS},
X {"d", ZONE, 4 HRS},
X {"e", ZONE, 5 HRS},
X {"f", ZONE, 6 HRS},
X {"g", ZONE, 7 HRS},
X {"h", ZONE, 8 HRS},
X {"i", ZONE, 9 HRS},
X {"k", ZONE, 10 HRS},
X {"l", ZONE, 11 HRS},
X {"m", ZONE, 12 HRS},
X {"n", ZONE, -1 HRS},
X {"o", ZONE, -2 HRS},
X {"p", ZONE, -3 HRS},
X {"q", ZONE, -4 HRS},
X {"r", ZONE, -5 HRS},
X {"s", ZONE, -6 HRS},
X {"t", ZONE, -7 HRS},
X {"u", ZONE, -8 HRS},
X {"v", ZONE, -9 HRS},
X {"w", ZONE, -10 HRS},
X {"x", ZONE, -11 HRS},
X {"y", ZONE, -12 HRS},
X {"z", ZONE, 0 HRS},
X {0, 0, 0}};
X
Xlookup(id)
Xchar *id;
X{
X#define gotit (yylval=i->value, i->type)
X
X char idvar[128];
X register char *j, *k;
X register struct table *i;
X int abbrev;
X
X (void) strcpy(idvar, id);
X j = idvar;
X k = id - 1;
X while (*++k)
X *j++ = isupper(*k) ? tolower(*k) : *k;
X *j = '\0';
X
X if (strlen(idvar) == 3)
X abbrev = 1;
X else
X if (strlen(idvar) == 4 && idvar[3] == '.') {
X abbrev = 1;
X idvar[3] = '\0';
X }
X else
X abbrev = 0;
X
X for (i = mdtab; i->name; i++) {
X k = idvar;
X for (j = i->name; *j++ == *k++;) {
X if (abbrev && j == i->name+3)
X return gotit;
X if (j[-1] == 0)
X return gotit;
X }
X }
X
X for (i = mztab; i->name; i++)
X if (strcmp(i->name, idvar) == 0)
X return gotit;
X
X for (i=mztab; i->name; i++)
X if (strcmp(i->name, idvar) == 0)
X return gotit;
X
X for (i=unittb; i->name; i++)
X if (strcmp(i->name, idvar) == 0)
X return gotit;
X
X if (idvar[strlen(idvar)-1] == 's')
X idvar[strlen(idvar)-1] = '\0';
X
X for (i=unittb; i->name; i++)
X if (strcmp(i->name, idvar) == 0)
X return gotit;
X
X for (i = othertb; i->name; i++)
X if (strcmp(i->name, idvar) == 0)
X return gotit;
X
X if (strlen(idvar) == 1 && isalpha(*idvar)) {
X for (i = milzone; i->name; i++)
X if (strcmp(i->name, idvar) == 0)
X return gotit;
X }
X
X return ID;
X}
X
Xtime_t
Xgetdate(p, now)
Xchar *p;
Xstruct timeb *now;
X{
X#define mcheck(f) if (f>1) err++
X time_t monthadd();
X int err;
X struct tm *lt;
X struct timeb ftz;
X
X time_t sdate, tod;
X
X lptr = p;
X if (now == ((struct timeb *) NULL)) {
X now = &ftz;
X ftime(&ftz);
X }
X lt = localtime(&now->time);
X year = lt->tm_year;
X month = lt->tm_mon+1;
X day = lt->tm_mday;
X relsec = 0; relmonth = 0;
X timeflag=zoneflag=dateflag=dayflag=relflag=0;
X ourzone = now->timezone;
X daylight = MAYBE;
X hh = mm = ss = 0;
X merid = 24;
X
X if (err = yyparse()) return (-1);
X
X mcheck(timeflag);
X mcheck(zoneflag);
X mcheck(dateflag);
X mcheck(dayflag);
X
X if (err) return (-1);
X if (dateflag || timeflag || dayflag) {
X sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
X if (sdate < 0) return -1;
X }
X else {
X sdate = now->time;
X if (relflag == 0)
X sdate -= (lt->tm_sec + lt->tm_min*60 +
X lt->tm_hour*(60L*60L));
X }
X
X sdate += relsec;
X sdate += monthadd(sdate, relmonth);
X
X if (dayflag && !dateflag) {
X tod = dayconv(dayord, dayreq, sdate);
X sdate += tod;
X }
X
X /*
X ** Have to do *something* with a legitimate -1 so it's distinguishable
X ** from the error return value. (Alternately could set errno on error.)
X */
X return (sdate == -1) ? 0 : sdate;
X}
X
Xyyerror(s) char *s;
X{}
END_OF_FILE_getdate.y
size="`wc -c < getdate.y`"
if test 13345 -ne "$size" ; then
echo "getdate.y: extraction error - got $size chars"
fi
fi
if test -f Makefile -a "$1" != "-c" ; then
echo "Makefile: file exists - will not be overwritten"
else
echo "x - Makefile (file 11 of 12, 1697 chars)"
sed -e 's/^X//' << 'END_OF_FILE_Makefile' > Makefile
X
X# %Z% %M% %I% %E% %U%
X# Makefile for "brkdig" (generated by /local/bin/makemake version 1.00.08)
X# Created by news@vector on Thu Sep 21 20:18:05 CDT 1989
X
XSHELL = /bin/sh
XCC = cc
XDEFS =
XCOPTS = -O
XLOPTS =
XLIBS = -lx
XDEBUG = -g -DDEBUG
XLINTFLAGS = -DLINT
X
XTARG = brkdig
XOTHERS = getdate.c
X
XSRCS = brkdig.c loaddefs.c block.c cleanhdr.c header.c fixfrom.c getdate.c
X
XOBJS = brkdig.o loaddefs.o block.o cleanhdr.o header.o fixfrom.o getdate.o
X
X# Any edits below this line will be lost if "makemake" is rerun!
X# Commands may be inserted after the '#%custom' line at the end of this file.
X
XCFLAGS = $(COPTS) $(DEFS) # $(DEBUG)
XLFLAGS = $(LOPTS) # $(DEBUG)
X
Xall: $(TARG) $(OTHERS)
Xinstall: all ; inst Install
Xclean: ; rm -f $(TARG) $(OBJS) a.out core $(TARG).lint
Xclobber: clean ; inst -u Install
Xlint: $(TARG).lint
X
X$(TARG): $(OBJS)
X $(CC) $(LFLAGS) -o $@ $(OBJS) $(LIBS)
X
X$(TARG).lint: $(TARG)
X lint $(LINTFLAGS) $(DEFS) $(SRCS) $(LIBS) > $@
X
Xbrkdig.o: brkdig.c brkdig.h
Xloaddefs.o: brkdig.h loaddefs.c
Xblock.o: block.c brkdig.h
Xcleanhdr.o: brkdig.h cleanhdr.c
Xheader.o: brkdig.h header.c
Xfixfrom.o: brkdig.h fixfrom.c
Xgetdate.o: getdate.c getdate.y
X
Xmake: ;
X /local/bin/makemake -i -v1.00.08 -aMakefile \
X -DSHELL='$(SHELL)' -DCC='$(CC)' -DDEFS='$(DEFS)' \
X -DCOPTS='$(COPTS)' -DLOPTS='$(LOPTS)' -DLIBS='$(LIBS)' \
X -DDEBUG='$(DEBUG)' -DLINTFLAGS='$(LINTFLAGS)' \
X -DOTHERS='$(OTHERS)' $(TARG) $(SRCS)
X
X#%custom - commands below this line will be maintained if 'makemake' is rerun
X
XARLIST = \
X README Defs-example brkdig.h brkdig.c \
X loaddefs.c block.c header.c cleanhdr.c fixfrom.c \
X getdate.y Makefile testaddr
X
Xshar: ; shar $(ARLIST) > brkdig.shar
X
END_OF_FILE_Makefile
size="`wc -c < Makefile`"
if test 1697 -ne "$size" ; then
echo "Makefile: extraction error - got $size chars"
fi
fi
if test -f testaddr -a "$1" != "-c" ; then
echo "testaddr: file exists - will not be overwritten"
else
echo "x - testaddr (file 12 of 12, 744 chars)"
sed -e 's/^X//' << 'END_OF_FILE_testaddr' > testaddr
X:
X# %Z% %M% %I% %E% %U%
X#
X# testaddr - Determine if an address is reachable.
X#
X# Mon Dec 4 08:46:36 1989 - Chip Rosenthal <chip@chinacat.Lonestar.ORG>
X# Original composition.
X#
X# This script uses smail2.5 to determine if an address is known. It is
X# required with "brkdig" because smail always returns a zero exit status
X# with the "-A" option. This script is intended for use in the "ADDR_CHECK"
X# parameter in the "brkdig" definitions file.
X
XUSAGE="usage: $0 addr"
XSMAIL=/bin/smail
X
Xif [ $# -ne 1 ] ; then
X echo "$USAGE" 1>&2
X exit 1
Xfi
X
Xaddr="$1" # addr to check
Xpath=`$SMAIL -A $addr 2>&1` # let smail route it
Xtest "$path" != "" -a "$path" != "$addr" # examine smail path result
Xexit $? # indicate whether addr worked
X
END_OF_FILE_testaddr
size="`wc -c < testaddr`"
if test 744 -ne "$size" ; then
echo "testaddr: extraction error - got $size chars"
fi
fi
echo "done - 12 files extracted"
exit 0