python update, 1 of 2
greg andruk
meowing at banet.net
Thu Sep 23 03:41:32 UTC 1999
python filter updates for the innd directory. Doc and sample changes to
follow.
Summary of changes:
- malloc, strlen, copies eliminated where practical.
- Method/function lookups are expensive so we cache them at load time.
Interned key strings speed up building the header dictionary.
- All headers now go into the dictionary and missing ones get assigned None,
so that filters can use a cheap 'is not None' instead of has_key().
- C function names and calls tweaked a bit to be more consistent with what
the perl thingy is currently doing. Message ID and article filters now
get measured by the timer.
- The filter_before_reload() method is there now, for real. Also added a
filter_close() method which runs on ctlinnd shutdown.
=-=-=-=-=
diff -cr ../dist/innd/art.c ./innd/art.c
*** ../dist/innd/art.c Sat Sep 18 03:20:47 1999
--- ./innd/art.c Wed Sep 22 23:15:00 1999
***************
*** 145,156 ****
ARTHEADER *ARTheadersENDOF = ENDOF(ARTheaders);
! #if defined(DO_PERL)
const char *filterPath;
! #endif /* DO_PERL */
! #if defined(DO_PYTHON)
! const char *pathForPython;
! #endif /* DO_PYTHON */
--- 145,153 ----
ARTHEADER *ARTheadersENDOF = ENDOF(ARTheaders);
! #if defined(DO_PERL) || defined(DO_PYTHON)
const char *filterPath;
! #endif /* DO_PERL || DO_PYTHON */
***************
*** 2005,2015 ****
}
}
#if defined(DO_PYTHON)
! pathForPython = HeaderFindMem(article->Data, article->Used, "Path", 4) ;
! /* TMRstart(TMR_PYTHON); */
! filterrc = (char *)PYHandleArticle(Data.Body, Data.LinesValue);
! /* TMRstop(TMR_PYTHON); */
if (filterrc != NULL) {
(void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, filterrc);
syslog(L_NOTICE, "rejecting[python] %s %s", Data.MessageID, buff);
--- 2002,2017 ----
}
}
+ #if defined(DO_PERL) || defined(DO_PYTHON)
+ filterPath = HeaderFindMem(article->Data, article->Used, "Path", 4) ;
+ #endif /* DO_PERL || DO_PYHTON */
+
#if defined(DO_PYTHON)
! TMRstart(TMR_PYTHON);
! filterrc = PYartfilter(Data.Body,
! &article->Data[article->Used] - Data.Body,
! Data.LinesValue);
! TMRstop(TMR_PYTHON);
if (filterrc != NULL) {
(void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, filterrc);
syslog(L_NOTICE, "rejecting[python] %s %s", Data.MessageID, buff);
***************
*** 2026,2032 ****
/* I suppose some masochist will run with Python and Perl in together */
#if defined(DO_PERL)
- filterPath = HeaderFindMem(article->Data, article->Used, "Path", 4) ;
TMRstart(TMR_PERL);
filterrc = PLartfilter(Data.Body, Data.LinesValue);
TMRstop(TMR_PERL);
--- 2028,2033 ----
diff -cr ../dist/innd/cc.c ./innd/cc.c
*** ../dist/innd/cc.c Sat Sep 18 03:20:47 1999
--- ./innd/cc.c Sat Sep 18 16:29:14 1999
***************
*** 678,684 ****
char *av[];
{
char *p;
! extern int PythonFilterActive;
switch (av[0][0]) {
default:
--- 678,684 ----
char *av[];
{
char *p;
! extern BOOL PythonFilterActive;
switch (av[0][0]) {
default:
***************
*** 777,783 ****
PLmode(Mode, OMrunning, p);
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! PythonMode(Mode, OMrunning, p);
#endif /* defined(DO_PYTHON) */
DISPOSE(ModeReason);
--- 777,783 ----
PLmode(Mode, OMrunning, p);
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! PYmode(Mode, OMrunning, p);
#endif /* defined(DO_PYTHON) */
DISPOSE(ModeReason);
***************
*** 858,864 ****
extern int PerlFilterActive;
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! extern int PythonFilterActive;
#endif /* defined(DO_PYTHON) */
/* nb: We assume here that BUFSIZ is >= 512, and that none of
--- 858,864 ----
extern int PerlFilterActive;
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! extern BOOL PythonFilterActive;
#endif /* defined(DO_PYTHON) */
/* nb: We assume here that BUFSIZ is >= 512, and that none of
***************
*** 1259,1265 ****
PLmode(Mode, NewMode, reason);
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! PythonMode(Mode, NewMode, reason);
#endif /* defined(DO_PYTHON) */
ICDwrite();
--- 1259,1265 ----
PLmode(Mode, NewMode, reason);
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! PYmode(Mode, NewMode, reason);
#endif /* defined(DO_PYTHON) */
ICDwrite();
diff -cr ../dist/innd/innd.c ./innd/innd.c
*** ../dist/innd/innd.c Sat Sep 18 03:20:48 1999
--- ./innd/innd.c Sat Sep 18 16:30:19 1999
***************
*** 923,929 ****
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! PYSetup();
#endif /* (DO_PYTHON) */
/* And away we go... */
--- 923,929 ----
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! PYsetup();
#endif /* (DO_PYTHON) */
/* And away we go... */
diff -cr ../dist/innd/innd.h ./innd/innd.h
*** ../dist/innd/innd.h Sat Sep 18 03:20:48 1999
--- ./innd/innd.h Sun Sep 19 01:48:58 1999
***************
*** 367,373 ****
typedef enum {TMR_IDLE, TMR_ARTWRITE, TMR_ARTLINK, TMR_HISWRITE,
TMR_HISSYNC, TMR_SITESEND, TMR_ARTCTRL, TMR_ARTCNCL,
! TMR_HISHAVE, TMR_HISGREP, TMR_PERL, TMR_OVERV, TMR_MAX} TMRTYPE;
--- 367,374 ----
typedef enum {TMR_IDLE, TMR_ARTWRITE, TMR_ARTLINK, TMR_HISWRITE,
TMR_HISSYNC, TMR_SITESEND, TMR_ARTCTRL, TMR_ARTCNCL,
! TMR_HISHAVE, TMR_HISGREP, TMR_PERL, TMR_OVERV,
! TMR_PYTHON, TMR_MAX} TMRTYPE;
***************
*** 657,666 ****
/* Python functions */
extern void PYfilter(BOOL value);
! extern int PYReadFilter(void);
! extern char *PYHandleArticle(char *artBody, int lines);
! extern char *PYHandleMessageID(char *messageID);
! extern void PythonMode(OPERATINGMODE Mode, OPERATINGMODE newmode, char *reason);
! extern void PYSetup(void);
extern void PYclose(void);
# endif /* defined(DO_PYTHON) */
--- 658,668 ----
/* Python functions */
extern void PYfilter(BOOL value);
! extern int PYreadfilter(void);
! extern char *PYartfilter(char *artBody, long artLen, int lines);
! extern char *PYmidfilter(char *messageID, int msglen);
! extern void PYmode(OPERATINGMODE Mode, OPERATINGMODE newmode,
! char *reason);
! extern void PYsetup(void);
extern void PYclose(void);
# endif /* defined(DO_PYTHON) */
diff -cr ../dist/innd/nc.c ./innd/nc.c
*** ../dist/innd/nc.c Sat Sep 18 03:20:48 1999
--- ./innd/nc.c Tue Sep 21 23:04:46 1999
***************
*** 483,498 ****
#if defined(DO_PYTHON)
/* invoke a Python message filter on the message id */
! if ((filterrc = (char *)PYHandleMessageID(p)) != NULL) {
cp->Refused++;
! msglen = strlen(p) + 5; /* 3 digits + space + id + null */
if (cp->Sendid.Size < msglen) {
! if (cp->Sendid.Size > 0) DISPOSE(cp->Sendid.Data);
! if (msglen > MAXHEADERSIZE) cp->Sendid.Size = msglen;
! else cp->Sendid.Size = MAXHEADERSIZE;
cp->Sendid.Data = NEW(char, cp->Sendid.Size);
}
! (void)sprintf(cp->Sendid.Data, "%d %s", NNTP_HAVEIT_VAL, filterrc);
NCwritereply(cp, cp->Sendid.Data);
DISPOSE(cp->Sendid.Data);
cp->Sendid.Size = 0;
--- 483,505 ----
#if defined(DO_PYTHON)
/* invoke a Python message filter on the message id */
! msglen = strlen(p);
! TMRstart(TMR_PYTHON);
! filterrc = PYmidfilter(p, msglen);
! TMRstop(TMR_PYTHON);
! if (filterrc) {
cp->Refused++;
! msglen += 5; /* 3 digits + space + id + null */
if (cp->Sendid.Size < msglen) {
! if (cp->Sendid.Size > 0)
! DISPOSE(cp->Sendid.Data);
! if (msglen > MAXHEADERSIZE)
! cp->Sendid.Size = msglen;
! else
! cp->Sendid.Size = MAXHEADERSIZE;
cp->Sendid.Data = NEW(char, cp->Sendid.Size);
}
! sprintf(cp->Sendid.Data, "%d %s", NNTP_HAVEIT_VAL, filterrc);
NCwritereply(cp, cp->Sendid.Data);
DISPOSE(cp->Sendid.Data);
cp->Sendid.Size = 0;
***************
*** 1275,1281 ****
NCcheck(CHANNEL *cp)
{
char *p;
! int msglen;
#if defined(DO_PERL) || defined(DO_PYTHON)
char *filterrc;
#endif /* DO_PERL || DO_PYTHON */
--- 1282,1288 ----
NCcheck(CHANNEL *cp)
{
char *p;
! int idlen, msglen;
#if defined(DO_PERL) || defined(DO_PYTHON)
char *filterrc;
#endif /* DO_PERL || DO_PYTHON */
***************
*** 1286,1292 ****
continue;
for ( ; ISWHITE(*p); p++)
continue;
! msglen = strlen(p) + 5; /* 3 digits + space + id + null */
if (cp->Sendid.Size < msglen) {
if (cp->Sendid.Size > 0) DISPOSE(cp->Sendid.Data);
if (msglen > MAXHEADERSIZE) cp->Sendid.Size = msglen;
--- 1293,1300 ----
continue;
for ( ; ISWHITE(*p); p++)
continue;
! idlen = strlen(p);
! msglen = idlen + 5; /* 3 digits + space + id + null */
if (cp->Sendid.Size < msglen) {
if (cp->Sendid.Size > 0) DISPOSE(cp->Sendid.Data);
if (msglen > MAXHEADERSIZE) cp->Sendid.Size = msglen;
***************
*** 1320,1329 ****
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! /* invoke a perl message filter on the message id */
! if ((filterrc = (char *)PYHandleMessageID(p)) != NULL) {
cp->Refused++;
! (void)sprintf(cp->Sendid.Data, "%d %s", NNTP_ERR_GOTID_VAL, p);
NCwritereply(cp, cp->Sendid.Data);
return;
}
--- 1328,1338 ----
#endif /* defined(DO_PERL) */
#if defined(DO_PYTHON)
! /* invoke a python message filter on the message id */
! filterrc = PYmidfilter(p, idlen);
! if (filterrc) {
cp->Refused++;
! sprintf(cp->Sendid.Data, "%d %s", NNTP_ERR_GOTID_VAL, p);
NCwritereply(cp, cp->Sendid.Data);
return;
}
diff -cr ../dist/innd/python.c ./innd/python.c
*** ../dist/innd/python.c Sat Sep 18 03:20:48 1999
--- ./innd/python.c Wed Sep 22 22:34:20 1999
***************
*** 1,12 ****
! /*
! * $Id: python.c,v 1.1 1999/05/20 09:22:51 kondou Exp $
! *
! * python.c: Embed Python in the style of innd's TCL and Perl stuff.
! *
! * Written by G.J. Andruk <meowing at banet.net> patterned after TCL/Perl
! * work by Bob Heiney and Christophe Wolfhugel. Meow.
! */
!
#include <stdio.h>
#include <sys/types.h>
--- 1,16 ----
! /*
! ** $Id: python.c,v 1.1 1999/05/20 09:22:51 kondou Exp $
! **
! ** python.c: Embed Python in the style of innd's TCL and Perl stuff.
! **
! ** Written by G.J. Andruk <meowing at banet.net> patterned after
! ** TCL/Perl work by Bob Heiney and Christophe Wolfhugel and a whole
! ** bunch of other people mentioned in the docs and sources for the
! ** other filters.
! **
! ** The astute reader may notice the commission of blatant atrocities
! ** against Python's OO model here. Don't tell Guido.
! */
#include <stdio.h>
#include <sys/types.h>
***************
*** 17,213 ****
#include "art.h"
#include "qio.h"
- #if defined(DO_PYTHON)
#include "Python.h"
! BOOL PythonFilterActive;
! ARTHEADER ARTheaders[], *ARTheadersENDOF;
! char *pathForPython;
! PyObject *PYFilterObject = NULL;
! PyObject *PYFilterModule = NULL;
! PyObject *PYResult;
! PyObject *PYheaditem[];
! STATIC char *PYSTARTUP = NULL;
! STATIC BUFFER PYpythonbuff;
! STATIC FILE *PYFilterFile;
void
PYfilter(value)
BOOL value;
{
! PythonFilterActive=value;
syslog(L_NOTICE, "%s Python filtering %s", LogName,
PythonFilterActive ? "enabled" : "disabled");
}
! /* Reject articles we don't like. */
char *
! PYHandleArticle(artBody, lines)
char* artBody;
! int lines;
{
ARTHEADER *hp;
int hdrnum;
int i;
char *p;
! static char buf[256];
! PyObject *PYheaders, *tryfunc, *result;
! if (!PythonFilterActive || PYFilterObject == NULL)
return NULL;
! /* Fill in the dictionary */
! PYheaders = PyDict_New(); /* Hmmm. Reuse instead of this business? */
hdrnum = 0;
for (hp = ARTheaders; hp < ARTheadersENDOF; hp++) {
! if (hp->Found && hp->Value && strcmp (hp->Name,"Path") != 0) {
! PYheaditem[hdrnum] = PyString_FromString(hp->Value);
! PyDict_SetItemString(PYheaders, (char *)hp->Name,
! PYheaditem[hdrnum++]);
! }
}
! /* Store article body */
if (artBody != NULL) {
! PYheaditem[hdrnum] = PyString_FromString(artBody);
! PyDict_SetItemString(PYheaders, "__BODY__", PYheaditem[hdrnum++]);
}
!
! /* Store article line count */
PYheaditem[hdrnum] = PyInt_FromLong((long) lines);
! PyDict_SetItemString(PYheaders, "__LINES__", PYheaditem[hdrnum++]);
! if (pathForPython != NULL) {
! char *p = strchr (pathForPython,'\n') ;
!
! *p = '\0' ;
! PYheaditem[hdrnum] = PyString_FromString(pathForPython);
! PyDict_SetItemString(PYheaders, "Path", PYheaditem[hdrnum++]);
! *p = '\n' ;
! }
!
! /*
! * Checking exists/callable for every article may be a little too
! * paranoid. Perhaps better done at load/reload time?
! */
! if ((tryfunc = PyObject_GetAttrString(PYFilterObject,
! "filter_art")) != NULL) {
! if (PyCallable_Check(tryfunc) == 1) {
! if ((result = PyObject_CallFunction(tryfunc,
! "O", PYheaders)) != NULL) {
! if (PyObject_IsTrue(result)) {
! strncpy(buf, PyString_AsString(result), sizeof(buf) - 1);
! Py_DECREF(result);
! } else {
! buf[0] = '\0';
! }
! } else {
! buf[0] = '\0';
! }
! }
! Py_DECREF(tryfunc);
! }
PyDict_Clear(PYheaders);
- Py_DECREF(PYheaders);
for (i = 0; i < hdrnum; i++)
! Py_DECREF(PYheaditem[i]);
! if (buf[0] != '\0')
! return buf ;
return NULL;
}
! /* Refuse articles offered thru CHECK or IHAVE that we don't like. */
char *
! PYHandleMessageID(messageID)
char *messageID;
{
static char buf[256];
! PyObject *tryfunc, *result;
! if (!PythonFilterActive || PYFilterObject == NULL)
return NULL;
! if ((tryfunc = PyObject_GetAttrString(PYFilterObject,
! "filter_messageid")) != NULL) {
! if (PyCallable_Check(tryfunc) == 1) {
! if ((result = PyObject_CallFunction(tryfunc,
! "s", messageID)) != NULL) {
! if (PyObject_IsTrue(result)) {
! strncpy(buf, PyString_AsString(result), sizeof(buf) - 1);
! } else {
! buf[0] = '\0';
! }
! Py_DECREF(result);
! } else {
! buf[0] = '\0';
! }
! }
! Py_DECREF(tryfunc);
! }
! if (buf[0] != '\0')
return buf;
return NULL;
}
! /* Tell the external module about our state. */
void
! PythonMode(Mode, NewMode, reason)
OPERATINGMODE Mode, NewMode;
char *reason;
{
! PyObject *tryfunc, *filtermode, *result;
char oldmode[10], newmode[10];
! if (!PythonFilterActive || PYFilterObject == NULL)
return;
! if (Mode == OMrunning)
! strcpy(oldmode, "running");
! if (Mode == OMpaused)
! strcpy(oldmode, "paused");
! if (Mode == OMthrottled)
! strcpy(oldmode, "throttled");
!
! if (NewMode == OMrunning)
! strcpy(newmode, "running");
! if (NewMode == OMpaused)
! strcpy(newmode, "paused");
! if (NewMode == OMthrottled)
! strcpy(newmode, "throttled");
!
! if ((tryfunc = PyObject_GetAttrString(PYFilterObject,
! "filter_mode")) != NULL) {
! if (PyCallable_Check(tryfunc) == 1) {
! result = PyObject_CallFunction(tryfunc, "sss",
! oldmode, newmode, reason);
! Py_DECREF(result);
! }
! Py_DECREF(tryfunc);
! }
}
! /* Called by the external module so it can register itself with INN. */
static PyObject *
PY_set_filter_hook(dummy, args)
PyObject *dummy, *args;
! {
! PyObject *result = NULL;
! PyObject *temp;
if (PyArg_ParseTuple(args, "O:set_filter_hook", &temp)) {
Py_XINCREF(temp);
--- 21,212 ----
#include "art.h"
#include "qio.h"
+ #if defined(DO_PYTHON)
#include "Python.h"
! BOOL PythonFilterActive;
! char *filterPath; /* this gets set in art.c */
! PyObject *PYFilterObject = NULL;
! PyObject *PYFilterModule = NULL;
!
! /* article filter bits and pieces */
! ARTHEADER ARTheaders[], *ARTheadersENDOF;
! PyObject *PYheaders = NULL;
! PyObject **PYheaditem;
! PyObject **PYheadkey;
! PyObject *PYpathkey, *PYlineskey, *PYbodykey;
!
! /* external functions */
! PyObject *msgid_method = NULL;
! PyObject *art_method = NULL;
! PyObject *mode_method = NULL;
! PyObject *pre_reload_method = NULL;
! PyObject *close_method = NULL;
+ /*
+ ** Turn filtering on or off.
+ */
void
PYfilter(value)
BOOL value;
{
! PythonFilterActive = value;
syslog(L_NOTICE, "%s Python filtering %s", LogName,
PythonFilterActive ? "enabled" : "disabled");
}
! /*
! ** Reject articles we don't like.
! */
char *
! PYartfilter(artBody, artLen, lines)
char* artBody;
! long artLen;
! int lines;
{
ARTHEADER *hp;
int hdrnum;
int i;
char *p;
! static char buf[256];
! PyObject *result;
! if (!PythonFilterActive || PYFilterObject == NULL || art_method == NULL)
return NULL;
! /* Add headers to the dictionary... */
hdrnum = 0;
for (hp = ARTheaders; hp < ARTheadersENDOF; hp++) {
! if (hp->Found && hp->Value && !EQ(hp->Name,"Path"))
! PYheaditem[hdrnum] = PyBuffer_FromMemory(hp->Value, hp->Length);
! else
! PYheaditem[hdrnum] = Py_None;
! PyDict_SetItem(PYheaders, PYheadkey[hdrnum], PYheaditem[hdrnum]);
! hdrnum++;
! }
!
! /* ...then the path, done separately to get the info innd adds... */
! if (filterPath != NULL) {
! p = strchr(filterPath,'\n');
! if (p)
! *p = '\0';
! PYheaditem[hdrnum] = PyBuffer_FromMemory(filterPath,
! strlen(filterPath));
! PyDict_SetItem(PYheaders, PYpathkey, PYheaditem[hdrnum++]);
! if (p)
! *p = '\n';
}
! /* ...then the body... */
if (artBody != NULL) {
! PYheaditem[hdrnum] = PyBuffer_FromMemory(artBody, artLen);
! PyDict_SetItem(PYheaders, PYbodykey, PYheaditem[hdrnum++]);
}
! /* ...and finally, the line count. */
PYheaditem[hdrnum] = PyInt_FromLong((long) lines);
! PyDict_SetItem(PYheaders, PYlineskey, PYheaditem[hdrnum++]);
+ /* Now see if the filter likes it. */
+ result = PyObject_CallFunction(art_method, "O", PYheaders);
+ if ((result != NULL) && PyObject_IsTrue(result))
+ strncpy(buf, PyString_AS_STRING(result), sizeof(buf) - 1);
+ else
+ *buf = '\0';
+ Py_XDECREF(result);
! /* Clean up after ourselves */
PyDict_Clear(PYheaders);
for (i = 0; i < hdrnum; i++)
! if (PYheaditem[i] != Py_None)
! Py_DECREF(PYheaditem[i]);
! if (*buf != '\0')
! return buf;
return NULL;
}
!
! /*
! ** Refuse message IDs offered thru CHECK or IHAVE that we don't like.
! */
char *
! PYmidfilter(messageID, msglen)
char *messageID;
+ int msglen;
{
static char buf[256];
! PyObject *result;
! if (!PythonFilterActive || PYFilterObject == NULL || msgid_method == NULL)
return NULL;
! result = PyObject_CallFunction(msgid_method, "s#", messageID, msglen);
! if ((result != NULL) && PyObject_IsTrue(result))
! strncpy(buf, PyString_AS_STRING(result), sizeof(buf) - 1);
! else
! *buf = '\0';
! Py_XDECREF(result);
!
! if (*buf != '\0')
return buf;
return NULL;
}
! /*
! ** Tell the external module about innd's state.
! */
void
! PYmode(Mode, NewMode, reason)
OPERATINGMODE Mode, NewMode;
char *reason;
{
! PyObject *result;
char oldmode[10], newmode[10];
! if (!PythonFilterActive || PYFilterObject == NULL || mode_method == NULL)
return;
! switch (Mode) {
! default: strcpy(oldmode, "unknown"); break;
! case OMrunning: strcpy(oldmode, "running"); break;
! case OMpaused: strcpy(oldmode, "paused"); break;
! case OMthrottled: strcpy(oldmode, "throttled"); break;
! }
!
! switch (NewMode) {
! default: strcpy(newmode, "unknown"); break;
! case OMrunning: strcpy(newmode, "running"); break;
! case OMpaused: strcpy(newmode, "paused"); break;
! case OMthrottled: strcpy(newmode, "throttled"); break;
! }
!
! result = PyObject_CallFunction(mode_method, "sss",
! oldmode, newmode, reason);
! Py_DECREF(result);
}
! /*
! ** Called by the external module so it can register itself with innd.
! */
static PyObject *
PY_set_filter_hook(dummy, args)
PyObject *dummy, *args;
! {
! PyObject *result = NULL;
! PyObject *temp;
if (PyArg_ParseTuple(args, "O:set_filter_hook", &temp)) {
Py_XINCREF(temp);
***************
*** 221,477 ****
! /* Allows external module to query innd if an ID is in history. */
static PyObject *
PY_havehist(self, args)
PyObject *self, *args;
{
! char *msgid;
! if (!PyArg_ParseTuple(args, "s", &msgid))
return NULL;
! if (HIShavearticle(HashMessageID(msgid))) {
! return Py_BuildValue("i", 1);
! } else {
! return Py_BuildValue("i", 0);
! }
}
! /* External module can locally delete an article. */
static PyObject *
PY_cancel(self, args)
PyObject *self, *args;
{
char *msgid;
char *parambuf[2];
! if (!PyArg_ParseTuple(args, "s", &msgid))
return NULL;
parambuf[0]= msgid;
parambuf[1]= 0;
! if (!CCcancel(parambuf)) {
! return Py_BuildValue("i", 1);
! } else {
! return Py_BuildValue("i", 0);
! }
}
! /* Stuff an ID into history so that it will be refused later. */
static PyObject *
PY_addhist(self, args)
PyObject *self, *args;
{
! char* msgid;
! char* arrivaltime;
! char* articletime;
! char* expiretime;
! char* articlepaths = "";
char tbuff[12];
! char* parambuf[6];
!
! if (!PyArg_ParseTuple(args, "s", &msgid))
return NULL;
sprintf(tbuff, "%d",time((long *)0));
- arrivaltime = articletime = expiretime = tbuff;
parambuf[0] = msgid;
! parambuf[1] = arrivaltime;
! parambuf[2] = articletime;
! parambuf[3] = expiretime;
parambuf[4] = articlepaths;
parambuf[5] = 0;
! if (!CCaddhist(parambuf)) {
! return Py_BuildValue("i", 1);
! } else {
! return Py_BuildValue("i", 0);
! }
}
! /* Get a newsgroup's status flag (m, y, x, etc.) */
static PyObject *
PY_newsgroup(self, args)
PyObject *self, *args;
{
! char* newsgroup;
! NEWSGROUP* ngp;
! char* end;
! char* rest;
int size;
! if (!PyArg_ParseTuple(args, "s", &newsgroup))
return NULL;
! if ((ngp = NGfind(newsgroup)) == NULL) {
! return Py_BuildValue("s", "");
! } else {
! /* ngp->Rest is newline-terminated; find the end. */
! end = strchr(ngp->Rest, '\n');
! if (end == NULL) {
! size = strlen(ngp->Rest);
! } else {
! size = end - ngp->Rest;
! }
!
! if (PYpythonbuff.Data == NULL) {
! PYpythonbuff.Size = SITE_BUFFER_SIZE;
! PYpythonbuff.Data = NEW(char, PYpythonbuff.Size);
! }
!
! /* SITE_BUFFER_SIZE should be *huge* for this, but be paranoid. */
! if (size > SITE_BUFFER_SIZE + 1)
! size = SITE_BUFFER_SIZE;
!
! strncpy(PYpythonbuff.Data, ngp->Rest, size);
! PYpythonbuff.Data[size] = '\0';
! return Py_BuildValue("s", PYpythonbuff.Data);
}
}
! /* Return an article header to the external module as a string */
static PyObject *
PY_head(self, args)
PyObject *self, *args;
{
char *msgid;
char *p;
char *q;
char *bufptr;
QIOSTATE *qp;
!
! if (!PyArg_ParseTuple(args, "s", &msgid))
return NULL;
! /* Get the article filenames; open the first file */
! if ((q = HISfilesfor(HashMessageID(msgid))) == NULL) {
return Py_BuildValue("s", "");
- }
- if ((p = strchr(q, ' ')))
- *p = '\0';
! if ((qp = QIOopen(q)) == NULL) {
! return Py_BuildValue("s", "");
! }
! if (PYpythonbuff.Data == NULL) {
! PYpythonbuff.Size = SITE_BUFFER_SIZE;
! PYpythonbuff.Data = NEW(char, PYpythonbuff.Size);
! }
!
! strcpy(PYpythonbuff.Data, "");
for (p = QIOread(qp); (p != NULL) && (*p != '\0'); p = QIOread(qp)) {
! if (PYpythonbuff.Size < (qp->Count + 3)) {
! PYpythonbuff.Size += SITE_BUFFER_SIZE;
! RENEW(PYpythonbuff.Data, char, PYpythonbuff.Size);
! }
! strncat(PYpythonbuff.Data, p, QIOlength(qp));
! strncat(PYpythonbuff.Data, "\n", 1);
}
- QIOclose(qp);
! return Py_BuildValue("s", PYpythonbuff.Data);
}
! /* Return a whole article to the external module as a string */
static PyObject *
PY_article(self, args)
PyObject *self, *args;
{
char *msgid;
char *p;
char *q;
char *bufptr;
QIOSTATE *qp;
!
! if (!PyArg_ParseTuple(args, "s", &msgid))
return NULL;
/* Get the article filenames; open the first file */
! if ((q = HISfilesfor(HashMessageID(msgid))) == NULL) {
! return Py_BuildValue("s", "");
! }
if (p = strchr(q, ' '))
*p = '\0';
! if ((qp = QIOopen(q)) == NULL) {
! return Py_BuildValue("s", "");
! }
!
! if (PYpythonbuff.Data == NULL) {
! PYpythonbuff.Size = SITE_BUFFER_SIZE;
! PYpythonbuff.Data = NEW(char, PYpythonbuff.Size);
! }
!
! strcpy(PYpythonbuff.Data, "");
for (p = QIOread(qp); (p != NULL); p = QIOread(qp)) {
! if (PYpythonbuff.Size < (qp->Count + 3)) {
! PYpythonbuff.Size += SITE_BUFFER_SIZE;
! RENEW(PYpythonbuff.Data, char, PYpythonbuff.Size);
! }
! strncat(PYpythonbuff.Data, p, QIOlength(qp));
! strncat(PYpythonbuff.Data, "\n", 1);
}
QIOclose(qp);
! return Py_BuildValue("s", PYpythonbuff.Data);
}
- /*
- * Python's syslog module isn't compiled in by default, and it's in
- * an 'optional' bit of the path. Doing it this way is easier to
- * explain.
- */
static PyObject *
PY_syslog(self, args)
PyObject *self, *args;
{
char *loglevel;
char *logmsg;
int priority;
! if (!PyArg_ParseTuple(args, "ss", &loglevel, &logmsg))
return NULL;
switch (*loglevel) {
! default: priority = LOG_NOTICE ;
! case 'a': case 'A': priority = LOG_ALERT ; break;
! case 'c': case 'C': priority = LOG_CRIT ; break;
! case 'e': case 'E': priority = LOG_ERR ; break;
! case 'w': case 'W': priority = LOG_WARNING ; break;
! case 'n': case 'N': priority = LOG_NOTICE ; break;
! case 'i': case 'I': priority = LOG_INFO ; break;
! case 'd': case 'D': priority = LOG_DEBUG ; break;
}
syslog(priority, "python: %s", logmsg);
! return Py_BuildValue("i", 0);
}
! /* Make the Python methods visible to the outside world */
static PyMethodDef INNPyMethods[] = {
! {"set_filter_hook", PY_set_filter_hook, METH_VARARGS},
{"havehist", PY_havehist, METH_VARARGS},
{"addhist", PY_addhist, METH_VARARGS},
{"cancel", PY_cancel, METH_VARARGS},
--- 220,489 ----
! /*
! ** Allow external module to ask innd if an ID is in history.
! */
static PyObject *
PY_havehist(self, args)
PyObject *self, *args;
{
! char *msgid;
! int msgidlen;
! if (!PyArg_ParseTuple(args, "s#", &msgid, &msgidlen))
return NULL;
!
! if (HIShavearticle(HashMessageID(msgid)))
! return PyInt_FromLong(1);
! return PyInt_FromLong(0);
}
! /*
! ** Allow external module to locally delete an article.
! */
static PyObject *
PY_cancel(self, args)
PyObject *self, *args;
{
char *msgid;
+ int msgidlen;
char *parambuf[2];
! if (!PyArg_ParseTuple(args, "s#", &msgid, &msgidlen))
return NULL;
parambuf[0]= msgid;
parambuf[1]= 0;
! if (!CCcancel(parambuf))
! return PyInt_FromLong(1);
! return PyInt_FromLong(0);
}
! /*
! ** Stuff an ID into history so that it will be refused later.
! */
static PyObject *
PY_addhist(self, args)
PyObject *self, *args;
{
! char *msgid;
! int msgidlen;
! char *articlepaths = "";
char tbuff[12];
! char *parambuf[6];
! if (!PyArg_ParseTuple(args, "s#", &msgid, &msgidlen))
return NULL;
sprintf(tbuff, "%d",time((long *)0));
parambuf[0] = msgid;
! parambuf[1] = parambuf[2] = parambuf[3] = tbuff;
parambuf[4] = articlepaths;
parambuf[5] = 0;
! if (!CCaddhist(parambuf))
! return PyInt_FromLong(1);
! return PyInt_FromLong(0);
}
! /*
! ** Get a newsgroup's status flag (j, m, n, x, y, =other.group)
! */
static PyObject *
PY_newsgroup(self, args)
PyObject *self, *args;
{
! char *newsgroup;
! int nglen;
! NEWSGROUP *ngp;
! char *end;
! char *rest;
int size;
! if (!PyArg_ParseTuple(args, "s#", &newsgroup, &nglen))
return NULL;
! ngp = NGfind(newsgroup);
! if (ngp == NULL)
! return PyString_FromStringAndSize(NULL, 0);
!
! /* ngp->Rest is newline-terminated; find the end. */
! end = strchr(ngp->Rest, '\n');
! if (end == NULL)
! size = strlen(ngp->Rest);
! else
! size = end - ngp->Rest;
!
! /* If an alias is longer than this, active is probably broken. */
! if (size > MAXHEADERSIZE) {
! syslog(L_ERROR, "too-long flag field in active for %s", newsgroup);
! size = MAXHEADERSIZE;
}
+
+ return PyString_FromStringAndSize(ngp->Rest, size);
}
! /*
! ** Return an article header to the external module as a string. We
! ** don't use a buffer object here because that would make it harder,
! ** for example, to compare two on-spool articles.
! */
static PyObject *
PY_head(self, args)
PyObject *self, *args;
{
char *msgid;
+ int msgidlen;
char *p;
char *q;
char *bufptr;
QIOSTATE *qp;
+ PyObject *header;
+ int headerlen;
+ int bytesused = 0;
+ char *headertxt;
! if (!PyArg_ParseTuple(args, "s#", &msgid, &msgidlen))
return NULL;
! /* Get the article filenames/token; open the first */
! if ((q = HISfilesfor(HashMessageID(msgid))) == NULL)
return Py_BuildValue("s", "");
! if ((p = strchr(q, ' '))) /* probably obsolete in 2.3 */
! *p = '\0';
! if ((qp = QIOopen(q)) == NULL)
! return PyString_FromStringAndSize(NULL, 0);
! headerlen = START_BUFF_SIZE;
! header = PyString_FromStringAndSize(NULL, headerlen);
! headertxt = PyString_AS_STRING(header);
for (p = QIOread(qp); (p != NULL) && (*p != '\0'); p = QIOread(qp)) {
! if (headerlen < (bytesused + qp->Length + 1)) {
! headerlen += GROW_AMOUNT(headerlen);
! _PyString_Resize (&header, headerlen);
! headertxt = PyString_AS_STRING(header);
! }
! strncpy(&headertxt[bytesused], p, qp->Length);
! bytesused += qp->Length;
! headertxt[bytesused++] = '\n';
}
! QIOclose(qp);
! if (bytesused != headerlen)
! _PyString_Resize(&header, bytesused);
! return header;
}
! /*
! ** Return a whole article to the external module as a string.
! */
static PyObject *
PY_article(self, args)
PyObject *self, *args;
{
char *msgid;
+ int msgidlen;
char *p;
char *q;
char *bufptr;
QIOSTATE *qp;
+ PyObject *art;
+ int artlen;
+ int bytesused = 0;
+ char *arttxt;
! if (!PyArg_ParseTuple(args, "s#", &msgid, &msgidlen))
return NULL;
/* Get the article filenames; open the first file */
! if ((q = HISfilesfor(HashMessageID(msgid))) == NULL)
! return Py_BuildValue("s", "");
if (p = strchr(q, ' '))
*p = '\0';
+ if ((qp = QIOopen(q)) == NULL)
+ return PyString_FromStringAndSize(NULL, 0);
! artlen = START_BUFF_SIZE;
! art = PyString_FromStringAndSize(NULL, artlen);
! arttxt = PyString_AS_STRING(art);
for (p = QIOread(qp); (p != NULL); p = QIOread(qp)) {
! if (artlen < (bytesused + QIOlength(qp) + 1)) {
! artlen += GROW_AMOUNT(artlen);
! _PyString_Resize (&art, artlen);
! arttxt = PyString_AS_STRING(art);
! }
! strncpy(&arttxt[bytesused], p, QIOlength(qp));
! bytesused += QIOlength(qp);
! arttxt[bytesused++] = '\n';
}
QIOclose(qp);
! if (bytesused != artlen)
! _PyString_Resize(&art, bytesused);
!
! return art;
}
+ /*
+ ** Python's syslog module isn't compiled in by default. It's easier
+ ** to do it this way, and the switch block looks pretty in a color
+ ** editor).
+ */
static PyObject *
PY_syslog(self, args)
PyObject *self, *args;
{
char *loglevel;
+ int levellen;
char *logmsg;
+ int msglen;
int priority;
! if (!PyArg_ParseTuple(args, "s#s#",
! &loglevel, &levellen, &logmsg, &msglen))
return NULL;
switch (*loglevel) {
! default: priority = LOG_NOTICE ;
! case 'd': case 'D': priority = LOG_DEBUG ; break;
! case 'i': case 'I': priority = LOG_INFO ; break;
! case 'n': case 'N': priority = LOG_NOTICE ; break;
! case 'w': case 'W': priority = LOG_WARNING ; break;
! case 'e': case 'E': priority = LOG_ERR ; break;
! case 'c': case 'C': priority = LOG_CRIT ; break;
! case 'a': case 'A': priority = LOG_ALERT ; break;
}
+
syslog(priority, "python: %s", logmsg);
! Py_INCREF(Py_None);
! return Py_None;
}
! /*
! ** Make the internal INN module's functions visible to Python.
! */
static PyMethodDef INNPyMethods[] = {
! {"set_filter_hook", PY_set_filter_hook, METH_VARARGS},
{"havehist", PY_havehist, METH_VARARGS},
{"addhist", PY_addhist, METH_VARARGS},
{"cancel", PY_cancel, METH_VARARGS},
***************
*** 484,523 ****
! /* used by ctlinnd reload */
int
PYreadfilter(void)
{
- PyObject *tryfunc, *result;
PyObject *newmodule = NULL;
if (!Py_IsInitialized()) {
! syslog(L_ERROR, "Python is not initialized");
return 0;
}
if ((newmodule = PyImport_ReloadModule(PYFilterModule)) == NULL) {
! syslog(L_ERROR, "Could not reload the Python filter module");
! } else {
! Py_DECREF(PYFilterModule);
! PYFilterModule = newmodule;
}
if (PYFilterObject == NULL) {
! syslog(L_ERROR, "Python reload: filter object is not defined");
PYfilter(FALSE);
return 0;
}
-
PYfilter(TRUE);
return 1;
}
! /* Called when innd first starts */
void
! PYSetup(void)
{
! char *modulename;
setenv("PYTHONPATH", innconf->pathfilter, 1);
Py_Initialize();
--- 496,602 ----
! /*
! ** This runs when innd shuts down.
! */
! void
! PYclose(void)
! {
! PyObject *result;
!
! if (close_method != NULL) {
! result = PyObject_CallFunction(close_method, NULL);
! Py_XDECREF(result);
! }
! }
!
!
!
! /*
! ** Check that a method exists and is callable. Set a pointer to
! ** the corresponding PyObject, or NULL if not found.
! */
! void
! PYdefonemethod(methptr, methname)
! PyObject **methptr;
! char *methname;
! {
! Py_XDECREF(*methptr);
! *methptr = PyObject_GetAttrString(PYFilterObject, methname);
! if (*methptr == NULL)
! syslog(L_NOTICE, "python method %s not found", methname);
! else if (PyCallable_Check(*methptr) == 0) {
! syslog(L_ERROR, "python object %s found but not a function", methname);
! Py_DECREF(*methptr);
! *methptr = NULL;
! }
! }
!
!
!
! /*
! ** Look up the filter methods, so we will know what's available when
! ** innd wants to call them.
! */
! void
! PYdefmethods(void)
! {
! PYdefonemethod(&msgid_method, "filter_messageid");
! PYdefonemethod(&art_method, "filter_art");
! PYdefonemethod(&mode_method, "filter_mode");
! PYdefonemethod(&pre_reload_method, "filter_before_reload");
! PYdefonemethod(&close_method, "filter_close");
! }
!
!
!
! /*
! ** Used by `ctlinnd reload filter.python'
! */
int
PYreadfilter(void)
{
PyObject *newmodule = NULL;
+ PyObject *result;
if (!Py_IsInitialized()) {
! syslog(L_ERROR, "python is not initialized");
return 0;
}
+
+ /* If there is a filter running, let it clean up first. */
+ if (pre_reload_method != NULL) {
+ result = PyObject_CallFunction(pre_reload_method, NULL);
+ Py_XDECREF(result);
+ }
+
if ((newmodule = PyImport_ReloadModule(PYFilterModule)) == NULL) {
! syslog(L_ERROR, "cant reload python filter module");
! PYfilter(FALSE);
! return 0;
}
+ Py_DECREF(PYFilterModule);
+ PYFilterModule = newmodule;
if (PYFilterObject == NULL) {
! syslog(L_ERROR, "python reload error, filter object not defined");
PYfilter(FALSE);
return 0;
}
PYfilter(TRUE);
+ PYdefmethods();
return 1;
}
! /*
! ** Called when innd first starts -- this gets the filters hooked in.
! */
void
! PYsetup(void)
{
! ARTHEADER *hp;
! int hdrindex;
setenv("PYTHONPATH", innconf->pathfilter, 1);
Py_Initialize();
***************
*** 525,559 ****
/* It makes Python sad when its stdout and stderr are closed. */
if ((fileno(stdout) == -1) || (fileno(stderr) == -1))
PyRun_SimpleString
! ("import sys; sys.stdout = sys.stderr = open('/dev/null', 'a')");
! if (Py_IsInitialized ()) {
! syslog(L_NOTICE, "Python initialized OK");
! } else {
! syslog(L_ERROR, "Python is not initialized");
return;
}
(void) Py_InitModule("INN", INNPyMethods);
! strcpy(modulename, _PATH_PYTHON_STARTUP_M);
! PYFilterModule = PyImport_ImportModule(modulename);
! if (PYFilterModule == NULL) {
! syslog(L_ERROR, "Python module failed to load");
! }
if (PYFilterObject == NULL) {
! syslog(L_ERROR, "Python filter object is not defined");
PYfilter(FALSE);
} else {
PYfilter(TRUE);
}
- }
!
! /* Maybe some day I'll even make this do something. */
! void
! PYclose(void)
! {
}
!
! #endif /* (DO_PYTHON) */
--- 604,643 ----
/* It makes Python sad when its stdout and stderr are closed. */
if ((fileno(stdout) == -1) || (fileno(stderr) == -1))
PyRun_SimpleString
! ("import sys; sys.stdout=sys.stderr=open('/dev/null', 'a')");
! if (!Py_IsInitialized ()) {
! syslog(L_ERROR, "python interpreter NOT initialized");
return;
}
+ syslog(L_NOTICE, "python interpreter initialized OK");
+
(void) Py_InitModule("INN", INNPyMethods);
!
! PYFilterModule = PyImport_ImportModule(_PATH_PYTHON_STARTUP_M);
! if (PYFilterModule == NULL)
! syslog(L_ERROR, "failed to import external python module");
!
if (PYFilterObject == NULL) {
! syslog(L_ERROR, "python filter object is not defined");
PYfilter(FALSE);
} else {
PYfilter(TRUE);
+ PYdefmethods();
+ syslog(L_NOTICE, "defined python methods");
}
+ /* Grab space for these so we aren't forever recreating them. */
+ PYheaders = PyDict_New();
+ PYheaditem = NEW(PyObject *, ARTheadersENDOF - ARTheaders);
+ PYheadkey = NEW(PyObject *, ARTheadersENDOF - ARTheaders);
! /* Preallocate keys for the article dictionary */
! for (hp = ARTheaders; hp < ARTheadersENDOF; hp++)
! PYheadkey[hp - ARTheaders] = PyString_InternFromString(hp->Name);
! PYpathkey = PyString_InternFromString("Path");
! PYlineskey = PyString_InternFromString("__LINES__");
! PYbodykey = PyString_InternFromString("__BODY__");
}
! #endif /* defined(DO_PYTHON) */
diff -cr ../dist/innd/timer.c ./innd/timer.c
*** ../dist/innd/timer.c Sat Sep 18 03:20:48 1999
--- ./innd/timer.c Sun Sep 19 01:47:58 1999
***************
*** 105,110 ****
--- 105,111 ----
case TMR_HISGREP: str = "hisgrep"; break;
case TMR_OVERV: str = "overv"; break;
case TMR_PERL: str = "perl"; break;
+ case TMR_PYTHON: str = "python"; break;
}
sprintf(buf, "%s %d(%d) ", str, cumulative[i], count[i]);
cumulative[i] = count[i] = 0;
More information about the inn-patches
mailing list