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