chiark / gitweb /
Import ezmlm-idx 0.40
[ezmlm] / sub_std / searchlog.c
1 /*$Id: searchlog.c,v 1.6 1999/10/09 14:22:38 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
3 #include "case.h"
4 #include "scan.h"
5 #include "stralloc.h"
6 #include "str.h"
7 #include "open.h"
8 #include "datetime.h"
9 #include "date822fmt.h"
10 #include "substdio.h"
11 #include "readwrite.h"
12 #include "strerr.h"
13 #include "error.h"
14 #include "errtxt.h"
15 #include "subscribe.h"
16
17 static stralloc line = {0};
18 static stralloc outline = {0};
19 static char date[DATE822FMT];
20 static datetime_sec when;
21 static struct datetime dt;
22 static substdio ssin;
23 static char inbuf[256];
24
25 static void die_nomem(fatal)
26 char *fatal;
27 {
28   strerr_die2x(100,fatal,ERR_NOMEM);
29 }
30
31 static void lineout(subwrite,fatal)
32 int subwrite();
33 char *fatal;
34 {
35   (void) scan_ulong(line.s,&when);
36   datetime_tai(&dt,when);               /* there is always at least a '\n' */
37   if (!stralloc_copyb(&outline,date,date822fmt(date,&dt) - 1))
38         die_nomem(fatal);
39   if (!stralloc_cats(&outline,": ")) die_nomem(fatal);
40   if (!stralloc_catb(&outline,line.s,line.len - 1)) die_nomem(fatal);
41   if (subwrite(outline.s,outline.len) == -1)
42         strerr_die3x(111,fatal,ERR_WRITE,"output");
43   return;
44 }
45
46 void searchlog(dir,search,subwrite,fatal)
47 /* opens dir/Log, and outputs via subwrite(s,len) any line that matches */
48 /* search. A '_' is search is a wildcard. Any other non-alphanum/'.' char */
49 /* is replaced by a '_' */
50
51 char *dir;              /* work directory */
52 char *search;           /* search string */
53 int subwrite();         /* output fxn */
54 char *fatal;            /* fatal */
55 {
56
57   register unsigned char x;
58   register unsigned char y;
59   register unsigned char *cp;
60   register unsigned char *cpsearch;
61   unsigned register char *cps;
62   unsigned register char ch;
63   unsigned char *cplast, *cpline;
64   unsigned int searchlen;
65   int fd,match;
66
67   searchlen = str_len(search);
68   case_lowerb(search,searchlen);
69   cps = (unsigned char *) search;
70   while ((ch = *(cps++))) {             /* search is potentially hostile */
71     if (ch >= 'a' && ch <= 'z') continue;
72     if (ch >= '0' && ch <= '9') continue;
73     if (ch == '.' || ch == '_') continue;
74     *(cps - 1) = '_';                   /* will [also] match char specified */
75   }
76
77   if (!stralloc_copys(&line,dir)) die_nomem(fatal);
78   if (!stralloc_cats(&line,"/Log")) die_nomem(fatal);
79   if (!stralloc_0(&line)) die_nomem(fatal);
80   fd = open_read(line.s);
81   if (fd == -1)
82     if (errno != error_noent)
83         strerr_die4sys(111,fatal,ERR_OPEN,line.s,": ");
84     else
85         strerr_die3x(100,fatal,line.s,ERR_NOEXIST);
86   substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
87
88   for (;;) {
89     if (getln(&ssin,&line,&match,'\n') == -1)
90       strerr_die2sys(111,fatal,ERR_READ_INPUT);
91     if (!match) break;
92     if (!searchlen) {
93       lineout(subwrite,fatal);
94     } else {            /* simple case-insensitive search */
95       cpline = (unsigned char *) line.s - 1;
96       cplast = cpline + line.len - searchlen; /* line has \0 at the end */
97       while ((cp = ++cpline) <= cplast) {
98         cpsearch = (unsigned char *) search;
99         for (;;) {
100           x = *cpsearch++;
101           if (!x) break;
102           y = *cp++ - 'A';
103           if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
104           if (x != y && x != '_') break;                /* '_' = wildcard */
105         }
106         if (!x) {
107           lineout(subwrite,fatal);
108           break;
109         }
110       }
111     }
112   }
113   close(fd);
114 }