]>
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
) {
52 chanservstdmessage ( sender
, QM_NOTENOUGHPARAMS
, "grep" );
58 return csg_execgrep ( sender
, cargv
[ 0 ]);
61 int csg_dorgrep ( void * source
, int cargc
, char ** cargv
) {
66 chanservstdmessage ( sender
, QM_NOTENOUGHPARAMS
, "rgrep" );
70 if (! protectedatoi ( cargv
[ 0 ], & startpoint
)) {
71 chanservsendmessage ( sender
, "Error in starting day number." );
76 chanservsendmessage ( sender
, "Invalid starting day number." );
80 if ( startpoint
> CSG_MAXSTARTPOINT
) {
81 chanservsendmessage ( sender
, "Sorry, the maximum starting day is %d days." , CSG_MAXSTARTPOINT
);
85 csg_curfile
= startpoint
;
87 return csg_execgrep ( sender
, cargv
[ 1 ]);
90 int csg_execgrep ( nick
* sender
, char * pattern
) {
96 if ( csg_maxmatches
> 0 ) {
97 chanservsendmessage ( sender
, "Sorry, the grepper is currently busy - try later." );
101 if (!( csg_curpat
= pcre_compile ( pattern
, 0 , & errptr
, & erroffset
, NULL
))) {
102 chanservsendmessage ( sender
, "Error in pattern at character %d : %s " , erroffset
, errptr
);
106 if ( csg_direction
== 0 || csg_curfile
== 0 ) {
107 if (( fd
= open ( "chanservlog" , O_RDONLY
))< 0 ) {
108 chanservsendmessage ( sender
, "Unable to open logfile." );
113 sprintf ( filename
, "chanservlog. %d " , csg_curfile
);
114 if (( fd
= open ( filename
, O_RDONLY
))< 0 ) {
115 chanservsendmessage ( sender
, "Unable to open logfile." );
121 /* Initialise stuff for the match */
124 csg_curnum
= sender
-> numeric
;
128 registerhandler ( fd
, POLLIN
, csg_handleevents
);
129 chanservsendmessage ( sender
, "Started grep for %s ..." , pattern
);
134 void csg_handleevents ( int fd
, short revents
) {
136 nick
* np
= getnickbynumeric ( csg_curnum
);
137 char * chp
, * linestart
;
141 /* If the target user has vanished, drop everything */
143 deregisterhandler ( fd
, 1 );
150 res
= read ( fd
, csg_readbuf
+ csg_bytesleft
, CSG_BUFSIZE
- csg_bytesleft
);
153 /* chanservsendmessage(np, "Closing file: res=%d, errno=%d(%s), bytes read=%d",res,errno,sys_errlist[errno],csg_bytesread); */
154 /* End of file (or error) */
155 deregisterhandler ( fd
, 1 );
156 if ( csg_direction
== 0 ) {
157 sprintf ( filename
, "chanservlog. %d " ,++ csg_curfile
);
161 chanservstdmessage ( np
, QM_ENDOFLIST
);
165 } else if ( csg_curfile
== 0 ) {
166 sprintf ( filename
, "chanservlog" );
168 sprintf ( filename
, "chanservlog. %d " , csg_curfile
);
171 if (( fd
= open ( filename
, O_RDONLY
))>= 0 ) {
172 /* Found the next file */
173 registerhandler ( fd
, POLLIN
, csg_handleevents
);
175 chanservstdmessage ( np
, QM_ENDOFLIST
);
185 linestart
= chp
= csg_readbuf
;
188 while ( csg_bytesleft
) {
190 if (* chp
== ' \r ' || * chp
== ' \n ' || * chp
== '\0' ) {
191 if ( linestart
== chp
) {
195 if (! pcre_exec ( csg_curpat
, NULL
, linestart
, strlen ( linestart
), 0 , 0 , NULL
, 0 )) {
196 chanservsendmessage ( np
, " %s " , linestart
);
197 if (++ csg_matches
>= csg_maxmatches
) {
198 chanservstdmessage ( np
, QM_TRUNCATED
, csg_maxmatches
);
199 chanservstdmessage ( np
, QM_ENDOFLIST
);
201 deregisterhandler ( fd
, 1 );
212 csg_bytesleft
=( chp
- linestart
);
213 memmove ( csg_readbuf
, linestart
, csg_bytesleft
);
216 pos
= lseek ( fd
, 0 , SEEK_CUR
);
217 if (! pread ( fd
, csg_readbuf
+ csg_bytesleft
, 1 , pos
)) {