Libinfo-89.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_service.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Services file lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28 #include <stdlib.h>
29 #include <mach/mach.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include "lookup.h"
33 #include <rpc/types.h>
34 #include <rpc/xdr.h>
35 #include "_lu_types.h"
36 #include <netdb.h>
37 #include "lu_utils.h"
38 #import <netinet/in.h>
39
40 extern struct servent *_old_getservbyport();
41 extern struct servent *_old_getservbyname();
42 extern struct servent *_old_getservent();
43 extern void _old_setservent();
44 extern void _old_endservent();
45 extern void _old_setservfile();
46
47 static lookup_state s_state = LOOKUP_CACHE;
48 static struct servent global_s;
49 static int global_free = 1;
50 static char *s_data = NULL;
51 static unsigned s_datalen;
52 static int s_nentries;
53 static int s_start = 1;
54 static XDR s_xdr;
55
56 static void
57 freeold(void)
58 {
59 char **aliases;
60
61 if (global_free == 1) return;
62
63 if (global_s.s_name != NULL) free(global_s.s_name);
64 global_s.s_name = NULL;
65
66 if (global_s.s_proto != NULL) free(global_s.s_proto);
67 global_s.s_proto = NULL;
68
69 aliases = global_s.s_aliases;
70 if (aliases != NULL)
71 {
72 while (*aliases != NULL) free(*aliases++);
73 free(global_s.s_aliases);
74 global_s.s_aliases = NULL;
75 }
76
77 global_free = 1;
78 }
79
80 static void
81 convert_s(_lu_servent *lu_s)
82 {
83 int i, len;
84
85 freeold();
86
87 global_s.s_name = strdup(lu_s->s_names.s_names_val[0]);
88
89 len = lu_s->s_names.s_names_len - 1;
90 global_s.s_aliases = (char **)malloc((len + 1) * sizeof(char *));
91
92 for (i = 0; i < len; i++)
93 {
94 global_s.s_aliases[i] = strdup(lu_s->s_names.s_names_val[i+1]);
95 }
96
97 global_s.s_aliases[len] = NULL;
98
99 if (lu_s->s_proto != NULL) global_s.s_proto = strdup(lu_s->s_proto);
100 global_s.s_port = lu_s->s_port;
101
102 global_free = 0;
103 }
104
105 static struct servent *
106 lu_getservbyport(int port, const char *proto)
107 {
108 unsigned datalen;
109 _lu_servent_ptr lu_s;
110 XDR xdr;
111 static int proc = -1;
112 char output_buf[_LU_MAXLUSTRLEN + 3 * BYTES_PER_XDR_UNIT];
113 unit lookup_buf[MAX_INLINE_UNITS];
114 XDR outxdr;
115
116 if (proc < 0)
117 {
118 if (_lookup_link(_lu_port, "getservbyport", &proc) != KERN_SUCCESS)
119 {
120 return (NULL);
121 }
122 }
123
124 /* Encode NULL for xmission to lookupd. */
125 if (!proto) proto = "";
126
127 xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
128 if (!xdr_int(&outxdr, &port) || !xdr__lu_string(&outxdr, &proto))
129 {
130 xdr_destroy(&outxdr);
131 return (NULL);
132 }
133
134 datalen = MAX_INLINE_UNITS;
135 if (_lookup_one(_lu_port, proc, (unit *)output_buf,
136 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
137 != KERN_SUCCESS)
138 {
139 xdr_destroy(&outxdr);
140 return (NULL);
141 }
142
143 xdr_destroy(&outxdr);
144
145 datalen *= BYTES_PER_XDR_UNIT;
146 xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
147 lu_s = NULL;
148 if (!xdr__lu_servent_ptr(&xdr, &lu_s) || (lu_s == NULL))
149 {
150 xdr_destroy(&xdr);
151 return (NULL);
152 }
153
154 xdr_destroy(&xdr);
155
156 convert_s(lu_s);
157 xdr_free(xdr__lu_servent_ptr, &lu_s);
158 return (&global_s);
159 }
160
161 static struct servent *
162 lu_getservbyname(const char *name, const char *proto)
163 {
164 unsigned datalen;
165 unit lookup_buf[MAX_INLINE_UNITS];
166 char output_buf[2 * (_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT)];
167 XDR outxdr;
168 XDR inxdr;
169 _lu_servent_ptr lu_s;
170 static int proc = -1;
171
172 if (proc < 0)
173 {
174 if (_lookup_link(_lu_port, "getservbyname", &proc) != KERN_SUCCESS)
175 {
176 return (NULL);
177 }
178 }
179
180 /* Encode NULL for xmission to lookupd. */
181 if (!proto) proto = "";
182
183 xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
184 if (!xdr__lu_string(&outxdr, &name) || !xdr__lu_string(&outxdr, &proto))
185 {
186 xdr_destroy(&outxdr);
187 return (NULL);
188 }
189
190 datalen = MAX_INLINE_UNITS;
191 if (_lookup_one(_lu_port, proc, (unit *)output_buf,
192 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
193 != KERN_SUCCESS)
194 {
195 xdr_destroy(&outxdr);
196 return (NULL);
197 }
198
199 xdr_destroy(&outxdr);
200
201 datalen *= BYTES_PER_XDR_UNIT;
202 xdrmem_create(&inxdr, lookup_buf, datalen,
203 XDR_DECODE);
204 lu_s = NULL;
205 if (!xdr__lu_servent_ptr(&inxdr, &lu_s) || (lu_s == NULL))
206 {
207 xdr_destroy(&inxdr);
208 return (NULL);
209 }
210
211 xdr_destroy(&inxdr);
212
213 convert_s(lu_s);
214 xdr_free(xdr__lu_servent_ptr, &lu_s);
215 return (&global_s);
216 }
217
218 static void
219 lu_endservent()
220 {
221 s_nentries = 0;
222 if (s_data != NULL)
223 {
224 freeold();
225 vm_deallocate(mach_task_self(), (vm_address_t)s_data, s_datalen);
226 s_data = NULL;
227 }
228 }
229
230 static void
231 lu_setservent()
232 {
233 lu_endservent();
234 s_start = 1;
235 }
236
237 static struct servent *
238 lu_getservent()
239 {
240 static int proc = -1;
241 _lu_servent lu_s;
242
243 if (s_start == 1)
244 {
245 s_start = 0;
246
247 if (proc < 0)
248 {
249 if (_lookup_link(_lu_port, "getservent", &proc) != KERN_SUCCESS)
250 {
251 lu_endservent();
252 return (NULL);
253 }
254 }
255
256 if (_lookup_all(_lu_port, proc, NULL, 0, &s_data, &s_datalen)
257 != KERN_SUCCESS)
258 {
259 lu_endservent();
260 return (NULL);
261 }
262
263 #ifdef NOTDEF
264 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
265 s_datalen *= BYTES_PER_XDR_UNIT;
266 #endif
267
268 xdrmem_create(&s_xdr, s_data, s_datalen,
269 XDR_DECODE);
270 if (!xdr_int(&s_xdr, &s_nentries))
271 {
272 xdr_destroy(&s_xdr);
273 lu_endservent();
274 return (NULL);
275 }
276 }
277
278 if (s_nentries == 0)
279 {
280 xdr_destroy(&s_xdr);
281 lu_endservent();
282 return (NULL);
283 }
284
285 bzero(&lu_s, sizeof(lu_s));
286 if (!xdr__lu_servent(&s_xdr, &lu_s))
287 {
288 xdr_destroy(&s_xdr);
289 lu_endservent();
290 return (NULL);
291 }
292
293 s_nentries--;
294 convert_s(&lu_s);
295 xdr_free(xdr__lu_servent, &lu_s);
296 return (&global_s);
297 }
298
299 struct servent *
300 getservbyport(int port, const char *proto)
301 {
302 LOOKUP2(lu_getservbyport, _old_getservbyport, port, proto, struct servent);
303 }
304
305 struct servent *
306 getservbyname(const char *name, const char *proto)
307 {
308 LOOKUP2(lu_getservbyname, _old_getservbyname, name, proto,
309 struct servent);
310 }
311
312 struct servent *
313 getservent(void)
314 {
315 GETENT(lu_getservent, _old_getservent, &s_state, struct servent);
316 }
317
318 void
319 setservent(int stayopen)
320 {
321 SETSTATE(lu_setservent, _old_setservent, &s_state, stayopen);
322 }
323
324 void
325 endservent(void)
326 {
327 UNSETSTATE(lu_endservent, _old_endservent, &s_state);
328 }