]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanserv_grep.c
3 #include "../core/events.h"
4 #include "../lib/irc_string.h"
15 #define CSG_BUFSIZE 1024
16 #define CSG_MAXSTARTPOINT 30
18 pcre
* csg_curpat
; /* Compiled pattern from pcre */
19 int csg_curfile
; /* Which logfile is being searched */
20 unsigned long csg_curnum
; /* What numeric is doing a search */
21 int csg_matches
; /* How many lines have been returned so far */
22 int csg_maxmatches
= 0 ; /* How many matches are allowed */
23 int csg_direction
; /* Log direction (0 = forward, 1 = reverse) */
26 char csg_readbuf
[ CSG_BUFSIZE
]; /* Buffer */
27 int csg_bytesleft
; /* How much valid data there is in the buffer */
29 void csg_handleevents ( int fd
, short revents
);
30 int csg_dogrep ( void * source
, int cargc
, char ** cargv
);
31 int csg_dorgrep ( void * source
, int cargc
, char ** cargv
);
32 int csg_execgrep ( nick
* sender
, char * pattern
);
35 extern ssize_t
pread ( int fd
, void * buf
, size_t count
, off_t offset
);
39 chanservaddcommand ( "grep" , QCMD_OPER
, 1 , csg_dogrep
, "Searches the logs." , "Usage: GREP <regex> \n Searches the logs. The current logfile will be specified first, followed by \n all older logfiles found. This will shuffle the order of results slightly. Where: \n regex - regular expression to search for. \n Note: For a case insensitive search, prepend (?i) to the regex." );
40 chanservaddcommand ( "rgrep" , QCMD_OPER
, 2 , csg_dorgrep
, "Searches the logs in reverse order." , "Usage: RGREP <days> <regex> \n Searches the logs. The oldest specified log will be specified first meaning \n that all events returned will be in strict chronological order. Where: \n days - number of days of history to search \n regex - regex to search for \n Note: For a case insensitive search, prepend (?i) to the regex." );
44 chanservremovecommand ( "grep" , csg_dogrep
);
45 chanservremovecommand ( "rgrep" , csg_dorgrep
);
48 int csg_dogrep ( void * source
, int cargc
, char ** cargv
) {
50 reguser
* rup
= getreguserfromnick ( sender
);
56 chanservstdmessage ( sender
, QM_NOTENOUGHPARAMS
, "grep" );
63 chanservwallmessage ( " %s ( %s ) used GREP %s " , sender
-> nick
, rup
-> username
, cargv
[ 0 ]);
64 cs_log ( sender
, "GREP %s " , cargv
[ 0 ]);
66 return csg_execgrep ( sender
, cargv
[ 0 ]);
69 int csg_dorgrep ( void * source
, int cargc
, char ** cargv
) {
72 reguser
* rup
= getreguserfromnick ( sender
);
78 chanservstdmessage ( sender
, QM_NOTENOUGHPARAMS
, "rgrep" );
82 if (! protectedatoi ( cargv
[ 0 ], & startpoint
)) {
83 chanservsendmessage ( sender
, "Error in starting day number." );
88 chanservsendmessage ( sender
, "Invalid starting day number." );
92 if ( startpoint
> CSG_MAXSTARTPOINT
) {
93 chanservsendmessage ( sender
, "Sorry, the maximum starting day is %d days." , CSG_MAXSTARTPOINT
);
97 chanservwallmessage ( " %s ( %s ) used RGREP %s %s " , sender
-> nick
, rup
-> username
, cargv
[ 0 ], cargv
[ 1 ]);
98 cs_log ( sender
, "RGREP %s %s " , cargv
[ 0 ], cargv
[ 1 ]);
100 csg_curfile
= startpoint
;
102 return csg_execgrep ( sender
, cargv
[ 1 ]);
105 int csg_execgrep ( nick
* sender
, char * pattern
) {
111 if ( csg_maxmatches
> 0 ) {
112 chanservsendmessage ( sender
, "Sorry, the grepper is currently busy - try later." );
116 if (!( csg_curpat
= pcre_compile ( pattern
, 0 , & errptr
, & erroffset
, NULL
))) {
117 chanservsendmessage ( sender
, "Error in pattern at character %d : %s " , erroffset
, errptr
);
121 if ( csg_direction
== 0 || csg_curfile
== 0 ) {
122 if (( fd
= open ( "chanservlog" , O_RDONLY
))< 0 ) {
123 chanservsendmessage ( sender
, "Unable to open logfile." );
128 sprintf ( filename
, "chanservlog. %d " , csg_curfile
);
129 if (( fd
= open ( filename
, O_RDONLY
))< 0 ) {
130 chanservsendmessage ( sender
, "Unable to open logfile." );
136 /* Initialise stuff for the match */
139 csg_curnum
= sender
-> numeric
;
143 registerhandler ( fd
, POLLIN
, csg_handleevents
);
144 chanservsendmessage ( sender
, "Started grep for %s ..." , pattern
);
149 void csg_handleevents ( int fd
, short revents
) {
151 nick
* np
= getnickbynumeric ( csg_curnum
);
152 char * chp
, * linestart
;
156 /* If the target user has vanished, drop everything */
158 deregisterhandler ( fd
, 1 );
165 res
= read ( fd
, csg_readbuf
+ csg_bytesleft
, CSG_BUFSIZE
- csg_bytesleft
);
168 /* chanservsendmessage(np, "Closing file: res=%d, errno=%d(%s), bytes read=%d",res,errno,sys_errlist[errno],csg_bytesread); */
169 /* End of file (or error) */
170 deregisterhandler ( fd
, 1 );
171 if ( csg_direction
== 0 ) {
172 sprintf ( filename
, "chanservlog. %d " ,++ csg_curfile
);
176 chanservstdmessage ( np
, QM_ENDOFLIST
);
180 } else if ( csg_curfile
== 0 ) {
181 sprintf ( filename
, "chanservlog" );
183 sprintf ( filename
, "chanservlog. %d " , csg_curfile
);
186 if (( fd
= open ( filename
, O_RDONLY
))>= 0 ) {
187 /* Found the next file */
188 registerhandler ( fd
, POLLIN
, csg_handleevents
);
190 chanservstdmessage ( np
, QM_ENDOFLIST
);
200 linestart
= chp
= csg_readbuf
;
203 while ( csg_bytesleft
) {
205 if (* chp
== ' \r ' || * chp
== ' \n ' || * chp
== '\0' ) {
206 if ( linestart
== chp
) {
210 if (! pcre_exec ( csg_curpat
, NULL
, linestart
, strlen ( linestart
), 0 , 0 , NULL
, 0 )) {
211 chanservsendmessage ( np
, " %s " , linestart
);
212 if (++ csg_matches
>= csg_maxmatches
) {
213 chanservstdmessage ( np
, QM_TRUNCATED
, csg_maxmatches
);
214 chanservstdmessage ( np
, QM_ENDOFLIST
);
216 deregisterhandler ( fd
, 1 );
227 csg_bytesleft
=( chp
- linestart
);
228 memmove ( csg_readbuf
, linestart
, csg_bytesleft
);
231 pos
= lseek ( fd
, 0 , SEEK_CUR
);
232 if (! pread ( fd
, csg_readbuf
+ csg_bytesleft
, 1 , pos
)) {