improve treatment of multi-line replies, ignore empty lines
[python/dscho.git] / Modules / nismodule.c
blob00c35616bfec213870dc7bf9a3f7617090723dbd
1 /***********************************************************
2 Written by:
3 Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
4 Vakgroep Spa,
5 Faculteit der Informatica,
6 Universiteit Twente,
7 Enschede,
8 the Netherlands.
9 ******************************************************************/
11 /* NIS module implementation */
13 #include "allobjects.h"
14 #include "modsupport.h"
15 #include "ceval.h"
17 #include <rpcsvc/ypclnt.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <rpc/rpc.h>
21 #include <rpcsvc/yp_prot.h>
23 static object *NisError;
25 static object *
26 nis_error (err)
27 int err;
29 err_setstr(NisError, yperr_string(err));
30 return NULL;
33 static struct nis_map {
34 char *alias;
35 char *map;
36 } aliases [] = {
37 {"passwd", "passwd.byname"},
38 {"group", "group.byname"},
39 {"networks", "networks.byaddr"},
40 {"hosts", "hosts.byname"},
41 {"protocols", "protocols.bynumber"},
42 {"services", "services.byname"},
43 {"aliases", "mail.aliases"},
44 {"ethers", "ethers.byname"},
45 {0L, 0L}
48 static char *
49 nis_mapname (map)
50 char *map;
52 int i;
54 for (i=0; aliases[i].alias != 0L; i++)
55 if (!strcmp (aliases[i].alias, map))
56 map = aliases[i].map;
57 return map;
60 typedef int (*foreachfunc) PROTO((int, char *, int, char *, int, char *));
62 static int
63 nis_foreach (instatus, inkey, inkeylen, inval, invallen, indata)
64 int instatus;
65 char *inkey;
66 int inkeylen;
67 char *inval;
68 int invallen;
69 object *indata;
71 if (instatus == YP_TRUE) {
72 object *key = newsizedstringobject(inkey, inkeylen);
73 object *val = newsizedstringobject(inval, invallen);
74 int err;
75 if (key == NULL || val == NULL) {
76 /* XXX error -- don't know how to handle */
77 err_clear();
78 XDECREF(key);
79 XDECREF(val);
80 return 1;
82 err = mappinginsert(indata, key, val);
83 DECREF(key);
84 DECREF(val);
85 if (err != 0) {
86 err_clear();
87 return 1;
89 return 0;
91 return 1;
94 static object *
95 nis_match (self, args)
96 object *self;
97 object *args;
99 char *match;
100 char *domain;
101 int keylen, len;
102 char *key, *map;
103 int err;
104 object *res;
106 if (!getargs(args, "(s#s)", &key, &keylen, &map))
107 return NULL;
108 if ((err = yp_get_default_domain(&domain)) != 0)
109 return nis_error(err);
110 BGN_SAVE
111 map = nis_mapname (map);
112 err = yp_match (domain, map, key, keylen, &match, &len);
113 END_SAVE
114 if (err != 0)
115 return nis_error(err);
116 res = newsizedstringobject (match, len);
117 free (match);
118 return res;
121 static object *
122 nis_cat (self, args)
123 object *self;
124 object *args;
126 char *domain;
127 char *map;
128 struct ypall_callback cb;
129 object *cat;
130 int err;
132 if (!getstrarg(args, &map))
133 return NULL;
134 if ((err = yp_get_default_domain(&domain)) != 0)
135 return nis_error(err);
136 cat = newdictobject ();
137 if (cat == NULL)
138 return NULL;
139 cb.foreach = (foreachfunc)nis_foreach;
140 cb.data = (char *)cat;
141 BGN_SAVE
142 map = nis_mapname (map);
143 err = yp_all (domain, map, &cb);
144 END_SAVE
145 if (err != 0) {
146 DECREF(cat);
147 return nis_error(err);
149 return cat;
152 /* These should be u_long on Sun h/w but not on 64-bit h/w.
153 This is not portable to machines with 16-bit ints and no prototypes */
154 #ifndef YPPROC_MAPLIST
155 #define YPPROC_MAPLIST 11
156 #endif
157 #ifndef YPPROG
158 #define YPPROG 100004
159 #endif
160 #ifndef YPVERS
161 #define YPVERS 2
162 #endif
164 typedef char *domainname;
165 typedef char *mapname;
167 enum nisstat {
168 NIS_TRUE = 1,
169 NIS_NOMORE = 2,
170 NIS_FALSE = 0,
171 NIS_NOMAP = -1,
172 NIS_NODOM = -2,
173 NIS_NOKEY = -3,
174 NIS_BADOP = -4,
175 NIS_BADDB = -5,
176 NIS_YPERR = -6,
177 NIS_BADARGS = -7,
178 NIS_VERS = -8
180 typedef enum nisstat nisstat;
182 struct nismaplist {
183 mapname map;
184 struct nismaplist *next;
186 typedef struct nismaplist nismaplist;
188 struct nisresp_maplist {
189 nisstat stat;
190 nismaplist *maps;
192 typedef struct nisresp_maplist nisresp_maplist;
194 static struct timeval TIMEOUT = { 25, 0 };
196 static
197 bool_t
198 nis_xdr_domainname(xdrs, objp)
199 XDR *xdrs;
200 domainname *objp;
202 if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) {
203 return (FALSE);
205 return (TRUE);
208 static
209 bool_t
210 nis_xdr_mapname(xdrs, objp)
211 XDR *xdrs;
212 mapname *objp;
214 if (!xdr_string(xdrs, objp, YPMAXMAP)) {
215 return (FALSE);
217 return (TRUE);
220 static
221 bool_t
222 nis_xdr_ypmaplist(xdrs, objp)
223 XDR *xdrs;
224 nismaplist *objp;
226 if (!nis_xdr_mapname(xdrs, &objp->map)) {
227 return (FALSE);
229 if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(nismaplist), nis_xdr_ypmaplist)) {
230 return (FALSE);
232 return (TRUE);
235 static
236 bool_t
237 nis_xdr_ypstat(xdrs, objp)
238 XDR *xdrs;
239 nisstat *objp;
241 if (!xdr_enum(xdrs, (enum_t *)objp)) {
242 return (FALSE);
244 return (TRUE);
248 static
249 bool_t
250 nis_xdr_ypresp_maplist(xdrs, objp)
251 XDR *xdrs;
252 nisresp_maplist *objp;
254 if (!nis_xdr_ypstat(xdrs, &objp->stat)) {
255 return (FALSE);
257 if (!xdr_pointer(xdrs, (char **)&objp->maps, sizeof(nismaplist), nis_xdr_ypmaplist)) {
258 return (FALSE);
260 return (TRUE);
264 static
265 nisresp_maplist *
266 nisproc_maplist_2(argp, clnt)
267 domainname *argp;
268 CLIENT *clnt;
270 static nisresp_maplist res;
272 memset(&res, 0, sizeof(res));
273 if (clnt_call(clnt, YPPROC_MAPLIST, nis_xdr_domainname, (caddr_t)argp,
274 nis_xdr_ypresp_maplist, (caddr_t)&res, TIMEOUT)
275 != RPC_SUCCESS) {
276 return (NULL);
278 return (&res);
281 static
282 nismaplist *
283 nis_maplist ()
285 nisresp_maplist *list;
286 char *dom;
287 CLIENT *cl, *clnt_create();
288 char *server;
290 yp_get_default_domain (&dom);
291 yp_master (dom, aliases[0].map, &server);
292 cl = clnt_create(server, YPPROG, YPVERS, "tcp");
293 if (cl == NULL) {
294 clnt_pcreateerror(server);
295 return NULL;
297 list = nisproc_maplist_2 (&dom, cl);
298 if (list == NULL)
299 return NULL;
300 if (list->stat != NIS_TRUE)
301 return NULL;
302 return list->maps;
305 static object *
306 nis_maps (self, args)
307 object *self;
308 object *args;
310 nismaplist *maps;
311 object *list;
313 if ((maps = nis_maplist ()) == NULL)
314 return NULL;
315 if ((list = newlistobject(0)) == NULL)
316 return NULL;
317 for (maps = maps->next; maps; maps = maps->next) {
318 if (addlistitem (list, newstringobject (maps->map)) < 0) {
319 DECREF(list);
320 list = NULL;
321 break;
324 /* XXX Shouldn't we free the list of maps now? */
325 return list;
328 static struct methodlist nis_methods[] = {
329 {"match", nis_match},
330 {"cat", nis_cat},
331 {"maps", nis_maps},
332 {NULL, NULL} /* Sentinel */
335 void
336 initnis ()
338 object *m, *d;
339 m = initmodule("nis", nis_methods);
340 d = getmoduledict(m);
341 NisError = newstringobject("nis.error");
342 if (NisError == NULL || dictinsert(d, "error", NisError) != 0)
343 fatal("Cannot define nis.error");