home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume09 / brkdig < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  62.3 KB

  1. From decwrl!wuarchive!uunet!allbery Wed Dec 27 19:58:43 PST 1989
  2. Article 1257 of comp.sources.misc:
  3. Path: decwrl!wuarchive!uunet!allbery
  4. From: chip@chinacat.Lonestar.ORG (Chip Rosenthal)
  5. Newsgroups: comp.sources.misc
  6. Subject: v09i091: brkdig - break mailing list digest into USENET messages
  7. Message-ID: <74793@uunet.UU.NET>
  8. Date: 27 Dec 89 23:55:19 GMT
  9. Sender: allbery@uunet.UU.NET
  10. Organization: Unicom Systems Development, Dallas
  11. Lines: 2281
  12. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  13.  
  14. Posting-number: Volume 9, Issue 91
  15. Submitted-by: chip@chinacat.Lonestar.ORG (Chip Rosenthal)
  16. Archive-name: brkdig
  17.  
  18. "brkdig" takes a mailing list digest, breaks it into individual messages,
  19. and provides headers appropriate for direct posting into USENET.  I developed
  20. "brkdig" when I administered the [TELECOM Digest]->comp.dcom.telecom gateway.
  21. It has been well tested under SCO XENIX.
  22.  
  23. There is one major portability issue:  "brkdig" uses the System V regex(3)
  24. routine, and takes advantage of its ability to extract information from the
  25. string.  I don't believe there is a direct BSD analog for this function.
  26.  
  27. #! /bin/sh
  28. # this is a "shar" archive - run through "/bin/sh" to extract 12 files:
  29. #   README Defs-example brkdig.h brkdig.c loaddefs.c block.c header.c cleanhdr.c fixfrom.c getdate.y Makefile testaddr
  30. # Wrapped by news@chinacat on Mon Dec 25 09:51:44 CST 1989
  31. # Unpacking this archive requires:  sed test wc (possibly mkdir)
  32. # Existing files will not be clobbered unless "-c" is specified on the cmd line.
  33. if test -f README -a "$1" != "-c" ; then
  34.     echo "README: file exists - will not be overwritten"
  35. else
  36.     echo "x - README (file 1 of 12, 2546 chars)"
  37.     sed -e 's/^X//' << 'END_OF_FILE_README' > README
  38. X
  39. X"brkdig" processes a mailing list digest into individual messages suitable
  40. Xfor posting to USENET.  There are two parts to this task:  slicing the
  41. Xdigest and generating the USENET headers.  The usage is:
  42. X
  43. X    brkdig [ -d max_days ] [ -f defs_file ] [ -I ] [ file ]
  44. X
  45. X        -d max_days    The "Date" of all messages is compared to a threshold,
  46. X            is stripped if too old.  This prevents inews from
  47. X            rejecting articles for being too old.  This switch
  48. X            overrides the default given in "brkdig.h".  A zero
  49. X            "max_days" value may be used to suppress the check.
  50. X
  51. X        -f defs_file    The digest definitions file which directs the
  52. X            gateway procedure.  This switch overrides the default
  53. X            given in "brkdig.h".
  54. X
  55. X        -I        This switch inhibits the creation of the messages, for
  56. X            debugging purposes.
  57. X
  58. X        file        Pathname to the digest to process.  If not specified,
  59. X            the standard input is processed.
  60. X
  61. X"brkdig" will generate a set of files, each containing an individual message
  62. Xfrom the digest, with headers ready to pass to "inews".  A log of the gateway
  63. Xprocessing is written to the standard error.  At successful conclusion, a
  64. Xsingle line is written to the standard output in the following format:
  65. X
  66. X    volume_num issue_num num_mssgs mssg_1_file ... mssg_N_file
  67. X
  68. X        volume_num    Volume number of the digest, padded to two digits
  69. X                        with leading zeros.
  70. X
  71. X        issue_num    Issue number of the digest, padded to three digits
  72. X                        with leading zeros.
  73. X
  74. X        num_mssgs    Number of messages in the digest, padded to two
  75. X                        digits with leading zeros.
  76. X
  77. X        mssg_1_file    Pathname to the first message extracted from the
  78. X                        digest -- all prepared for posting.
  79. X
  80. X         .
  81. X         .
  82. X         .
  83. X
  84. X    mssg_N_file    Pathname to the last message extracted.
  85. X
  86. XTherefore, to process and post the messages you could use a command
  87. Xsequence such as:
  88. X
  89. X    if set -- `brkdig $digest_file` ; then
  90. X    : brkdig worked
  91. X    else
  92. X    exit 1
  93. X    fi
  94. X    shift ; shift ; shift    # throw away first three fields
  95. X    for file in $* ; do
  96. X    /usr/lib/news/inews -h < $file
  97. X    rm $file
  98. X    done
  99. X
  100. XThe key to the digest processing is the definitions file.  Definitions
  101. Xin this file are generally a keyword, followed by a parameter.  Comments
  102. Xare introduced with a "#" and are ignored.  The "Defs-example" file
  103. X(included in this distribution) is an example definitions file.  It also
  104. Xcontains comments which describe the required format.
  105. X
  106. X
  107. XChip Rosenthal
  108. X<chip@vector.Dallas.TX.US>
  109. X@(#) README 1.2 89/12/25 09:48:05
  110. X
  111. END_OF_FILE_README
  112.     size="`wc -c < README`"
  113.     if test 2546 -ne "$size" ; then
  114.     echo "README: extraction error - got $size chars"
  115.     fi
  116. fi
  117. if test -f Defs-example -a "$1" != "-c" ; then
  118.     echo "Defs-example: file exists - will not be overwritten"
  119. else
  120.     echo "x - Defs-example (file 2 of 12, 7240 chars)"
  121.     sed -e 's/^X//' << 'END_OF_FILE_Defs-example' > Defs-example
  122. X##############################################################################
  123. X#
  124. X# @(#) Defs-example 1.1 89/12/25 09:45:30
  125. X#
  126. X# Defs-example - Sample "brkdig" definitions file.
  127. X#
  128. X# This example file is configured for the TELECOM Digest.  It is based
  129. X# on the actual file used when I gatewayed the TELECOM Digest into
  130. X# comp.dcom.telecom.
  131. X#
  132. X# Mon Dec  4 08:40:23 1989 - Chip Rosenthal <chip@chinacat.Lonestar.ORG>
  133. X#    Commented for inclusion in "brkdig" release.
  134. X#
  135. X##############################################################################
  136. X
  137. X
  138. X##############################################################################
  139. X#
  140. X# DIGEST_NAME - Name displayed on log output.
  141. X#    The parameter is a name displayed in the log output just to identify
  142. X#    the type of digest processed, and not is used anywhere else.
  143. X
  144. XDIGEST_NAME    TELECOM
  145. X
  146. X
  147. X##############################################################################
  148. X#
  149. X# TEMP_NAME - Pattern for creating temporary file names.
  150. X#    The parameter is a sprintf(3) pattern for generating names for the
  151. X#    individual message files.  The parameter will be formatted with
  152. X#    three numeric arguments - the digest volume number, issue number,
  153. X#    and message number.
  154. X
  155. XTEMP_NAME    /tmp/msg-v%02di%03dm%02d
  156. X
  157. X
  158. X##############################################################################
  159. X#
  160. X# ADDR_CHECK - Command to check e-mail addresses.
  161. X#    The parameter is a command which verifies whether an e-mail address
  162. X#    is valid.  This is used *only* when the From: address in a messaage
  163. X#    is a bang path rather than an RFC-822 address.  "brkdig" will attempt
  164. X#    to build a valid address from the path and use this command to check
  165. X#    it out.  This is important because inews will step on bad addresses.
  166. X#    The command must return a zero result on a valid address and a nonzero
  167. X#    result on a bad address.  The parameter is a sprintf(3) pattern and
  168. X#    will be formatted with one argument - the address to check.
  169. X
  170. XADDR_CHECK    smail -bv '%s' </dev/null >/dev/null 2>&1    # smail3.1
  171. X#ADDR_CHECK    /usenet/telecom-digest/work/testaddr '%s'    # smail2.5
  172. X
  173. X
  174. X##############################################################################
  175. X#
  176. X# Patterns within the digest, specified as regex(3) regular expressions.
  177. X#
  178. X#   PAT_TITLE    The parameter is a regex(3) format regular expression which
  179. X#        identifies the title line in the digest.  This line must
  180. X#        include the digest volume and issue numbers, and the parameter
  181. X#        must include the commands to extract these two parameters.
  182. X#        The volume number will be extracted as "$0" and the issue
  183. X#        number will be extracted as "$1".  Please refer to the
  184. X#        regex(3) manual page for information on forming such regular
  185. X#        expressions.
  186. X#
  187. X#   PAT_HDRSEP    This parameter is a regular expression which describes the
  188. X#        line which seperates the digest header from the first message
  189. X#        in the digest.
  190. X#
  191. X#   PAT_MSSGSEP    This parameter is a regular expression which describes the
  192. X#        line which seperates messages in the digest.
  193. X#
  194. X#   PAT_DIGEND    This parameter is a regular expression which describes any
  195. X#        line in the digest trailer.  This is used to confirm that an
  196. X#        entire, untruncated digest was received and processed
  197. X#        correctly.  Note that an actual telecom digest ends with a
  198. X#        line something like: "End of TELECOM Digest V9 #183", but we
  199. X#        have to use '.' instead of '#' in the pattern because '#' is
  200. X#        the comment character within this file.
  201. X
  202. X
  203. XPAT_TITLE    ^TELECOM Digest .* Volume ([0-9]{1,6})$0 : Issue ([0-9]{1,6})$1
  204. X
  205. XPAT_HDRSEP    ^------------------------------------------------------------------{1,9}$
  206. X
  207. XPAT_MSSGSEP    ^----------------------------{1,5}$
  208. X
  209. XPAT_DIGEND    ^End of TELECOM Digest V[0-9]* .[0-9]*$
  210. X
  211. X
  212. X##############################################################################
  213. X#
  214. X# Message header definitions.
  215. X#
  216. X#    The USENET headers are generated according to the table specified
  217. X#    below.  Headers are generated in the order given, and are controlled
  218. X#    by the "flag" type.  Some header types need a value to be specified
  219. X#    in the definition.  The flags, whether they need a value, and a
  220. X#    description are as follows:
  221. X#
  222. X#    flag     value?    description
  223. X#    -------- ------    ----------------------------------------------------
  224. X#    HDR_REQ     yes    Must appear - use our value if user doesn't give one.
  225. X#    HDR_OPT  no    Optional - generate only if the user provided one.
  226. X#    HDR_IGN     no    Silently ignore this if the user provided one.
  227. X#    HDR_ADD     yes    Ignore any user-supplied value and insert our own.
  228. X#    HDR_FMT     yes    Like "HDR_ADD", but format value with vol/iss/mssg no.
  229. X#    HDR_FROM yes    Like "HDR_REQ", but perform special "From:" checks.
  230. X#    HDR_DATE no    Like "HDR_OPT", but perform special "Date:" checks.
  231. X#
  232. X# More detailed explainations of the header flags are as follows:
  233. X#
  234. X# HDR_REQ    This header must appear in the news article header.  If
  235. X#        the original message contains this header, then its value
  236. X#        will be used.  Otherwise, we will fill in a default value.
  237. X# 
  238. X# HDR_OPT    This header may appear in the news article header.  If
  239. X#        the original message contains this header, then its value
  240. X#        will be used.  Otherwise, this header will not appear in
  241. X#        the news article.
  242. X# 
  243. X# HDR_ADD    The news article will contain this header with the value
  244. X#        we specify.  If the original message contains this header
  245. X#        then it will be silently ignored.
  246. X# 
  247. X# HDR_IGN    This header will never be placed in the news article.
  248. X#        If the original message contains this header then it will
  249. X#        be silently ignored.
  250. X# 
  251. X# HDR_FMT    This is similar to a "HDR_ADD" field, except the header
  252. X#        value given in the specifications file should be a
  253. X#        sprintf(3) pattern  The pattern will be formatted with
  254. X#        four numeric fields:  the digest volume number, the digest
  255. X#        issue number, a message number, and the total number of
  256. X#        messages in the digest.  The message number starts at 1
  257. X#        and increments with each message in the digest.
  258. X# 
  259. X# HDR_FROM    This is similar to a "HDR_REQ" field, except the header
  260. X#        value is subject to special address processing.  That is,
  261. X#        the value used will be guaranteed to be an RFC822ish
  262. X#        looking address.
  263. X# 
  264. X# HDR_DATE    This is similar to a "HDR_OPT" field, except the header
  265. X#        value is subject to special date processing.  That is,
  266. X#        the value will be compared to a threshold, and if found
  267. X#        to be too old will be suppressed.  The threshold is defined
  268. X#        by MAX_AGE in the "brkdig.h" file, and may be changed
  269. X#        with the "-d" command line option.
  270. X#
  271. X# NOTE:    In the following, I replaced "vector.dallas.tx.us", the site
  272. X#    upon which this definitions file was used with "BOGUS.ADDRESS".
  273. X
  274. X# type     header            value
  275. X#------     ---------------------    ---------------------------------------------
  276. XHDR_ADD     Path            telecom-gateway
  277. XHDR_FROM From            nobody@nowhere.UUCP (this is a bogus address)
  278. XHDR_ADD     Newsgroups        comp.dcom.telecom
  279. XHDR_REQ     Subject        (none)
  280. XHDR_FMT     Message-ID        <telecom-v%02di%04dm%02d@BOGUS.ADDRESS>
  281. XHDR_DATE Date
  282. XHDR_OPT     References
  283. XHDR_OPT     Keywords
  284. XHDR_OPT     Summary
  285. XHDR_OPT     Reply-To
  286. XHDR_OPT     Followup-To
  287. XHDR_OPT     Organization
  288. XHDR_ADD     Approved        telecom-request@BOGUS.ADDRESS
  289. XHDR_ADD     X-Submissions-To    telecom@eecs.nwu.edu
  290. XHDR_ADD     X-Administrivia-To    telecom-request@BOGUS.ADDRESS
  291. XHDR_FMT     X-TELECOM-Digest    volume %d, issue %d, message %d of %d
  292. XHDR_IGN     To
  293. XHDR_IGN     Cc
  294. XHDR_IGN     CC
  295. XHDR_IGN     Lines
  296. X
  297. END_OF_FILE_Defs-example
  298.     size="`wc -c < Defs-example`"
  299.     if test 7240 -ne "$size" ; then
  300.     echo "Defs-example: extraction error - got $size chars"
  301.     fi
  302. fi
  303. if test -f brkdig.h -a "$1" != "-c" ; then
  304.     echo "brkdig.h: file exists - will not be overwritten"
  305. else
  306.     echo "x - brkdig.h (file 3 of 12, 3331 chars)"
  307.     sed -e 's/^X//' << 'END_OF_FILE_brkdig.h' > brkdig.h
  308. X/* @(#) brkdig.h 1.2 89/09/21 20:25:59
  309. X *
  310. X * Module:    brkdig.h - global definitions
  311. X * Package:    brkdig - digest processor
  312. X *
  313. X * Thu Sep 21 20:16:47 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  314. X *    Added "clean_header()".
  315. X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  316. X *    Cleanup and beta release.
  317. X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  318. X *    Original composition.
  319. X */
  320. X
  321. X
  322. X/*
  323. X * DEFS_FILE - Default file with digest configuration definitions.  May be
  324. X * overridden with "-f" command line option.
  325. X */
  326. X#define DEFS_FILE    "Defs"
  327. X
  328. X
  329. X/*
  330. X * MAX_AGE - Maximum message age in seconds.  The "Date" field will be
  331. X * stripped from messages if they are over this value to prevent inews
  332. X * from rejecting the message.  A non-positive (e.g. zero) value suppresses
  333. X * this check.  May be overriden by "-d".
  334. X */
  335. X#define MAX_AGE        ( 7 * (24*60*60) )
  336. X
  337. X
  338. X#define BUFLEN        1024    /* input line buffer sizes        */
  339. X#define MAXMSSGS    128    /* maximum messages in a digest        */
  340. X#define MAXHDRS        64    /* maximum number of headers defined    */
  341. X#define TRUE        1
  342. X#define FALSE        0
  343. X
  344. X
  345. X/*
  346. X * USENET header types - used in (struct header_definitions)
  347. X */
  348. X#define HDR_REQ        1    /* this header must be in the message    */
  349. X#define HDR_FROM    2    /* special handling of "From:" header    */
  350. X#define HDR_DATE    3    /* special handling of "Date:" header    */
  351. X#define HDR_ADD        4    /* add this header; ignore user's value    */
  352. X#define HDR_FMT        5    /* like HDR_ADD, but format it first    */
  353. X#define HDR_OPT        6    /* this header may be used if present    */
  354. X#define HDR_IGN        7    /* this header should be suppressed    */
  355. X
  356. X
  357. X#ifndef LINT
  358. X# define SCCSID(STR) static char sccsid[] = STR;
  359. X#else
  360. X# define SCCSID(STR)
  361. X#endif
  362. X
  363. X
  364. X#ifdef M_XENIX
  365. X# ifdef NULL
  366. X#   undef NULL
  367. X#   define NULL 0
  368. X# endif
  369. X#endif
  370. X
  371. X
  372. X#ifdef INTERN
  373. X# define EXTERN
  374. X# define INIT(X)    = X
  375. X#else
  376. X# define EXTERN        extern
  377. X# define INIT(X)
  378. X#endif
  379. X
  380. X
  381. X/*
  382. X * Structure of a block of text.
  383. X */
  384. Xstruct text_block {
  385. X    char **line;        /* dynamically allocated list of lines    */
  386. X    int nlines;            /* number of lines in the list        */
  387. X    int max;            /* list will hold this many lines    */
  388. X};
  389. X
  390. Xstruct header_definition {
  391. X    int type;            /* code to define header processing    */
  392. X    char *name;            /* name of this header            */
  393. X    char *value;        /* value we will supply            */
  394. X};
  395. X
  396. X
  397. X/*
  398. X * Globals
  399. X */
  400. XEXTERN int Inhibit        INIT(FALSE);    /* inhibit file creation      */
  401. XEXTERN int Max_age        INIT(MAX_AGE);    /* limit on "Date" acceptance */
  402. XEXTERN int Num_hdrs        INIT(0);    /* num "Hdr_defs[]" defined   */
  403. XEXTERN char *Defs_file        INIT(DEFS_FILE);/* file with header defs      */
  404. XEXTERN char *Dig_name        INIT(NULL);    /* name of this digest          */
  405. XEXTERN char *Tmp_name        INIT(NULL);    /* pattern for temp files     */
  406. XEXTERN char *Addrchk_cmd    INIT(NULL);    /* cmd to check email addr    */
  407. XEXTERN char *Pat_title        INIT(NULL);    /* regex for digest header    */
  408. XEXTERN char *Pat_hdrsep        INIT(NULL);    /* re for end of header          */
  409. XEXTERN char *Pat_mssgsep    INIT(NULL);    /* re for message seperator   */
  410. XEXTERN char *Pat_digend        INIT(NULL);    /* re for end of digest          */
  411. XEXTERN struct header_definition Hdr_defs[MAXHDRS]; /* hdr generation specs    */
  412. X
  413. X
  414. X/*
  415. X * Global procedures.
  416. X */
  417. Xint block_load();
  418. Xint block_extract();
  419. Xint block_find();
  420. Xvoid clean_header();
  421. Xvoid output_header();
  422. Xchar *fix_bang_from();
  423. Xchar *Sstrdup();
  424. Xchar *Smalloc();
  425. Xchar *Srealloc();
  426. X
  427. END_OF_FILE_brkdig.h
  428.     size="`wc -c < brkdig.h`"
  429.     if test 3331 -ne "$size" ; then
  430.     echo "brkdig.h: extraction error - got $size chars"
  431.     fi
  432. fi
  433. if test -f brkdig.c -a "$1" != "-c" ; then
  434.     echo "brkdig.c: file exists - will not be overwritten"
  435. else
  436.     echo "x - brkdig.c (file 4 of 12, 6458 chars)"
  437.     sed -e 's/^X//' << 'END_OF_FILE_brkdig.c' > brkdig.c
  438. X/* @(#) brkdig.c 1.2 89/09/21 20:25:58
  439. X *
  440. X * Module:    brkdig.c - digest processor main program
  441. X * Package:    brkdig - digest processor
  442. X *
  443. X * Thu Sep 21 20:16:47 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  444. X *    Added "clean_header()".
  445. X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  446. X *    Cleanup and beta release.
  447. X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  448. X *    Original composition.
  449. X */
  450. X
  451. X#include <stdio.h>
  452. X#include <errno.h>
  453. X#define INTERN
  454. X#include "brkdig.h"
  455. X
  456. XSCCSID("@(#) brkdig.c 1.2 89/09/21 20:25:58")
  457. X
  458. X#define USAGE "usage: %s [-d max_days] [-f defs_file] [-I] [file]\n"
  459. X
  460. X/*
  461. X * There are two phases to the digest processor.  In the first phase, we
  462. X * break up the digest into all of its individual pieces, specifically the
  463. X * digest header, all of the message headers, and all of the message bodies.
  464. X * In the second phase, we run through all of the message headers and bodies
  465. X * and generate news articles.
  466. X *
  467. X * The digest text is manipulated in a (struct text_block).  We start by
  468. X * loading the entire digest into a "Digest" block, and then pull out the
  469. X * pieces.  Two procedures, block_find() and block_extract() are used.  The
  470. X * block_find() procedure takes a (struct text_block) and a regular expression,
  471. X * and returns the index of the first line in the block containing the RE.
  472. X * the block_extract() procedure pulls a range of lines out of one block,
  473. X * and places them into another.
  474. X */
  475. X
  476. Xstruct text_block Digest;        /* entire digest loaded here    */
  477. Xstruct text_block Digheader;        /* the digest header        */
  478. Xstruct text_block Mssgheader[MAXMSSGS];    /* all the message headers    */
  479. Xstruct text_block Mssgbody[MAXMSSGS];    /* all the message bodies    */
  480. X
  481. Xextern int errno;
  482. Xextern char *sys_errlist[];
  483. X
  484. X
  485. X/*VARARGS*/
  486. Xstatic void abort(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  487. Xchar *fmt, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9;
  488. X{
  489. X    fputs("  ", stderr);
  490. X    fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  491. X    fputs("\n  ABORTING - please process digest manually\n", stderr);
  492. X    (void) exit(1);
  493. X    /*NOTREACHED*/
  494. X}
  495. X
  496. X
  497. Xmain(argc,argv)
  498. Xint argc;
  499. Xchar *argv[];
  500. X{
  501. X    char volno_str[8], issno_str[8], *fname;
  502. X    int volno, issno, nmssgs, n, i;
  503. X    FILE *fp;
  504. X    static char tmpfname[BUFLEN];
  505. X    extern char *optarg;
  506. X    extern int optind;
  507. X    extern char *regcmp();
  508. X
  509. X    /*
  510. X     * Process command line arguments.
  511. X     */
  512. X    while ( (i=getopt(argc,argv,"d:f:I")) != EOF ) {
  513. X    switch ( i ) {
  514. X    case 'd':
  515. X        Max_age = atoi(optarg) * (24*60*60);
  516. X        break;
  517. X    case 'f':
  518. X        Defs_file = optarg;
  519. X        break;
  520. X    case 'I':
  521. X        Inhibit = TRUE;
  522. X        break;
  523. X    default:
  524. X        fprintf(stderr, USAGE, argv[0]);
  525. X        (void) exit(1);
  526. X    }
  527. X    }
  528. X    switch ( argc-optind ) {
  529. X    case 0:  fname = NULL; break;
  530. X    case 1:  fname = argv[optind]; break;
  531. X    default: fprintf(stderr, USAGE, argv[0]); (void) exit(1);
  532. X    }
  533. X
  534. X    /*
  535. X     * Load the definitions.
  536. X     */
  537. X    (void) load_defs(Defs_file);
  538. X    fprintf(stderr, "%s: receiving %s digest...\n", argv[0], Dig_name);
  539. X
  540. X    /*
  541. X     * Load in the digest.
  542. X     */
  543. X    if ( block_load(&Digest, fname) != 0 )
  544. X    abort("couldn't read file \"%s\" (%s)", fname, sys_errlist[errno]);
  545. X
  546. X    /*
  547. X     * Locate the end of the digest header.
  548. X     */
  549. X    if ( ( i = block_find(&Digest, Pat_hdrsep, (char *)0) ) < 0 )
  550. X    abort("couldn't locate end of digest header");
  551. X
  552. X    /*
  553. X     * Pull the header out of the digest.
  554. X     */
  555. X    if ( block_extract(&Digheader, &Digest, 0, i) < 0 )
  556. X    abort("couldn't extract header from digest");
  557. X
  558. X    /*
  559. X     * Locate the digest title within the header.
  560. X     */
  561. X    if (block_find(&Digheader, Pat_title, volno_str, issno_str, (char *)0) < 0)
  562. X    abort("couldn't locate digest title line");
  563. X    volno = atoi(volno_str);
  564. X    issno = atoi(issno_str);
  565. X    fprintf(stderr,"  processing volume %d issue %d\n",volno,issno);
  566. X
  567. X    /*
  568. X     * Extract all of the mesasges.
  569. X     */
  570. X    for (
  571. X    nmssgs = 0 ;
  572. X    ( i=block_find(&Digest, Pat_mssgsep, (char *)0) ) >= 0 ;
  573. X    ++nmssgs
  574. X    ) {
  575. X    if ( block_extract(&Mssgbody[nmssgs], &Digest, 0, i) < 0 )
  576. X        abort("mssg %d - couldn't extract from digest", nmssgs+1);
  577. X    (void) block_extract((struct text_block *)0, &Mssgbody[nmssgs], i, i);
  578. X    }
  579. X    fprintf(stderr, "  extracted %d messages from digest\n", nmssgs);
  580. X
  581. X    /*
  582. X     * Perform some sanity checks on the message extraction.
  583. X     */
  584. X    if ( nmssgs == 0 )
  585. X    abort("didn't extract any messages");
  586. X    if ( block_find(&Digest, Pat_digend, (char *)0) < 0 )
  587. X    abort("couldn't locate digest trailer");
  588. X    if ( block_find(&Digest, "^From ", (char *)0) >= 0 )
  589. X    abort("looks like unextracted messages remain");
  590. X
  591. X    /*
  592. X     * Split up the message headers and bodies.
  593. X     */
  594. X    for ( n = 0 ; n < nmssgs ; ++n ) {
  595. X    if ( ( i = block_find(&Mssgbody[n], "^$", (char *)0) ) < 0 )
  596. X        abort("mssg %d - couldn't find end of header", n+1);
  597. X    if ( block_extract(&Mssgheader[n], &Mssgbody[n], 0, i) < 0 )
  598. X        abort("mssg %d - couldn't extract message header", n+1);
  599. X    clean_header(&Mssgheader[n], n+1);
  600. X    }
  601. X
  602. X    /*
  603. X     * Process the messages.
  604. X     */
  605. X    for ( n = 0 ; n < nmssgs ; ++n ) {
  606. X
  607. X    /*
  608. X     * Open message file.
  609. X     */
  610. X    (void) sprintf(tmpfname, Tmp_name, volno, issno, n+1);
  611. X    if ( (fp=fopen((Inhibit ? "/dev/null" : tmpfname), "w")) == NULL ) {
  612. X        abort("mssg %d - couldn't create \"%s\" (%s)",
  613. X        n+1, tmpfname, sys_errlist[errno]);
  614. X    }
  615. X
  616. X    /*
  617. X     * Dump the article.
  618. X     */
  619. X    output_header(fp, &Mssgheader[n], volno, issno, n+1, nmssgs);
  620. X    putc('\n', fp);
  621. X    for ( i = 0 ; i < Mssgbody[n].nlines ; ++i ) {
  622. X        fputs(Mssgbody[n].line[i], fp);
  623. X        putc('\n', fp);
  624. X    }
  625. X
  626. X    (void) fclose(fp);
  627. X
  628. X    }
  629. X
  630. X    fprintf(stderr, "  extraction complete.\n");
  631. X
  632. X    /*
  633. X     * Output information for poster.
  634. X     */
  635. X    (void) printf("%02d %03d %02d", volno, issno, nmssgs);
  636. X    for ( i = 0 ; i < nmssgs ; ++i ) {
  637. X    (void) putchar(' ');
  638. X    (void) printf(Tmp_name, volno, issno, i+1);
  639. X    }
  640. X    (void) putchar('\n');
  641. X
  642. X    (void) exit(0);
  643. X    /*NOTREACHED*/
  644. X}
  645. X
  646. X
  647. Xstatic char malloc_error[] = "malloc: out of space\n";
  648. X
  649. Xchar *Sstrdup(s)
  650. Xchar *s;
  651. X{
  652. X    extern char *strcpy();
  653. X    return strcpy( Smalloc((unsigned)strlen(s)+1), s );
  654. X}
  655. X
  656. Xchar *Smalloc(n)
  657. Xunsigned n;
  658. X{
  659. X    char *s;
  660. X    extern char *malloc();
  661. X    if ( (s=malloc(n)) == NULL ) {
  662. X    fputs(malloc_error,stderr);
  663. X    (void) exit(2);
  664. X    }
  665. X    return s;
  666. X}
  667. X
  668. Xchar *Srealloc(s,n)
  669. Xchar *s;
  670. Xunsigned n;
  671. X{
  672. X    extern char *realloc();
  673. X    if ( s == NULL )
  674. X    return Smalloc(n);
  675. X    if ( (s=realloc(s,n)) == NULL ) {
  676. X    fputs(malloc_error,stderr);
  677. X    (void) exit(2);
  678. X    }
  679. X    return s;
  680. X}
  681. X
  682. X
  683. END_OF_FILE_brkdig.c
  684.     size="`wc -c < brkdig.c`"
  685.     if test 6458 -ne "$size" ; then
  686.     echo "brkdig.c: extraction error - got $size chars"
  687.     fi
  688. fi
  689. if test -f loaddefs.c -a "$1" != "-c" ; then
  690.     echo "loaddefs.c: file exists - will not be overwritten"
  691. else
  692.     echo "x - loaddefs.c (file 5 of 12, 3732 chars)"
  693.     sed -e 's/^X//' << 'END_OF_FILE_loaddefs.c' > loaddefs.c
  694. X/* @(#) loaddefs.c 1.1 89/08/25 20:47:41
  695. X *
  696. X * Module:    loaddefs.c - definitions file processing
  697. X * Package:    brkdig - digest processor
  698. X *
  699. X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  700. X *    Original composition.
  701. X */
  702. X
  703. X#include <stdio.h>
  704. X#include <ctype.h>
  705. X#include <string.h>
  706. X#include "brkdig.h"
  707. X
  708. X#define Strmatch(S1,S2)        ( strcmp((S1),(S2)) == 0 )
  709. X
  710. X
  711. Xvoid load_defs(fname)
  712. Xchar *fname;
  713. X{
  714. X    char **defp, *cmd, *arg, *s;
  715. X    int lineno, htype;
  716. X    FILE *fp;
  717. X    static char buf[BUFLEN];
  718. X
  719. X    if ( (fp=fopen(fname,"r")) == NULL ) {
  720. X    perror(fname);
  721. X    (void) exit(1);
  722. X    }
  723. X
  724. X    for ( lineno = 1 ; fgets(buf,sizeof(buf),fp) != NULL ; ++lineno ) {
  725. X
  726. X    /*
  727. X     * Trim comments, trailing spaces.
  728. X     */
  729. X    if ( (s=strchr(buf,'#')) != NULL )
  730. X        *s = '\0';
  731. X    for ( s = buf+strlen(buf)-1 ; s >= buf && isspace(*s) ; --s ) ;
  732. X    *(s+1) = '\0';
  733. X    if ( buf[0] == '\0' )
  734. X        continue;
  735. X
  736. X    /*
  737. X     * Split the line into a command and argument.
  738. X     */
  739. X    for ( cmd = buf ; isspace(*cmd) ; ++cmd ) ;
  740. X    for ( arg = cmd ; *arg != '\0' && !isspace(*arg) ; ++arg ) ;
  741. X    if ( *arg == '\0' ) {
  742. X        fprintf(stderr,"%s(%d): missing argument to '%s'\n",
  743. X        fname,lineno,cmd);
  744. X        (void) exit(1);
  745. X    }
  746. X    for ( *arg++ = '\0' ; isspace(*arg) ; ++arg ) ;
  747. X
  748. X    /*
  749. X     * Process the command.
  750. X     */
  751. X    defp = NULL;
  752. X    htype = -1;
  753. X    if ( Strmatch(cmd,"DIGEST_NAME") )    defp = &Dig_name;
  754. X    else if ( Strmatch(cmd,"TEMP_NAME") )    defp = &Tmp_name;
  755. X    else if ( Strmatch(cmd,"ADDR_CHECK") )    defp = &Addrchk_cmd;
  756. X    else if ( Strmatch(cmd,"PAT_TITLE") )    defp = &Pat_title;
  757. X    else if ( Strmatch(cmd,"PAT_HDRSEP") )    defp = &Pat_hdrsep;
  758. X    else if ( Strmatch(cmd,"PAT_MSSGSEP") )    defp = &Pat_mssgsep;
  759. X    else if ( Strmatch(cmd,"PAT_DIGEND") )    defp = &Pat_digend;
  760. X    else if ( Strmatch(cmd,"HDR_ADD") )    htype = HDR_ADD;
  761. X    else if ( Strmatch(cmd,"HDR_DATE") )    htype = HDR_DATE;
  762. X    else if ( Strmatch(cmd,"HDR_FMT") )    htype = HDR_FMT;
  763. X    else if ( Strmatch(cmd,"HDR_FROM") )    htype = HDR_FROM;
  764. X    else if ( Strmatch(cmd,"HDR_IGN") )    htype = HDR_IGN;
  765. X    else if ( Strmatch(cmd,"HDR_OPT") )    htype = HDR_OPT;
  766. X    else if ( Strmatch(cmd,"HDR_REQ") )    htype = HDR_REQ;
  767. X    else {
  768. X        fprintf(stderr,"%s(%d): unknown command '%s'\n",
  769. X        fname,lineno,cmd);
  770. X        (void) exit(1);
  771. X    }
  772. X
  773. X    if ( defp != NULL ) {
  774. X        if ( *defp != NULL ) {
  775. X        fprintf(stderr,"%s(%d): duplicate definition of '%s'\n",
  776. X            fname,lineno,cmd);
  777. X        (void) exit(1);
  778. X        }
  779. X        *defp = Sstrdup(arg);
  780. X    }
  781. X
  782. X    if ( htype >= 0 ) {
  783. X        if ( Num_hdrs >= MAXHDRS ) {
  784. X        fprintf(stderr,"%s(%d): too many header specifications\n",
  785. X            fname,lineno);
  786. X        (void) exit(1);
  787. X        }
  788. X        Hdr_defs[Num_hdrs].type = htype;
  789. X        for ( s = arg ; *s != '\0' && !isspace(*s) ; ++s ) ;
  790. X        if ( *s == '\0' ) {
  791. X        Hdr_defs[Num_hdrs].value = NULL;
  792. X        } else {
  793. X        for ( *s++ = '\0' ; isspace(*s) ; ++s ) ;
  794. X        Hdr_defs[Num_hdrs].value = Sstrdup(s);
  795. X        }
  796. X        Hdr_defs[Num_hdrs].name = Sstrdup(arg);
  797. X        ++Num_hdrs;
  798. X    }
  799. X
  800. X    }
  801. X
  802. X    if ( Dig_name == NULL ) {
  803. X    fprintf(stderr,"%s: parameter 'DIG_NAME' unspecified\n", fname);
  804. X    (void) exit(1);
  805. X    }
  806. X    if ( Tmp_name == NULL ) {
  807. X    fprintf(stderr,"%s: parameter 'TMP_NAME' unspecified\n", fname);
  808. X    (void) exit(1);
  809. X    }
  810. X    if ( Addrchk_cmd == NULL ) {
  811. X    fprintf(stderr,"%s: parameter 'ADDRCHK_CMD' unspecified\n", fname);
  812. X    (void) exit(1);
  813. X    }
  814. X    if ( Pat_title == NULL ) {
  815. X    fprintf(stderr,"%s: parameter 'PAT_TITLE' unspecified\n", fname);
  816. X    (void) exit(1);
  817. X    }
  818. X    if ( Pat_hdrsep == NULL ) {
  819. X    fprintf(stderr,"%s: parameter 'PAT_HDRSEP' unspecified\n", fname);
  820. X    (void) exit(1);
  821. X    }
  822. X    if ( Pat_mssgsep == NULL ) {
  823. X    fprintf(stderr,"%s: parameter 'PAT_MSSGSEP' unspecified\n", fname);
  824. X    (void) exit(1);
  825. X    }
  826. X    if ( Pat_digend == NULL ) {
  827. X    fprintf(stderr,"%s: parameter 'PAT_DIGEND' unspecified\n", fname);
  828. X    (void) exit(1);
  829. X    }
  830. X
  831. X}
  832. X
  833. END_OF_FILE_loaddefs.c
  834.     size="`wc -c < loaddefs.c`"
  835.     if test 3732 -ne "$size" ; then
  836.     echo "loaddefs.c: extraction error - got $size chars"
  837.     fi
  838. fi
  839. if test -f block.c -a "$1" != "-c" ; then
  840.     echo "block.c: file exists - will not be overwritten"
  841. else
  842.     echo "x - block.c (file 6 of 12, 4263 chars)"
  843.     sed -e 's/^X//' << 'END_OF_FILE_block.c' > block.c
  844. X/* @(#) block.c 1.1 89/08/25 20:47:39
  845. X *
  846. X * Module:    block.c - text block manipulation routines
  847. X * Package:    brkdig - digest processor
  848. X *
  849. X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  850. X *    Cleanup and beta release.
  851. X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  852. X *    Original composition.
  853. X */
  854. X
  855. X#include <stdio.h>
  856. X#include <ctype.h>
  857. X#include <string.h>
  858. X#include "brkdig.h"
  859. X
  860. XSCCSID("@(#) block.c 1.1 89/08/25 20:47:39")
  861. X
  862. Xstatic struct text_block *block_clean();
  863. X
  864. X
  865. X/*
  866. X * block_load() - load the contents of a file into a block.
  867. X *    The block will be initialized prior to loading.  Any information
  868. X *    currently in the block prior to the load will be lost.
  869. X */
  870. Xint block_load(b,fname)
  871. Xstruct text_block *b;
  872. Xchar *fname;
  873. X{
  874. X    FILE *fp;
  875. X    char *s;
  876. X    static char buf[1024];
  877. X
  878. X    if ( fname == NULL )
  879. X    fp = stdin;
  880. X    else if ( (fp=fopen(fname,"r")) == NULL )
  881. X    return -1;
  882. X
  883. X    b->nlines = b->max = 0;
  884. X    b->line = NULL;
  885. X
  886. X    while ( fgets(buf,sizeof(buf),fp) != NULL ) {
  887. X
  888. X    /*
  889. X     * Expand block if more space is needed.
  890. X     */
  891. X    if ( b->nlines >= b->max ) {
  892. X        b->max = ( b->max == 0 ? 128 : b->max << 1 ) ;
  893. X        b->line = 
  894. X        (char **)Srealloc( (char *)b->line, b->max*sizeof(char *) );
  895. X    }
  896. X
  897. X    /*
  898. X     * Trim trailing space.
  899. X     */
  900. X    for ( s = buf+strlen(buf)-1 ; s >= buf && isspace(*s) ; --s ) ;
  901. X    *(s+1) = '\0';
  902. X
  903. X    /*
  904. X     * Append line to block.
  905. X     */
  906. X    b->line[b->nlines++] = Sstrdup(buf);
  907. X
  908. X    }
  909. X
  910. X    if ( fname != NULL )
  911. X    (void) fclose(fp);
  912. X    (void) block_clean(b);
  913. X    return 0;
  914. X}
  915. X
  916. X
  917. X/*
  918. X * block_extract() - move a group of lines from one block to another
  919. X *    Lines are numbered "0" through "nlines-1".  The inclusive range
  920. X *    of lines is deleted from the "b_old" block.  The "b_new" block is
  921. X *    initialized, and the deleted lines are placed there.  If there was
  922. X *    any information in the "b_new" block prior to extraction then it
  923. X *    will be lost.  If the "b_new" block is NULL, then this procedure
  924. X *    just deletes the range of lines from the "b_old" block.
  925. X */
  926. Xint block_extract(b_new,b_old,nstart,nend)
  927. Xstruct text_block *b_new;
  928. Xstruct text_block *b_old;
  929. Xint nstart;
  930. Xint nend;
  931. X{
  932. X    int nlines, i;
  933. X
  934. X    if ( nstart < 0 || nend >= b_old->nlines || nstart > nend )
  935. X    return -1;
  936. X
  937. X    nlines = nend-nstart+1;
  938. X
  939. X    if ( b_new != NULL ) {
  940. X    b_new->max = b_new->nlines = nlines;
  941. X    b_new->line = (char **) Smalloc( b_new->max * sizeof(char *) );
  942. X    for ( i = 0 ; i < nlines ; ++i )
  943. X        b_new->line[i] = b_old->line[nstart+i];
  944. X    (void) block_clean(b_new);
  945. X    }
  946. X
  947. X    for ( i = nend+1 ; i < b_old->nlines ; ++i )
  948. X    b_old->line[i-nlines] = b_old->line[i];
  949. X    b_old->nlines -= nlines;
  950. X    (void) block_clean(b_old);
  951. X
  952. X    return 0;
  953. X}
  954. X
  955. X
  956. X/*
  957. X * block_find() - find the first instance of a pattern in a block.
  958. X *    The "pattern" is a regular expression.  The arguments allow up
  959. X *    to five sections of the line to be extracted (c.f. regexp(3)).
  960. X *    The index (between "0" and "nlines-1") of the first line in the
  961. X *    block which matches the pattern is returned.  A "-1" is returned
  962. X *    upon search failure or error.
  963. X */
  964. X/*VARARGS*/
  965. Xint block_find(b,pattern,a0,a1,a2,a3,a4)
  966. Xstruct text_block *b;
  967. Xchar *pattern, *a0, *a1, *a2, *a3, *a4;
  968. X{
  969. X    char *re;
  970. X    int i;
  971. X    extern char *regcmp(), *regex();
  972. X    extern void free();
  973. X
  974. X    if ( (re=regcmp(pattern,(char *)0)) == NULL ) {
  975. X    fputs("malloc: out of space\n",stderr);
  976. X    (void) exit(2);
  977. X    }
  978. X
  979. X    for ( i = 0 ; i < b->nlines ; ++i ) {
  980. X    if ( regex(re,b->line[i],a0,a1,a2,a3,a4,(char *)0) != NULL )
  981. X        break;
  982. X    }
  983. X
  984. X    (void) free(re);
  985. X    return ( i < b->nlines ? i : -1 );
  986. X}
  987. X
  988. X
  989. X/*
  990. X * block_clean() - trim leading and trailing blank lines from a block.
  991. X *    The "nlines" count is updated to reflect any changes.
  992. X */
  993. Xstatic struct text_block *block_clean(b)
  994. Xstruct text_block *b;
  995. X{
  996. X    int i, j;
  997. X    char *s;
  998. X
  999. X    /*
  1000. X     * Trim leading blank lines.
  1001. X     */
  1002. X    for ( i = 0 ; i < b->nlines ; ++i ) {
  1003. X    for ( s = b->line[i] ; isspace(*s) ; ++s ) ;
  1004. X    if ( *s != '\0' )
  1005. X        break;
  1006. X    }
  1007. X    if ( i > 0 ) {
  1008. X    for ( j = i ; j < b->nlines ; ++j )
  1009. X        b->line[j-i] = b->line[j];
  1010. X    b->nlines -= i;
  1011. X    }
  1012. X
  1013. X    /*
  1014. X     * Trim trailing blank lines.
  1015. X     */
  1016. X    for ( i = b->nlines-1 ; i >= 0 ; --i ) {
  1017. X    for ( s = b->line[i] ; isspace(*s) ; ++s ) ;
  1018. X    if ( *s != '\0' )
  1019. X        break;
  1020. X    }
  1021. X    b->nlines = i+1;
  1022. X
  1023. X    return b;
  1024. X}
  1025. X
  1026. X
  1027. END_OF_FILE_block.c
  1028.     size="`wc -c < block.c`"
  1029.     if test 4263 -ne "$size" ; then
  1030.     echo "block.c: extraction error - got $size chars"
  1031.     fi
  1032. fi
  1033. if test -f header.c -a "$1" != "-c" ; then
  1034.     echo "header.c: file exists - will not be overwritten"
  1035. else
  1036.     echo "x - header.c (file 7 of 12, 6640 chars)"
  1037.     sed -e 's/^X//' << 'END_OF_FILE_header.c' > header.c
  1038. X/* @(#) header.c 1.1 89/08/25 20:47:41
  1039. X *
  1040. X * Module:    header.c - news article header generation
  1041. X * Package:    brkdig - digest processor
  1042. X *
  1043. X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  1044. X *    Cleanup and beta release.
  1045. X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  1046. X *    Original composition.
  1047. X */
  1048. X
  1049. X#include <stdio.h>
  1050. X#include <ctype.h>
  1051. X#include <string.h>
  1052. X#include "brkdig.h"
  1053. X
  1054. XSCCSID("@(#) header.c 1.1 89/08/25 20:47:41")
  1055. X
  1056. X
  1057. Xstatic char *find_header();
  1058. Xstatic char *append_header();
  1059. X
  1060. X
  1061. Xstatic void hdr_error(mssgno,hdr_name,problem,old_value,new_value)
  1062. Xint mssgno;
  1063. Xchar *hdr_name;
  1064. Xchar *problem;
  1065. Xchar *old_value;
  1066. Xchar *new_value;
  1067. X{
  1068. X    fprintf(stderr,"  message %d - \"%s\" header problem - %s\n",
  1069. X    mssgno, hdr_name, problem);
  1070. X    if ( old_value != NULL )
  1071. X    fprintf(stderr,"  ..removing \"%s: %s\"\n", hdr_name, old_value);
  1072. X    if ( new_value != NULL )
  1073. X    fprintf(stderr,"  ....adding \"%s: %s\"\n", hdr_name, new_value);
  1074. X}
  1075. X
  1076. X
  1077. Xvoid output_header(fp,b,volno,issno,mssgno,nummssgs)
  1078. XFILE *fp;
  1079. Xstruct text_block *b;
  1080. Xint volno, issno, mssgno, nummssgs;
  1081. X{
  1082. X    int hdrno, i;
  1083. X    long time_now, time_post;
  1084. X    char *appendhdr, *name, *value, *new_value;
  1085. X    static char fmtbuf[BUFLEN];
  1086. X    extern long time(), getdate();
  1087. X    extern void free();
  1088. X
  1089. X    (void) time(&time_now);
  1090. X    appendhdr = NULL;
  1091. X
  1092. X    /*
  1093. X     * Go through all of the header items.
  1094. X     */
  1095. X    for ( hdrno = 0 ; hdrno < Num_hdrs ; ++hdrno ) {
  1096. X
  1097. X    name = Hdr_defs[hdrno].name;
  1098. X
  1099. X    /*
  1100. X     * Process the header.
  1101. X     */
  1102. X    switch ( Hdr_defs[hdrno].type ) {
  1103. X
  1104. X    case HDR_REQ:
  1105. X        if ( (value=find_header(b,name,mssgno)) == NULL ) {
  1106. X        value = Hdr_defs[hdrno].value;
  1107. X        hdr_error(mssgno, name, "required header not in message",
  1108. X            (char *)NULL, value);
  1109. X        }
  1110. X        break;
  1111. X
  1112. X    case HDR_ADD:
  1113. X        (void) find_header(b,name,mssgno);
  1114. X        value = Hdr_defs[hdrno].value;
  1115. X        break;
  1116. X
  1117. X    case HDR_FMT:
  1118. X        (void) find_header(b,name,mssgno);
  1119. X        (void) sprintf(fmtbuf,
  1120. X        Hdr_defs[hdrno].value, volno, issno, mssgno, nummssgs);
  1121. X        value = fmtbuf;
  1122. X        break;
  1123. X
  1124. X    case HDR_OPT:
  1125. X        value = find_header(b,name,mssgno);
  1126. X        break;
  1127. X
  1128. X    case HDR_IGN:
  1129. X        (void) find_header(b,name,mssgno);
  1130. X        value = NULL;
  1131. X        break;
  1132. X
  1133. X    case HDR_FROM:
  1134. X
  1135. X        /*
  1136. X         * Make sure the user gave us an address.
  1137. X         */
  1138. X        if ( (value=find_header(b,name,mssgno)) == NULL ) {
  1139. X        value = Hdr_defs[hdrno].value;
  1140. X        hdr_error(mssgno, name, "required header not in message",
  1141. X            (char *)NULL, value);
  1142. X        appendhdr = append_header(appendhdr,
  1143. X            "message missing 'From' field - bogus address added",
  1144. X            (char *)NULL, (char *)NULL
  1145. X        );
  1146. X        break;
  1147. X        }
  1148. X
  1149. X        /*
  1150. X         * If there is a '@' in it, then assume it is OK.
  1151. X         */
  1152. X        if ( strchr(value,'@') != NULL )
  1153. X        break;
  1154. X
  1155. X        /*
  1156. X         * Try to munge bang-paths into an address.  If that doesn't
  1157. X         * work then use a bogus default.
  1158. X         */
  1159. X        if ( (new_value=fix_bang_from(value)) == NULL )
  1160. X        new_value = Hdr_defs[hdrno].value;
  1161. X        hdr_error(mssgno, name, "address is not valid USENET syntax",
  1162. X        value, new_value);
  1163. X        appendhdr = append_header(appendhdr,
  1164. X        "original 'From' address is not valid USENET syntax",
  1165. X        "X-Originally-From", value
  1166. X        );
  1167. X        value = new_value;
  1168. X        break;
  1169. X
  1170. X
  1171. X    case HDR_DATE:
  1172. X
  1173. X        /*
  1174. X         * If the user didn't specify a date, that's OK.
  1175. X         */
  1176. X        if ( (value=find_header(b,name,mssgno)) == NULL )
  1177. X        break;
  1178. X
  1179. X        /*
  1180. X         * Verify that the syntax is correct.
  1181. X         */
  1182. X        if ( (time_post=getdate(value,(char *)NULL)) <= 0 ) {
  1183. X        hdr_error(mssgno, name, "date is not valid USENET syntax",
  1184. X            value, (char *)NULL);
  1185. X        appendhdr = append_header(appendhdr,
  1186. X            "original 'Date' value is not valid USENET syntax",
  1187. X            "X-Original-Date", value
  1188. X        );
  1189. X        value = NULL;
  1190. X        break;
  1191. X        }
  1192. X
  1193. X        /*
  1194. X         * Verify that it isn't too old - otherwise inews might reject it.
  1195. X         */
  1196. X        if ( Max_age > 0 && time_now-time_post > Max_age ) {
  1197. X        hdr_error(mssgno, name, "date is too old for posting",
  1198. X            value, (char *)NULL);
  1199. X        appendhdr = append_header(appendhdr,
  1200. X            "original 'Date' value is too old for posting",
  1201. X            "X-Original-Date", value
  1202. X        );
  1203. X        value = NULL;
  1204. X        break;
  1205. X        }
  1206. X
  1207. X        /*
  1208. X         * The date looks good.
  1209. X         */
  1210. X        break;
  1211. X
  1212. X    default:
  1213. X        hdr_error(mssgno, name, "INTERNAL ERROR - bad header code",
  1214. X        (char *)NULL, (char *)NULL);
  1215. X        (void) exit(1);
  1216. X
  1217. X    }
  1218. X
  1219. X    if ( value != NULL )
  1220. X        fprintf(fp, "%s: %s\n", name, value);
  1221. X
  1222. X    }
  1223. X
  1224. X    for ( i = 0 ; i < b->nlines ; ++i ) {
  1225. X    if ( b->line[i] != NULL ) {
  1226. X        name = b->line[i];
  1227. X        for ( value = name ; *value != ':' && *value != '\0' ; ++value ) ;
  1228. X        if ( *value != '\0' )
  1229. X        for ( *value++ = '\0' ; isspace(*value) ; ++value ) ;
  1230. X        hdr_error(mssgno, name, "unknown or unsupported header",
  1231. X        value, (char *)NULL);
  1232. X    }
  1233. X    }
  1234. X
  1235. X    if ( appendhdr != NULL ) {
  1236. X    fputs(appendhdr,fp);
  1237. X    (void) free(appendhdr);
  1238. X    }
  1239. X
  1240. X}
  1241. X
  1242. X
  1243. Xstatic char *find_header(b,name,mssgno)
  1244. Xstruct text_block *b;
  1245. Xchar *name;
  1246. Xint mssgno;
  1247. X{
  1248. X    int count, len, i;
  1249. X    char *value, *s;
  1250. X    static char valbuf[BUFLEN];
  1251. X    extern void free();
  1252. X    extern char *strcpy();
  1253. X
  1254. X    len = strlen(name);
  1255. X    value = NULL;
  1256. X    count = 0;
  1257. X
  1258. X    for ( i = 0 ; i < b->nlines ; ++i ) {
  1259. X
  1260. X    /*
  1261. X     * See if this is a header line we want.
  1262. X     */
  1263. X    if ( b->line[i] == NULL )
  1264. X        continue;
  1265. X    if ( strncmp(b->line[i],name,len) != 0 )
  1266. X        continue;
  1267. X    if ( b->line[i][len] != ':' || !isspace(b->line[i][len+1]) )
  1268. X        continue;
  1269. X
  1270. X    /* 
  1271. X     * Locate and save off the value.
  1272. X     */
  1273. X    for ( s = b->line[i]+len+1 ; isspace(*s) ; ++s ) ;
  1274. X    if ( *s != '\0' ) {
  1275. X        if ( ++count > 1 ) {
  1276. X        hdr_error(mssgno, name, "duplicate header value",
  1277. X            s, (char *)NULL);
  1278. X        } else {
  1279. X        value = strcpy(valbuf,s);
  1280. X        }
  1281. X    }
  1282. X
  1283. X    /*
  1284. X     * Erase and free up the header.
  1285. X     */
  1286. X    (void) free(b->line[i]);
  1287. X    b->line[i] = NULL;
  1288. X
  1289. X    }
  1290. X
  1291. X    return value;
  1292. X}
  1293. X
  1294. X
  1295. Xstatic char *append_header(h,problem,add_hdr,add_value)
  1296. Xchar *h, *problem, *add_hdr, *add_value;
  1297. X{
  1298. X    unsigned len;
  1299. X    char *newh;
  1300. X    static char warning_mssg[] = "X-GATEWAY-WARNING: ";
  1301. X    extern char *malloc(), *realloc();
  1302. X
  1303. X    len =
  1304. X    sizeof(warning_mssg)-1
  1305. X        + strlen(problem)
  1306. X        + sizeof("\n")-1
  1307. X    + strlen(add_hdr)
  1308. X        + sizeof(": ")-1
  1309. X        + strlen(add_value)
  1310. X        + sizeof("\n")-1
  1311. X    ;
  1312. X
  1313. X    newh = ( h == NULL ? malloc(len+1) : realloc(h,strlen(h)+len+1) );
  1314. X    if ( newh == NULL ) {
  1315. X    fputs("malloc: out of space\n",stderr);
  1316. X    (void) exit(1);
  1317. X    }
  1318. X    if ( h == NULL )
  1319. X    *newh = '\0';
  1320. X
  1321. X    (void) strcat(newh,warning_mssg);
  1322. X    (void) strcat(newh,problem);
  1323. X    (void) strcat(newh,"\n");
  1324. X    if ( add_hdr != NULL && add_value != NULL ) {
  1325. X    (void) strcat(newh,add_hdr);
  1326. X    (void) strcat(newh,": ");
  1327. X    (void) strcat(newh,add_value);
  1328. X    (void) strcat(newh,"\n");
  1329. X    }
  1330. X
  1331. X    return newh;
  1332. X}
  1333. X
  1334. END_OF_FILE_header.c
  1335.     size="`wc -c < header.c`"
  1336.     if test 6640 -ne "$size" ; then
  1337.     echo "header.c: extraction error - got $size chars"
  1338.     fi
  1339. fi
  1340. if test -f cleanhdr.c -a "$1" != "-c" ; then
  1341.     echo "cleanhdr.c: file exists - will not be overwritten"
  1342. else
  1343.     echo "x - cleanhdr.c (file 8 of 12, 1686 chars)"
  1344.     sed -e 's/^X//' << 'END_OF_FILE_cleanhdr.c' > cleanhdr.c
  1345. X/* @(#) cleanhdr.c 1.1 89/09/21 20:26:07
  1346. X *
  1347. X * Module:    cleanhdr.c - header block cleanups
  1348. X * Package:    brkdig - digest processor
  1349. X *
  1350. X * Thu Sep 21 20:00:31 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  1351. X *    Original composition.
  1352. X */
  1353. X
  1354. X#include <stdio.h>
  1355. X#include <ctype.h>
  1356. X#include <string.h>
  1357. X#include "brkdig.h"
  1358. X
  1359. XSCCSID("@(#) cleanhdr.c 1.1 89/09/21 20:26:07")
  1360. X
  1361. X/*
  1362. X * clean_header() - perform various header cleanups.
  1363. X *    This procedure attempts to work around various limitations and
  1364. X *    glitches which occur to headers when passed through mail.
  1365. X */
  1366. Xvoid clean_header(h,mssgno)
  1367. Xstruct text_block *h;
  1368. Xint mssgno;
  1369. X{
  1370. X    char *s;
  1371. X    int i, j;
  1372. X
  1373. X    for ( i = 0 ; i < h->nlines ; ++i ) {
  1374. X
  1375. X    /*
  1376. X     * Assume a line starting with whitespace is a continuation line.
  1377. X     */
  1378. X    if ( i > 0 && isspace(*h->line[i]) ) {
  1379. X        for ( s = h->line[i] ; isspace(*s) ; ++s ) ;
  1380. X        *--s = ' ';
  1381. X        j = strlen(h->line[i-1]) + strlen(s) + 1;
  1382. X        h->line[i-1] = Srealloc( h->line[i-1], j );
  1383. X        (void) strcat(h->line[i-1],s);
  1384. X        (void) free(h->line[i]);
  1385. X        for ( j = i+1 ; j < h->nlines ; ++j )
  1386. X        h->line[j-1] = h->line[j];
  1387. X        --h->nlines;
  1388. X        --i;
  1389. X        continue;
  1390. X    }
  1391. X
  1392. X    /*
  1393. X     * Convert ">From" to "From".
  1394. X     */
  1395. X    if ( strncmp( h->line[i], ">From:", sizeof(">From:")-1 ) == 0 ) {
  1396. X        for ( s = h->line[i] ; *s != '\0' ; ++s )
  1397. X        *s = *(s+1);
  1398. X    }
  1399. X
  1400. X    /*
  1401. X     * Verify that this looks like a header.
  1402. X     */
  1403. X    for ( s = h->line[i] ; *s != '\0' && *s != ':' && !isspace(*s) ; ++s ) ;
  1404. X    if ( *s != ':' ) {
  1405. X        fprintf(stderr,"  message %d - illegal header removed \"%s\"\n",
  1406. X        mssgno, h->line[i]);
  1407. X        for ( j = i+1 ; j < h->nlines ; ++j )
  1408. X        h->line[j-1] = h->line[j];
  1409. X        --h->nlines;
  1410. X        --i;
  1411. X        continue;
  1412. X    }
  1413. X
  1414. X    }
  1415. X
  1416. X}
  1417. END_OF_FILE_cleanhdr.c
  1418.     size="`wc -c < cleanhdr.c`"
  1419.     if test 1686 -ne "$size" ; then
  1420.     echo "cleanhdr.c: extraction error - got $size chars"
  1421.     fi
  1422. fi
  1423. if test -f fixfrom.c -a "$1" != "-c" ; then
  1424.     echo "fixfrom.c: file exists - will not be overwritten"
  1425. else
  1426.     echo "x - fixfrom.c (file 9 of 12, 3936 chars)"
  1427.     sed -e 's/^X//' << 'END_OF_FILE_fixfrom.c' > fixfrom.c
  1428. X/* @(#) fixfrom.c 1.1 89/08/25 20:47:40
  1429. X *
  1430. X * Module:    fixfrom.c - fix bang-path style from lines
  1431. X * Package:    brkdig - digest processor
  1432. X *
  1433. X * Fri Aug 25 20:46:32 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  1434. X *    Cleanup and beta release.
  1435. X * Sun Jul 16 03:13:45 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US>
  1436. X *    Original composition.
  1437. X */
  1438. X
  1439. X#include <stdio.h>
  1440. X#include <ctype.h>
  1441. X#include <string.h>
  1442. X#include "brkdig.h"
  1443. X
  1444. XSCCSID("@(#) fixfrom.c 1.1 89/08/25 20:47:40")
  1445. X
  1446. Xstatic int checkaddr();
  1447. X
  1448. X/*
  1449. X * fix_bang_from() - convert "From" field to an RFC822 address
  1450. X *
  1451. X * The "from" argument is a "from" field which contains a bang-path rather
  1452. X * than a valid address.  The path is converted to a legal (and hopefully
  1453. X * valid) address.  If the field doesn't contain a bang path or the conversion
  1454. X * fails, then NULL is returned.
  1455. X *
  1456. X * Two attempts are performed at translation.  In the first attempt, we
  1457. X * look for a fully qualified domain name, and build an address from there.
  1458. X * If several such qualified names exist, then the rightmost is taken.  For
  1459. X * example, we would convert "cs.utech.edu!bigvax!moscvax.krem.org!ihnp4!fred"
  1460. X * to "inhp4!fred@moscvax.krem.org".
  1461. X *
  1462. X * In the second attempt, we try to build addresses until we find one our
  1463. X * router program understands.  For example, given "utech!bigvax!ihnp4!fred",
  1464. X * we would try (in order) "fred@ihnp4.UUCP", "ihnp4!fred@bigvax.UUCP", and
  1465. X * "bigvax!ihnp4!fred@utech.UUCP".
  1466. X *
  1467. X * If neither of these approaches work we give up and return NULL.
  1468. X */
  1469. Xchar *fix_bang_from(from)
  1470. Xchar *from;
  1471. X{
  1472. X    static char pathbuf[BUFLEN], addrbuf[BUFLEN];
  1473. X    char *pathelem[64], *s1, *s2;
  1474. X    int nelem, n, i;
  1475. X
  1476. X    (void) strcpy(pathbuf,from);
  1477. X
  1478. X    /*
  1479. X     * Extract anything enclosed in '<' angle brackets '>'
  1480. X     */
  1481. X    if ( (s1=strchr(pathbuf,'<')) != NULL && (s2=strchr(s1,'>')) != NULL ) {
  1482. X    *s2 = '\0';
  1483. X    (void) strcpy(pathbuf,s1+1);
  1484. X    }
  1485. X
  1486. X    /*
  1487. X     * Throw out anything enclosed in '(' parens ')'
  1488. X     */
  1489. X    if ( (s1=strchr(pathbuf,'(')) != NULL && (s2=strchr(s1,')')) != NULL )
  1490. X    (void) strcpy(s1,s2+1);
  1491. X
  1492. X    /*
  1493. X     * Trim leading space.
  1494. X     */
  1495. X    for ( s1 = pathbuf ; isspace(*s1) ; ++s1 ) ;
  1496. X    if ( s1 != pathbuf )
  1497. X    (void) strcpy(pathbuf,s1);
  1498. X
  1499. X    /*
  1500. X     * Terminate the line after the first word.
  1501. X     */
  1502. X    for ( s1 = pathbuf ; *s1 != '\0' && !isspace(*s1) ; ++s1 ) ;
  1503. X    *s1 = '\0';
  1504. X
  1505. X    /*
  1506. X     * We are only dealing with bang paths here.
  1507. X     */
  1508. X    if ( strchr(pathbuf,'!') == NULL )
  1509. X    return NULL;
  1510. X
  1511. X    /*
  1512. X     * Break the path at the '!' bangs.
  1513. X     */
  1514. X   for (
  1515. X    s1 = pathbuf, nelem = 0 ;
  1516. X    (pathelem[nelem]=strtok(s1,"!")) != NULL ;
  1517. X    s1 = NULL, ++nelem
  1518. X    ) ;
  1519. X
  1520. X    /*
  1521. X     * Search for an element which is a fully qualified domain name.
  1522. X     */
  1523. X    for ( n = nelem-2 ; n >= 0 ; --n ) {
  1524. X    if ( strchr(pathelem[n],'.') == NULL )
  1525. X        continue;
  1526. X    addrbuf[0] = '\0';
  1527. X    for ( i = n+1 ; i < nelem ; ++i ) {
  1528. X        if ( i > n+1 )
  1529. X        (void) strcat(addrbuf,"!");
  1530. X        (void) strcat(addrbuf,pathelem[i]);
  1531. X    }
  1532. X    (void) strcat(addrbuf,"@");
  1533. X    (void) strcat(addrbuf,pathelem[n]);
  1534. X    return addrbuf;
  1535. X    }
  1536. X
  1537. X    /*
  1538. X     * Search for an element which we can build an address from.
  1539. X     */
  1540. X    for ( n = nelem-2 ; n >= 0 ; --n ) {
  1541. X    addrbuf[0] = '\0';
  1542. X    for ( i = n+1 ; i < nelem ; ++i ) {
  1543. X        if ( i > n+1 )
  1544. X        (void) strcat(addrbuf,"!");
  1545. X        (void) strcat(addrbuf,pathelem[i]);
  1546. X    }
  1547. X    (void) strcat(addrbuf,"@");
  1548. X    (void) strcat(addrbuf,pathelem[n]);
  1549. X    (void) strcat(addrbuf,".UUCP");
  1550. X    if ( checkaddr(addrbuf) )
  1551. X        return addrbuf;
  1552. X    }
  1553. X
  1554. X    return NULL;
  1555. X}
  1556. X
  1557. X
  1558. X
  1559. Xstatic int checkaddr(addr)
  1560. Xchar *addr;
  1561. X{
  1562. X    static char cmdbuf[BUFLEN];
  1563. X    int status, pid;
  1564. X
  1565. X    (void) sprintf(cmdbuf,Addrchk_cmd,addr);
  1566. X    switch ( (pid=fork()) ) {
  1567. X    case -1:            /* fork error */
  1568. X    perror("fork");
  1569. X    (void) exit(1);
  1570. X    case 0:            /* child */
  1571. X    (void) execl( "/bin/sh", "sh", "-c", cmdbuf, (char *)NULL );
  1572. X    perror("exec");
  1573. X    (void) exit(1);
  1574. X    default:
  1575. X    while ( wait(&status) != pid ) ;
  1576. X    return ( status == 0 );
  1577. X    }
  1578. X}
  1579. X
  1580. END_OF_FILE_fixfrom.c
  1581.     size="`wc -c < fixfrom.c`"
  1582.     if test 3936 -ne "$size" ; then
  1583.     echo "fixfrom.c: extraction error - got $size chars"
  1584.     fi
  1585. fi
  1586. if test -f getdate.y -a "$1" != "-c" ; then
  1587.     echo "getdate.y: file exists - will not be overwritten"
  1588. else
  1589.     echo "x - getdate.y (file 10 of 12, 13345 chars)"
  1590.     sed -e 's/^X//' << 'END_OF_FILE_getdate.y' > getdate.y
  1591. X%token ID MONTH DAY MERIDIAN SNUMBER UNUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
  1592. X%{
  1593. X    /*     Originally from: Steven M. Bellovin (unc!smb)    */ 
  1594. X    /*    Dept. of Computer Science            */
  1595. X    /*    University of North Carolina at Chapel Hill    */
  1596. X    /*    @(#)getdate.y    2.19    1/17/89    */
  1597. X
  1598. X/*
  1599. X * Fri Mar 24 22:57:24 1989 - Chip Rosenthal <chip@vector.UUCP>
  1600. X *    Added new "tspec" to handle HH:MM:SS.mm type times.
  1601. X *    Added new "dtspec" to handle DD-MMM-YYYY type dates.
  1602. X *    Yep...it ain't RFC822...but what does VMS care?
  1603. X */
  1604. X
  1605. X/*****
  1606. X#include "defs.h"
  1607. X******/
  1608. X#include <sys/types.h>
  1609. X#ifdef USG
  1610. Xstruct timeb
  1611. X{
  1612. X    time_t    time;
  1613. X    unsigned short millitm;
  1614. X    short    timezone;
  1615. X    short    dstflag;
  1616. X};
  1617. X#else
  1618. X#include <sys/timeb.h>
  1619. X#endif
  1620. X#include <ctype.h>
  1621. X
  1622. X#if defined(BSD4_2)
  1623. X#include <sys/time.h>
  1624. X#else /* sane */
  1625. X#include <time.h>
  1626. X#endif /* sane */
  1627. X
  1628. X#define    NULL    0
  1629. X#define daysec (24L*60L*60L)
  1630. X    static int timeflag, zoneflag, dateflag, dayflag, relflag;
  1631. X    static time_t relsec, relmonth;
  1632. X    static int hh, mm, ss, merid, daylight;
  1633. X    static int dayord, dayreq;
  1634. X    static int month, day, year;
  1635. X    static int ourzone;
  1636. X#define AM 1
  1637. X#define PM 2
  1638. X#define DAYLIGHT 1
  1639. X#define STANDARD 2
  1640. X#define MAYBE    3
  1641. X%}
  1642. X
  1643. X%%
  1644. Xtimedate:         /* empty */
  1645. X    | timedate item;
  1646. X
  1647. Xitem:    tspec =
  1648. X        {timeflag++;}
  1649. X    | zone =
  1650. X        {zoneflag++;}
  1651. X    | dtspec =
  1652. X        {dateflag++;}
  1653. X    | dyspec =
  1654. X        {dayflag++;}
  1655. X    | rspec =
  1656. X        {relflag++;}
  1657. X    | nspec;
  1658. X
  1659. Xnspec:    UNUMBER =
  1660. X        {if (timeflag && dateflag && !relflag) year = $1;
  1661. X        else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
  1662. X
  1663. Xtspec:    UNUMBER MERIDIAN =
  1664. X        {hh = $1; mm = 0; ss = 0; merid = $2;}
  1665. X    | UNUMBER ':' UNUMBER =
  1666. X        {hh = $1; mm = $3; merid = 24;}
  1667. X    | UNUMBER ':' UNUMBER MERIDIAN =
  1668. X        {hh = $1; mm = $3; merid = $4;}
  1669. X    | UNUMBER ':' UNUMBER SNUMBER =
  1670. X        {hh = $1; mm = $3; merid = 24;
  1671. X        daylight = STANDARD; ourzone = -($4%100 + 60*($4/100));}
  1672. X    | UNUMBER ':' UNUMBER ':' UNUMBER =
  1673. X        {hh = $1; mm = $3; ss = $5; merid = 24;}
  1674. X    | UNUMBER ':' UNUMBER ':' UNUMBER '.' UNUMBER =
  1675. X        {hh = $1; mm = $3; ss = $5; merid = 24; /* added 3/24/89 CR */ }
  1676. X    | UNUMBER ':' UNUMBER ':' UNUMBER MERIDIAN =
  1677. X        {hh = $1; mm = $3; ss = $5; merid = $6;}
  1678. X    | UNUMBER ':' UNUMBER ':' UNUMBER SNUMBER =
  1679. X        {hh = $1; mm = $3; ss = $5; merid = 24;
  1680. X        daylight = STANDARD; ourzone = -($6%100 + 60*($6/100));};
  1681. X
  1682. Xzone:    ZONE =
  1683. X        {ourzone = $1; daylight = STANDARD;}
  1684. X    | DAYZONE =
  1685. X        {ourzone = $1; daylight = DAYLIGHT;};
  1686. X
  1687. Xdyspec:    DAY =
  1688. X        {dayord = 1; dayreq = $1;}
  1689. X    | DAY ',' =
  1690. X        {dayord = 1; dayreq = $1;}
  1691. X    | UNUMBER DAY =
  1692. X        {dayord = $1; dayreq = $2;};
  1693. X
  1694. Xdtspec:    UNUMBER '/' UNUMBER =
  1695. X        {month = $1; day = $3;}
  1696. X    | UNUMBER '/' UNUMBER '/' UNUMBER =
  1697. X        {month = $1; day = $3; year = $5;}
  1698. X    | UNUMBER MONTH SNUMBER =
  1699. X        {month = $2; day = $1; year = -$3; /* added 3/24/89 CR */ }
  1700. X    | MONTH UNUMBER =
  1701. X        {month = $1; day = $2;}
  1702. X    | MONTH UNUMBER ',' UNUMBER =
  1703. X        {month = $1; day = $2; year = $4;}
  1704. X    | UNUMBER MONTH =
  1705. X        {month = $2; day = $1;}
  1706. X    | UNUMBER MONTH UNUMBER =
  1707. X        {month = $2; day = $1; year = $3;};
  1708. X
  1709. X
  1710. Xrspec:    SNUMBER UNIT =
  1711. X        {relsec +=  60L * $1 * $2;}
  1712. X    | SNUMBER MUNIT =
  1713. X        {relmonth += $1 * $2;}
  1714. X    | SNUMBER SUNIT =
  1715. X        {relsec += $1;}
  1716. X    | UNIT =
  1717. X        {relsec +=  60L * $1;}
  1718. X    | MUNIT =
  1719. X        {relmonth += $1;}
  1720. X    | SUNIT =
  1721. X        {relsec++;}
  1722. X    | rspec AGO =
  1723. X        {relsec = -relsec; relmonth = -relmonth;};
  1724. X%%
  1725. X
  1726. Xstatic int mdays[12] =
  1727. X    {31, 0, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31};
  1728. X#define epoch 1970
  1729. X
  1730. Xextern struct tm *localtime();
  1731. X
  1732. Xtime_t
  1733. Xdateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
  1734. Xint mm, dd, yy, h, m, s, mer, zone, dayflag;
  1735. X{
  1736. X    time_t tod, jdate;
  1737. X    register int i;
  1738. X    time_t timeconv();
  1739. X
  1740. X    if (yy < 0) yy = -yy;
  1741. X    if (yy < 100) yy += 1900;
  1742. X    mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
  1743. X    if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
  1744. X        dd < 1 || dd > mdays[--mm]) return (-1);
  1745. X    jdate = dd-1;
  1746. X        for (i=0; i<mm; i++) jdate += mdays[i];
  1747. X    for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
  1748. X    jdate *= daysec;
  1749. X    jdate += zone * 60L;
  1750. X    if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
  1751. X    jdate += tod;
  1752. X    if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
  1753. X        jdate += -1*60*60;
  1754. X    return (jdate);
  1755. X}
  1756. X
  1757. Xtime_t
  1758. Xdayconv(ord, day, now)
  1759. Xint ord, day; time_t now;
  1760. X{
  1761. X    register struct tm *loctime;
  1762. X    time_t tod;
  1763. X    time_t daylcorr();
  1764. X
  1765. X    tod = now;
  1766. X    loctime = localtime(&tod);
  1767. X    tod += daysec * ((day - loctime->tm_wday + 7) % 7);
  1768. X    tod += 7*daysec*(ord<=0?ord:ord-1);
  1769. X    return daylcorr(tod, now);
  1770. X}
  1771. X
  1772. Xtime_t
  1773. Xtimeconv(hh, mm, ss, mer)
  1774. Xregister int hh, mm, ss, mer;
  1775. X{
  1776. X    if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
  1777. X    switch (mer) {
  1778. X        case AM: if (hh < 1 || hh > 12) return(-1);
  1779. X             return (60L * ((hh%12)*60L + mm)+ss);
  1780. X        case PM: if (hh < 1 || hh > 12) return(-1);
  1781. X             return (60L * ((hh%12 +12)*60L + mm)+ss);
  1782. X        case 24: if (hh < 0 || hh > 23) return (-1);
  1783. X             return (60L * (hh*60L + mm)+ss);
  1784. X        default: return (-1);
  1785. X    }
  1786. X}
  1787. Xtime_t
  1788. Xmonthadd(sdate, relmonth)
  1789. Xtime_t sdate, relmonth;
  1790. X{
  1791. X    struct tm *ltime;
  1792. X    time_t dateconv();
  1793. X    time_t daylcorr();
  1794. X    int mm, yy;
  1795. X
  1796. X    if (relmonth == 0) return 0;
  1797. X    ltime = localtime(&sdate);
  1798. X    mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
  1799. X    yy = mm/12;
  1800. X    mm = mm%12 + 1;
  1801. X    return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
  1802. X        ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
  1803. X}
  1804. X
  1805. Xtime_t
  1806. Xdaylcorr(future, now)
  1807. Xtime_t future, now;
  1808. X{
  1809. X    int fdayl, nowdayl;
  1810. X
  1811. X    nowdayl = (localtime(&now)->tm_hour+1) % 24;
  1812. X    fdayl = (localtime(&future)->tm_hour+1) % 24;
  1813. X    return (future-now) + 60L*60L*(nowdayl-fdayl);
  1814. X}
  1815. X
  1816. Xstatic char *lptr;
  1817. X
  1818. Xyylex()
  1819. X{
  1820. X    extern int yylval;
  1821. X    int sign = 0;
  1822. X    register char c;
  1823. X    register char *p;
  1824. X    char idbuf[20];
  1825. X    int pcnt;
  1826. X
  1827. X    for (;;) {
  1828. X        while (isspace(*lptr))
  1829. X            lptr++;
  1830. X
  1831. X        if (isdigit(c = *lptr) || c == '-' || c == '+') {
  1832. X            if (c== '-' || c == '+') {
  1833. X                if (c=='-') sign = -1;
  1834. X                else sign = 1;
  1835. X                if (!isdigit(*++lptr)) {
  1836. X                    /* yylval = sign; return (UNUMBER); */
  1837. X                    return yylex();    /* skip the '-' sign */
  1838. X                }
  1839. X            }
  1840. X            yylval = 0;
  1841. X            while (isdigit(c = *lptr++))
  1842. X                yylval = 10*yylval + c - '0';
  1843. X            lptr--;
  1844. X            if (sign < 0)
  1845. X                yylval = -yylval;
  1846. X            if (sign != 0)
  1847. X                return SNUMBER;
  1848. X             else
  1849. X                return UNUMBER;
  1850. X
  1851. X        } else if (isalpha(c)) {
  1852. X            p = idbuf;
  1853. X            while (isalpha(c = *lptr++) || c=='.')
  1854. X                if (p < &idbuf[sizeof(idbuf)-1]) *p++ = c;
  1855. X            *p = '\0';
  1856. X            lptr--;
  1857. X            return (lookup(idbuf));
  1858. X        }
  1859. X
  1860. X        else if (c == '(') {
  1861. X            pcnt = 0;
  1862. X            do {
  1863. X                c = *lptr++;
  1864. X                if (c == '\0') return(c);
  1865. X                else if (c == '(') pcnt++;
  1866. X                else if (c == ')') pcnt--;
  1867. X            } while (pcnt > 0);
  1868. X        }
  1869. X
  1870. X        else return (*lptr++);
  1871. X    }
  1872. X}
  1873. X
  1874. Xstruct table {
  1875. X    char *name;
  1876. X    int type, value;
  1877. X};
  1878. X
  1879. Xstruct table mdtab[] = {
  1880. X    {"january", MONTH, 1},
  1881. X    {"february", MONTH, 2},
  1882. X    {"march", MONTH, 3},
  1883. X    {"april", MONTH, 4},
  1884. X    {"may", MONTH, 5},
  1885. X    {"june", MONTH, 6},
  1886. X    {"july", MONTH, 7},
  1887. X    {"august", MONTH, 8},
  1888. X    {"september", MONTH, 9},
  1889. X    {"sept", MONTH, 9},
  1890. X    {"october", MONTH, 10},
  1891. X    {"november", MONTH, 11},
  1892. X    {"december", MONTH, 12},
  1893. X
  1894. X    {"sunday", DAY, 0},
  1895. X    {"monday", DAY, 1},
  1896. X    {"tuesday", DAY, 2},
  1897. X    {"tues", DAY, 2},
  1898. X    {"wednesday", DAY, 3},
  1899. X    {"wednes", DAY, 3},
  1900. X    {"thursday", DAY, 4},
  1901. X    {"thur", DAY, 4},
  1902. X    {"thurs", DAY, 4},
  1903. X    {"friday", DAY, 5},
  1904. X    {"saturday", DAY, 6},
  1905. X    {0, 0, 0}};
  1906. X
  1907. X#define HRS *60
  1908. X#define HALFHR 30
  1909. Xstruct table mztab[] = {
  1910. X    {"a.m.", MERIDIAN, AM},
  1911. X    {"am", MERIDIAN, AM},
  1912. X    {"p.m.", MERIDIAN, PM},
  1913. X    {"pm", MERIDIAN, PM},
  1914. X    {"nst", ZONE, 3 HRS + HALFHR},        /* Newfoundland */
  1915. X    {"n.s.t.", ZONE, 3 HRS + HALFHR},
  1916. X    {"ast", ZONE, 4 HRS},        /* Atlantic */
  1917. X    {"a.s.t.", ZONE, 4 HRS},
  1918. X    {"adt", DAYZONE, 4 HRS},
  1919. X    {"a.d.t.", DAYZONE, 4 HRS},
  1920. X    {"est", ZONE, 5 HRS},        /* Eastern */
  1921. X    {"e.s.t.", ZONE, 5 HRS},
  1922. X    {"edt", DAYZONE, 5 HRS},
  1923. X    {"e.d.t.", DAYZONE, 5 HRS},
  1924. X    {"cst", ZONE, 6 HRS},        /* Central */
  1925. X    {"c.s.t.", ZONE, 6 HRS},
  1926. X    {"cdt", DAYZONE, 6 HRS},
  1927. X    {"c.d.t.", DAYZONE, 6 HRS},
  1928. X    {"mst", ZONE, 7 HRS},        /* Mountain */
  1929. X    {"m.s.t.", ZONE, 7 HRS},
  1930. X    {"mdt", DAYZONE, 7 HRS},
  1931. X    {"m.d.t.", DAYZONE, 7 HRS},
  1932. X    {"pst", ZONE, 8 HRS},        /* Pacific */
  1933. X    {"p.s.t.", ZONE, 8 HRS},
  1934. X    {"pdt", DAYZONE, 8 HRS},
  1935. X    {"p.d.t.", DAYZONE, 8 HRS},
  1936. X    {"yst", ZONE, 9 HRS},        /* Yukon */
  1937. X    {"y.s.t.", ZONE, 9 HRS},
  1938. X    {"ydt", DAYZONE, 9 HRS},
  1939. X    {"y.d.t.", DAYZONE, 9 HRS},
  1940. X    {"hst", ZONE, 10 HRS},        /* Hawaii */
  1941. X    {"h.s.t.", ZONE, 10 HRS},
  1942. X    {"hdt", DAYZONE, 10 HRS},
  1943. X    {"h.d.t.", DAYZONE, 10 HRS},
  1944. X
  1945. X    {"gmt", ZONE, 0 HRS},
  1946. X    {"g.m.t.", ZONE, 0 HRS},
  1947. X    {"bst", DAYZONE, 0 HRS},        /* British Summer Time */
  1948. X    {"b.s.t.", DAYZONE, 0 HRS},
  1949. X    {"eet", ZONE, 0 HRS},        /* European Eastern Time */
  1950. X    {"e.e.t.", ZONE, 0 HRS},
  1951. X    {"eest", DAYZONE, 0 HRS},    /* European Eastern Summer Time */
  1952. X    {"e.e.s.t.", DAYZONE, 0 HRS},
  1953. X    {"met", ZONE, -1 HRS},        /* Middle European Time */
  1954. X    {"m.e.t.", ZONE, -1 HRS},
  1955. X    {"mest", DAYZONE, -1 HRS},    /* Middle European Summer Time */
  1956. X    {"m.e.s.t.", DAYZONE, -1 HRS},
  1957. X    {"wet", ZONE, -2 HRS },        /* Western European Time */
  1958. X    {"w.e.t.", ZONE, -2 HRS },
  1959. X    {"west", DAYZONE, -2 HRS},    /* Western European Summer Time */
  1960. X    {"w.e.s.t.", DAYZONE, -2 HRS},
  1961. X
  1962. X    {"jst", ZONE, -9 HRS},        /* Japan Standard Time */
  1963. X    {"j.s.t.", ZONE, -9 HRS},    /* Japan Standard Time */
  1964. X                    /* No daylight savings time */
  1965. X
  1966. X    {"aest", ZONE, -10 HRS},    /* Australian Eastern Time */
  1967. X    {"a.e.s.t.", ZONE, -10 HRS},
  1968. X    {"aesst", DAYZONE, -10 HRS},    /* Australian Eastern Summer Time */
  1969. X    {"a.e.s.s.t.", DAYZONE, -10 HRS},
  1970. X    {"acst", ZONE, -(9 HRS + HALFHR)},    /* Australian Central Time */
  1971. X    {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
  1972. X    {"acsst", DAYZONE, -(9 HRS + HALFHR)},    /* Australian Central Summer */
  1973. X    {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
  1974. X    {"awst", ZONE, -8 HRS},        /* Australian Western Time */
  1975. X    {"a.w.s.t.", ZONE, -8 HRS},    /* (no daylight time there, I'm told */
  1976. X    {0, 0, 0}};
  1977. X
  1978. Xstruct table unittb[] = {
  1979. X    {"year", MUNIT, 12},
  1980. X    {"month", MUNIT, 1},
  1981. X    {"fortnight", UNIT, 14*24*60},
  1982. X    {"week", UNIT, 7*24*60},
  1983. X    {"day", UNIT, 1*24*60},
  1984. X    {"hour", UNIT, 60},
  1985. X    {"minute", UNIT, 1},
  1986. X    {"min", UNIT, 1},
  1987. X    {"second", SUNIT, 1},
  1988. X    {"sec", SUNIT, 1},
  1989. X    {0, 0, 0}};
  1990. X
  1991. Xstruct table othertb[] = {
  1992. X    {"tomorrow", UNIT, 1*24*60},
  1993. X    {"yesterday", UNIT, -1*24*60},
  1994. X    {"today", UNIT, 0},
  1995. X    {"now", UNIT, 0},
  1996. X    {"last", UNUMBER, -1},
  1997. X    {"this", UNIT, 0},
  1998. X    {"next", UNUMBER, 2},
  1999. X    {"first", UNUMBER, 1},
  2000. X    /* {"second", UNUMBER, 2}, */
  2001. X    {"third", UNUMBER, 3},
  2002. X    {"fourth", UNUMBER, 4},
  2003. X    {"fifth", UNUMBER, 5},
  2004. X    {"sixth", UNUMBER, 6},
  2005. X    {"seventh", UNUMBER, 7},
  2006. X    {"eighth", UNUMBER, 8},
  2007. X    {"ninth", UNUMBER, 9},
  2008. X    {"tenth", UNUMBER, 10},
  2009. X    {"eleventh", UNUMBER, 11},
  2010. X    {"twelfth", UNUMBER, 12},
  2011. X    {"ago", AGO, 1},
  2012. X    {0, 0, 0}};
  2013. X
  2014. Xstruct table milzone[] = {
  2015. X    {"a", ZONE, 1 HRS},
  2016. X    {"b", ZONE, 2 HRS},
  2017. X    {"c", ZONE, 3 HRS},
  2018. X    {"d", ZONE, 4 HRS},
  2019. X    {"e", ZONE, 5 HRS},
  2020. X    {"f", ZONE, 6 HRS},
  2021. X    {"g", ZONE, 7 HRS},
  2022. X    {"h", ZONE, 8 HRS},
  2023. X    {"i", ZONE, 9 HRS},
  2024. X    {"k", ZONE, 10 HRS},
  2025. X    {"l", ZONE, 11 HRS},
  2026. X    {"m", ZONE, 12 HRS},
  2027. X    {"n", ZONE, -1 HRS},
  2028. X    {"o", ZONE, -2 HRS},
  2029. X    {"p", ZONE, -3 HRS},
  2030. X    {"q", ZONE, -4 HRS},
  2031. X    {"r", ZONE, -5 HRS},
  2032. X    {"s", ZONE, -6 HRS},
  2033. X    {"t", ZONE, -7 HRS},
  2034. X    {"u", ZONE, -8 HRS},
  2035. X    {"v", ZONE, -9 HRS},
  2036. X    {"w", ZONE, -10 HRS},
  2037. X    {"x", ZONE, -11 HRS},
  2038. X    {"y", ZONE, -12 HRS},
  2039. X    {"z", ZONE, 0 HRS},
  2040. X    {0, 0, 0}};
  2041. X
  2042. Xlookup(id)
  2043. Xchar *id;
  2044. X{
  2045. X#define gotit (yylval=i->value,  i->type)
  2046. X
  2047. X    char idvar[128];
  2048. X    register char *j, *k;
  2049. X    register struct table *i;
  2050. X    int abbrev;
  2051. X
  2052. X    (void) strcpy(idvar, id);
  2053. X    j = idvar;
  2054. X    k = id - 1;
  2055. X    while (*++k)
  2056. X        *j++ = isupper(*k) ? tolower(*k) : *k;
  2057. X    *j = '\0';
  2058. X
  2059. X    if (strlen(idvar) == 3)
  2060. X        abbrev = 1;
  2061. X    else
  2062. X        if (strlen(idvar) == 4 && idvar[3] == '.') {
  2063. X            abbrev = 1;
  2064. X            idvar[3] = '\0';
  2065. X        }
  2066. X    else
  2067. X        abbrev = 0;
  2068. X
  2069. X    for (i = mdtab; i->name; i++) {
  2070. X        k = idvar;
  2071. X        for (j = i->name; *j++ == *k++;) {
  2072. X            if (abbrev && j == i->name+3)
  2073. X                return gotit;
  2074. X            if (j[-1] == 0)
  2075. X                return gotit;
  2076. X        }
  2077. X    }
  2078. X
  2079. X    for (i = mztab; i->name; i++)
  2080. X        if (strcmp(i->name, idvar) == 0)
  2081. X            return gotit;
  2082. X
  2083. X    for (i=mztab; i->name; i++)
  2084. X        if (strcmp(i->name, idvar) == 0)
  2085. X            return gotit;
  2086. X
  2087. X    for (i=unittb; i->name; i++)
  2088. X        if (strcmp(i->name, idvar) == 0)
  2089. X            return gotit;
  2090. X
  2091. X    if (idvar[strlen(idvar)-1] == 's')
  2092. X        idvar[strlen(idvar)-1] = '\0';
  2093. X
  2094. X    for (i=unittb; i->name; i++)
  2095. X        if (strcmp(i->name, idvar) == 0)
  2096. X            return gotit;
  2097. X
  2098. X    for (i = othertb; i->name; i++)
  2099. X        if (strcmp(i->name, idvar) == 0)
  2100. X            return gotit;
  2101. X
  2102. X    if (strlen(idvar) == 1 && isalpha(*idvar)) {
  2103. X        for (i = milzone; i->name; i++)
  2104. X            if (strcmp(i->name, idvar) == 0)
  2105. X                return gotit;
  2106. X    }
  2107. X
  2108. X    return ID;
  2109. X}
  2110. X
  2111. Xtime_t
  2112. Xgetdate(p, now)
  2113. Xchar *p;
  2114. Xstruct timeb *now;
  2115. X{
  2116. X#define mcheck(f)    if (f>1) err++
  2117. X    time_t monthadd();
  2118. X    int err;
  2119. X    struct tm *lt;
  2120. X    struct timeb ftz;
  2121. X
  2122. X    time_t sdate, tod;
  2123. X
  2124. X    lptr = p;
  2125. X    if (now == ((struct timeb *) NULL)) {
  2126. X        now = &ftz;
  2127. X        ftime(&ftz);
  2128. X    }
  2129. X    lt = localtime(&now->time);
  2130. X    year = lt->tm_year;
  2131. X    month = lt->tm_mon+1;
  2132. X    day = lt->tm_mday;
  2133. X    relsec = 0; relmonth = 0;
  2134. X    timeflag=zoneflag=dateflag=dayflag=relflag=0;
  2135. X    ourzone = now->timezone;
  2136. X    daylight = MAYBE;
  2137. X    hh = mm = ss = 0;
  2138. X    merid = 24;
  2139. X
  2140. X    if (err = yyparse()) return (-1);
  2141. X
  2142. X    mcheck(timeflag);
  2143. X    mcheck(zoneflag);
  2144. X    mcheck(dateflag);
  2145. X    mcheck(dayflag);
  2146. X
  2147. X    if (err) return (-1);
  2148. X    if (dateflag || timeflag || dayflag) {
  2149. X        sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
  2150. X        if (sdate < 0) return -1;
  2151. X    }
  2152. X    else {
  2153. X        sdate = now->time;
  2154. X        if (relflag == 0)
  2155. X            sdate -= (lt->tm_sec + lt->tm_min*60 +
  2156. X                lt->tm_hour*(60L*60L));
  2157. X    }
  2158. X
  2159. X    sdate += relsec;
  2160. X    sdate += monthadd(sdate, relmonth);
  2161. X
  2162. X    if (dayflag && !dateflag) {
  2163. X        tod = dayconv(dayord, dayreq, sdate);
  2164. X        sdate += tod;
  2165. X    }
  2166. X
  2167. X    /*
  2168. X    ** Have to do *something* with a legitimate -1 so it's distinguishable
  2169. X    ** from the error return value.  (Alternately could set errno on error.)
  2170. X    */
  2171. X    return (sdate == -1) ? 0 : sdate;
  2172. X}
  2173. X
  2174. Xyyerror(s) char *s;
  2175. X{}
  2176. END_OF_FILE_getdate.y
  2177.     size="`wc -c < getdate.y`"
  2178.     if test 13345 -ne "$size" ; then
  2179.     echo "getdate.y: extraction error - got $size chars"
  2180.     fi
  2181. fi
  2182. if test -f Makefile -a "$1" != "-c" ; then
  2183.     echo "Makefile: file exists - will not be overwritten"
  2184. else
  2185.     echo "x - Makefile (file 11 of 12, 1697 chars)"
  2186.     sed -e 's/^X//' << 'END_OF_FILE_Makefile' > Makefile
  2187. X
  2188. X# %Z% %M% %I% %E% %U%
  2189. X# Makefile for "brkdig" (generated by /local/bin/makemake version 1.00.08)
  2190. X# Created by news@vector on Thu Sep 21 20:18:05 CDT 1989
  2191. X
  2192. XSHELL = /bin/sh
  2193. XCC = cc
  2194. XDEFS = 
  2195. XCOPTS = -O
  2196. XLOPTS = 
  2197. XLIBS = -lx
  2198. XDEBUG = -g -DDEBUG
  2199. XLINTFLAGS = -DLINT
  2200. X
  2201. XTARG = brkdig
  2202. XOTHERS = getdate.c
  2203. X
  2204. XSRCS = brkdig.c loaddefs.c block.c cleanhdr.c header.c fixfrom.c getdate.c
  2205. X
  2206. XOBJS = brkdig.o loaddefs.o block.o cleanhdr.o header.o fixfrom.o getdate.o
  2207. X
  2208. X# Any edits below this line will be lost if "makemake" is rerun!
  2209. X# Commands may be inserted after the '#%custom' line at the end of this file.
  2210. X
  2211. XCFLAGS = $(COPTS) $(DEFS) # $(DEBUG)
  2212. XLFLAGS = $(LOPTS) # $(DEBUG)
  2213. X
  2214. Xall:        $(TARG) $(OTHERS)
  2215. Xinstall:    all        ; inst Install
  2216. Xclean:                ; rm -f $(TARG) $(OBJS) a.out core $(TARG).lint
  2217. Xclobber:    clean        ; inst -u Install
  2218. Xlint:        $(TARG).lint
  2219. X
  2220. X$(TARG):        $(OBJS)
  2221. X        $(CC) $(LFLAGS) -o $@ $(OBJS) $(LIBS)
  2222. X
  2223. X$(TARG).lint:    $(TARG)
  2224. X        lint $(LINTFLAGS) $(DEFS) $(SRCS) $(LIBS) > $@
  2225. X
  2226. Xbrkdig.o: brkdig.c brkdig.h
  2227. Xloaddefs.o: brkdig.h loaddefs.c
  2228. Xblock.o: block.c brkdig.h
  2229. Xcleanhdr.o: brkdig.h cleanhdr.c
  2230. Xheader.o: brkdig.h header.c
  2231. Xfixfrom.o: brkdig.h fixfrom.c
  2232. Xgetdate.o: getdate.c getdate.y
  2233. X
  2234. Xmake:        ;
  2235. X        /local/bin/makemake -i -v1.00.08 -aMakefile \
  2236. X            -DSHELL='$(SHELL)' -DCC='$(CC)' -DDEFS='$(DEFS)' \
  2237. X            -DCOPTS='$(COPTS)' -DLOPTS='$(LOPTS)' -DLIBS='$(LIBS)' \
  2238. X            -DDEBUG='$(DEBUG)' -DLINTFLAGS='$(LINTFLAGS)' \
  2239. X            -DOTHERS='$(OTHERS)' $(TARG) $(SRCS)
  2240. X
  2241. X#%custom - commands below this line will be maintained if 'makemake' is rerun
  2242. X
  2243. XARLIST =                                \
  2244. X    README Defs-example brkdig.h brkdig.c                \
  2245. X    loaddefs.c block.c header.c cleanhdr.c fixfrom.c        \
  2246. X    getdate.y Makefile testaddr
  2247. X
  2248. Xshar:    ; shar $(ARLIST) > brkdig.shar
  2249. X
  2250. END_OF_FILE_Makefile
  2251.     size="`wc -c < Makefile`"
  2252.     if test 1697 -ne "$size" ; then
  2253.     echo "Makefile: extraction error - got $size chars"
  2254.     fi
  2255. fi
  2256. if test -f testaddr -a "$1" != "-c" ; then
  2257.     echo "testaddr: file exists - will not be overwritten"
  2258. else
  2259.     echo "x - testaddr (file 12 of 12, 744 chars)"
  2260.     sed -e 's/^X//' << 'END_OF_FILE_testaddr' > testaddr
  2261. X:
  2262. X# %Z% %M% %I% %E% %U%
  2263. X#
  2264. X# testaddr - Determine if an address is reachable.
  2265. X#
  2266. X# Mon Dec  4 08:46:36 1989 - Chip Rosenthal <chip@chinacat.Lonestar.ORG>
  2267. X#    Original composition.
  2268. X#
  2269. X# This script uses smail2.5 to determine if an address is known.  It is
  2270. X# required with "brkdig" because smail always returns a zero exit status
  2271. X# with the "-A" option.  This script is intended for use in the "ADDR_CHECK"
  2272. X# parameter in the "brkdig" definitions file.
  2273. X
  2274. XUSAGE="usage: $0 addr"
  2275. XSMAIL=/bin/smail
  2276. X
  2277. Xif [ $# -ne 1 ] ; then
  2278. X    echo "$USAGE" 1>&2
  2279. X    exit 1
  2280. Xfi
  2281. X
  2282. Xaddr="$1"                    # addr to check
  2283. Xpath=`$SMAIL -A $addr 2>&1`            # let smail route it
  2284. Xtest "$path" != "" -a "$path" != "$addr"    # examine smail path result
  2285. Xexit $?                        # indicate whether addr worked
  2286. X
  2287. END_OF_FILE_testaddr
  2288.     size="`wc -c < testaddr`"
  2289.     if test 744 -ne "$size" ; then
  2290.     echo "testaddr: extraction error - got $size chars"
  2291.     fi
  2292. fi
  2293. echo "done - 12 files extracted"
  2294. exit 0
  2295.  
  2296.  
  2297.