home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume18 / headers < prev    next >
Text File  |  1989-03-12  |  13KB  |  509 lines

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