chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[innduct.git] / nnrpd / python.c
diff --git a/nnrpd/python.c b/nnrpd/python.c
deleted file mode 100644 (file)
index a68e85d..0000000
+++ /dev/null
@@ -1,777 +0,0 @@
-/*  $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) */