1 /*$Id: searchlog.c,v 1.15 1999/11/10 04:08:27 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
9 #include "date822fmt.h"
11 #include "readwrite.h"
15 #include "subscribe.h"
18 static stralloc line
= {0};
19 static stralloc outline
= {0};
20 static char date
[DATE822FMT
];
21 static datetime_sec when
;
22 static struct datetime dt
;
24 static char inbuf
[256];
26 static void die_nomem(fatal
)
29 strerr_die2x(111,fatal
,ERR_NOMEM
);
32 static void lineout(subwrite
,fatal
)
36 (void) scan_ulong(line
.s
,&when
);
37 datetime_tai(&dt
,when
); /* there is always at least a '\n' */
38 if (!stralloc_copyb(&outline
,date
,date822fmt(date
,&dt
) - 1))
40 if (!stralloc_cats(&outline
,": ")) die_nomem(fatal
);
41 if (!stralloc_catb(&outline
,line
.s
,line
.len
- 1)) die_nomem(fatal
);
42 if (subwrite(outline
.s
,outline
.len
) == -1)
43 strerr_die3x(111,fatal
,ERR_WRITE
,"output");
47 void searchlog(dir
,search
,subwrite
,fatal
)
48 /* opens dir/Log, and outputs via subwrite(s,len) any line that matches */
49 /* search. A '_' is search is a wildcard. Any other non-alphanum/'.' char */
50 /* is replaced by a '_'. mysql version. Falls back on "manual" search of */
51 /* local Log if no mysql connect info. */
53 char *dir
; /* work directory */
54 char *search
; /* search string */
55 int subwrite(); /* output fxn */
56 char *fatal
; /* fatal */
59 register unsigned char x
;
60 register unsigned char y
;
61 register unsigned char *cp
;
62 register unsigned char *cpsearch
;
63 unsigned register char *cps
;
64 unsigned register char ch
;
65 unsigned char *cplast
, *cpline
;
66 unsigned int searchlen
;
72 char *table
= (char *) 0;
73 char **ptable
= &table
;
74 char *sublist
= (char *) 0;
75 unsigned long *lengths
;
77 if (!search
) search
= ""; /* defensive */
78 searchlen
= str_len(search
);
79 case_lowerb(search
,searchlen
);
80 cps
= (unsigned char *) search
;
81 while ((ch
= *(cps
++))) { /* search is potentially hostile */
82 if (ch
>= 'a' && ch
<= 'z') continue;
83 if (ch
>= '0' && ch
<= '9') continue;
84 if (ch
== '.' || ch
== '_') continue;
85 *(cps
- 1) = '_'; /* will match char specified as well */
88 if ((ret
= opensql(dir
,ptable
))) {
89 if (*ret
) strerr_die2x(111,fatal
,ret
);
90 /* fallback to local log */
91 if (!stralloc_copys(&line
,dir
)) die_nomem(fatal
);
92 if (!stralloc_cats(&line
,"/Log")) die_nomem(fatal
);
93 if (!stralloc_0(&line
)) die_nomem(fatal
);
94 fd
= open_read(line
.s
);
96 if (errno
!= error_noent
)
97 strerr_die4sys(111,fatal
,ERR_OPEN
,line
.s
,": ");
99 strerr_die3x(100,fatal
,line
.s
,ERR_NOEXIST
);
100 substdio_fdbuf(&ssin
,read
,fd
,inbuf
,sizeof(inbuf
));
103 if (getln(&ssin
,&line
,&match
,'\n') == -1)
104 strerr_die2sys(111,fatal
,ERR_READ_INPUT
);
107 lineout(subwrite
,fatal
);
109 cpline
= (unsigned char *) line
.s
- 1;
110 cplast
= cpline
+ line
.len
- searchlen
; /* line has \0 at the end */
111 while ((cp
= ++cpline
) <= cplast
) {
112 cpsearch
= (unsigned char *) search
;
117 if (y
<= (unsigned char) ('Z' - 'A')) y
+= 'a'; else y
+= 'A';
118 if (x
!= y
&& x
!= '_') break; /* '_' = wildcard */
121 lineout(subwrite
,fatal
);
130 /* SELECT (*) FROM list_slog WHERE fromline LIKE '%search%' OR address */
131 /* LIKE '%search%' ORDER BY tai; */
132 /* The '*' is formatted to look like the output of the non-mysql version */
133 /* This requires reading the entire table, since search fields are not */
134 /* indexed, but this is a rare query and time is not of the essence. */
136 if (!stralloc_cats(&line
,"SELECT CONCAT(FROM_UNIXTIME(UNIX_TIMESTAMP(tai)),"
137 "'-0000: ',UNIX_TIMESTAMP(tai),' ',edir,etype,' ',address,' ',"
138 "fromline) FROM ")) die_nomem(fatal
);
139 if (!stralloc_cats(&line
,table
)) die_nomem(fatal
);
140 if (!stralloc_cats(&line
,"_slog ")) die_nomem(fatal
);
141 if (*search
) { /* We can afford to wait for LIKE '%xx%' */
142 if (!stralloc_cats(&line
,"WHERE fromline LIKE '%")) die_nomem(fatal
);
143 if (!stralloc_cats(&line
,search
)) die_nomem(fatal
);
144 if (!stralloc_cats(&line
,"%' OR address LIKE '%")) die_nomem(fatal
);
145 if (!stralloc_cats(&line
,search
)) die_nomem(fatal
);
146 if (!stralloc_cats(&line
,"%'")) die_nomem(fatal
);
147 } /* ordering by tai which is an index */
148 if (!stralloc_cats(&line
," ORDER by tai")) die_nomem(fatal
);
150 if (mysql_real_query((MYSQL
*) psql
,line
.s
,line
.len
)) /* query */
151 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
152 if (!(result
= mysql_use_result((MYSQL
*) psql
)))
153 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
154 while ((row
= mysql_fetch_row(result
))) {
155 if (!(lengths
= mysql_fetch_lengths(result
)))
156 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
157 if (subwrite(row
[0],lengths
[0]) == -1) die_write(fatal
);
159 if (!mysql_eof(result
))
160 strerr_die2x(111,fatal
,mysql_error((MYSQL
*) psql
));
161 mysql_free_result(result
);