+++ /dev/null
-/* $Id: python.c 7893 2008-06-22 10:24:42Z iulius $
-**
-** python.c: Embed Python in the style of nnrpd's TCL and Perl stuff
-** (authentication and authorization hooks only at this point).
-**
-** Written by Ilya Etingof <ilya@glas.net>, 1999.
-**
-** This code bases on Python work for innd filtering done by
-** G.J. Andruk <meowing@banet.net>. Also it borrows some ideas from
-** TCL/Perl work done by Bob Heiney and Christophe Wolfhugel.
-**
-** A quick note regarding Python exceptions: functions like
-** PyObject_GetAttrString(PyObject *o, const char *attr_name)
-** raise an exception when they fail, even though they return NULL.
-** And as exceptions accumulate from caller to caller and so on,
-** it generates weird issues with Python scripts afterwards. So such
-** uses should be checked before. For instance with:
-** PyObject_HasAttrString(PyObject *o, const char *attr_name).
-*/
-
-#include "config.h"
-#include "clibrary.h"
-
-#include "inn/innconf.h"
-#include "nnrpd.h"
-#include "inn/hashtab.h"
-
-#if defined(DO_PYTHON)
-
-#include "Python.h"
-
-/* 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 */
-#define PYTHONmain 1
-#define PYTHONinit 2
-#define PYTHONclose 3
-
-#define PYTHONmethods_max 4
-
-/* key names for attributes dictionary */
-#define PYTHONhostname "hostname"
-#define PYTHONipaddress "ipaddress"
-#define PYTHONport "port"
-#define PYTHONinterface "interface"
-#define PYTHONintipaddr "intipaddr"
-#define PYTHONintport "intport"
-#define PYTHONuser "user"
-#define PYTHONpass "pass"
-#define PYTHONtype "type"
-#define PYTHONnewsgroup "newsgroup"
-
-/* Max number of items in dictionary to pass to auth methods */
-#define _PY_MAX_AUTH_ITEM 10
-
-
-/* Pointers to external Python objects */
-PyObject *PYAuthObject = NULL;
-
-/* Dictionary of params to pass to authentication methods */
-PyObject *PYauthinfo = NULL;
-PyObject **PYauthitem = NULL;
-
-/* 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);
-static const void *file_key(const void *p);
-static bool file_equal(const void *k, const void *p);
-static void file_free(void *p);
-static void file_trav(void *data, void* null);
-
-bool PythonLoaded = false;
-
-/* structure for storage of attributes for a module file */
-typedef struct PyFile {
- char *file;
- bool loaded[PYTHONtypes_max];
- PyObject *procs[PYTHONtypes_max][PYTHONmethods_max];
-} PyFile;
-
-/* hash for storing files */
-struct hash *files;
-
-/* for passing the dynamic module filename from perm.c */
-char* dynamic_file;
-
-/*
-** Authenticate connecting host by username&password.
-**
-** 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, char *newUser) {
- PyObject *result, *item, *proc;
- int authnum;
- int code, i;
- char *temp;
-
- PY_load_python();
- proc = PY_setup(PYTHONauthen, PYTHONmain, file);
-
- /* Return if authentication method is not defined */
- if (proc == NULL)
- return -1;
-
- /* Initialize PythonAuthObject with connect method specific items */
- authnum = 0;
-
- /* Client hostname */
- PYauthitem[authnum] = PyBuffer_FromMemory(ClientHost, strlen(ClientHost));
- PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]);
-
- /* Client IP number */
- PYauthitem[authnum] = PyBuffer_FromMemory(ClientIpString, strlen(ClientIpString));
- PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]);
-
- /* Client port number */
- PYauthitem[authnum] = PyInt_FromLong(ClientPort);
- PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]);
-
- /* Server interface the connection comes to */
- PYauthitem[authnum] = PyBuffer_FromMemory(ServerHost, strlen(ServerHost));
- PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]);
-
- /* Server IP number */
- PYauthitem[authnum] = PyBuffer_FromMemory(ServerIpString, strlen(ServerIpString));
- PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]);
-
- /* Server port number */
- PYauthitem[authnum] = PyInt_FromLong(ServerPort);
- PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]);
-
- /* Username if known */
- if (Username == NULL) {
- PYauthitem[authnum] = Py_None;
- } else {
- PYauthitem[authnum] = PyBuffer_FromMemory(Username, strlen(Username));
- }
- PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]);
-
- /* Password if known */
- if (Password == NULL) {
- PYauthitem[authnum] = Py_None;
- } else {
- PYauthitem[authnum] = PyBuffer_FromMemory(Password, strlen(Password));
- }
- PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]);
-
- /* Now invoke authenticate method and see if it likes this user */
- result = PyObject_CallFunction(proc, "O", PYauthinfo);
-
- /* 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");
- Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ACCESS_VAL);
- ExitWithStats(1, true);
- }
-
- /* Get the NNTP response code */
- item = PyTuple_GetItem(result, 0);
-
- /* Check the item */
- if (!PyInt_Check(item))
- {
- syslog(L_ERROR, "python authenticate method returned bad NNTP response code");
- Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ACCESS_VAL);
- ExitWithStats(1, true);
- }
-
- /* Store the code */
- code = PyInt_AS_LONG(item);
-
- /* Get the error string */
- item = PyTuple_GetItem(result, 1);
-
- /* Check the item */
- if (!PyString_Check(item))
- {
- syslog(L_ERROR, "python authenticate method returned bad error string");
- Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ACCESS_VAL);
- ExitWithStats(1, true);
- }
-
- /* Store error string */
- temp = PyString_AS_STRING(item);
- errorstring = xstrdup(temp);
-
- if (PyTuple_Size(result) == 3) {
-
- /* Get the username string */
- item = PyTuple_GetItem(result, 2);
-
- /* 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_ACCESS_VAL);
- ExitWithStats(1, true);
- }
-
- /* Store error string */
- temp = PyString_AS_STRING(item);
- newUser = xstrdup(temp);
- }
-
- /* Clean up the dictionary object */
- PyDict_Clear(PYauthinfo);
-
- /* Clean up dictionary items */
- for (i = 0; i < authnum; i++) {
- if (PYauthitem[i] != Py_None) {
- Py_DECREF(PYauthitem[i]);
- }
- }
-
- /* Log auth result */
- syslog(L_NOTICE, "python authenticate method succeeded, return code %d, error string %s", code, errorstring);
-
- /* Return response code */
- return code;
-}
-
-/*
-** Create an access group based on the values returned by the script in file
-**
-*/
-void PY_access(char* file, struct vector *access_vec, char *Username) {
- PyObject *result, *key, *value, *proc;
- char *buffer;
- int authnum;
- int i;
-
- PY_load_python();
- proc = PY_setup(PYTHONaccess, PYTHONmain, file);
-
- /* 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_ACCESS_VAL);
- ExitWithStats(1, true);
- }
-
- /* Initialize PythonAuthObject with group method specific items */
- authnum = 0;
-
- /* Client hostname */
- PYauthitem[authnum] = PyBuffer_FromMemory(ClientHost, strlen(ClientHost));
- PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]);
-
- /* Client IP number */
- PYauthitem[authnum] = PyBuffer_FromMemory(ClientIpString, strlen(ClientIpString));
- PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]);
-
- /* Client port number */
- PYauthitem[authnum] = PyInt_FromLong(ClientPort);
- PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]);
-
- /* Server interface the connection comes to */
- PYauthitem[authnum] = PyBuffer_FromMemory(ServerHost, strlen(ServerHost));
- PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]);
-
- /* Server IP number */
- PYauthitem[authnum] = PyBuffer_FromMemory(ServerIpString, strlen(ServerIpString));
- PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]);
-
- /* Server port number */
- PYauthitem[authnum] = PyInt_FromLong(ServerPort);
- PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]);
-
- /* Username */
- PYauthitem[authnum] = PyBuffer_FromMemory(Username, strlen(Username));
- PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]);
-
- /* Password is not known */
- PYauthitem[authnum] = Py_None;
- PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]);
-
- /*
- * Now invoke newsgroup access method
- */
- result = PyObject_CallFunction(proc, "O", PYauthinfo);
-
- /* Check the response */
- if (result == NULL || result == Py_None || !PyDict_Check(result)) {
- syslog(L_ERROR, "python access method returned wrong result -- expected a dictionary");
- Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ACCESS_VAL);
- ExitWithStats(1, true);
- }
-
- /* resize vector to dictionary length */
- vector_resize(access_vec, PyDict_Size(result) - 1);
-
- /* store dict values in proper format in access vector */
- i = 0;
- buffer = xmalloc(BIG_BUFFER);
-
- while(PyDict_Next(result, &i, &key, &value)) {
- if (!PyString_Check(key)) {
- syslog(L_ERROR, "python access method return dictionary key %i not a string", i);
- Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ACCESS_VAL);
- ExitWithStats(1, false);
- }
- if (!PyString_Check(value)) {
- syslog(L_ERROR, "python access method return dictionary value %i not a string", i);
- Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ACCESS_VAL);
- ExitWithStats(1, false);
- }
-
- strlcpy(buffer, PyString_AsString(key), BIG_BUFFER);
- strlcat(buffer, ": \"", BIG_BUFFER);
- strlcat(buffer, PyString_AsString(value), BIG_BUFFER);
- strlcat(buffer, "\"\n", BIG_BUFFER);
-
- vector_add(access_vec, xstrdup(buffer));
- }
-
- free(buffer);
-
- /* Clean up the dictionary object */
- PyDict_Clear(PYauthinfo);
- /* Clean up dictionary items */
- for (i = 0; i < authnum; i++) {
- if (PYauthitem[i] != Py_None) {
- Py_DECREF(PYauthitem[i]);
- }
- }
-
- /* Log auth result */
- syslog(L_NOTICE, "python access method succeeded");
-}
-
-/*
-** Initialize dynamic access control code
-*/
-
-void PY_dynamic_init (char* file) {
- dynamic_file = xstrdup(file);
- PY_use_dynamic = true;
-}
-
-
-/*
-** 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.
-*/
-int PY_dynamic(char *Username, char *NewsGroup, int PostFlag, char **reply_message) {
- PyObject *result, *item, *proc;
- char *string, *temp;
- int authnum;
- int i;
-
- PY_load_python();
- proc = PY_setup(PYTHONdynamic, PYTHONmain, dynamic_file);
-
- /* Return if dynamic method is not defined */
- if (proc == NULL)
- return -1;
-
- /* Initialize PythonAuthObject with group method specific items */
- authnum = 0;
-
- /* Client hostname */
- PYauthitem[authnum] = PyBuffer_FromMemory(ClientHost, strlen(ClientHost));
- PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]);
-
- /* Client IP number */
- PYauthitem[authnum] = PyBuffer_FromMemory(ClientIpString, strlen(ClientIpString));
- PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]);
-
- /* Client port number */
- PYauthitem[authnum] = PyInt_FromLong(ClientPort);
- PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]);
-
- /* Server interface the connection comes to */
- PYauthitem[authnum] = PyBuffer_FromMemory(ServerHost, strlen(ServerHost));
- PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]);
-
- /* Server IP number */
- PYauthitem[authnum] = PyBuffer_FromMemory(ServerIpString, strlen(ServerIpString));
- PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]);
-
- /* Server port number */
- PYauthitem[authnum] = PyInt_FromLong(ServerPort);
- PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]);
-
- /* Username */
- PYauthitem[authnum] = PyBuffer_FromMemory(Username, strlen(Username));
- PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]);
-
- /* Password is not known */
- PYauthitem[authnum] = Py_None;
- PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]);
-
- /* Assign authentication type */
- PYauthitem[authnum] = PyBuffer_FromMemory(PostFlag ? "post" : "read", 4);
- PyDict_SetItemString(PYauthinfo, PYTHONtype, PYauthitem[authnum++]);
-
- /* 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.
- */
- result = PyObject_CallFunction(proc, "O", PYauthinfo);
-
- /* Check the response */
- if (result == NULL || (result != Py_None && !PyString_Check(result)))
- {
- syslog(L_ERROR, "python dynamic method (%s access) returned wrong result: %s", PostFlag ? "post" : "read", result);
- Reply("%d Internal Error (7). Goodbye\r\n", NNTP_ACCESS_VAL);
- ExitWithStats(1, false);
- }
-
- /* Get the response string */
- if (result == Py_None) {
- string = NULL;
- } else {
- temp = PyString_AS_STRING(result);
- string = xstrdup(temp);
- }
- /* Clean up the dictionary object */
- PyDict_Clear(PYauthinfo);
-
- /* Clean up dictionary items */
- for (i = 0; i < authnum; i++) {
- if (PYauthitem[i] != Py_None) {
- Py_DECREF(PYauthitem[i]);
- }
- }
-
- /* 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 */
- if (reply_message != NULL)
- *reply_message = string;
-
- /* 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
-** must point to NULL.
-*/
-void
-PY_close_python(void)
-{
- if (files != NULL) {
- hash_traverse(files, file_trav, NULL);
- hash_free(files);
- files = NULL;
- }
- if (dynamic_file != NULL) {
- free(dynamic_file);
- dynamic_file = NULL;
- }
-}
-
-/*
-** Traversal function for PY_close_python
-*/
-void
-file_trav(void *data, void* null UNUSED)
-{
- PyFile *fp = data;
- int j;
- PyObject *result, *func;
-
- for (j = 1; j < PYTHONtypes_max; j++) {
- if (fp->loaded[j] != false) {
- func = fp->procs[j][PYTHONclose];
- if (func != NULL) {
- result = PyObject_CallFunction(func, NULL);
- Py_XDECREF(result);
- }
- }
- }
-}
-
-/*
-** 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(PyObject *self UNUSED, PyObject *args)
-{
- char *loglevel;
- int levellen;
- char *logmsg;
- int msglen;
- int priority;
-
- /* Get loglevel and message */
- if (!PyArg_ParseTuple(args, "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;
- 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;
- }
-
- /* Log the message */
- syslog(priority, "python: %s", logmsg);
-
- /* Return None */
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-
-/*
-** Make the internal nnrpd module's functions visible to Python.
-*/
-static PyMethodDef nnrpdPyMethods[] = {
- {"set_auth_hook", PY_set_auth_hook, METH_VARARGS},
- {"syslog", PY_syslog, METH_VARARGS},
- {NULL, NULL}
-};
-
-
-/*
-** Called by the external module so it can register itself with nnrpd.
-*/
-static PyObject *
-PY_set_auth_hook(PyObject *dummy UNUSED, PyObject *args)
-{
- PyObject *result = NULL;
- PyObject *temp;
-
- /* set_auth_hook method should return a pointer to nnrpd auth object */
- if (PyArg_ParseTuple(args, "O:set_auth_hook", &temp)) {
- Py_XINCREF(temp);
- Py_XDECREF(PYAuthObject);
- PYAuthObject = temp;
- Py_INCREF(Py_None);
- result = Py_None;
- }
-
- /* Return a pointer to nnrpd auth method */
- return result;
-}
-
-/*
-** Load the Python interpreter
-*/
-void PY_load_python() {
- if (!PythonLoaded) {
- /* add path for nnrpd module */
- setenv("PYTHONPATH", innconf->pathfilter, 1);
-
- /* Load up the interpreter ;-O */
- Py_Initialize();
-
- /* 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')");
-
- /* See if Python initialized OK */
- if (!Py_IsInitialized ()) {
- syslog(L_ERROR, "python interpreter NOT initialized");
- return;
- }
-
-
- /* Build a module interface to certain nnrpd functions */
- (void) Py_InitModule("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 */
-
- files = hash_create(4, hash_string, file_key,
- file_equal, file_free);
-
- PythonLoaded = true;
-
- syslog(L_NOTICE, "python interpreter initialized OK");
- }
-}
-
-/*
-** Check that a method exists and is callable. Set up a pointer to
-** the corresponding PyObject, or NULL if not found.
-*/
-void
-PYdefonemethod(PyFile *fp, int type, int method, char *methname, int realtype) {
- PyObject **methptr;
-
- methptr = &fp->procs[type][method];
- /* There is no need to check the existence of methods useless for our realtype. */
- if (type == realtype) {
- /*
- ** We check with HasAttrString() the existence of the method because
- ** otherwise, in case it does not exist, an exception is raised by Python,
- ** although the result of the function is NULL.
- */
- if (PyObject_HasAttrString(PYAuthObject, (char *) methname) == 1) {
- /* Get a pointer to given method. */
- *methptr = PyObject_GetAttrString(PYAuthObject, (char *) methname);
- } else {
- *methptr = NULL;
- }
-
- /* See if such method is defined */
- if (*methptr == NULL)
- syslog(L_NOTICE, "python method %s not found", methname);
- 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;
- }
- }
- } else {
- *methptr = NULL;
- }
-}
-
-
-/*
-** Look up all the known python methods and set up
-** pointers to them so that we could call them from nnrpd.
-*/
-void
-PYdefmethods(PyFile *fp, int realtype)
-{
- /* Get a reference to authenticate() method */
- PYdefonemethod(fp, PYTHONauthen, PYTHONmain, "authenticate", realtype);
-
- /* Get a reference to authen_init() method */
- PYdefonemethod(fp, PYTHONauthen, PYTHONinit, "authen_init", realtype);
-
- /* Get a reference to authen_close() method */
- PYdefonemethod(fp, PYTHONauthen, PYTHONclose, "authen_close", realtype);
-
- /* Get a reference to access() method */
- PYdefonemethod(fp, PYTHONaccess, PYTHONmain, "access", realtype);
-
- /* Get a reference to access_init() method */
- PYdefonemethod(fp, PYTHONaccess, PYTHONinit, "access_init", realtype);
-
- /* Get a reference to access_close() method */
- PYdefonemethod(fp, PYTHONaccess, PYTHONclose, "access_close", realtype);
-
- /* Get a reference to dynamic() method */
- PYdefonemethod(fp, PYTHONdynamic, PYTHONmain, "dynamic", realtype);
-
- /* Get a reference to dynamic_init() method */
- PYdefonemethod(fp, PYTHONdynamic, PYTHONinit, "dynamic_init", realtype);
-
- /* Get a reference to dynamic_close() method */
- PYdefonemethod(fp, PYTHONdynamic, PYTHONclose, "dynamic_close", realtype);
-}
-
-
-/*
-** Called when a python hook is needed -- this gets the scripts hooked in.
-*/
-PyObject*
-PY_setup(int type, int method, char *file)
-{
- int i;
- PyFile *fp;
- PyObject *result;
-
- /* check to see if this file is in files */
- if (!(hash_lookup(files, file))) {
- fp = xmalloc(sizeof(PyFile));
- fp->file = xstrdup(file);
-
- for (i = 1; i < PYTHONtypes_max; i++) {
- fp->loaded[i] = false;
- }
-
- /* Load up external module */
- (void) PyImport_ImportModule(file);
-
- /* 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_ACCESS_VAL);
- PY_close_python();
- ExitWithStats(1, false);
- } else {
- /* Set up pointers to known Python methods */
- PYdefmethods(fp, type);
- }
- hash_insert(files, file, fp);
-
- if ((!fp->loaded[type]) && (fp->procs[type][PYTHONinit] != NULL)) {
- result = PyObject_CallFunction(fp->procs[type][PYTHONinit], NULL);
- if (result != NULL) {
- Py_XDECREF(result);
- }
- fp->loaded[type] = true;
- }
- return fp->procs[type][method];
- }
- return NULL;
-}
-
-/*
-** Return the key (filename) from a file struct, used by the hash table.
-*/
-static const void *
-file_key(const void *p)
-{
- const struct PyFile *f = p;
-
- return f->file;
-}
-
-/*
-** Check to see if a provided key matches the key of a PyFile struct,
-** used by the hash table.
-*/
-static bool
-file_equal(const void *k, const void *p)
-{
- const char *key = k;
- const struct PyFile *f = p;
-
- return strcmp(key, f->file) == 0;
-}
-
-/*
-** Free a file, used by the hash table.
-*/
-static void
-file_free(void *p)
-{
- struct PyFile *fp = p;
- int i, j;
-
- free(fp->file);
-
- for (i = 1; i < PYTHONtypes_max; i++) {
- for (j = 1; j < PYTHONmethods_max; j++) {
- if (fp->procs[i][j] != NULL) {
- Py_DECREF(fp->procs[i][j]);
- }
- }
- }
-
- free(fp);
-}
-
-#endif /* defined(DO_PYTHON) */