|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 6113 (0x17e1) Types: TextFile Names: »search.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/euug-87hel/sec1/news/misc/search/search.c«
/* search [options] ... [file|directory] ... Search saved news articles for a match, and summarize the matching articles. Options are: -f show file name -b show article's body -h show article's header -a show entire article (== -b -h) -k key show header lines with this key; *suppress* matching header lines if combined with -h or -a -m [key]:[val] process only matching articles -p pipe output through pager (for each article separately) -e allow editing of the file Directories are scanned recursively for matching files. If no files or directories are given, searches ~/News/save, or $SAVE if defined. If none of the parameters -f, -b, -h, -a, -k or -e are given, -k Subject is assumed. */ #include "lib/defs.h" #include "lib/scanheaders.h" /* Getopt globals: */ extern int optind; extern char *optarg; int process(); /* Forward */ /* Command line options. */ bool do_name= FALSE; bool do_header= FALSE; bool do_body= FALSE; bool use_pager= FALSE; bool edit_file= FALSE; main(argc, argv) int argc; char **argv; { int c; int status= 0; while ((c= getopt(argc, argv, "abefhpk:m:")) != EOF) { switch (c) { case 'f': do_name= TRUE; break; case 'h': do_header= TRUE; break; case 'k': set_keyword(optarg); break; case 'm': set_pattern(optarg); break; case 'a': do_header= do_body= TRUE; break; case 'b': do_body= TRUE; break; case 'p': use_pager= TRUE; break; case 'e': edit_file= TRUE; break; default: usage(argv[0]); } } add_defaults(); /* If no flags given */ if (argc-optind < 1) { char *save= getenv("SAVE"); if (save == NULL || *save == EOS) { char buf[BUFSIZ]; save= getenv("HOME"); if (save == NULL || *save == EOS) usage(argv[0]); sprintf(buf, "%s/News/save", save); save= strsave(buf); } status |= descend(save, process); } else { do { if (isdir(argv[optind])) status |= descend(argv[optind], process); else status |= process(argv[optind]); } while (++optind < argc); } exit(status); } /* Issue 'usage' error message and exit. */ usage(progname) char *progname; { fprintf(stderr, "usage: %s [-abefhp] [-m key:match] [-k key] ... file|dir ...\n", progname); exit(2); } /* Process one file given by name. */ int process(name) char *name; { FILE *fp; int status; if ((fp= fopen(name, "r")) == NULL) { perror(name); return 1; } status= fprocess(fp, name); (void) fclose(fp); return status; } /* Process one file, given as a FILE pointer. */ int match(); /* Forward */ int display(); /* Forward */ bool have_pattern= FALSE; int fprocess(fp, name) FILE *fp; char *name; { int code= have_pattern ? scanheaders(fp, name, match) : FOUND_MATCH; switch (code) { case FOUND_MATCH: startfile(name); rewind(fp); (void) scanheaders(fp, name, display); endfile(fp, name); /* Fall through */ case NO_MATCH: return 0; case EMPTY_FILE: fprintf(stderr, "%s: empty file\n", name); break; case NO_HEADERS: fprintf(stderr, "%s: no headers\n", name); break; case BAD_HEADER: fprintf(stderr, "%s: bad headers\n", name); break; case BAD_LINE: fprintf(stderr, "%s: bad header line\n", name); break; default: fprintf(stderr, "%s: bad header, code %d\n", name, code); break; } return 1; } /* Set the search pattern. */ char *the_key; int key_len; char *the_val; int val_len; set_pattern(pattern) char *pattern; { char *key= pattern; char *value= pattern; while (iskwchar(*value)) ++value; if (*value != EOS) *value++ = EOS; the_key= key; key_len= strlen(the_key); the_val= trim(value); val_len= strlen(the_val); have_pattern= key_len + val_len > 0; } /* See if key, value match with the given pattern. */ /*ARGSUSED*/ bool match(key, value, file, first) char *key; char *value; char *file; bool first; { return cistrncmp(the_key, key, key_len) == 0 && cimatch(the_val, value, val_len); } /* Set the keywords to be used in displaying the header. */ #define MAXKEYWORDS 50 int nkeywords= 0; char *keywords[MAXKEYWORDS]; set_keyword(key) char *key; { if (nkeywords >= MAXKEYWORDS) { fprintf(stderr, "too many -k parameters\n"); exit(2); } keywords[nkeywords++]= key; } /* Print a header line, if it matches the specifications. */ FILE *ofile= stdout; bool display(key, value, file, first) char *key; char *value; char *file; bool first; { if (okay(key)) { if (first) fprintf(ofile, "%s: ", key); else fprintf(ofile, "\t"); fprintf(ofile, "%s\n", trim(value)); } return FALSE; } /* Do we want to print this key? */ bool okay(key) char *key; { int i; for (i= 0; i < nkeywords; ++i) { if (cistrncmp(key, keywords[i], strlen(keywords[i])) == 0) return !do_header; } return do_header; } startfile(file) char *file; { if (use_pager) { static char *pager; if (pager == NULL) { pager= getenv("PAGER"); if (pager == NULL || *pager == EOS) pager= "more"; } ofile= popen(pager, "w"); } if (do_name) fprintf(ofile, "%s\n", file); } endfile(fp, file) FILE *fp; char *file; { if (do_header || (nkeywords + do_name) > 1) fprintf(ofile, "\n"); if (do_body) copyrest(fp, ofile); if (use_pager) { int status= pclose(ofile); if (status != 0) fprintf("pager exit code %d\n", status); } if (edit_file) { static char *editor; char command[BUFSIZ]; char line[10]; char *reply; int status; if (editor == NULL) { editor= getenv("EDITOR"); if (editor == NULL || *editor == EOS) editor= getenv("VISUAL"); if (editor == NULL || *editor == EOS) editor= "vi"; } sprintf(command, "%s %s", editor, file); fprintf(stderr, "Edit? [yn] "); safegets(line, sizeof line, stdin); reply= trim(line); if (*reply == 'n' || *reply == 'N') return; status= system(command); if (status != 0) fprintf(stderr, "editor exit code %d\n", status); } } /* Add defaults, to ensure at least some output is generated for every match. */ add_defaults() { if (do_header + do_body + do_name + nkeywords == 0) set_keyword("Subject"); }