home *** CD-ROM | disk | FTP | other *** search
- /* $Header: header.c,v 2.5 89/11/10 12:23:54 network Exp $
- *
- * A program to parse RFC 822 mail/news headers.
- *
- * usage: header [-c] [-n] [-v] [-f field] ... files
- *
- * Default action is to print entire header. If one or more -f options
- * are given, only the specified fields are printed. The field names are
- * not printed unless -n is specified. Field name comparisons are case
- * insensitive unless -c is specified. If -v is specified, all headers
- * except those specified with -f are printed. NOTE: -v implies -n.
- *
- * Output lines are preceeded by the filename if more than one file is
- * specified.
- *
- * This program is intended for use in delivery files, to extract multi-
- * line header fields.
- *
- * $Log: header.c,v $
- * Revision 2.5 89/11/10 12:23:54 network
- * Delintify.
- *
- * Revision 2.4 89/10/30 16:08:48 network
- * Don't automatically print field names with "-v". (Sorry, Tom.)
- *
- * Revision 2.3 89/10/30 16:03:29 network
- * Add "-v" (everything except) option.
- * Submitted by Tom Neff <tneff%bfmny0@uunet.uu.net>.
- *
- * Revision 2.2 89/06/09 13:08:07 network
- * Adapt to BSD quirks.
- *
- * Revision 2.1 89/06/09 12:25:29 network
- * Update RCS revisions.
- *
- * Revision 1.5 89/06/09 12:23:51 network
- * Baseline for 2.0 release.
- *
- */
-
- #include <stdio.h>
- #include <ctype.h>
-
- /*
- * Manifest constants
- */
-
- #define TRUE 1
- #define FALSE 0
-
- /*
- * Other useful macros.
- */
-
- #define GETSIZE(buf) (sizeof(buf) - 1)
-
- #define ISFROM(p) ((p)[0] == 'F' && (p)[1] == 'r' && (p)[2] == 'o' \
- && (p)[3] == 'm' && (p)[4] == ' ')
-
- /*
- * External data.
- */
-
- /* Variables set by getopt() [blech] */
-
- extern int optind, opterr;
- extern char *optarg;
-
- /*
- * Library functions.
- */
-
- extern char *malloc();
- extern char *realloc();
- extern void free();
-
- /*
- * Global data
- */
-
- int field_count = 0;
- int field_alloc = 0;
- char **field_names = NULL;
-
- int nocasematch = TRUE; /* ignore case in header matches */
- int printnames = FALSE; /* print field names with data */
- int except = FALSE; /* reverse sense of -f */
-
- /*----------------------------------------------------------------------
- * The Program.
- */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int c, errors;
-
- field_alloc = 8;
- field_names = (char **) malloc(field_alloc * sizeof(char **));
- if (field_names == NULL)
- nomem();
-
- errors = FALSE;
- while ((c = getopt(argc, argv, "cnvf:")) != EOF)
- {
- switch (c)
- {
- case 'c':
- nocasematch = FALSE;
- break;
- case 'n':
- printnames = TRUE;
- break;
- case 'v':
- except = TRUE;
- break;
- case 'f':
- if (field_count >= field_alloc)
- {
- field_alloc *= 2;
- field_names =
- (char **) realloc((char *)field_names,
- field_alloc * sizeof(char **));
- if (field_names == NULL)
- nomem();
- }
- field_names[field_count++] = optarg;
- break;
- default:
- errors = TRUE;
- break;
- }
- }
-
- if (errors)
- usage();
-
- if (optind == argc)
- header(stdin, (char *)NULL);
- else
- {
- FILE *fp;
- int a, filenames;
-
- filenames = ((argc - optind) > 1);
- for (a = optind; a < argc; ++a)
- {
- if ((fp = fopen(argv[a], "r")) == NULL)
- {
- errors = TRUE;
- perror(argv[a]);
- continue;
- }
-
- header(fp, (filenames ? argv[a] : (char *)NULL));
- (void) fclose(fp);
- }
- }
-
- exit(errors ? 1 : 0);
- /* NOTREACHED */
- }
-
- usage()
- {
- (void) fprintf(stderr,
- "usage: header [-c] [-n] [-v] [-f fieldname] ... files\n");
- exit(1);
- }
-
- nomem()
- {
- (void) fprintf(stderr, "header: out of memory\n");
- exit(1);
- }
-
- header(fp, filename)
- FILE *fp;
- char *filename;
- {
- char buf[1024];
-
- if (fgets(buf, GETSIZE(buf), fp) == NULL)
- return;
-
- /* Ignore From_ line(s). */
-
- while (ISFROM(buf) || buf[0] == '>')
- {
- if (fgets(buf, GETSIZE(buf), fp) == NULL)
- return;
- }
-
- while (buf[0] != '\n')
- {
- char *p;
- int print_this;
-
- p = buf;
- while (isupper(*p) || islower(*p) || isdigit(*p) || *p == '-')
- ++p;
- if (p == buf || *p != ':')
- break;
- print_this = field(buf, p - buf);
- if (except)
- print_this = !print_this;
- if (print_this)
- {
- if (filename)
- {
- (void) fputs(filename, stdout);
- (void) fputc(':', stdout);
- }
- ++p;
- if (*p == ' ' || *p == '\t')
- ++p;
- if (field_count == 0 || printnames)
- (void) fputs(buf, stdout);
- else
- (void) fputs(p, stdout);
- }
-
- /* get the next input line */
- if (fgets(buf, GETSIZE(buf), fp) == NULL)
- break;
-
- /* deal with continuation lines */
- while (buf[0] == ' ' || buf[0] == '\t')
- {
- if (print_this)
- {
- if (filename)
- {
- (void) fputs(filename, stdout);
- (void) fputc(':', stdout);
- }
- (void) fputs(buf, stdout);
- }
-
- if (fgets(buf, GETSIZE(buf), fp) == NULL)
- {
- buf[0] = '\n';
- break;
- }
- }
- }
- }
-
- int
- field(s, n)
- char *s;
- int n;
- {
- int i;
-
- if (field_count == 0)
- return TRUE;
-
- for (i = 0; i < field_count; ++i)
- {
- char *f = field_names[i];
-
- if (strlen(f) == n)
- {
- if (nocasematch)
- {
- if (ci_strncmp(f, s, n) == 0)
- return TRUE;
- }
- else
- {
- if (strncmp(f, s, n) == 0)
- return TRUE;
- }
- }
- }
-
- return FALSE;
- }
-
- int
- ci_strncmp(s, t, n)
- char *s, *t;
- int n;
- {
- char c, d;
-
- while (n-- > 0)
- {
- c = *s++;
- d = *t++;
- if ((c == 0) && (d == 0))
- break;
- if (isupper(c))
- c = tolower(c);
- if (isupper(d))
- d = tolower(d);
- if (c > d)
- return 1;
- if (c < d)
- return -1;
- }
-
- return 0;
- }
-