home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Modules / nismodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  7.3 KB  |  383 lines

  1. /***********************************************************
  2.     Written by:
  3.     Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
  4.     B&O group,
  5.     Faculteit der Informatica,
  6.     Universiteit Twente,
  7.     Enschede,
  8.     the Netherlands.
  9. ******************************************************************/
  10.  
  11. /* NIS module implementation */
  12.  
  13. #include "Python.h"
  14.  
  15. #include <sys/time.h>
  16. #include <sys/types.h>
  17. #include <rpc/rpc.h>
  18. #include <rpcsvc/yp_prot.h>
  19. #include <rpcsvc/ypclnt.h>
  20.  
  21. #ifdef __sgi
  22. /* This is missing from rpcsvc/ypclnt.h */
  23. extern int yp_get_default_domain(char **);
  24. #endif
  25.  
  26. static PyObject *NisError;
  27.  
  28. static PyObject *
  29. nis_error (int err)
  30. {
  31.     PyErr_SetString(NisError, yperr_string(err));
  32.     return NULL;
  33. }
  34.  
  35. static struct nis_map {
  36.     char *alias;
  37.     char *map;
  38.     int  fix;
  39. } aliases [] = {
  40.     {"passwd",    "passwd.byname",    0},
  41.     {"group",    "group.byname",        0},
  42.     {"networks",    "networks.byaddr",    0},
  43.     {"hosts",    "hosts.byname",        0},
  44.     {"protocols",    "protocols.bynumber",    0},
  45.     {"services",    "services.byname",    0},
  46.     {"aliases",    "mail.aliases",        1}, /* created with 'makedbm -a' */
  47.     {"ethers",    "ethers.byname",    0},
  48.     {0L,        0L,            0}
  49. };
  50.  
  51. static char *
  52. nis_mapname (char *map, int *pfix)
  53. {
  54.     int i;
  55.  
  56.     *pfix = 0;
  57.     for (i=0; aliases[i].alias != 0L; i++) {
  58.         if (!strcmp (aliases[i].alias, map)) {
  59.             *pfix = aliases[i].fix;
  60.             return aliases[i].map;
  61.         }
  62.         if (!strcmp (aliases[i].map, map)) {
  63.             *pfix = aliases[i].fix;
  64.             return aliases[i].map;
  65.         }
  66.     }
  67.  
  68.     return map;
  69. }
  70.  
  71. typedef int (*foreachfunc)(int, char *, int, char *, int, char *);
  72.  
  73. struct ypcallback_data {
  74.     PyObject    *dict;
  75.     int            fix;
  76. };
  77.  
  78. static int
  79. nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
  80.              int invallen, struct ypcallback_data *indata)
  81. {
  82.     if (instatus == YP_TRUE) {
  83.         PyObject *key;
  84.         PyObject *val;
  85.         int err;
  86.  
  87.         if (indata->fix) {
  88.             inkeylen--;
  89.             invallen--;
  90.         }
  91.         key = PyString_FromStringAndSize(inkey, inkeylen);
  92.         val = PyString_FromStringAndSize(inval, invallen);
  93.         if (key == NULL || val == NULL) {
  94.             /* XXX error -- don't know how to handle */
  95.             PyErr_Clear();
  96.             Py_XDECREF(key);
  97.             Py_XDECREF(val);
  98.             return 1;
  99.         }
  100.         err = PyDict_SetItem(indata->dict, key, val);
  101.         Py_DECREF(key);
  102.         Py_DECREF(val);
  103.         if (err != 0) {
  104.             PyErr_Clear();
  105.             return 1;
  106.         }
  107.         return 0;
  108.     }
  109.     return 1;
  110. }
  111.  
  112. static PyObject *
  113. nis_match (PyObject *self, PyObject *args)
  114. {
  115.     char *match;
  116.     char *domain;
  117.     int keylen, len;
  118.     char *key, *map;
  119.     int err;
  120.     PyObject *res;
  121.     int fix;
  122.  
  123.     if (!PyArg_Parse(args, "(t#s)", &key, &keylen, &map))
  124.         return NULL;
  125.     if ((err = yp_get_default_domain(&domain)) != 0)
  126.         return nis_error(err);
  127.     map = nis_mapname (map, &fix);
  128.     if (fix)
  129.         keylen++;
  130.     Py_BEGIN_ALLOW_THREADS
  131.     err = yp_match (domain, map, key, keylen, &match, &len);
  132.     Py_END_ALLOW_THREADS
  133.     if (fix)
  134.         len--;
  135.     if (err != 0)
  136.         return nis_error(err);
  137.     res = PyString_FromStringAndSize (match, len);
  138.     free (match);
  139.     return res;
  140. }
  141.  
  142. static PyObject *
  143. nis_cat (PyObject *self, PyObject *args)
  144. {
  145.     char *domain;
  146.     char *map;
  147.     struct ypall_callback cb;
  148.     struct ypcallback_data data;
  149.     PyObject *dict;
  150.     int err;
  151.  
  152.     if (!PyArg_Parse(args, "s", &map))
  153.         return NULL;
  154.     if ((err = yp_get_default_domain(&domain)) != 0)
  155.         return nis_error(err);
  156.     dict = PyDict_New ();
  157.     if (dict == NULL)
  158.         return NULL;
  159.     cb.foreach = (foreachfunc)nis_foreach;
  160.     data.dict = dict;
  161.     map = nis_mapname (map, &data.fix);
  162.     cb.data = (char *)&data;
  163.     Py_BEGIN_ALLOW_THREADS
  164.     err = yp_all (domain, map, &cb);
  165.     Py_END_ALLOW_THREADS
  166.     if (err != 0) {
  167.         Py_DECREF(dict);
  168.         return nis_error(err);
  169.     }
  170.     return dict;
  171. }
  172.  
  173. /* These should be u_long on Sun h/w but not on 64-bit h/w.
  174.    This is not portable to machines with 16-bit ints and no prototypes */
  175. #ifndef YPPROC_MAPLIST
  176. #define YPPROC_MAPLIST    11
  177. #endif
  178. #ifndef YPPROG
  179. #define YPPROG        100004
  180. #endif
  181. #ifndef YPVERS
  182. #define YPVERS        2
  183. #endif
  184.  
  185. typedef char *domainname;
  186. typedef char *mapname;
  187.  
  188. enum nisstat {
  189.     NIS_TRUE = 1,
  190.     NIS_NOMORE = 2,
  191.     NIS_FALSE = 0,
  192.     NIS_NOMAP = -1,
  193.     NIS_NODOM = -2,
  194.     NIS_NOKEY = -3,
  195.     NIS_BADOP = -4,
  196.     NIS_BADDB = -5,
  197.     NIS_YPERR = -6,
  198.     NIS_BADARGS = -7,
  199.     NIS_VERS = -8
  200. };
  201. typedef enum nisstat nisstat;
  202.  
  203. struct nismaplist {
  204.     mapname map;
  205.     struct nismaplist *next;
  206. };
  207. typedef struct nismaplist nismaplist;
  208.  
  209. struct nisresp_maplist {
  210.     nisstat stat;
  211.     nismaplist *maps;
  212. };
  213. typedef struct nisresp_maplist nisresp_maplist;
  214.  
  215. static struct timeval TIMEOUT = { 25, 0 };
  216.  
  217. static
  218. bool_t
  219. nis_xdr_domainname(XDR *xdrs, domainname *objp)
  220. {
  221.     if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
  222.         return (FALSE);
  223.     }
  224.     return (TRUE);
  225. }
  226.  
  227. static
  228. bool_t
  229. nis_xdr_mapname(XDR *xdrs, mapname *objp)
  230. {
  231.     if (!xdr_string(xdrs, objp, YPMAXMAP)) {
  232.         return (FALSE);
  233.     }
  234.     return (TRUE);
  235. }
  236.  
  237. static
  238. bool_t
  239. nis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
  240. {
  241.     if (!nis_xdr_mapname(xdrs, &objp->map)) {
  242.         return (FALSE);
  243.     }
  244.     if (!xdr_pointer(xdrs, (char **)&objp->next,
  245.              sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
  246.     {
  247.         return (FALSE);
  248.     }
  249.     return (TRUE);
  250. }
  251.  
  252. static
  253. bool_t
  254. nis_xdr_ypstat(XDR *xdrs, nisstat *objp)
  255. {
  256.     if (!xdr_enum(xdrs, (enum_t *)objp)) {
  257.         return (FALSE);
  258.     }
  259.     return (TRUE);
  260. }
  261.  
  262.  
  263. static
  264. bool_t
  265. nis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
  266. {
  267.     if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
  268.         return (FALSE);
  269.     }
  270.     if (!xdr_pointer(xdrs, (char **)&objp->maps,
  271.              sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
  272.     {
  273.         return (FALSE);
  274.     }
  275.     return (TRUE);
  276. }
  277.  
  278.  
  279. static
  280. nisresp_maplist *
  281. nisproc_maplist_2(domainname *argp, CLIENT *clnt)
  282. {
  283.     static nisresp_maplist res;
  284.  
  285.     memset(&res, 0, sizeof(res));
  286.     if (clnt_call(clnt, YPPROC_MAPLIST,
  287.               (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
  288.               (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
  289.               TIMEOUT) != RPC_SUCCESS)
  290.     {
  291.         return (NULL);
  292.     }
  293.     return (&res);
  294. }
  295.  
  296. static
  297. nismaplist *
  298. nis_maplist (void)
  299. {
  300.     nisresp_maplist *list;
  301.     char *dom;
  302.     CLIENT *cl, *clnt_create();
  303.     char *server = NULL;
  304.     int mapi = 0;
  305.         int err;
  306.  
  307.     if ((err = yp_get_default_domain (&dom)) != 0) {
  308.         nis_error(err);
  309.         return NULL;
  310.     }
  311.  
  312.     while (!server && aliases[mapi].map != 0L) {
  313.         yp_master (dom, aliases[mapi].map, &server);
  314.         mapi++;
  315.     }
  316.         if (!server) {
  317.             PyErr_SetString(NisError, "No NIS master found for any map");
  318.             return NULL;
  319.         }
  320.     cl = clnt_create(server, YPPROG, YPVERS, "tcp");
  321.     if (cl == NULL) {
  322.         PyErr_SetString(NisError, clnt_spcreateerror(server));
  323.         goto finally;
  324.     }
  325.     list = nisproc_maplist_2 (&dom, cl);
  326.     clnt_destroy(cl);
  327.     if (list == NULL)
  328.         goto finally;
  329.     if (list->stat != NIS_TRUE)
  330.         goto finally;
  331.  
  332.     free(server);
  333.     return list->maps;
  334.  
  335.   finally:
  336.     free(server);
  337.     return NULL;
  338. }
  339.  
  340. static PyObject *
  341. nis_maps (PyObject *self, PyObject *args)
  342. {
  343.     nismaplist *maps;
  344.     PyObject *list;
  345.  
  346.         if (!PyArg_NoArgs(args))
  347.         return NULL;
  348.     if ((maps = nis_maplist ()) == NULL)
  349.         return NULL;
  350.     if ((list = PyList_New(0)) == NULL)
  351.         return NULL;
  352.     for (maps = maps; maps; maps = maps->next) {
  353.         PyObject *str = PyString_FromString(maps->map);
  354.         if (!str || PyList_Append(list, str) < 0)
  355.         {
  356.             Py_DECREF(list);
  357.             list = NULL;
  358.             break;
  359.         }
  360.         Py_DECREF(str);
  361.     }
  362.     /* XXX Shouldn't we free the list of maps now? */
  363.     return list;
  364. }
  365.  
  366. static PyMethodDef nis_methods[] = {
  367.     {"match",    nis_match},
  368.     {"cat",        nis_cat},
  369.     {"maps",    nis_maps},
  370.     {NULL,        NULL}         /* Sentinel */
  371. };
  372.  
  373. void
  374. initnis (void)
  375. {
  376.     PyObject *m, *d;
  377.     m = Py_InitModule("nis", nis_methods);
  378.     d = PyModule_GetDict(m);
  379.     NisError = PyErr_NewException("nis.error", NULL, NULL);
  380.     if (NisError != NULL)
  381.         PyDict_SetItemString(d, "error", NisError);
  382. }
  383.