]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanserv_grep.c
3 #include "../core/events.h"
4 #include "../lib/irc_string.h"
14 #include "../lib/version.h"
16 MODULE_VERSION ( QVERSION
)
18 #define CSG_BUFSIZE 1024
19 #define CSG_MAXSTARTPOINT 30
21 pcre
* csg_curpat
; /* Compiled pattern from pcre */
22 int csg_curfile
; /* Which logfile is being searched */
23 unsigned long csg_curnum
; /* What numeric is doing a search */
24 int csg_matches
; /* How many lines have been returned so far */
25 int csg_maxmatches
= 0 ; /* How many matches are allowed */
26 int csg_direction
; /* Log direction (0 = forward, 1 = reverse) */
29 char csg_readbuf
[ CSG_BUFSIZE
]; /* Buffer */
30 int csg_bytesleft
; /* How much valid data there is in the buffer */
32 void csg_handleevents ( int fd
, short revents
);
33 int csg_dogrep ( void * source
, int cargc
, char ** cargv
);
34 int csg_dorgrep ( void * source
, int cargc
, char ** cargv
);
35 int csg_execgrep ( nick
* sender
, char * pattern
);
38 extern ssize_t
pread ( int fd
, void * buf
, size_t count
, off_t offset
);
42 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." );
43 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." );
47 chanservremovecommand ( "grep" , csg_dogrep
);
48 chanservremovecommand ( "rgrep" , csg_dorgrep
);
51 int csg_dogrep ( void * source
, int cargc
, char ** cargv
) {
53 reguser
* rup
= getreguserfromnick ( sender
);
59 chanservstdmessage ( sender
, QM_NOTENOUGHPARAMS
, "grep" );
66 chanservwallmessage ( " %s ( %s ) used GREP %s " , sender
-> nick
, rup
-> username
, cargv
[ 0 ]);
67 cs_log ( sender
, "GREP %s " , cargv
[ 0 ]);
69 return csg_execgrep ( sender
, cargv
[ 0 ]);
72 int csg_dorgrep ( void * source
, int cargc
, char ** cargv
) {
75 reguser
* rup
= getreguserfromnick ( sender
);
81 chanservstdmessage ( sender
, QM_NOTENOUGHPARAMS
, "rgrep" );
85 if (! protectedatoi ( cargv
[ 0 ], & startpoint
)) {
86 chanservsendmessage ( sender
, "Error in starting day number." );
91 chanservsendmessage ( sender
, "Invalid starting day number." );
95 if ( startpoint
> CSG_MAXSTARTPOINT
) {
96 chanservsendmessage ( sender
, "Sorry, the maximum starting day is %d days." , CSG_MAXSTARTPOINT
);
100 chanservwallmessage ( " %s ( %s ) used RGREP %s %s " , sender
-> nick
, rup
-> username
, cargv
[ 0 ], cargv
[ 1 ]);
101 cs_log ( sender
, "RGREP %s %s " , cargv
[ 0 ], cargv
[ 1 ]);
103 csg_curfile
= startpoint
;
105 return csg_execgrep ( sender
, cargv
[ 1 ]);
108 int csg_execgrep ( nick
* sender
, char * pattern
) {
114 if ( csg_maxmatches
> 0 ) {
115 chanservsendmessage ( sender
, "Sorry, the grepper is currently busy - try later." );
119 if (!( csg_curpat
= pcre_compile ( pattern
, 0 , & errptr
, & erroffset
, NULL
))) {
120 chanservsendmessage ( sender
, "Error in pattern at character %d : %s " , erroffset
, errptr
);
124 if ( csg_direction
== 0 || csg_curfile
== 0 ) {
125 if (( fd
= open ( "chanservlog" , O_RDONLY
))< 0 ) {
126 chanservsendmessage ( sender
, "Unable to open logfile." );
131 sprintf ( filename
, "chanservlog. %d " , csg_curfile
);
132 if (( fd
= open ( filename
, O_RDONLY
))< 0 ) {
133 chanservsendmessage ( sender
, "Unable to open logfile." );
139 /* Initialise stuff for the match */
142 csg_curnum
= sender
-> numeric
;
146 registerhandler ( fd
, POLLIN
, csg_handleevents
);
147 chanservsendmessage ( sender
, "Started grep for %s ..." , pattern
);
152 void csg_handleevents ( int fd
, short revents
) {
154 nick
* np
= getnickbynumeric ( csg_curnum
);
155 char * chp
, * linestart
;
159 /* If the target user has vanished, drop everything */
161 deregisterhandler ( fd
, 1 );
168 res
= read ( fd
, csg_readbuf
+ csg_bytesleft
, CSG_BUFSIZE
- csg_bytesleft
);
171 /* chanservsendmessage(np, "Closing file: res=%d, errno=%d(%s), bytes read=%d",res,errno,sys_errlist[errno],csg_bytesread); */
172 /* End of file (or error) */
173 deregisterhandler ( fd
, 1 );
174 if ( csg_direction
== 0 ) {
175 sprintf ( filename
, "chanservlog. %d " ,++ csg_curfile
);
179 chanservstdmessage ( np
, QM_ENDOFLIST
);
183 } else if ( csg_curfile
== 0 ) {
184 sprintf ( filename
, "chanservlog" );
186 sprintf ( filename
, "chanservlog. %d " , csg_curfile
);
189 if (( fd
= open ( filename
, O_RDONLY
))>= 0 ) {
190 /* Found the next file */
191 registerhandler ( fd
, POLLIN
, csg_handleevents
);
193 chanservstdmessage ( np
, QM_ENDOFLIST
);
203 linestart
= chp
= csg_readbuf
;
206 while ( csg_bytesleft
) {
208 if (* chp
== ' \r ' || * chp
== ' \n ' || * chp
== '\0' ) {
209 if ( linestart
== chp
) {
213 if (! pcre_exec ( csg_curpat
, NULL
, linestart
, strlen ( linestart
), 0 , 0 , NULL
, 0 )) {
214 chanservsendmessage ( np
, " %s " , linestart
);
215 if (++ csg_matches
>= csg_maxmatches
) {
216 chanservstdmessage ( np
, QM_TRUNCATED
, csg_maxmatches
);
217 chanservstdmessage ( np
, QM_ENDOFLIST
);
219 deregisterhandler ( fd
, 1 );
230 csg_bytesleft
=( chp
- linestart
);
231 memmove ( csg_readbuf
, linestart
, csg_bytesleft
);
234 pos
= lseek ( fd
, 0 , SEEK_CUR
);
235 if (! pread ( fd
, csg_readbuf
+ csg_bytesleft
, 1 , pos
)) {