]> jfr.im git - irc/quakenet/newserv.git/blame - chanserv/chanservgrep.c
Added some log rotation support and other tweaks.
[irc/quakenet/newserv.git] / chanserv / chanservgrep.c
CommitLineData
c86edd1d
Q
1
2#include "chanserv.h"
3#include "../core/events.h"
4#include <pcre.h>
5#include <sys/poll.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <unistd.h>
10#include <string.h>
11#include <stdio.h>
4ad1cf7a 12#include <unistd.h>
c86edd1d 13
43583524 14#define CSG_BUFSIZE 1024
c86edd1d
Q
15
16pcre *csg_curpat; /* Compiled pattern from pcre */
17int csg_curfile; /* Which logfile is being searched */
18unsigned long csg_curnum; /* What numeric is doing a search */
19int csg_matches; /* How many lines have been returned so far */
20int csg_maxmatches=0; /* How many matches are allowed */
43583524 21int csg_bytesread;
c86edd1d
Q
22
23char csg_readbuf[CSG_BUFSIZE]; /* Buffer */
24int csg_bytesleft; /* How much valid data there is in the buffer */
25
26void csg_handleevents(int fd, short revents);
27int csg_dogrep(void *source, int cargc, char **cargv);
28
4ad1cf7a
CP
29#if !defined(pread)
30extern ssize_t pread(int fd, void *buf, size_t count, off_t offset);
31#endif
32
c86edd1d 33void _init() {
1f0d7c8b 34 chanservaddcommand("grep", QCMD_OPER, 1, csg_dogrep, "Searches the logs.","");
c86edd1d
Q
35}
36
37void _fini() {
38 chanservremovecommand("grep", csg_dogrep);
39}
40
41int csg_dogrep(void *source, int cargc, char **cargv) {
42 nick *sender=source;
43 const char *errptr;
44 int erroffset;
45 int fd;
46
47 if (cargc<1) {
48 chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "grep");
49 return CMD_ERROR;
50 }
51
52 if (csg_maxmatches>0) {
53 chanservsendmessage(sender, "Sorry, grep is currently busy - try later.");
54 return CMD_ERROR;
55 }
56
57 if (!(csg_curpat=pcre_compile(cargv[0], 0, &errptr, &erroffset, NULL))) {
58 chanservsendmessage(sender, "Error in pattern at character %d: %s",erroffset,errptr);
59 return CMD_ERROR;
60 }
61
43583524 62 if ((fd=open("chanservlog",O_RDONLY))<0) {
c86edd1d
Q
63 chanservsendmessage(sender, "Unable to open logfile.");
64 free(csg_curpat);
65 return CMD_ERROR;
66 }
67
68 /* Initialise stuff for the match */
69 csg_maxmatches=500;
70 csg_matches=0;
71 csg_curnum=sender->numeric;
72 csg_curfile=0;
73 csg_bytesleft=0;
43583524 74 csg_bytesread=0;
c86edd1d
Q
75
76 registerhandler(fd, POLLIN, csg_handleevents);
77 chanservsendmessage(sender, "Started grep for %s...",cargv[0]);
78
79 return CMD_OK;
80}
81
82void csg_handleevents(int fd, short revents) {
83 int res;
84 nick *np=getnickbynumeric(csg_curnum);
85 char *chp, *linestart;
86 char filename[50];
87 off_t pos;
88
89 /* If the target user has vanished, drop everything */
90 if (!np) {
91 deregisterhandler(fd, 1);
92 free(csg_curpat);
93 csg_maxmatches=0;
94 return;
95 }
96
97retry:
98 res=read(fd, csg_readbuf+csg_bytesleft, CSG_BUFSIZE-csg_bytesleft);
99
100 if (res<=0) {
43583524 101/* chanservsendmessage(np, "Closing file: res=%d, errno=%d(%s), bytes read=%d",res,errno,sys_errlist[errno],csg_bytesread); */
c86edd1d
Q
102 /* End of file (or error) */
103 deregisterhandler(fd, 1);
104 sprintf(filename,"chanservlog.%d",++csg_curfile);
105 if ((fd=open(filename,O_RDONLY))>=0) {
106 /* Found the next file */
107 registerhandler(fd, POLLIN, csg_handleevents);
108 } else {
109 chanservstdmessage(np, QM_ENDOFLIST);
110 free(csg_curpat);
111 csg_maxmatches=0;
112 }
113
114 return;
115 }
116
43583524 117 csg_bytesread+=res;
118
c86edd1d
Q
119 linestart=chp=csg_readbuf;
120 csg_bytesleft+=res;
121
122 while (csg_bytesleft) {
123 csg_bytesleft--;
124 if (*chp=='\r' || *chp=='\n' || *chp=='\0') {
125 if (linestart==chp) {
126 linestart=(++chp);
127 } else {
128 *chp++='\0';
129 if (!pcre_exec(csg_curpat, NULL, linestart, strlen(linestart), 0, 0, NULL, 0)) {
130 chanservsendmessage(np, "%s", linestart);
131 if (++csg_matches >= csg_maxmatches) {
132 chanservstdmessage(np, QM_ENDOFLIST);
133 free(csg_curpat);
134 deregisterhandler(fd, 1);
135 csg_maxmatches=0;
136 }
137 }
138 linestart=chp;
139 }
140 } else {
141 chp++;
142 }
143 }
144
145 csg_bytesleft=(chp-linestart);
146 memmove(csg_readbuf, linestart, csg_bytesleft);
147
148 /* BSD hack */
149 pos=lseek(fd, 0, SEEK_CUR);
150 if (!pread(fd, csg_readbuf+csg_bytesleft, 1, pos)) {
151 /* EOF */
152 goto retry;
153 }
154}