INN commit: trunk (innd/python.c nnrpd/python.c)
INN Commit
Russ_Allbery at isc.org
Sun Jun 22 09:28:07 UTC 2008
Date: Sunday, June 22, 2008 @ 02:28:06
Author: iulius
Revision: 7888
Add more comments and prettify existing ones.
Fix a few typos.
Modified:
trunk/innd/python.c
trunk/nnrpd/python.c
----------------+
innd/python.c | 74 +++++++++----
nnrpd/python.c | 299 ++++++++++++++++++++++++++++++-------------------------
2 files changed, 219 insertions(+), 154 deletions(-)
Modified: innd/python.c
===================================================================
--- innd/python.c 2008-06-22 07:57:28 UTC (rev 7887)
+++ innd/python.c 2008-06-22 09:28:06 UTC (rev 7888)
@@ -1,7 +1,7 @@
/* $Id$
**
-** Embed Python in the style of innd's Tcl and Perl stuff.
-**
+** Embed Python in the style of innd's 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.
@@ -18,24 +18,24 @@
#include "innd.h"
-#if defined(DO_PYTHON)
+#ifdef DO_PYTHON
-/* Python redefines _POSIX_C_SOURCE, so undef it to suppress warnings. */
+/* Python redefines _POSIX_C_SOURCE, so undef it to suppress warnings. */
#undef _POSIX_C_SOURCE
#include "Python.h"
bool PythonFilterActive;
-char *filterPath; /* this gets set in art.c */
+char *filterPath; /* This gets set in art.c. */
PyObject *PYFilterObject = NULL;
PyObject *PYFilterModule = NULL;
-/* article filter bits and pieces */
+/* Article filter bits and pieces. */
PyObject *PYheaders = NULL;
PyObject **PYheaditem;
PyObject **PYheadkey;
PyObject *PYpathkey, *PYlineskey, *PYbodykey;
-/* external functions */
+/* External functions. */
PyObject *msgid_method = NULL;
PyObject *art_method = NULL;
PyObject *mode_method = NULL;
@@ -56,8 +56,9 @@
}
+
/*
-** Front end for PYfilter()
+** Front end for PYfilter().
*/
const char *
PYcontrol(char **av)
@@ -82,6 +83,7 @@
}
+
/*
** Reject articles we don't like.
*/
@@ -129,21 +131,22 @@
*buf = '\0';
Py_XDECREF(result);
- /* Clean up after ourselves */
+ /* 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')
+ if (*buf != '\0')
return buf;
return NULL;
}
+
/*
-** Refuse message IDs offered thru CHECK or IHAVE that we don't like.
+** Refuse Message-IDs offered through CHECK or IHAVE that we don't like.
*/
char *
PYmidfilter(char *messageID, int msglen)
@@ -162,7 +165,7 @@
*buf = '\0';
Py_XDECREF(result);
- if (*buf != '\0')
+ if (*buf != '\0')
return buf;
return NULL;
}
@@ -215,6 +218,7 @@
PyObject *result = NULL;
PyObject *temp;
+ /* set_filter_hook method should return a pointer to innd auth object. */
if (PyArg_ParseTuple(args, (char *) "O:set_filter_hook", &temp)) {
Py_XINCREF(temp);
Py_XDECREF(PYFilterObject);
@@ -222,6 +226,8 @@
Py_INCREF(Py_None);
result = Py_None;
}
+
+ /* Return a pointer to innd auth method. */
return result;
}
@@ -299,7 +305,7 @@
/*
-** Get a newsgroup's status flag (j, m, n, x, y, =other.group)
+** Get a newsgroup's status flag (j, m, n, x, y, =other.group).
*/
static PyObject *
PY_newsgroup(PyObject *self UNUSED, PyObject *args)
@@ -334,6 +340,7 @@
}
+
/*
** 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,
@@ -366,6 +373,7 @@
}
+
/*
** Return a whole article to the external module as a string.
*/
@@ -411,10 +419,12 @@
int msglen;
int priority;
+ /* Get loglevel and message. */
if (!PyArg_ParseTuple(args, (char *) "s#s#",
&loglevel, &levellen, &logmsg, &msglen))
return NULL;
+ /* Assign syslog priority by abbreviated names. */
switch (*loglevel) {
default: priority = LOG_NOTICE ;
case 'd': case 'D': priority = LOG_DEBUG ; break;
@@ -426,13 +436,16 @@
case 'a': case 'A': priority = LOG_ALERT ; break;
}
+ /* Log the message. */
syslog(priority, "python: %s", logmsg);
+ /* Return None. */
Py_INCREF(Py_None);
return Py_None;
}
+
/*
** Compute a hash digest for a string.
*/
@@ -452,7 +465,7 @@
if (lines > 0) {
worksize = insize;
- /* chop leading whitespace */
+ /* Chop leading whitespace. */
for (p=instring ; worksize>0 && isspace(*p) ; p++) {
if (*p == '\n')
lines--;
@@ -460,15 +473,15 @@
}
wpos = p;
- /* and trailing */
+ /* And trailing. */
for (p=&wpos[worksize] ; worksize>0 && isspace(*p) ; p--) {
if (*p == '\n')
lines--;
worksize--;
}
- /* chop last 3 lines if we have >= 5. From above chop the
- * last line has no CR so we use 1 less here. */
+ /* Chop last 3 lines if we have >= 5. From above chop the
+ * last line which has no CR so we use 1 less here. */
if (lines >= 4) {
for (i=0, p=wpos+worksize ; i<2 ; p--)
if (*p == '\n')
@@ -506,6 +519,7 @@
}
+
/*
** Make the internal INN module's functions visible to Python. Python
** annoyingly doesn't use const where appropriate in its structure
@@ -529,6 +543,7 @@
};
+
/*
** This runs when innd shuts down.
*/
@@ -553,13 +568,20 @@
PYdefonemethod(PyObject **methptr, const char *methname)
{
Py_XDECREF(*methptr);
+
+ /* Get a pointer to given method. */
*methptr = PyObject_GetAttrString(PYFilterObject, (char *) methname);
+
+ /* See if such method is defined. */
if (*methptr == NULL)
syslog(L_NOTICE, "python method %s not found", methname);
- else if (PyCallable_Check(*methptr) == 0) {
+ else {
+ /* See if it is callable. */
+ if (PyCallable_Check(*methptr) == 0) {
syslog(L_ERROR, "python object %s found but not a function", methname);
Py_DECREF(*methptr);
*methptr = NULL;
+ }
}
}
@@ -648,20 +670,26 @@
const ARTHEADER *hp;
size_t hdrcount;
+ /* Add path for nnrpd module. The environment variable PYTHONPATH
+ * does it; one can also append innconf->pathfilter to sys.path once
+ * Python has been initialized. */
setenv("PYTHONPATH", innconf->pathfilter, 1);
+
+ /* Load up the interpreter ;-O */
Py_Initialize();
- /* It makes Python sad when its stdout and stderr are closed. */
+ /* It makes Python sad when its stdout or stderr are closed. */
if ((fileno(stdout) == -1) || (fileno(stderr) == -1))
PyRun_SimpleString
("import sys; sys.stdout=sys.stderr=open('/dev/null', 'a')");
+ /* See if Python initialized OK. */
if (!Py_IsInitialized ()) {
syslog(L_ERROR, "python interpreter NOT initialized");
return;
}
- syslog(L_NOTICE, "python interpreter initialized OK");
+ /* Build a module interface to certain INN functions. */
Py_InitModule((char *) "INN", INNPyMethods);
PYFilterModule = PyImport_ImportModule((char *) INN_PATH_PYTHON_STARTUP_M);
@@ -678,8 +706,8 @@
}
/* Grab space for these so we aren't forever recreating them. We also
- put the body and the line count into PYheaditem, so it needs to be
- two elements longer than the total number of headers. */
+ * cut the body and the line count into PYheaditem, so it needs to be
+ * two elements longer than the total number of headers. */
PYheaders = PyDict_New();
hdrcount = ARRAY_END(ARTheaders) - ARTheaders;
PYheaditem = xmalloc((hdrcount + 2) * sizeof(PyObject *));
@@ -691,6 +719,8 @@
PYpathkey = PyString_InternFromString("Path");
PYlineskey = PyString_InternFromString("__LINES__");
PYbodykey = PyString_InternFromString("__BODY__");
+
+ syslog(L_NOTICE, "python interpreter initialized OK");
}
#endif /* defined(DO_PYTHON) */
Modified: nnrpd/python.c
===================================================================
--- nnrpd/python.c 2008-06-22 07:57:28 UTC (rev 7887)
+++ nnrpd/python.c 2008-06-22 09:28:06 UTC (rev 7888)
@@ -1,12 +1,13 @@
/* $Id$
**
-** python.c: Embed Python in the style of nnrpd's TCL and Perl stuff
-** (authentication and authorization hooks only at this point).
-**
+** python.c: Embed Python in the style of nnrpd's Perl stuff
+** (authentication, authorization and dynamic hooks
+** only at this point).
+**
** Written by Ilya Etingof <ilya at glas.net>, 1999.
**
** This code bases on Python work for innd filtering done by
-** G.J. Andruk <meowing at banet.net>. Also it borrows some ideas from
+** G.J. Andruk <meowing at banet.net>. Also it borrows some ideas from
** TCL/Perl work done by Bob Heiney and Christophe Wolfhugel.
*/
@@ -17,27 +18,28 @@
#include "nnrpd.h"
#include "inn/hashtab.h"
-#if defined(DO_PYTHON)
-/* Python redefines _POSIX_C_SOURCE, so undef it to suppress warnings. */
+#ifdef DO_PYTHON
+
+/* Python redefines _POSIX_C_SOURCE, so undef it to suppress warnings. */
#undef _POSIX_C_SOURCE
#include "Python.h"
-/* values relate name of hook to array index */
+/* Values relate name of hook to array index. */
#define PYTHONauthen 1
#define PYTHONaccess 2
#define PYTHONdynamic 3
#define PYTHONtypes_max 4
-/* values relate type of method to array index */
+/* Values relate type of method to array index. */
#define PYTHONmain 1
#define PYTHONinit 2
#define PYTHONclose 3
#define PYTHONmethods_max 4
-/* key names for attributes dictionary */
+/* Key names for attributes dictionary. */
#define PYTHONhostname "hostname"
#define PYTHONipaddress "ipaddress"
#define PYTHONport "port"
@@ -49,18 +51,18 @@
#define PYTHONtype "type"
#define PYTHONnewsgroup "newsgroup"
-/* Max number of items in dictionary to pass to auth methods */
+/* Max number of items in dictionary to pass to auth methods. */
#define _PY_MAX_AUTH_ITEM 10
-/* Pointers to external Python objects */
+/* Pointers to external Python objects. */
PyObject *PYAuthObject = NULL;
-/* Dictionary of params to pass to authentication methods */
+/* Dictionary of params to pass to authentication methods. */
PyObject *PYauthinfo = NULL;
PyObject **PYauthitem = NULL;
-/* Forward declaration */
+/* Forward declaration. */
static PyObject *PY_set_auth_hook(PyObject *dummy, PyObject *args);
void PY_load_python(void);
PyObject* PY_setup(int type, int method, char *file);
@@ -69,26 +71,28 @@
static void file_free(void *p);
static void file_trav(void *data, void* null);
-bool PythonLoaded = false;
+bool PythonLoaded = false;
-/* structure for storage of attributes for a module file */
+/* Structure for storage of attributes for a module file. */
typedef struct PyFile {
- char *file;
+ char *file;
bool loaded[PYTHONtypes_max];
PyObject *procs[PYTHONtypes_max][PYTHONmethods_max];
} PyFile;
-/* hash for storing files */
+/* Hash for storing files. */
struct hash *files;
-/* for passing the dynamic module filename from perm.c */
-char* dynamic_file;
+/* For passing the dynamic module filename from perm.c. */
+char* dynamic_file;
+
+
/*
-** Authenticate connecting host by username&password.
+** Authenticate connecting host by username&password.
**
-** Return NNTP reply code as returned by Python method or -1 if method
-** is not defined.
+** Return NNTP reply code as returned by Python method or -1 if method
+** is not defined.
*/
int
PY_authenticate(char* file, char *Username, char *Password, char *errorstring,
@@ -102,38 +106,38 @@
PY_load_python();
proc = PY_setup(PYTHONauthen, PYTHONmain, file);
- /* Return if authentication method is not defined */
+ /* Return if authentication method is not defined. */
if (proc == NULL)
return -1;
- /* Initialize PythonAuthObject with connect method specific items */
+ /* Initialize PythonAuthObject with connect method specific items. */
authnum = 0;
- /* Client hostname */
+ /* Client hostname. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.host, strlen(Client.host));
PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]);
- /* Client IP number */
+ /* Client IP number. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.ip, strlen(Client.ip));
PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]);
- /* Client port number */
+ /* Client port number. */
PYauthitem[authnum] = PyInt_FromLong(Client.port);
PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]);
- /* Server interface the connection comes to */
+ /* Server interface the connection comes to. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.serverhost, strlen(Client.serverhost));
PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]);
- /* Server IP number */
+ /* Server IP number. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.serverip, strlen(Client.serverip));
PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]);
- /* Server port number */
+ /* Server port number. */
PYauthitem[authnum] = PyInt_FromLong(Client.serverport);
PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]);
- /* Username if known */
+ /* Username if known. */
if (Username == NULL) {
PYauthitem[authnum] = Py_None;
} else {
@@ -141,7 +145,7 @@
}
PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]);
- /* Password if known */
+ /* Password if known. */
if (Password == NULL) {
PYauthitem[authnum] = Py_None;
} else {
@@ -149,11 +153,13 @@
}
PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]);
- /* Now invoke authenticate method and see if it likes this user */
+ /*
+ ** Now invoke authenticate method and see if it likes this user.
+ **/
result = PyObject_CallFunction(proc, (char *) "O", PYauthinfo);
- /* Check the response */
- if (result == NULL || !PyTuple_Check(result)
+ /* Check the response. */
+ if (result == NULL || !PyTuple_Check(result)
|| ((PyTuple_Size(result) != 2) && (PyTuple_Size(result) != 3)))
{
syslog(L_ERROR, "python authenticate method returned wrong result");
@@ -161,10 +167,10 @@
ExitWithStats(1, true);
}
- /* Get the NNTP response code */
+ /* Get the NNTP response code. */
item = PyTuple_GetItem(result, 0);
- /* Check the item */
+ /* Check the item. */
if (!PyInt_Check(item))
{
syslog(L_ERROR, "python authenticate method returned bad NNTP response code");
@@ -172,13 +178,13 @@
ExitWithStats(1, true);
}
- /* Store the code */
+ /* Store the code. */
code = PyInt_AS_LONG(item);
- /* Get the error string */
+ /* Get the error string. */
item = PyTuple_GetItem(result, 1);
- /* Check the item */
+ /* Check the item. */
if (!PyString_Check(item))
{
syslog(L_ERROR, "python authenticate method returned bad error string");
@@ -186,47 +192,51 @@
ExitWithStats(1, true);
}
- /* Store error string */
+ /* Store error string. */
temp = PyString_AS_STRING(item);
strlcpy(errorstring, temp, BIG_BUFFER);
if (PyTuple_Size(result) == 3) {
- /* Get the username string */
+ /* Get the username string. */
item = PyTuple_GetItem(result, 2);
- /* Check the item */
+ /* Check the item. */
if (!PyString_Check(item)) {
syslog(L_ERROR, "python authenticate method returned bad username string");
Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ERR_ACCESS);
ExitWithStats(1, true);
}
- /* Store user string */
+ /* Store user string. */
temp = PyString_AS_STRING(item);
strlcpy(newUser, temp, BIG_BUFFER);
}
- /* Clean up the dictionary object */
+ /* Clean up the dictionary object. */
PyDict_Clear(PYauthinfo);
- /* Clean up dictionary items */
+ /* Clean up dictionary items. */
for (i = 0; i < authnum; i++) {
if (PYauthitem[i] != Py_None) {
Py_DECREF(PYauthitem[i]);
}
}
- /* Log auth result */
+ /* Log auth result. */
syslog(L_NOTICE, "python authenticate method succeeded, return code %d, error string %s", code, errorstring);
- /* Return response code */
+ /* Return response code. */
return code;
}
+
+
/*
-** Create an access group based on the values returned by the script in file
+** Create an access group based on the values returned by the script in file.
**
+** The access_vec vector is set.
+** If the access group cannot be generated, the connection is closed.
*/
void
PY_access(char* file, struct vector *access_vec, char *Username)
@@ -239,64 +249,64 @@
PY_load_python();
proc = PY_setup(PYTHONaccess, PYTHONmain, file);
- /* Exit if access method is not defined */
+ /* Exit if access method is not defined. */
if (proc == NULL) {
syslog(L_ERROR, "python access method not defined");
Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ERR_ACCESS);
ExitWithStats(1, true);
}
- /* Initialize PythonAuthObject with group method specific items */
+ /* Initialize PythonAuthObject with group method specific items. */
authnum = 0;
- /* Client hostname */
+ /* Client hostname. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.host, strlen(Client.host));
PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]);
- /* Client IP number */
+ /* Client IP number. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.ip, strlen(Client.ip));
PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]);
- /* Client port number */
+ /* Client port number. */
PYauthitem[authnum] = PyInt_FromLong(Client.port);
PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]);
- /* Server interface the connection comes to */
+ /* Server interface the connection comes to. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.serverhost, strlen(Client.serverhost));
PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]);
- /* Server IP number */
+ /* Server IP number. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.serverip, strlen(Client.serverip));
PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]);
- /* Server port number */
+ /* Server port number. */
PYauthitem[authnum] = PyInt_FromLong(Client.serverport);
PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]);
- /* Username */
+ /* Username. */
PYauthitem[authnum] = PyBuffer_FromMemory(Username, strlen(Username));
PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]);
- /* Password is not known */
+ /* Password is not known. */
PYauthitem[authnum] = Py_None;
PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]);
/*
- * Now invoke newsgroup access method
- */
+ ** Now invoke newsgroup access method.
+ **/
result = PyObject_CallFunction(proc, (char *) "O", PYauthinfo);
- /* Check the response */
+ /* Check the response. */
if (result == NULL || result == Py_None || !PyDict_Check(result)) {
- syslog(L_ERROR, "python access method returned wrong result - expected a dictionary");
+ syslog(L_ERROR, "python access method returned wrong result -- expected a dictionary");
Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ERR_ACCESS);
ExitWithStats(1, true);
}
- /* resize vector to dictionary length */
+ /* Resize vector to dictionary length. */
vector_resize(access_vec, PyDict_Size(result) - 1);
- /* store dict values in proper format in access vector */
+ /* Store dict values in proper format in access vector. */
i = 0;
buffer = xmalloc(BIG_BUFFER);
@@ -321,22 +331,25 @@
}
free(buffer);
-
- /* Clean up the dictionary object */
+
+ /* Clean up the dictionary object. */
PyDict_Clear(PYauthinfo);
- /* Clean up dictionary items */
+
+ /* Clean up dictionary items. */
for (i = 0; i < authnum; i++) {
if (PYauthitem[i] != Py_None) {
Py_DECREF(PYauthitem[i]);
}
}
- /* Log auth result */
+ /* Log auth result. */
syslog(L_NOTICE, "python access method succeeded");
}
+
+
/*
-** Initialize dynamic access control code
+** Initialize dynamic access control code.
*/
void
@@ -347,12 +360,13 @@
}
+
/*
-** Determine dynamic user access rights to a given newsgroup.
+** Determine dynamic user access rights to a given newsgroup.
**
-** Return 0 if requested privelege is granted or positive value
-** and a reply_message pointer initialized with reply message.
-** Return negative value if dynamic method is not defined.
+** Return 0 if the requested privilege is granted or a positive value
+** and a reply_message pointer initialized with reply message.
+** Return negative value if dynamic method is not defined.
*/
int
PY_dynamic(char *Username, char *NewsGroup, int PostFlag, char **reply_message)
@@ -365,97 +379,99 @@
PY_load_python();
proc = PY_setup(PYTHONdynamic, PYTHONmain, dynamic_file);
- /* Return if dynamic method is not defined */
+ /* Return if dynamic method is not defined. */
if (proc == NULL)
return -1;
- /* Initialize PythonAuthObject with group method specific items */
+ /* Initialize PythonAuthObject with group method specific items. */
authnum = 0;
- /* Client hostname */
+ /* Client hostname. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.host, strlen(Client.host));
PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]);
- /* Client IP number */
+ /* Client IP number. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.ip, strlen(Client.ip));
PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]);
- /* Client port number */
+ /* Client port number. */
PYauthitem[authnum] = PyInt_FromLong(Client.port);
PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]);
- /* Server interface the connection comes to */
+ /* Server interface the connection comes to. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.serverhost, strlen(Client.serverhost));
PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]);
- /* Server IP number */
+ /* Server IP number. */
PYauthitem[authnum] = PyBuffer_FromMemory(Client.serverip, strlen(Client.serverip));
PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]);
- /* Server port number */
+ /* Server port number. */
PYauthitem[authnum] = PyInt_FromLong(Client.serverport);
PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]);
- /* Username */
+ /* Username. */
PYauthitem[authnum] = PyBuffer_FromMemory(Username, strlen(Username));
PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]);
- /* Password is not known */
+ /* Password is not known. */
PYauthitem[authnum] = Py_None;
PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]);
- /* Assign authentication type */
+ /* Assign authentication type. */
PYauthitem[authnum] =
PyBuffer_FromMemory((char *)(PostFlag ? "post" : "read"), 4);
PyDict_SetItemString(PYauthinfo, PYTHONtype, PYauthitem[authnum++]);
- /* Newsgroup user tries to access */
+ /* Newsgroup user tries to access. */
PYauthitem[authnum] = PyBuffer_FromMemory(NewsGroup, strlen(NewsGroup));
PyDict_SetItemString(PYauthinfo, PYTHONnewsgroup, PYauthitem[authnum++]);
/*
- * Now invoke newsgroup dynamic access method and see if
- * it likes this user to access this newsgroup.
- */
+ ** Now invoke newsgroup dynamic access method and see if
+ ** it likes this user to access this newsgroup.
+ **/
result = PyObject_CallFunction(proc, (char *) "O", PYauthinfo);
- /* Check the response */
+ /* Check the response. */
if (result == NULL || (result != Py_None && !PyString_Check(result)))
{
- syslog(L_ERROR, "python dyanmic method (%s access) returned wrong result", PostFlag ? "post" : "read");
+ syslog(L_ERROR, "python dynamic method (%s access) returned wrong result", PostFlag ? "post" : "read");
Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ERR_ACCESS);
ExitWithStats(1, false);
}
- /* Get the response string */
+ /* Get the response string. */
if (result == Py_None) {
string = NULL;
} else {
temp = PyString_AS_STRING(result);
string = xstrdup(temp);
}
- /* Clean up the dictionary object */
+
+ /* Clean up the dictionary object. */
PyDict_Clear(PYauthinfo);
- /* Clean up dictionary items */
+ /* Clean up dictionary items. */
for (i = 0; i < authnum; i++) {
if (PYauthitem[i] != Py_None) {
Py_DECREF(PYauthitem[i]);
}
}
- /* Log auth result */
+ /* Log auth result. */
syslog(L_NOTICE, "python dynamic method (%s access) succeeded, refusion string: %s", PostFlag ? "post" : "read", string == NULL ? "<empty>" : string);
- /* Initialize reply string */
+ /* Initialize reply string. */
if (reply_message != NULL)
*reply_message = string;
- /* Return result */
+ /* Return result. */
return string == NULL ? 0 : 1;
}
+
/*
** This runs when nnrpd shuts down. If Python is closed and reopened
** in the same process, files and dynamic_file are reused so they
@@ -475,15 +491,17 @@
}
}
+
+
/*
-** Traversal function for PY_close_python
+** Traversal function for PY_close_python.
*/
void
file_trav(void *data, void* null UNUSED)
{
PyFile *fp = data;
int j;
- PyObject *result, *func;
+ PyObject *result, *func;
for (j = 1; j < PYTHONtypes_max; j++) {
if (fp->loaded[j] != false) {
@@ -496,6 +514,8 @@
}
}
+
+
/*
** 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
@@ -510,12 +530,12 @@
int msglen;
int priority;
- /* Get loglevel and message */
+ /* Get loglevel and message. */
if (!PyArg_ParseTuple(args, (char *) "s#s#", &loglevel, &levellen,
&logmsg, &msglen))
return NULL;
- /* Assign syslog priority by abbreviated names */
+ /* Assign syslog priority by abbreviated names. */
switch (*loglevel) {
default: priority = LOG_NOTICE ;
case 'd': case 'D': priority = LOG_DEBUG ; break;
@@ -527,15 +547,16 @@
case 'a': case 'A': priority = LOG_ALERT ; break;
}
- /* Log the message */
+ /* Log the message. */
syslog(priority, "python: %s", logmsg);
- /* Return None */
+ /* Return None. */
Py_INCREF(Py_None);
return Py_None;
}
+
/*
** Make the internal nnrpd module's functions visible to Python. Python
** annoyingly doesn't use const where appropriate in its structure
@@ -552,6 +573,7 @@
};
+
/*
** Called by the external module so it can register itself with nnrpd.
*/
@@ -561,7 +583,7 @@
PyObject *result = NULL;
PyObject *temp;
- /* set_auth_hook method should return a pointer to nnrpd auth object */
+ /* Set_auth_hook method should return a pointer to nnrpd auth object. */
if (PyArg_ParseTuple(args, (char *) "O:set_auth_hook", &temp)) {
Py_XINCREF(temp);
Py_XDECREF(PYAuthObject);
@@ -570,46 +592,49 @@
result = Py_None;
}
- /* Return a pointer to nnrpd auth method */
+ /* Return a pointer to nnrpd auth method. */
return result;
}
+
+
/*
-** Load the Python interpreter
+** Load the Python interpreter.
*/
void
PY_load_python(void)
{
if (!PythonLoaded) {
- /* add path for nnrpd module */
+ /* Add path for nnrpd module. The environment variable PYTHONPATH
+ ** does it; one can also append innconf->pathfilter to sys.path once
+ ** Python has been initialized.
+ **/
setenv("PYTHONPATH", innconf->pathfilter, 1);
/* Load up the interpreter ;-O */
Py_Initialize();
- /* It makes Python sad when its stdout and stderr are closed. */
- if (feof(stdout) || feof(stderr))
+ /* It makes Python sad when its stdout or stderr are closed. */
+ if ((fileno(stdout) == -1) || (fileno(stderr) == -1))
PyRun_SimpleString("import sys; sys.stdout=sys.stderr=open('/dev/null', 'a')");
- /* See if Python initialized OK */
- if (!Py_IsInitialized ()) {
+ /* See if Python initialized OK. */
+ if (!Py_IsInitialized()) {
syslog(L_ERROR, "python interpreter NOT initialized");
return;
}
-
- /* Build a module interface to certain nnrpd functions */
+ /* Build a module interface to certain nnrpd functions. */
Py_InitModule((char *) "nnrpd", nnrpdPyMethods);
/*
** Grab space for authinfo dictionary so we aren't forever
** recreating them.
- */
+ **/
PYauthinfo = PyDict_New();
PYauthitem = xcalloc(_PY_MAX_AUTH_ITEM, sizeof(PyObject *));
- /* create hash to store file attributes */
-
+ /* Create hash to store file attributes. */
files = hash_create(4, hash_string, file_key,
file_equal, file_free);
@@ -619,6 +644,8 @@
}
}
+
+
/*
** Check that a method exists and is callable. Set up a pointer to
** the corresponding PyObject, or NULL if not found.
@@ -630,14 +657,14 @@
methptr = &fp->procs[type][method];
- /* Get a pointer to given method */
+ /* Get a pointer to given method. */
*methptr = PyObject_GetAttrString(PYAuthObject, (char *) methname);
- /* See if such method is defined */
+ /* See if such method is defined. */
if (*methptr == NULL)
syslog(L_NOTICE, "python method %s not found", methname);
else {
- /* See if it is callable */
+ /* See if it is callable. */
if (PyCallable_Check(*methptr) == 0) {
syslog(L_ERROR, "python object %s found but not a function", methname);
Py_DECREF(*methptr);
@@ -647,6 +674,7 @@
}
+
/*
** Look up all the known python methods and set up
** pointers to them so that we could call them from nnrpd.
@@ -654,35 +682,36 @@
static void
PYdefmethods(PyFile *fp)
{
- /* Get a reference to authenticate() method */
+ /* Get a reference to authenticate() method. */
PYdefonemethod(fp, PYTHONauthen, PYTHONmain, "authenticate");
- /* Get a reference to authen_init() method */
+ /* Get a reference to authen_init() method. */
PYdefonemethod(fp, PYTHONauthen, PYTHONinit, "authen_init");
- /* Get a reference to authen_close() method */
+ /* Get a reference to authen_close() method. */
PYdefonemethod(fp, PYTHONauthen, PYTHONclose, "authen_close");
- /* Get a reference to access() method */
+ /* Get a reference to access() method. */
PYdefonemethod(fp, PYTHONaccess, PYTHONmain, "access");
- /* Get a reference to access_init() method */
+ /* Get a reference to access_init() method. */
PYdefonemethod(fp, PYTHONaccess, PYTHONinit, "access_init");
- /* Get a reference to access_close() method */
+ /* Get a reference to access_close() method. */
PYdefonemethod(fp, PYTHONaccess, PYTHONclose, "access_close");
- /* Get a reference to dynamic() method */
+ /* Get a reference to dynamic() method. */
PYdefonemethod(fp, PYTHONdynamic, PYTHONmain, "dynamic");
- /* Get a reference to dynamic_init() method */
+ /* Get a reference to dynamic_init() method. */
PYdefonemethod(fp, PYTHONdynamic, PYTHONinit, "dynamic_init");
- /* Get a reference to dynamic_close() method */
+ /* Get a reference to dynamic_close() method. */
PYdefonemethod(fp, PYTHONdynamic, PYTHONclose, "dynamic_close");
}
+
/*
** Called when a python hook is needed -- this gets the scripts hooked in.
*/
@@ -693,7 +722,7 @@
PyFile *fp;
PyObject *result;
- /* check to see if this file is in files */
+ /* Check to see if this file is in files. */
if (!(hash_lookup(files, file))) {
fp = xmalloc(sizeof(PyFile));
fp->file = xstrdup(file);
@@ -702,17 +731,17 @@
fp->loaded[i] = false;
}
- /* Load up external module */
+ /* Load up external module. */
(void) PyImport_ImportModule(file);
- /* See if nnrpd auth object is defined in auth module */
+ /* See if nnrpd auth object is defined in auth module. */
if (PYAuthObject == NULL) {
syslog(L_ERROR, "python auth object is not defined");
Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ERR_ACCESS);
PY_close_python();
ExitWithStats(1, false);
} else {
- /* Set up pointers to known Python methods */
+ /* Set up pointers to known Python methods. */
PYdefmethods(fp);
}
hash_insert(files, file, fp);
@@ -729,6 +758,8 @@
return NULL;
}
+
+
/*
** Return the key (filename) from a file struct, used by the hash table.
*/
@@ -740,6 +771,8 @@
return f->file;
}
+
+
/*
** Check to see if a provided key matches the key of a PyFile struct,
** used by the hash table.
@@ -753,6 +786,8 @@
return strcmp(key, f->file) == 0;
}
+
+
/*
** Free a file, used by the hash table.
*/
More information about the inn-committers
mailing list