home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume9 / brkdig < prev    next >
Text File  |  1989-12-27  |  64KB  |  2,289 lines

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