home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume18 / headers < prev    next >
Encoding:
Internet Message Format  |  1989-03-14  |  12.5 KB

  1. Path: wugate!wucs1!uunet!bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v18i021:  Selectively retrieve news article headers
  5. Message-ID: <1557@papaya.bbn.com>
  6. Date: 13 Mar 89 23:27:38 GMT
  7. Lines: 505
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: bin@primate.wisc.edu (Brain in Neutral)
  11. Posting-number: Volume 18, Issue 21
  12. Archive-name: headers
  13.  
  14. "headers" is a program used to retrieve selected header lines from
  15. files containing Usenet articles.  It provides a convenient way to
  16. scan through large numbers of articles for pertinent information,
  17. and it is faster than using grep.  A typical use is to cd into a news
  18. spooling or archive directory and say "headers * | more".
  19.  
  20. #    This is a shell archive.
  21. #    Remove everything above and including the cut line.
  22. #    Then run the rest of the file through sh.
  23. #-----cut here-----cut here-----cut here-----cut here-----
  24. #!/bin/sh
  25. # shar:    Shell Archiver
  26. #    Run the following text with /bin/sh to create:
  27. #    Readme
  28. #    Installation
  29. #    Makefile
  30. #    headers.c
  31. #    headers.1
  32. echo shar: extracting Readme '(329 characters)'
  33. sed 's/^XX//' << \SHAR_EOF > Readme
  34. XX"headers" is a program used to retrieve selected header lines from
  35. XXfiles containing Usenet articles.  It provides a convenient way to
  36. XXscan through large numbers of articles for pertinent information,
  37. XXand it is faster than using grep.  A typical use is to cd into a news
  38. XXspooling or archive directory and say "headers * | more".
  39. XX
  40. SHAR_EOF
  41. if test 329 -ne "`wc -c Readme`"
  42. then
  43. echo shar: error transmitting Readme '(should have been 329 characters)'
  44. fi
  45. echo shar: extracting Installation '(370 characters)'
  46. sed 's/^XX//' << \SHAR_EOF > Installation
  47. XX1) Decide where you want to install headers and change BINDIR in the
  48. XXMakefile accordingly.
  49. XX
  50. XX2) If you run a BSD-like Unix, define BSD (-DBSD) in the CFLAGS, else
  51. XXif you are SYSV-like, define SYSV (-DSYSV).  The latter hasn't been tested,
  52. XXsince I don't have a SYSV machine.  Somebody that does, send me patches
  53. XXif necessary.
  54. XX
  55. XX3) Comments, bugs to dubois@primate.wisc.edu
  56. SHAR_EOF
  57. if test 370 -ne "`wc -c Installation`"
  58. then
  59. echo shar: error transmitting Installation '(should have been 370 characters)'
  60. fi
  61. echo shar: extracting Makefile '(492 characters)'
  62. sed 's/^XX//' << \SHAR_EOF > Makefile
  63. XXBINDIR=/usr/local
  64. XXLIBDIR=
  65. XXLIB=
  66. XXINSTALL=-c -m 755 -o bin -g system
  67. XXTROFF=xroff
  68. XXMACROS=-man.new
  69. XXPRINTER=lpr
  70. XX
  71. XX# define BSD or SYSV (latter is untested)
  72. XX
  73. XXCFLAGS=-DBSD
  74. XX
  75. XXall: headers
  76. XXinstall: iheaders iman
  77. XXclean:
  78. XX    rm -f *.o headers
  79. XX
  80. XXOBJ=headers.o
  81. XX
  82. XXheaders: ${OBJ}
  83. XX    cc ${OBJ} ${LIB} -o headers
  84. XXiheaders: headers
  85. XX    install ${INSTALL} headers ${BINDIR}
  86. XX
  87. XXman: headers.1
  88. XX    ${TROFF} ${MACROS} headers.1 | ${PRINTER}
  89. XX
  90. XXiman: headers.1
  91. XX    cp headers.1 /usr/man/manl/headers.l
  92. XX    chmod 444 /usr/man/manl/headers.l
  93. SHAR_EOF
  94. if test 492 -ne "`wc -c Makefile`"
  95. then
  96. echo shar: error transmitting Makefile '(should have been 492 characters)'
  97. fi
  98. echo shar: extracting headers.c '(5653 characters)'
  99. sed 's/^XX//' << \SHAR_EOF > headers.c
  100. XX/*
  101. XX    headers
  102. XX
  103. XX    Retrieve selected news article headers.  Only reads into the article
  104. XX    file as far as the blank line separating the headers from the body.
  105. XX    This is more efficient than other searching methods that may read
  106. XX    the entire file.  A convenient way to see what's in a newsgroup:
  107. XX
  108. XX        cd /usr/spool/news/comp/unix/wizards
  109. XX        headers * | more
  110. XX
  111. XX    syntax:  headers [ -f specfile ] [ -hheaderspec ... ] file ...
  112. XX
  113. XX    The set of headers to pull is found in the file specfile or in
  114. XX    the specs given after -h option(s).  If neither -f nor -h are
  115. XX    given, and the HEADERS environment variable names a file, that
  116. XX    file will be used.  Otherwise the Subject:, From: and Date:
  117. XX    headers are the default (with reasonable alternates for
  118. XX    each if they are missing).  Capitalization is not important.
  119. XX
  120. XX    The program reads each of the headers and determines whether
  121. XX    they are any of the ones desired.  When all headers have been
  122. XX    read, the ones found are printed out according to the order
  123. XX    of the specifications.
  124. XX
  125. XX    This code is in the public domain.
  126. XX
  127. XX    06 Dec 84 Version 1.0.  Paul DuBois, dubois@primate.wisc.edu
  128. XX    22 Nov 88 v1.1 Revised to do case-insensitive comparisons.
  129. XX        Added -h option capability.
  130. XX*/
  131. XX
  132. XX# include    <stdio.h>
  133. XX# include    <ctype.h>
  134. XX# include    <varargs.h>
  135. XX# ifdef BSD
  136. XX# include    <strings.h>
  137. XX# else if SYSV
  138. XX# include    <string.h>
  139. XX# endif
  140. XX
  141. XX
  142. XX# define    New(x)        ((x *) calloc (1, sizeof (x)))
  143. XX
  144. XXextern char    *calloc ();
  145. XX
  146. XXchar    *newstr ();
  147. XXvoid    panic ();
  148. XX
  149. XXtypedef struct Header    Header;
  150. XX
  151. XXstruct Header
  152. XX{
  153. XX    char    *hName;        /* name of header field */
  154. XX    char    hBuf[BUFSIZ];    /* line from article for this header */
  155. XX    Header    *nextGrp;    /* next group of headers */
  156. XX    Header    *nextHdr;    /* next header in this group */
  157. XX};
  158. XX
  159. XX
  160. XXHeader    *head = NULL;        /* pointer to output spec structure */
  161. XX
  162. XX
  163. XXmain (argc, argv)
  164. XXint    argc;
  165. XXchar    **argv;
  166. XX{
  167. XXchar    *p, *getenv ();
  168. XX    
  169. XX    if (*++argv != NULL && strncmp (*argv, "-h", 2) == 0)    /* cmd line */
  170. XX    {
  171. XX        for (;;)
  172. XX        {
  173. XX            GroupSpecs (&argv[0][2]);
  174. XX            if (strncmp (*++argv, "-h", 2) != 0)
  175. XX                break;
  176. XX        }
  177. XX    }
  178. XX    else if (strcmp ("-f", *argv) == 0)            /* named file */
  179. XX    {
  180. XX        if (*++argv == NULL)
  181. XX            panic ("No header file named after -f");
  182. XX        FileSpecs (*argv++);
  183. XX    }
  184. XX    else if ((p = getenv ("HEADERS")) != NULL)        /* env var */
  185. XX        FileSpecs (p);
  186. XX    else                            /* default */
  187. XX    {
  188. XX        GroupSpecs ("subject summary keywords");
  189. XX        GroupSpecs ("from reply-to sender");
  190. XX        GroupSpecs ("date");
  191. XX    }
  192. XX
  193. XX    while (*argv != NULL)        /* process input files */
  194. XX        Headers (*argv++);
  195. XX    exit (0);
  196. XX}
  197. XX
  198. XX
  199. XX/*
  200. XX    Read specifications from file
  201. XX*/
  202. XX
  203. XXFileSpecs (fname)
  204. XXchar    *fname;
  205. XX{
  206. XXchar    buf[BUFSIZ];
  207. XX
  208. XX    if (freopen (fname, "r", stdin) == NULL)
  209. XX        panic ("Can't open specfile %s", fname);
  210. XX    while (fgets (buf, BUFSIZ, stdin) != NULL)
  211. XX        GroupSpecs (buf);
  212. XX}
  213. XX
  214. XX/*
  215. XX    Process specification for one group of header names
  216. XX*/
  217. XX
  218. XXGroupSpecs (bp)
  219. XXchar    *bp;
  220. XX{
  221. XXstatic Header    *gtail;        /* last group in list of groups */
  222. XXHeader        *htail;        /* last header in current group */
  223. XX
  224. XX    if ((bp = strtok (bp, " ,\t\n")) != NULL)
  225. XX    {
  226. XX        if (head == NULL)    /* first group? */
  227. XX        {
  228. XX            if ((head = New (Header)) == NULL)
  229. XX                panic ("GroupSpecs: out of memory");
  230. XX            gtail = head;
  231. XX        }
  232. XX        else            /* add list to last one */
  233. XX        {
  234. XX            if ((gtail->nextGrp = New (Header)) == NULL)
  235. XX                panic ("GroupSpecs: out of memory");
  236. XX            gtail = gtail->nextGrp;
  237. XX        }
  238. XX        gtail->hName = newstr (bp);
  239. XX        lower (gtail->hName);
  240. XX        htail = gtail;
  241. XX        while ((bp = strtok (NULL, " ,\t\n")) != NULL)
  242. XX        {
  243. XX            if ((htail->nextHdr = New (Header)) == NULL)
  244. XX                    panic ("GroupSpecs: out of memory");
  245. XX            htail = htail->nextHdr;
  246. XX            htail->hName = newstr (bp);
  247. XX            lower (htail->hName);
  248. XX        }
  249. XX    }
  250. XX}
  251. XX
  252. XX
  253. XX/*
  254. XX    Clear header buffers so won't get debris from previous articles,
  255. XX    then read headers from article and save any that are present in
  256. XX    the specifications, and print 'em out.
  257. XX*/
  258. XX
  259. XXHeaders (article)
  260. XXchar    *article;
  261. XX{
  262. XXchar    c;
  263. XXchar    buf[BUFSIZ];
  264. XXchar    hdrName[BUFSIZ];
  265. XXchar    *hp, *bp;
  266. XXHeader    *lp, *ep;
  267. XX
  268. XX    if (freopen (article, "r", stdin) == NULL)
  269. XX    {
  270. XX        fprintf (stderr, "%s: cannot open article\n", article);
  271. XX        return;
  272. XX    }
  273. XX
  274. XX    for (lp = head; lp != NULL; lp = lp->nextGrp)
  275. XX        for (ep = lp; ep != NULL; ep = ep->nextHdr)
  276. XX            ep->hBuf[0] = '\0';
  277. XX
  278. XX    while (fgets (buf, BUFSIZ, stdin) != NULL)
  279. XX    {
  280. XX        if (*buf == '\n' || *buf == '\0')
  281. XX            break;        /* end of header section */
  282. XX
  283. XX        hp = hdrName;        /* get header name */
  284. XX        bp = buf;
  285. XX        while ((c = *bp) && c != ':' && c != ' ' && c != '\n')
  286. XX        {
  287. XX            *hp++ = c;
  288. XX            ++bp;
  289. XX        }
  290. XX        *hp = '\0';
  291. XX        lower (hdrName);
  292. XX        CheckHeader (hdrName, buf);
  293. XX    }
  294. XX
  295. XX    printf ("\n%s\n", article);
  296. XX    for (lp = head; lp != NULL; lp = lp->nextGrp)
  297. XX    {
  298. XX        for (ep = lp; ep != NULL; ep = ep->nextHdr)
  299. XX        {
  300. XX            if (ep->hBuf[0] != '\0')
  301. XX            {
  302. XX                fputs (ep->hBuf, stdout);
  303. XX                break;
  304. XX            }
  305. XX        }
  306. XX    }
  307. XX}
  308. XX
  309. XX
  310. XX/*
  311. XX    Check whether the header name is in the specs and save the
  312. XX    line from the article if so.
  313. XX*/
  314. XX
  315. XXCheckHeader (hdrName, artLine)
  316. XXchar    *hdrName, *artLine;
  317. XX{
  318. XXHeader    *lp, *ep;
  319. XX
  320. XX    for (lp = head; lp != NULL; lp = lp->nextGrp)
  321. XX    {
  322. XX        for (ep = lp; ep != NULL; ep = ep->nextHdr)
  323. XX        {
  324. XX            if (strcmp (ep->hName, hdrName) == 0)
  325. XX            {
  326. XX                strcpy (ep->hBuf, artLine);
  327. XX                return;
  328. XX            }
  329. XX        }
  330. XX    }
  331. XX}
  332. XX
  333. XX
  334. XX/*
  335. XX    Convert string to lowercase
  336. XX*/
  337. XX
  338. XXlower (s)
  339. XXchar    *s;
  340. XX{
  341. XX    while (*s)
  342. XX    {
  343. XX        if (isupper (*s))
  344. XX            *s = tolower (*s);
  345. XX        ++s;
  346. XX    }
  347. XX}
  348. XX
  349. XX
  350. XX/*
  351. XX    Get space for string, copy arg into it, and return pointer.
  352. XX*/
  353. XX
  354. XXchar *newstr (s)
  355. XXchar    *s;
  356. XX{
  357. XXchar    *p;
  358. XX
  359. XX    if ((p = calloc (1, (strlen (s) + 1))) == NULL)
  360. XX        panic ("newstr: out of memory");
  361. XX    strcpy (p, s);
  362. XX    return (p);
  363. XX}
  364. XX
  365. XX
  366. XX/*
  367. XX    panic - print message and die with status 1.  Uses vprintf
  368. XX    so that panic can take variable argument lists.
  369. XX*/
  370. XX
  371. XXvoid
  372. XXpanic (va_alist)
  373. XXva_dcl
  374. XX{
  375. XXva_list    args;
  376. XXchar    *fmt;
  377. XX
  378. XX    va_start (args);
  379. XX    fmt = va_arg (args, char *);
  380. XX    vfprintf (stderr, fmt, args);
  381. XX    va_end (args);
  382. XX    fprintf (stderr, "\n");
  383. XX    exit (1);
  384. XX}
  385. SHAR_EOF
  386. if test 5653 -ne "`wc -c headers.c`"
  387. then
  388. echo shar: error transmitting headers.c '(should have been 5653 characters)'
  389. fi
  390. echo shar: extracting headers.1 '(2833 characters)'
  391. sed 's/^XX//' << \SHAR_EOF > headers.1
  392. XX.\" xroff -man.new % | lpr
  393. XX.TH HEADERS 1
  394. XX.UC 4
  395. XX.SH NAME
  396. XXheaders \- selectively retrieve news article headers
  397. XX.SH SYNTAX
  398. XX.B headers
  399. XX[
  400. XX.B \-f
  401. XX.I specfile
  402. XX]
  403. XX.I file
  404. XX.B \&...
  405. XX.br
  406. XX.B headers
  407. XX[
  408. XX.B \-h\fIheaderspec\fR
  409. XX.B \&...
  410. XX]
  411. XX.I file
  412. XX.B \&...
  413. XX.SH DESCRIPTION
  414. XX.I Headers
  415. XXlooks through the header section of Usenet news articles
  416. XXand prints headers on a user-selectable basis.
  417. XXBecause it only
  418. XXreads the header section and not the body of articles, it provides
  419. XXa fast way of looking through large numbers of articles (particularly
  420. XXin sources groups).
  421. XXMultiple
  422. XXheaders per article can be retrieved, and headers can be grouped
  423. XXso that if one is missing (e.g., "From:"), another can be selected
  424. XXin its place (e.g., "Reply-To:").
  425. XXIn a sense,
  426. XX.I headers
  427. XXacts like an intelligent
  428. XX.I fgrep
  429. XXfor news articles.
  430. XX.PP
  431. XXThe headers to print can be specified either on the command
  432. XXline or in a file.
  433. XXCapitalization is irrelevant with either method.
  434. XXIf the
  435. XX.B \-f
  436. XXoption is used, the contents of
  437. XX.I specfile
  438. XXwill be examined for specifications.
  439. XXThe header groups should be listed one per line in this file.
  440. XXThe groups should be
  441. XXlisted in the order you want the headers to be printed.
  442. XXWithin each group, list first the header you really want, followed by
  443. XXany reasonable alternative headers to print if that one is missing.
  444. XXHeader names should be separated by whitespace (blanks, tabs) or commas.
  445. XXExample:
  446. XX.sp .5
  447. XX.in +1i
  448. XX.nf
  449. XXsubject
  450. XXfrom sender reply-to
  451. XXdate posted posted-date
  452. XX.fi
  453. XX.in -1i
  454. XX.sp .5
  455. XXThis example will print the "Subject:" header first, followed by the "From:"
  456. XXheader (or the "Sender:" or "Reply-To:" header if there is no "From:"),
  457. XXfollowed by
  458. XXthe "Date:" header.
  459. XX.PP
  460. XXAlternatively, the
  461. XX.B \-h
  462. XXoption may be used, once for each header group.
  463. XXHeader names in each group should be separated by commas.
  464. XXThe above example would be written
  465. XX.sp .5
  466. XX.ti +1i
  467. XXheaders\0-hsubject\0-hfrom,sender,reply-to\0-hdate
  468. XX.sp .5
  469. XXIf neither
  470. XX.B \-f
  471. XXnor
  472. XX.B \-h
  473. XXis used, but the HEADERS environment variable is set to the name of a file,
  474. XXthat file will be examined in the same fashion as for
  475. XX.B \-f
  476. XXto determine specifications.
  477. XXFailing all of these, the default specifications are:
  478. XX.sp .5
  479. XX.in +1i
  480. XX.nf
  481. XXsubject summary keywords
  482. XXfrom reply-to sender
  483. XXdate
  484. XX.fi
  485. XX.in -1i
  486. XX.sp .5
  487. XX.PP
  488. XXAfter digesting the specifications, each file is examined in turn;
  489. XXthe name of the file is printed followed by any
  490. XXany headers found, according to the order of the specifications.
  491. XX.SH NOTE
  492. XXThe output of
  493. XX.I headers
  494. XXcan be put into a file and used as input to
  495. XX.IR lookbib .
  496. XX.SH "SEE ALSO"
  497. XXfgrep(1), lookbib(1), news(5)
  498. XX.SH "WHO-TO-BLAME"
  499. XXPaul DuBois, dubois@primate.wisc.edu
  500. XX.SH BUGS
  501. XXDoesn't stat the input files to determine whether they're really
  502. XXplain files (as opposed to, say, directories).
  503. XXThis isn't usually a problem; directory contents typically don't satisfy
  504. XXmany of the specifications.
  505. SHAR_EOF
  506. if test 2833 -ne "`wc -c headers.1`"
  507. then
  508. echo shar: error transmitting headers.1 '(should have been 2833 characters)'
  509. fi
  510. #    End of shell archive
  511. exit 0
  512.  
  513. -- 
  514. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  515.