symbian-qemu-0.9.1-12/python-2.6.1/Modules/nismodule.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 PyDoc_STRVAR(get_default_domain__doc__, 
       
    27 "get_default_domain() -> str\n\
       
    28 Corresponds to the C library yp_get_default_domain() call, returning\n\
       
    29 the default NIS domain.\n");
       
    30 
       
    31 PyDoc_STRVAR(match__doc__,
       
    32 "match(key, map, domain = defaultdomain)\n\
       
    33 Corresponds to the C library yp_match() call, returning the value of\n\
       
    34 key in the given map. Optionally domain can be specified but it\n\
       
    35 defaults to the system default domain.\n");
       
    36 
       
    37 PyDoc_STRVAR(cat__doc__,
       
    38 "cat(map, domain = defaultdomain)\n\
       
    39 Returns the entire map as a dictionary. Optionally domain can be\n\
       
    40 specified but it defaults to the system default domain.\n");
       
    41 
       
    42 PyDoc_STRVAR(maps__doc__,
       
    43 "maps(domain = defaultdomain)\n\
       
    44 Returns an array of all available NIS maps within a domain. If domain\n\
       
    45 is not specified it defaults to the system default domain.\n");
       
    46 
       
    47 static PyObject *NisError;
       
    48 
       
    49 static PyObject *
       
    50 nis_error (int err)
       
    51 {
       
    52 	PyErr_SetString(NisError, yperr_string(err));
       
    53 	return NULL;
       
    54 }
       
    55 
       
    56 static struct nis_map {
       
    57 	char *alias;
       
    58 	char *map;
       
    59 	int  fix;
       
    60 } aliases [] = {
       
    61 	{"passwd",	"passwd.byname",	0},
       
    62 	{"group",	"group.byname",		0},
       
    63 	{"networks",	"networks.byaddr",	0},
       
    64 	{"hosts",	"hosts.byname",		0},
       
    65 	{"protocols",	"protocols.bynumber",	0},
       
    66 	{"services",	"services.byname",	0},
       
    67 	{"aliases",	"mail.aliases",		1}, /* created with 'makedbm -a' */
       
    68 	{"ethers",	"ethers.byname",	0},
       
    69 	{0L,		0L,			0}
       
    70 };
       
    71 
       
    72 static char *
       
    73 nis_mapname (char *map, int *pfix)
       
    74 {
       
    75 	int i;
       
    76 
       
    77 	*pfix = 0;
       
    78 	for (i=0; aliases[i].alias != 0L; i++) {
       
    79 		if (!strcmp (aliases[i].alias, map)) {
       
    80 			*pfix = aliases[i].fix;
       
    81 			return aliases[i].map;
       
    82 		}
       
    83 		if (!strcmp (aliases[i].map, map)) {
       
    84 			*pfix = aliases[i].fix;
       
    85 			return aliases[i].map;
       
    86 		}
       
    87 	}
       
    88 
       
    89 	return map;
       
    90 }
       
    91 
       
    92 #ifdef __APPLE__
       
    93 typedef int (*foreachfunc)(unsigned long, char *, int, char *, int, void *);
       
    94 #else
       
    95 typedef int (*foreachfunc)(int, char *, int, char *, int, char *);
       
    96 #endif
       
    97 
       
    98 struct ypcallback_data {
       
    99 	PyObject	*dict;
       
   100 	int			fix;
       
   101 	PyThreadState *state;
       
   102 };
       
   103 
       
   104 static int
       
   105 nis_foreach (int instatus, char *inkey, int inkeylen, char *inval,
       
   106              int invallen, struct ypcallback_data *indata)
       
   107 {
       
   108 	if (instatus == YP_TRUE) {
       
   109 		PyObject *key;
       
   110 		PyObject *val;
       
   111 		int err;
       
   112 
       
   113 		PyEval_RestoreThread(indata->state);
       
   114 		if (indata->fix) {
       
   115 		    if (inkeylen > 0 && inkey[inkeylen-1] == '\0')
       
   116 			inkeylen--;
       
   117 		    if (invallen > 0 && inval[invallen-1] == '\0')
       
   118 			invallen--;
       
   119 		}
       
   120 		key = PyString_FromStringAndSize(inkey, inkeylen);
       
   121 		val = PyString_FromStringAndSize(inval, invallen);
       
   122 		if (key == NULL || val == NULL) {
       
   123 			/* XXX error -- don't know how to handle */
       
   124 			PyErr_Clear();
       
   125 			Py_XDECREF(key);
       
   126 			Py_XDECREF(val);
       
   127 			return 1;
       
   128 		}
       
   129 		err = PyDict_SetItem(indata->dict, key, val);
       
   130 		Py_DECREF(key);
       
   131 		Py_DECREF(val);
       
   132 		if (err != 0)
       
   133 			PyErr_Clear();
       
   134 		indata->state = PyEval_SaveThread();
       
   135 		if (err != 0)
       
   136 		  	return 1;
       
   137 		return 0;
       
   138 	}
       
   139 	return 1;
       
   140 }
       
   141 
       
   142 static PyObject *
       
   143 nis_get_default_domain (PyObject *self)
       
   144 {
       
   145 	char *domain;
       
   146 	int err;
       
   147 	PyObject *res;
       
   148 
       
   149 	if ((err = yp_get_default_domain(&domain)) != 0)
       
   150 		return nis_error(err);
       
   151 
       
   152 	res = PyString_FromStringAndSize (domain, strlen(domain));
       
   153 	return res;
       
   154 }
       
   155 
       
   156 static PyObject *
       
   157 nis_match (PyObject *self, PyObject *args, PyObject *kwdict)
       
   158 {
       
   159 	char *match;
       
   160 	char *domain = NULL;
       
   161 	int keylen, len;
       
   162 	char *key, *map;
       
   163 	int err;
       
   164 	PyObject *res;
       
   165 	int fix;
       
   166 	static char *kwlist[] = {"key", "map", "domain", NULL};
       
   167 
       
   168 	if (!PyArg_ParseTupleAndKeywords(args, kwdict,
       
   169 					 "t#s|s:match", kwlist,
       
   170 					 &key, &keylen, &map, &domain))
       
   171 		return NULL;
       
   172 	if (!domain && ((err = yp_get_default_domain(&domain)) != 0))
       
   173 		return nis_error(err);
       
   174 	map = nis_mapname (map, &fix);
       
   175 	if (fix)
       
   176 	    keylen++;
       
   177 	Py_BEGIN_ALLOW_THREADS
       
   178 	err = yp_match (domain, map, key, keylen, &match, &len);
       
   179 	Py_END_ALLOW_THREADS
       
   180 	if (fix)
       
   181 	    len--;
       
   182 	if (err != 0)
       
   183 		return nis_error(err);
       
   184 	res = PyString_FromStringAndSize (match, len);
       
   185 	free (match);
       
   186 	return res;
       
   187 }
       
   188 
       
   189 static PyObject *
       
   190 nis_cat (PyObject *self, PyObject *args, PyObject *kwdict)
       
   191 {
       
   192 	char *domain = NULL;
       
   193 	char *map;
       
   194 	struct ypall_callback cb;
       
   195 	struct ypcallback_data data;
       
   196 	PyObject *dict;
       
   197 	int err;
       
   198 	static char *kwlist[] = {"map", "domain", NULL};
       
   199 
       
   200 	if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s|s:cat",
       
   201 				         kwlist, &map, &domain))
       
   202 		return NULL;
       
   203 	if (!domain && ((err = yp_get_default_domain(&domain)) != 0))
       
   204 		return nis_error(err);
       
   205 	dict = PyDict_New ();
       
   206 	if (dict == NULL)
       
   207 		return NULL;
       
   208 	cb.foreach = (foreachfunc)nis_foreach;
       
   209 	data.dict = dict;
       
   210 	map = nis_mapname (map, &data.fix);
       
   211 	cb.data = (char *)&data;
       
   212 	data.state = PyEval_SaveThread();
       
   213 	err = yp_all (domain, map, &cb);
       
   214 	PyEval_RestoreThread(data.state);
       
   215 	if (err != 0) {
       
   216 		Py_DECREF(dict);
       
   217 		return nis_error(err);
       
   218 	}
       
   219 	return dict;
       
   220 }
       
   221 
       
   222 /* These should be u_long on Sun h/w but not on 64-bit h/w.
       
   223    This is not portable to machines with 16-bit ints and no prototypes */
       
   224 #ifndef YPPROC_MAPLIST
       
   225 #define YPPROC_MAPLIST	11
       
   226 #endif
       
   227 #ifndef YPPROG
       
   228 #define YPPROG		100004
       
   229 #endif
       
   230 #ifndef YPVERS
       
   231 #define YPVERS		2
       
   232 #endif
       
   233 
       
   234 typedef char *domainname;
       
   235 typedef char *mapname;
       
   236 
       
   237 enum nisstat {
       
   238 	NIS_TRUE = 1,
       
   239 	NIS_NOMORE = 2,
       
   240 	NIS_FALSE = 0,
       
   241 	NIS_NOMAP = -1,
       
   242 	NIS_NODOM = -2,
       
   243 	NIS_NOKEY = -3,
       
   244 	NIS_BADOP = -4,
       
   245 	NIS_BADDB = -5,
       
   246 	NIS_YPERR = -6,
       
   247 	NIS_BADARGS = -7,
       
   248 	NIS_VERS = -8
       
   249 };
       
   250 typedef enum nisstat nisstat;
       
   251 
       
   252 struct nismaplist {
       
   253 	mapname map;
       
   254 	struct nismaplist *next;
       
   255 };
       
   256 typedef struct nismaplist nismaplist;
       
   257 
       
   258 struct nisresp_maplist {
       
   259 	nisstat stat;
       
   260 	nismaplist *maps;
       
   261 };
       
   262 typedef struct nisresp_maplist nisresp_maplist;
       
   263 
       
   264 static struct timeval TIMEOUT = { 25, 0 };
       
   265 
       
   266 static
       
   267 bool_t
       
   268 nis_xdr_domainname(XDR *xdrs, domainname *objp)
       
   269 {
       
   270 	if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
       
   271 		return (FALSE);
       
   272 	}
       
   273 	return (TRUE);
       
   274 }
       
   275 
       
   276 static
       
   277 bool_t
       
   278 nis_xdr_mapname(XDR *xdrs, mapname *objp)
       
   279 {
       
   280 	if (!xdr_string(xdrs, objp, YPMAXMAP)) {
       
   281 		return (FALSE);
       
   282 	}
       
   283 	return (TRUE);
       
   284 }
       
   285 
       
   286 static
       
   287 bool_t
       
   288 nis_xdr_ypmaplist(XDR *xdrs, nismaplist *objp)
       
   289 {
       
   290 	if (!nis_xdr_mapname(xdrs, &objp->map)) {
       
   291 		return (FALSE);
       
   292 	}
       
   293 	if (!xdr_pointer(xdrs, (char **)&objp->next,
       
   294 			 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
       
   295 	{
       
   296 		return (FALSE);
       
   297 	}
       
   298 	return (TRUE);
       
   299 }
       
   300 
       
   301 static
       
   302 bool_t
       
   303 nis_xdr_ypstat(XDR *xdrs, nisstat *objp)
       
   304 {
       
   305 	if (!xdr_enum(xdrs, (enum_t *)objp)) {
       
   306 		return (FALSE);
       
   307 	}
       
   308 	return (TRUE);
       
   309 }
       
   310 
       
   311 
       
   312 static
       
   313 bool_t
       
   314 nis_xdr_ypresp_maplist(XDR *xdrs, nisresp_maplist *objp)
       
   315 {
       
   316 	if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
       
   317 		return (FALSE);
       
   318 	}
       
   319 	if (!xdr_pointer(xdrs, (char **)&objp->maps,
       
   320 			 sizeof(nismaplist), (xdrproc_t)nis_xdr_ypmaplist))
       
   321 	{
       
   322 		return (FALSE);
       
   323 	}
       
   324 	return (TRUE);
       
   325 }
       
   326 
       
   327 
       
   328 static
       
   329 nisresp_maplist *
       
   330 nisproc_maplist_2(domainname *argp, CLIENT *clnt)
       
   331 {
       
   332 	static nisresp_maplist res;
       
   333 
       
   334 	memset(&res, 0, sizeof(res));
       
   335 	if (clnt_call(clnt, YPPROC_MAPLIST,
       
   336 		      (xdrproc_t)nis_xdr_domainname, (caddr_t)argp,
       
   337 		      (xdrproc_t)nis_xdr_ypresp_maplist, (caddr_t)&res,
       
   338 		      TIMEOUT) != RPC_SUCCESS)
       
   339 	{
       
   340 		return (NULL);
       
   341 	}
       
   342 	return (&res);
       
   343 }
       
   344 
       
   345 static
       
   346 nismaplist *
       
   347 nis_maplist (char *dom)
       
   348 {
       
   349 	nisresp_maplist *list;
       
   350 	CLIENT *cl;
       
   351 	char *server = NULL;
       
   352 	int mapi = 0;
       
   353 
       
   354 	while (!server && aliases[mapi].map != 0L) {
       
   355 		yp_master (dom, aliases[mapi].map, &server);
       
   356 		mapi++;
       
   357 	}
       
   358         if (!server) {
       
   359             PyErr_SetString(NisError, "No NIS master found for any map");
       
   360             return NULL;
       
   361         }
       
   362 	cl = clnt_create(server, YPPROG, YPVERS, "tcp");
       
   363 	if (cl == NULL) {
       
   364 		PyErr_SetString(NisError, clnt_spcreateerror(server));
       
   365 		goto finally;
       
   366 	}
       
   367 	list = nisproc_maplist_2 (&dom, cl);
       
   368 	clnt_destroy(cl);
       
   369 	if (list == NULL)
       
   370 		goto finally;
       
   371 	if (list->stat != NIS_TRUE)
       
   372 		goto finally;
       
   373 
       
   374 	free(server);
       
   375 	return list->maps;
       
   376 
       
   377   finally:
       
   378 	free(server);
       
   379 	return NULL;
       
   380 }
       
   381 
       
   382 static PyObject *
       
   383 nis_maps (PyObject *self, PyObject *args, PyObject *kwdict)
       
   384 {
       
   385 	char *domain = NULL;
       
   386 	nismaplist *maps;
       
   387 	PyObject *list;
       
   388         int err;
       
   389 	static char *kwlist[] = {"domain", NULL};
       
   390 
       
   391 	if (!PyArg_ParseTupleAndKeywords(args, kwdict,
       
   392 					 "|s:maps", kwlist, &domain))
       
   393 		return NULL;
       
   394 	if (!domain && ((err = yp_get_default_domain (&domain)) != 0)) {
       
   395 		nis_error(err);
       
   396 		return NULL;
       
   397 	}
       
   398 
       
   399 	if ((maps = nis_maplist (domain)) == NULL)
       
   400 		return NULL;
       
   401 	if ((list = PyList_New(0)) == NULL)
       
   402 		return NULL;
       
   403 	for (maps = maps; maps; maps = maps->next) {
       
   404 		PyObject *str = PyString_FromString(maps->map);
       
   405 		if (!str || PyList_Append(list, str) < 0)
       
   406 		{
       
   407 			Py_DECREF(list);
       
   408 			list = NULL;
       
   409 			break;
       
   410 		}
       
   411 		Py_DECREF(str);
       
   412 	}
       
   413 	/* XXX Shouldn't we free the list of maps now? */
       
   414 	return list;
       
   415 }
       
   416 
       
   417 static PyMethodDef nis_methods[] = {
       
   418 	{"match",		(PyCFunction)nis_match,
       
   419 					METH_VARARGS | METH_KEYWORDS,
       
   420 					match__doc__},
       
   421 	{"cat",			(PyCFunction)nis_cat,
       
   422 					METH_VARARGS | METH_KEYWORDS,
       
   423 					cat__doc__},
       
   424 	{"maps",		(PyCFunction)nis_maps,
       
   425 					METH_VARARGS | METH_KEYWORDS,
       
   426 					maps__doc__},
       
   427 	{"get_default_domain",	(PyCFunction)nis_get_default_domain,
       
   428  					METH_NOARGS,
       
   429 					get_default_domain__doc__},
       
   430 	{NULL,			NULL}		 /* Sentinel */
       
   431 };
       
   432 
       
   433 PyDoc_STRVAR(nis__doc__,
       
   434 "This module contains functions for accessing NIS maps.\n");
       
   435 
       
   436 void
       
   437 initnis (void)
       
   438 {
       
   439 	PyObject *m, *d;
       
   440 	m = Py_InitModule3("nis", nis_methods, nis__doc__);
       
   441 	if (m == NULL)
       
   442 		return;
       
   443 	d = PyModule_GetDict(m);
       
   444 	NisError = PyErr_NewException("nis.error", NULL, NULL);
       
   445 	if (NisError != NULL)
       
   446 		PyDict_SetItemString(d, "error", NisError);
       
   447 }