ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
searchlog.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "getln.h"
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 "buffer.h"
11#include "readwrite.h"
12#include "logmsg.h"
13#include "error.h"
14#include "errtxt.h"
15#include "subscribe.h"
16#include "idx.h"
17#include <mysql.h>
18
24
25extern MYSQL *mysql;
26
27extern void die_write(void);
28
29static stralloc line = {0};
30static stralloc outline = {0};
31static char date[DATE822FMT];
32static datetime_sec when;
33static struct datetime dt;
34static buffer bi;
35static char inbuf[256];
36
37static void lineout(int subwrite())
38{
39 scan_ulong(line.s,&when);
40 datetime_tai(&dt,when); /* there is always at least a '\n' */
41 if (!stralloc_copyb(&outline,date,date822fmt(date,&dt) - 1))
42 die_nomem();
43 if (!stralloc_cats(&outline,": ")) die_nomem();
44 if (!stralloc_catb(&outline,line.s,line.len - 1)) die_nomem();
45 if (subwrite(outline.s,outline.len) == -1)
46 logmsg(WHO,111,FATAL,B("ERR_WRITE :","output"));
47 return;
48}
49
60
61void searchlog(const char *dir,char *search,int subwrite())
62{
63 unsigned char x;
64 unsigned char y;
65 unsigned char *cp;
66 unsigned char *cpsearch;
67 unsigned char *cps;
68 unsigned char ch;
69 unsigned char *cplast, *cpline;
70 unsigned int searchlen;
71 int fd,match;
72 const char *ret;
73
74 MYSQL_RES *result;
75 MYSQL_ROW row;
76 const char *table = (char *) 0;
77 const char **ptable = &table;
78 unsigned long *lengths;
79
80 if (!search) search = (char *)""; /* defensive */
81 searchlen = str_len(search);
82 case_lowerb(search,searchlen);
83 cps = (unsigned char *) search;
84 while ((ch = *(cps++))) { /* search is potentially hostile */
85 if (ch >= 'a' && ch <= 'z') continue;
86 if (ch >= '0' && ch <= '9') continue;
87 if (ch == '.' || ch == '_') continue;
88 *(cps - 1) = '_'; /* will match char specified as well */
89 }
90
91 if ((ret = opensql(dir,ptable))) {
92 if (*ret) logmsg(WHO,111,FATAL,ret);
93
94 /* fallback to local log */
95
96 if (!stralloc_copys(&line,dir)) die_nomem();
97 if (!stralloc_cats(&line,"/Log")) die_nomem();
98 if (!stralloc_0(&line)) die_nomem();
99
100 fd = open_read(line.s);
101 if (fd == -1)
102 if (errno != ENOENT)
103 logmsg(WHO,111,FATAL,B("ERR_OPEN :",line.s));
104 else
105 logmsg(WHO,100,FATAL,line.s,"ERR_NOEXIST");
106
107 buffer_init(&bi,buffer_unixread,fd,inbuf,sizeof(inbuf));
108
109 for (;;) {
110 if (getln(&bi,&line,&match,'\n') == -1) logmsg(WHO,111,FATAL,ERR_READ_INPUT);
111 if (!match) break;
112 if (!searchlen) {
113 lineout(subwrite);
114 } else {
115 cpline = (unsigned char *) line.s - 1;
116 cplast = cpline + line.len - searchlen; /* line has \0 at the end */
117 while ((cp = ++cpline) <= cplast) {
118 cpsearch = (unsigned char *) search;
119 for (;;) {
120 x = *cpsearch++;
121 if (!x) break;
122 y = *cp++ - 'A';
123 if (y <= (unsigned char) ('Z' - 'A')) y += 'a'; else y += 'A';
124 if (x != y && x != '_') break; /* '_' = wildcard */
125 }
126 if (!x) { lineout(subwrite); break; }
127 }
128 }
129 }
130 close(fd);
131 } else {
132
133/* SELECT (*) FROM list_slog WHERE fromline LIKE '%search%' OR address */
134/* LIKE '%search%' ORDER BY tai; */
135/* The '*' is formatted to look like the output of the non-mysql version */
136/* This requires reading the entire table, since search fields are not */
137/* indexed, but this is a rare query and time is not of the essence. */
138
139 if (!stralloc_cats(&line,"SELECT CONCAT(FROM_UNIXTIME(UNIX_TIMESTAMP(tai)),"
140 "'-0000: ',UNIX_TIMESTAMP(tai),' ',edir,etype,' ',address,' ',"
141 "fromline) FROM ")) die_nomem();
142 if (!stralloc_cats(&line,table)) die_nomem();
143 if (!stralloc_cats(&line,"_slog ")) die_nomem();
144 if (*search) { /* We can afford to wait for LIKE '%xx%' */
145 if (!stralloc_cats(&line,"WHERE fromline LIKE '%")) die_nomem();
146 if (!stralloc_cats(&line,search)) die_nomem();
147 if (!stralloc_cats(&line,"%' OR address LIKE '%")) die_nomem();
148 if (!stralloc_cats(&line,search)) die_nomem();
149 if (!stralloc_cats(&line,"%'")) die_nomem();
150 } /* ordering by tai which is an index */
151 if (!stralloc_cats(&line," ORDER by tai")) die_nomem();
152
153 if (mysql_real_query(mysql,line.s,line.len)) /* query */
154 logmsg(WHO,111,FATAL,mysql_error(mysql));
155
156 if (!(result = mysql_use_result(mysql)))
157 logmsg(WHO,111,FATAL,mysql_error(mysql));
158
159 while ((row = mysql_fetch_row(result))) {
160 if (!(lengths = mysql_fetch_lengths(result)))
161 logmsg(WHO,111,FATAL,mysql_error(mysql));
162 if (subwrite(row[0],lengths[0]) == -1) die_write();
163 }
164
165 if (!mysql_eof(result))
166 logmsg(WHO,111,FATAL,mysql_error(mysql));
167
168 mysql_free_result(result);
169 }
170}
#define DATE822FMT
Definition date822fmt.h:4
Error messages. If you translate these, I would urge you to keep the English version as well....
#define ERR_READ_INPUT
Definition errtxt.h:26
long datetime_sec
Definition datetime.h:15
const char * opensql(const char *dir, const char **table)
Definition opensql.c:13
void die_nomem()
Definition getconf.c:17
#define WHO
Definition author.c:1
char inbuf[1024]
char * dir
buffer bi
void searchlog(const char *dir, char *search, int subwrite())
Definition searchlog.c:60
const char * cp
Definition ezmlm-cron.c:76
unsigned int date822fmt(char *s, const struct datetime *dt)
Definition date822fmt.c:9
int fd
Definition ezmlm-cgi.c:141
datetime_sec when
Definition ezmlm-cgi.c:173
struct datetime dt
Definition ezmlm-cgi.c:174
int match
Definition ezmlm-cgi.c:140
void datetime_tai(struct datetime *dt, datetime_sec t)
Definition datetime.c:9
int subwrite(char *s, unsigned int l)
Definition ezmlm-list.c:29
MYSQL * mysql
Definition opensql.c:23
const char * logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done)
Definition loginfo.c:32
void die_write(void)
Definition subscribe.c:41