|
|
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");
}