5 FUTURE: natural (sort of) language parsing
8 PPA: if multiple users match the same user@host or *@host it'll send multiple glines?!
11 #include "regexgline.h"
13 typedef struct rg_glinenode
{
15 struct rg_struct
*reason
;
16 struct rg_glinenode
*next
;
19 typedef struct rg_glinelist
{
20 struct rg_glinenode
*start
;
21 struct rg_glinenode
*end
;
24 void rg_dogline(struct rg_glinelist
*gll
, nick
*np
, struct rg_struct
*rp
, char *matched
);
27 sstring
*max_casualties
, *max_spew
, *expiry_time
, *max_per_gline
;
29 max_casualties
= getcopyconfigitem("regexgline", "maxcasualties", RGStringise(RG_MAX_CASUALTIES_DEFAULT
), 8);
30 if(!protectedatoi(max_casualties
->content
, &rg_max_casualties
))
31 rg_max_casualties
= RG_MAX_CASUALTIES_DEFAULT
;
33 freesstring(max_casualties
);
35 max_spew
= getcopyconfigitem("regexgline", "maxspew", RGStringise(RG_MAX_SPEW_DEFAULT
), 8);
36 if(!protectedatoi(max_spew
->content
, &rg_max_spew
))
37 rg_max_spew
= RG_MAX_SPEW_DEFAULT
;
39 freesstring(max_spew
);
41 expiry_time
= getcopyconfigitem("regexgline", "expirytime", RGStringise(RG_EXPIRY_TIME_DEFAULT
), 8);
42 if(!protectedatoi(expiry_time
->content
, &rg_expiry_time
))
43 rg_expiry_time
= RG_EXPIRY_TIME_DEFAULT
;
45 freesstring(expiry_time
);
47 max_per_gline
= getcopyconfigitem("regexgline", "maxpergline", RGStringise(RG_MAX_PER_GLINE_DEFAULT
), 8);
48 if(!protectedatoi(max_per_gline
->content
, &rg_max_per_gline
))
49 rg_max_per_gline
= RG_MAX_PER_GLINE_DEFAULT
;
51 freesstring(max_per_gline
);
56 registercontrolcmd("regexgline", 10, 4, rg_gline
);
57 registercontrolcmd("regexdelgline", 10, 1, rg_delgline
);
58 registercontrolcmd("regexglist", 10, 1, rg_glist
);
59 registercontrolcmd("regexspew", 10, 1, rg_spew
);
60 registercontrolcmd("regexidlookup", 10, 1, rg_idlist
);
62 registerhook(HOOK_NICK_NEWNICK
, &rg_nick
);
63 registerhook(HOOK_NICK_RENAME
, &rg_nick
);
66 rg_schedule
= schedulerecurring(time(NULL
) + 1, 0, 1, rg_checkexpiry
, NULL
);
71 struct rg_struct
*gp
= rg_list
, *oldgp
;
73 deregisterhook(HOOK_NICK_NEWNICK
, &rg_nick
);
74 deregisterhook(HOOK_NICK_RENAME
, &rg_nick
);
75 deregistercontrolcmd("regexspew", rg_spew
);
76 deregistercontrolcmd("regexglist", rg_glist
);
77 deregistercontrolcmd("regexdelgline", rg_delgline
);
78 deregistercontrolcmd("regexgline", rg_gline
);
79 deregistercontrolcmd("regexidlookup", rg_idlist
);
82 deleteschedule(rg_schedule
, &rg_checkexpiry
, NULL
);
96 void rg_checkexpiry(void *arg
) {
97 struct rg_struct
*rp
= rg_list
, *lp
= NULL
;
98 time_t current
= time(NULL
);
101 if (current
>= rp
->expires
) {
118 void rg_initglinelist(struct rg_glinelist
*gll
) {
123 void rg_flushglines(struct rg_glinelist
*gll
) {
124 struct rg_glinenode
*nn
, *pn
;
125 for(nn
=gll
->start
;nn
;nn
=pn
) {
127 if(nn
->reason
->type
== 3)
128 killuser(NULL
, nn
->np
, "%s (ID: %08lx)", nn
->reason
->reason
->content
, nn
->reason
->glineid
);
132 rg_initglinelist(gll
);
135 int rg_dbconnect(void) {
136 sstring
*dbhost
, *dbusername
, *dbpassword
, *dbdatabase
, *dbport
;
138 dbhost
= getcopyconfigitem("regexgline", "dbhost", "localhost", HOSTLEN
);
139 dbusername
= getcopyconfigitem("regexgline", "dbusername", "regexgline", 20);
140 dbpassword
= getcopyconfigitem("regexgline", "dbpassword", "moo", 20);
141 dbdatabase
= getcopyconfigitem("regexgline", "dbdatabase", "regexgline", 20);
142 dbport
= getcopyconfigitem("regexgline", "dbport", "3306", 8);
144 if(rg_sqlconnect(dbhost
->content
, dbusername
->content
, dbpassword
->content
, dbdatabase
->content
, strtol(dbport
->content
, NULL
, 10))) {
145 Error("regexgline", ERR_FATAL
, "Cannot connect to database host!");
146 return 1; /* PPA: splidge: do something here 8]! */
152 freesstring(dbusername
);
153 freesstring(dbpassword
);
154 freesstring(dbdatabase
);
160 int rg_dbload(void) {
161 rg_sqlquery("CREATE TABLE regexglines (id INT(10) PRIMARY KEY AUTO_INCREMENT, gline TEXT NOT NULL, setby VARCHAR(%d) NOT NULL, reason VARCHAR(%d) NOT NULL, expires BIGINT NOT NULL, type TINYINT(4) NOT NULL DEFAULT 1)", ACCOUNTLEN
, RG_REASON_MAX
);
162 rg_sqlquery("CREATE TABLE regexlogs (id INT(10) PRIMARY KEY AUTO_INCREMENT, host VARCHAR(%d) NOT NULL, account VARCHAR(%d) NOT NULL, event TEXT NOT NULL, arg TEXT NOT NULL, ts TIMESTAMP)", RG_MASKLEN
- 1, ACCOUNTLEN
);
163 rg_sqlquery("CREATE TABLE regexglinelog (id INT(10) PRIMARY KEY AUTO_INCREMENT, glineid INT(10) NOT NULL, ts TIMESTAMP, matched TEXT NOT NULL)");
165 if(!rg_sqlquery("SELECT id, gline, setby, reason, expires, type FROM regexglines")) {
167 if((res
= rg_sqlstoreresult())) {
169 while((row
= rg_sqlgetrow(res
))) {
170 if (!rg_newsstruct(row
[0], row
[1], row
[2], row
[3], row
[4], row
[5], 0, 0))
171 rg_sqlquery("DELETE FROM regexglines WHERE id = %s", row
[0]);
180 void rg_nick(int hooknum
, void *arg
) {
181 nick
*np
= (nick
*)arg
;
182 struct rg_struct
*rp
;
183 char hostname
[RG_MASKLEN
];
185 struct rg_glinelist gll
;
187 rg_initglinelist(&gll
);
189 hostlen
= RGBuildMatchHostname(hostname
, np
);
191 for(rp
=rg_list
;rp
;rp
=rp
->next
) {
192 if(pcre_exec(rp
->regex
, rp
->hint
, hostname
, hostlen
, 0, 0, NULL
, 0) >= 0) {
193 rg_dogline(&gll
, np
, rp
, hostname
);
198 rg_flushglines(&gll
);
201 int rg_gline(void *source
, int cargc
, char **cargv
) {
202 nick
*np
= (nick
*)source
, *tnp
;
204 const char *expirybuf
;
205 int expiry
, count
, j
, hostlen
;
206 struct rg_struct
*rp
;
207 struct rg_glinelist gll
;
209 char eemask
[RG_QUERY_BUF_SIZE
], eesetby
[RG_QUERY_BUF_SIZE
], eereason
[RG_QUERY_BUF_SIZE
];
210 char hostname
[RG_MASKLEN
];
213 controlreply(np
, "syntax: regexgline [mask] [duration] [type: 1: gline user@host 2: gline *@host 3: KILL] [reason]");
217 if ((strlen(cargv
[2]) != 1) || ((cargv
[2][0] != '1') && (cargv
[2][0] != '2') && (cargv
[2][0] != '3'))) {
218 controlreply(np
, "Invalid type specified!");
222 if (!(expiry
= durationtolong(cargv
[1]))) {
223 controlreply(np
, "Invalid duration specified!");
227 for(rp
=rg_list
;rp
;rp
=rp
->next
) {
228 if (RGMasksEqual(rp
->mask
->content
, cargv
[0])) {
229 controlreply(np
, "That regexp gline already exists!");
234 if (rg_sanitycheck(cargv
[0], &count
)) {
235 controlreply(np
, "Error in expression.");
237 } else if (count
< 0) {
238 controlreply(np
, "That expression would hit too many users (%d)!", -count
);
242 realexpiry
= expiry
+ time(NULL
);
244 rg_sqlescape_string(eemask
, cargv
[0], strlen(cargv
[0]));
245 rg_sqlescape_string(eesetby
, np
->nick
, strlen(np
->nick
));
246 rg_sqlescape_string(eereason
, cargv
[3], strlen(cargv
[3]));
248 rg_sqlquery("INSERT INTO regexglines (gline, setby, reason, expires, type) VALUES ('%s', '%s', '%s', %d, %s)", eemask
, eesetby
, eereason
, realexpiry
, cargv
[2]);
249 if (!rg_sqlquery("SELECT id FROM regexglines WHERE gline = '%s' AND setby = '%s' AND reason = '%s' AND expires = %d AND type = %s ORDER BY ID DESC LIMIT 1", eemask
, eesetby
, eereason
, realexpiry
, cargv
[2])) {
251 if((res
= rg_sqlstoreresult())) {
253 row
= rg_sqlgetrow(res
);
255 rp
= rg_newsstruct(row
[0], cargv
[0], np
->nick
, cargv
[3], "", cargv
[2], realexpiry
, 0);
258 rg_sqlquery("DELETE FROM regexglines WHERE gline = '%s' AND setby = '%s' AND reason = '%s' AND expires = %d AND type = %s ORDER BY ID DESC LIMIT 1", eemask
, eesetby
, eereason
, realexpiry
, cargv
[2]);
259 controlreply(np
, "Error allocating - regexgline NOT ADDED.");
264 rg_sqlquery("DELETE FROM regexglines WHERE gline = '%s' AND setby = '%s' AND reason = '%s' AND expires = %d AND type = %s ORDER BY ID DESC LIMIT 1", eemask
, eesetby
, eereason
, realexpiry
, cargv
[2]);
265 controlreply(np
, "Error selecting ID from database - regexgline NOT ADDED.");
269 rg_sqlquery("DELETE FROM regexglines WHERE gline = '%s' AND setby = '%s' AND reason = '%s' AND expires = %d AND type = %s ORDER BY ID DESC LIMIT 1", eemask
, eesetby
, eereason
, realexpiry
, cargv
[2]);
270 controlreply(np
, "Error fetching ID from database - regexgline NOT ADDED.");
274 rg_sqlquery("DELETE FROM regexglines WHERE gline = '%s' AND setby = '%s' AND reason = '%s' AND expires = %d AND type = %s ORDER BY ID DESC LIMIT 1", eemask
, eesetby
, eereason
, realexpiry
, cargv
[2]);
275 controlreply(np
, "Error executing query - regexgline NOT ADDED.");
279 rg_initglinelist(&gll
);
281 for(j
=0;j
<NICKHASHSIZE
;j
++) {
282 for(tnp
=nicktable
[j
];tnp
;tnp
=tnp
->next
) {
283 hostlen
= RGBuildMatchHostname(hostname
, tnp
);
284 if(pcre_exec(rp
->regex
, rp
->hint
, hostname
, hostlen
, 0, 0, NULL
, 0) >= 0)
285 rg_dogline(&gll
, tnp
, rp
, hostname
);
289 rg_flushglines(&gll
);
291 expirybuf
= longtoduration(expiry
, 0);
293 rg_logevent(np
, "regexgline", "%s %d %d %s", cargv
[0], expiry
, count
, cargv
[3]);
294 controlreply(np
, "Added regexgline: %s (expires in: %s, hit %d user%s): %s", cargv
[0], expirybuf
, count
, (count
!=1)?"s":"", cargv
[3]);
295 controlnoticeopers("%s added regexgline: %s (expires in: %s, hit %d user%s): %s", np
->nick
, cargv
[0], expirybuf
, count
, (count
!=1)?"s":"", cargv
[3]);
300 int rg_sanitycheck(char *mask
, int *count
) {
302 char hostname
[RG_MASKLEN
];
303 int erroroffset
, hostlen
, j
, masklen
= strlen(mask
);
308 if((masklen
< RG_MIN_MASK_LEN
) || (masklen
> RG_REGEXGLINE_MAX
))
311 if(!(regex
= pcre_compile(mask
, RG_PCREFLAGS
, &error
, &erroroffset
, NULL
))) {
312 Error("regexgline", ERR_WARNING
, "Error compiling expression %s at offset %d: %s", mask
, erroroffset
, error
);
315 hint
= pcre_study(regex
, 0, &error
);
317 Error("regexgline", ERR_WARNING
, "Error studying expression %s: %s", mask
, error
);
324 for(j
=0;j
<NICKHASHSIZE
;j
++) {
325 for(np
=nicktable
[j
];np
;np
=np
->next
) {
326 hostlen
= RGBuildMatchHostname(hostname
, np
);
327 if(pcre_exec(regex
, hint
, hostname
, hostlen
, 0, 0, NULL
, 0) >= 0) {
337 if(*count
>= rg_max_casualties
)
343 int rg_delgline(void *source
, int cargc
, char **cargv
) {
344 nick
*np
= (nick
*)source
;
345 struct rg_struct
*rp
= rg_list
, *last
= NULL
;
349 controlreply(np
, "syntax: regexdelgline [mask]");
353 rg_logevent(np
, "regexdelgline", "%s", cargv
[0]);
355 if(RGMasksEqual(rp
->mask
->content
, cargv
[0])) {
357 rg_sqlquery("DELETE FROM regexglines WHERE id = %d", rp
->id
);
359 last
->next
= rp
->next
;
373 controlreply(np
, "Deleted (matched: %d).", count
);
374 controlnoticeopers("%s removed regexgline: %s (matches: %d)", np
->nick
, cargv
[0], count
);
376 controlreply(np
, "No glines matched: %s", cargv
[0]);
381 int rg_idlist(void *source
, int cargc
, char **cargv
) {
382 nick
*np
= (nick
*)source
;
385 controlreply(np
, "syntax: regexidlookup [gline id]");
387 } else if (strlen(cargv
[0]) != 8) {
388 controlreply(np
, "Invalid gline id!");
391 struct rg_struct
*rp
;
392 unsigned long id
= 0;
396 if(0xff == rc_hexlookup
[(int)cargv
[0][i
]]) {
397 controlreply(np
, "Invalid gline id!");
400 id
= (id
<< 4) | rc_hexlookup
[(int)cargv
[0][i
]];
404 controlreply(np
, "Mask Expires Set by Type Reason");
405 for(rp
=rg_list
;rp
;rp
=rp
->next
)
406 if(id
== rp
->glineid
)
407 rg_displaygline(np
, rp
);
408 controlreply(np
, "Done.");
414 int rg_glist(void *source
, int cargc
, char **cargv
) {
415 nick
*np
= (nick
*)source
;
416 struct rg_struct
*rp
;
424 if(!(regex
= pcre_compile(cargv
[0], RG_PCREFLAGS
, &error
, &erroroffset
, NULL
))) {
425 controlreply(np
, "Error compiling expression %s at offset %d: %s", cargv
[0], erroroffset
, error
);
428 hint
= pcre_study(regex
, 0, &error
);
430 controlreply(np
, "Error studying expression %s: %s", cargv
[0], error
);
436 rg_logevent(np
, "regexglist", "%s", cargv
[0]);
437 controlreply(np
, "Mask Expires Set by Type Reason");
438 for(rp
=rg_list
;rp
;rp
=rp
->next
)
439 if(pcre_exec(regex
, hint
, rp
->mask
->content
, rp
->mask
->length
, 0, 0, NULL
, 0) >= 0)
440 rg_displaygline(np
, rp
);
447 rg_logevent(np
, "regexglist", "");
448 controlreply(np
, "Mask Expires Set by Type Reason");
449 for(rp
=rg_list
;rp
;rp
=rp
->next
)
450 rg_displaygline(np
, rp
);
453 controlreply(np
, "Done.");
457 void rg_displaygline(nick
*np
, struct rg_struct
*rp
) { /* could be a macro? I'll assume the C compiler inlines it */
458 controlreply(np
, "%-25s %-20s %-15s %-4d %s", rp
->mask
->content
, longtoduration(rp
->expires
- time(NULL
), 0), rp
->setby
->content
, rp
->type
, rp
->reason
->content
);
461 int rg_spew(void *source
, int cargc
, char **cargv
) {
462 nick
*np
= (nick
*)source
, *tnp
;
463 int counter
= 0, erroroffset
, hostlen
, j
;
467 char hostname
[RG_MASKLEN
];
470 controlreply(np
, "syntax: regexspew [mask]");
474 if(!(regex
= pcre_compile(cargv
[0], RG_PCREFLAGS
, &error
, &erroroffset
, NULL
))) {
475 controlreply(np
, "Error compiling expression %s at offset %d: %s", cargv
[0], erroroffset
, error
);
478 hint
= pcre_study(regex
, 0, &error
);
480 controlreply(np
, "Error studying expression %s: %s", cargv
[0], error
);
486 rg_logevent(np
, "regexspew", "%s", cargv
[0]);
488 for(j
=0;j
<NICKHASHSIZE
;j
++) {
489 for(tnp
=nicktable
[j
];tnp
;tnp
=tnp
->next
) {
490 hostlen
= RGBuildHostname(hostname
, tnp
);
491 if(pcre_exec(regex
, hint
, hostname
, hostlen
, 0, 0, NULL
, 0) >= 0) {
492 if(counter
== rg_max_spew
) {
493 controlreply(np
, "Reached maximum spew count (%d) - aborting display.", rg_max_spew
);
494 } else if (counter
< rg_max_spew
) {
495 controlreply(np
, "%s=(%s) (%s)", hostname
, IPtostr(tnp
->ipaddress
), tnp
->realname
->name
->content
);
501 controlreply(np
, "Done - %d matches.", counter
);
510 int rg_sqlconnect(char *dbhost
, char *dbuser
, char *dbpass
, char *db
, unsigned int port
) {
512 if(!mysql_real_connect(&rg_sql
, dbhost
, dbuser
, dbpass
, db
, port
, NULL
, 0))
517 void rg_sqldisconnect(void) {
518 mysql_close(&rg_sql
);
521 void rg_sqlescape_string(char *dest
, char *source
, size_t length
) {
522 if(length
>= RG_QUERY_BUF_SIZE
)
523 length
= RG_QUERY_BUF_SIZE
- 1;
525 mysql_escape_string(dest
, source
, length
);
528 int rg_sqlquery(char *format
, ...) {
529 char rg_sqlquery
[RG_QUERY_BUF_SIZE
];
532 va_start(va
, format
);
533 vsnprintf(rg_sqlquery
, sizeof(rg_sqlquery
), format
, va
);
536 return mysql_query(&rg_sql
, rg_sqlquery
);
539 rg_sqlresult
rg_sqlstoreresult(void) {
540 return mysql_store_result(&rg_sql
);
543 rg_sqlrow
rg_sqlgetrow(rg_sqlresult res
) {
544 return mysql_fetch_row(res
);
547 void rg_sqlfree(rg_sqlresult res
) {
548 mysql_free_result(res
);
551 void rg_startup(void) {
554 struct rg_struct
*rp
;
555 struct rg_glinelist gll
;
556 char hostname
[RG_MASKLEN
];
558 rg_initglinelist(&gll
);
560 for(j
=0;j
<NICKHASHSIZE
;j
++) {
561 for(np
=nicktable
[j
];np
;np
=np
->next
) {
562 hostlen
= RGBuildMatchHostname(hostname
, np
);
563 for(rp
=rg_list
;rp
;rp
=rp
->next
) {
564 if(pcre_exec(rp
->regex
, rp
->hint
, hostname
, hostlen
, 0, 0, NULL
, 0) >= 0) {
565 rg_dogline(&gll
, np
, rp
, hostname
);
572 rg_flushglines(&gll
);
575 void rg_freestruct(struct rg_struct
*rp
) {
576 freesstring(rp
->mask
);
577 freesstring(rp
->setby
);
578 freesstring(rp
->reason
);
579 pcre_free(rp
->regex
);
585 struct rg_struct
*rg_newstruct(time_t expires
) {
586 struct rg_struct
*rp
;
588 if (time(NULL
) >= expires
)
591 rp
= (struct rg_struct
*)malloc(sizeof(struct rg_struct
));
593 struct rg_struct
*tp
, *lp
;
598 rp
->expires
= expires
;
603 for(lp
=NULL
,tp
=rg_list
;tp
;lp
=tp
,tp
=tp
->next
) {
604 if (expires
<= tp
->expires
) { /* <= possible, slight speed increase */
627 struct rg_struct
*rg_newsstruct(char *id
, char *mask
, char *setby
, char *reason
, char *expires
, char *type
, time_t iexpires
, int iid
) {
628 struct rg_struct
*newrow
, *lp
, *cp
;
630 char glineiddata
[1024];
632 if(!protectedatoi(expires
, &rexpires
))
638 newrow
= rg_newstruct(rexpires
);
644 if(!(newrow
->regex
= pcre_compile(mask
, RG_PCREFLAGS
, &error
, &erroroffset
, NULL
))) {
645 Error("regexgline", ERR_WARNING
, "Error compiling expression %s at offset %d: %s", mask
, erroroffset
, error
);
648 newrow
->hint
= pcre_study(newrow
->regex
, 0, &error
);
650 Error("regexgline", ERR_WARNING
, "Error studying expression %s: %s", mask
, error
);
651 pcre_free(newrow
->regex
);
657 if(!protectedatoi(id
, &newrow
->id
))
663 newrow
->mask
= getsstring(mask
, RG_REGEXGLINE_MAX
);
665 Error("regexgline", ERR_WARNING
, "Error allocating memory for mask!");
669 newrow
->setby
= getsstring(setby
, ACCOUNTLEN
);
671 Error("regexgline", ERR_WARNING
, "Error allocating memory for setby!");
675 newrow
->reason
= getsstring(reason
, RG_REASON_MAX
);
676 if(!newrow
->reason
) {
677 Error("regexgline", ERR_WARNING
, "Error allocating memory for reason!");
681 if(!protectedatoi(type
, &newrow
->type
))
682 newrow
->type
= 0; /* just in case */
684 snprintf(glineiddata
, sizeof(glineiddata
), "%s regexgline %s %s %s %d %d", mynumeric
->content
, mask
, setby
, reason
, iexpires
, newrow
->type
);
685 newrow
->glineid
= crc32(glineiddata
);
692 freesstring(newrow
->mask
);
694 freesstring(newrow
->setby
);
696 freesstring(newrow
->reason
);
697 pcre_free(newrow
->regex
);
699 pcre_free(newrow
->hint
);
702 for(lp
=NULL
,cp
=rg_list
;cp
;lp
=cp
,cp
=cp
->next
) {
716 void rg_dogline(struct rg_glinelist
*gll
, nick
*np
, struct rg_struct
*rp
, char *matched
) { /* PPA: if multiple users match the same user@host or *@host it'll send multiple glines?! */
717 char hostname
[RG_MASKLEN
];
720 rg_loggline(rp
, matched
);
725 for(usercount
=0,tnp
=np
->host
->nicks
;tnp
;tnp
=tnp
->nextbyhost
)
726 if(!ircd_strcmp(np
->ident
, tnp
->ident
))
729 snprintf(hostname
, sizeof(hostname
), "%s@%s", np
->ident
, IPtostr(np
->ipaddress
));
730 } else if (rp
->type
== 2) {
731 usercount
= np
->host
->clonecount
;
732 snprintf(hostname
, sizeof(hostname
), "*@%s", IPtostr(np
->ipaddress
));
733 } else if (rp
->type
== 3) {
734 struct rg_glinenode
*nn
= (struct rg_glinenode
*)malloc(sizeof(struct rg_glinenode
));
750 if (usercount
> rg_max_per_gline
) { /* too many users on this host, so we're ignoring it */
751 /* controlchanmsg(findchannel("#twilightzone"), "Looks like I'm ignoring another Nomad gline: GL * +%s %d :%s due to %d clones\r\n", hostname, time(NULL) + rg_expiry_time, rp->reason->content, usercount); */
755 irc_send("%s GL * +%s %d :%s (ID: %08lx)\r\n", mynumeric
->content
, hostname
, rg_expiry_time
, rp
->reason
->content
, rp
->glineid
);
758 void rg_logevent(nick
*np
, char *event
, char *details
, ...) {
759 char eeevent
[RG_QUERY_BUF_SIZE
], eedetails
[RG_QUERY_BUF_SIZE
], eemask
[RG_QUERY_BUF_SIZE
], eeaccount
[RG_QUERY_BUF_SIZE
];
760 char buf
[513], account
[ACCOUNTLEN
+ 1], mask
[RG_MASKLEN
];
765 va_start(va
, details
);
766 vsnprintf(buf
, sizeof(buf
), details
, va
);
771 strncpy(account
, np
->authname
, sizeof(account
) - 1);
772 account
[sizeof(account
) - 1] = '\0';
776 masklen
= RGBuildMatchHostname(mask
, np
);
782 rg_sqlescape_string(eeevent
, event
, strlen(event
));
783 rg_sqlescape_string(eedetails
, buf
, strlen(buf
));
784 rg_sqlescape_string(eeaccount
, event
, strlen(account
));
785 rg_sqlescape_string(eemask
, mask
, masklen
);
787 rg_sqlquery("INSERT INTO regexlogs (host, account, event, arg) VALUES ('%s', '%s', '%s', '%s')", eemask
, eeaccount
, eeevent
, eedetails
);
790 void rg_loggline(struct rg_struct
*rg
, char *matched
) {
791 char eematched
[RG_QUERY_BUF_SIZE
];
793 rg_sqlescape_string(eematched
, matched
, strlen(matched
));
795 rg_sqlquery("INSERT INTO regexglinelog (glineid, matched) VALUES (%d, '%s')", rg
->id
, eematched
);