ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
searchlog.c
Go to the documentation of this file.
1#include "getln.h"
2#include "case.h"
3#include "scan.h"
4#include "stralloc.h"
5#include "str.h"
6#include "open.h"
7#include "datetime.h"
8#include "date822fmt.h"
9#include "buffer.h"
10#include "readwrite.h"
11#include "logmsg.h"
12#include "error.h"
13#include "errtxt.h"
14#include "subscribe.h"
15#include "idx.h"
16#include <unistd.h>
17#include <libpq-fe.h>
18
19#define WHO "searchlog"
20
26
27extern PGconn *pgsql;
28
29extern void die_write(void);
30
31static stralloc line = {0};
32static stralloc outline = {0};
33static char date[DATE822FMT];
34static datetime_sec when;
35static struct datetime dt;
36static buffer bi;
37static char inbuf[256];
38
39static void lineout(int subwrite())
40{
41 scan_ulong(line.s,&when);
42 datetime_tai(&dt,when); /* there is always at least a '\n' */
43 if (!stralloc_copyb(&outline,date,date822fmt(date,&dt) - 1)) die_nomem();
44 if (!stralloc_cats(&outline,": ")) die_nomem();
45 if (!stralloc_catb(&outline,line.s,line.len - 1)) die_nomem();
46 if (subwrite(outline.s,outline.len) == -1)
47 logmsg(WHO,111,FATAL,B("ERR_WRITE :","output"));
48 return;
49}
50
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 PGresult *result;
75 int row_nr;
76 int length;
77 char *row;
78
79 const char *table = (char *) 0;
80
81 if (!search) search = (char *)""; /* defensive */
82 searchlen = str_len(search);
83 case_lowerb(search,searchlen);
84 cps = (unsigned char *) search;
85
86 while ((ch = *(cps++))) { /* search is potentially hostile */
87 if (ch >= 'a' && ch <= 'z') continue;
88 if (ch >= '0' && ch <= '9') continue;
89 if (ch == '.' || ch == '_') continue;
90 *(cps - 1) = '_'; /* will match char specified as well */
91 }
92
93 if ((ret = opensql(dir,&table))) {
94 if (*ret) logmsg(WHO,111,FATAL,ret);
95
96 /* fallback to local log */
97
98 if (!stralloc_copys(&line,dir)) die_nomem();
99 if (!stralloc_cats(&line,"/Log")) die_nomem();
100 if (!stralloc_0(&line)) die_nomem();
101 fd = open_read(line.s);
102 if (fd == -1)
103 if (errno != ENOENT)
104 logmsg(WHO,111,FATAL,B("ERR_OPEN :",line.s));
105 else
106 logmsg(WHO,100,FATAL,B(line.s," ERR_NOEXIST"));
107
108 buffer_init(&bi,buffer_unixread,fd,inbuf,sizeof(inbuf));
109
110 for (;;) {
111 if (getln(&bi,&line,&match,'\n') == -1)
112 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
113 if (!match) break;
114 if (!searchlen) {
115 lineout(subwrite);
116 } else {
117 cpline = (unsigned char *) line.s - 1;
118 cplast = cpline + line.len - searchlen; /* line has \0 at the end */
119 while ((cp = ++cpline) <= cplast) {
120 cpsearch = (unsigned char *) search;
121 for (;;) {
122 x = *cpsearch++;
123 if (!x) break;
124 y = *cp++ - 'A';
125 if (y <= (unsigned char) ('Z' - 'A')) y += 'a'; else y += 'A';
126 if (x != y && x != '_') break; /* '_' = wildcard */
127 }
128 if (!x) {
129 lineout(subwrite);
130 break;
131 }
132 }
133 }
134 }
135 close(fd);
136 } else {
137
138/* SELECT (*) FROM list_slog WHERE fromline LIKE '%search%' OR address */
139/* LIKE '%search%' ORDER BY tai; */
140/* The '*' is formatted to look like the output of the non-mysql version */
141/* This requires reading the entire table, since search fields are not */
142/* indexed, but this is a rare query and time is not of the essence. */
143
144 if (!stralloc_cats(&line,"SELECT tai::datetime||': '||tai::int8||' '"
145 "||address||' '||edir||etype||' '||fromline FROM ")) die_nomem();
146
147 if (!stralloc_cats(&line,table)) die_nomem();
148 if (!stralloc_cats(&line,"_slog ")) die_nomem();
149
150 if (*search) { /* We can afford to wait for LIKE '%xx%' */
151 if (!stralloc_cats(&line,"WHERE fromline LIKE '%")) die_nomem();
152 if (!stralloc_cats(&line,search)) die_nomem();
153 if (!stralloc_cats(&line,"%' OR address LIKE '%")) die_nomem();
154 if (!stralloc_cats(&line,search)) die_nomem();
155 if (!stralloc_cats(&line,"%'")) die_nomem();
156 } /* ordering by tai which is an index */
157 if (!stralloc_cats(&line," ORDER by tai")) die_nomem();
158 if (!stralloc_0(&line)) die_nomem();
159
160 result = PQexec(pgsql,line.s);
161 if (result == NULL)
162 logmsg(WHO,111,FATAL,PQerrorMessage(pgsql));
163
164 if (PQresultStatus(result) != PGRES_TUPLES_OK)
165 logmsg(WHO,111,FATAL,PQresultErrorMessage(result));
166
167 for (row_nr = 0; row_nr < PQntuples(result); row_nr++) {
168 row = PQgetvalue(result,row_nr,0);
169 length = PQgetlength(result,row_nr,0);
170 if (subwrite(row,length) == -1) die_write();
171 }
172 PQclear(result);
173
174 }
175}
#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
PGconn * pgsql
Definition opensql.c:22
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