Libinfo-78.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 free(global_s.s_name);
64
65 aliases = global_s.s_aliases;
66 if (aliases != NULL)
67 {
68 while (*aliases != NULL) free(*aliases++);
69 free(global_s.s_aliases);
70 }
71
72 global_free = 1;
73 }
74
75 static void
76 convert_s(_lu_servent *lu_s)
77 {
78 int i, len;
79
80 freeold();
81
82 global_s.s_name = strdup(lu_s->s_names.s_names_val[0]);
83
84 len = lu_s->s_names.s_names_len - 1;
85 global_s.s_aliases = (char **)malloc((len + 1) * sizeof(char *));
86
87 for (i = 0; i < len; i++)
88 {
89 global_s.s_aliases[i] = strdup(lu_s->s_names.s_names_val[i+1]);
90 }
91
92 global_s.s_aliases[len] = NULL;
93
94 global_s.s_proto = lu_s->s_proto;
95 global_s.s_port = lu_s->s_port;
96
97 global_free = 0;
98 }
99
100 static struct servent *
101 lu_getservbyport(int port, const char *proto)
102 {
103 unsigned datalen;
104 _lu_servent_ptr lu_s;
105 XDR xdr;
106 static int proc = -1;
107 char output_buf[_LU_MAXLUSTRLEN + 3 * BYTES_PER_XDR_UNIT];
108 unit lookup_buf[MAX_INLINE_UNITS];
109 XDR outxdr;
110
111 if (proc < 0)
112 {
113 if (_lookup_link(_lu_port, "getservbyport", &proc) != KERN_SUCCESS)
114 {
115 return (NULL);
116 }
117 }
118
119 /* Encode NULL for xmission to lookupd. */
120 if (!proto) proto = "";
121
122 xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
123 if (!xdr_int(&outxdr, &port) || !xdr__lu_string(&outxdr, &proto))
124 {
125 xdr_destroy(&outxdr);
126 return (NULL);
127 }
128
129 datalen = MAX_INLINE_UNITS;
130 if (_lookup_one(_lu_port, proc, (unit *)output_buf,
131 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
132 != KERN_SUCCESS)
133 {
134 xdr_destroy(&outxdr);
135 return (NULL);
136 }
137
138 xdr_destroy(&outxdr);
139
140 datalen *= BYTES_PER_XDR_UNIT;
141 xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
142 lu_s = NULL;
143 if (!xdr__lu_servent_ptr(&xdr, &lu_s) || (lu_s == NULL))
144 {
145 xdr_destroy(&xdr);
146 return (NULL);
147 }
148
149 xdr_destroy(&xdr);
150
151 convert_s(lu_s);
152 xdr_free(xdr__lu_servent_ptr, &lu_s);
153 return (&global_s);
154 }
155
156 static struct servent *
157 lu_getservbyname(const char *name, const char *proto)
158 {
159 unsigned datalen;
160 unit lookup_buf[MAX_INLINE_UNITS];
161 char output_buf[2 * (_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT)];
162 XDR outxdr;
163 XDR inxdr;
164 _lu_servent_ptr lu_s;
165 static int proc = -1;
166
167 if (proc < 0)
168 {
169 if (_lookup_link(_lu_port, "getservbyname", &proc) != KERN_SUCCESS)
170 {
171 return (NULL);
172 }
173 }
174
175 /* Encode NULL for xmission to lookupd. */
176 if (!proto) proto = "";
177
178 xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
179 if (!xdr__lu_string(&outxdr, &name) || !xdr__lu_string(&outxdr, &proto))
180 {
181 xdr_destroy(&outxdr);
182 return (NULL);
183 }
184
185 datalen = MAX_INLINE_UNITS;
186 if (_lookup_one(_lu_port, proc, (unit *)output_buf,
187 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
188 != KERN_SUCCESS)
189 {
190 xdr_destroy(&outxdr);
191 return (NULL);
192 }
193
194 xdr_destroy(&outxdr);
195
196 datalen *= BYTES_PER_XDR_UNIT;
197 xdrmem_create(&inxdr, lookup_buf, datalen,
198 XDR_DECODE);
199 lu_s = NULL;
200 if (!xdr__lu_servent_ptr(&inxdr, &lu_s) || (lu_s == NULL))
201 {
202 xdr_destroy(&inxdr);
203 return (NULL);
204 }
205
206 xdr_destroy(&inxdr);
207
208 convert_s(lu_s);
209 xdr_free(xdr__lu_servent_ptr, &lu_s);
210 return (&global_s);
211 }
212
213 static void
214 lu_endservent()
215 {
216 s_nentries = 0;
217 if (s_data != NULL)
218 {
219 freeold();
220 vm_deallocate(mach_task_self(), (vm_address_t)s_data, s_datalen);
221 s_data = NULL;
222 }
223 }
224
225 static void
226 lu_setservent()
227 {
228 lu_endservent();
229 s_start = 1;
230 }
231
232 static struct servent *
233 lu_getservent()
234 {
235 static int proc = -1;
236 _lu_servent lu_s;
237
238 if (s_start == 1)
239 {
240 s_start = 0;
241
242 if (proc < 0)
243 {
244 if (_lookup_link(_lu_port, "getservent", &proc) != KERN_SUCCESS)
245 {
246 lu_endservent();
247 return (NULL);
248 }
249 }
250
251 if (_lookup_all(_lu_port, proc, NULL, 0, &s_data, &s_datalen)
252 != KERN_SUCCESS)
253 {
254 lu_endservent();
255 return (NULL);
256 }
257
258 #ifdef NOTDEF
259 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
260 s_datalen *= BYTES_PER_XDR_UNIT;
261 #endif
262
263 xdrmem_create(&s_xdr, s_data, s_datalen,
264 XDR_DECODE);
265 if (!xdr_int(&s_xdr, &s_nentries))
266 {
267 xdr_destroy(&s_xdr);
268 lu_endservent();
269 return (NULL);
270 }
271 }
272
273 if (s_nentries == 0)
274 {
275 xdr_destroy(&s_xdr);
276 lu_endservent();
277 return (NULL);
278 }
279
280 bzero(&lu_s, sizeof(lu_s));
281 if (!xdr__lu_servent(&s_xdr, &lu_s))
282 {
283 xdr_destroy(&s_xdr);
284 lu_endservent();
285 return (NULL);
286 }
287
288 s_nentries--;
289 convert_s(&lu_s);
290 xdr_free(xdr__lu_servent, &lu_s);
291 return (&global_s);
292 }
293
294 struct servent *
295 getservbyport(int port, const char *proto)
296 {
297 LOOKUP2(lu_getservbyport, _old_getservbyport, port, proto, struct servent);
298 }
299
300 struct servent *
301 getservbyname(const char *name, const char *proto)
302 {
303 LOOKUP2(lu_getservbyname, _old_getservbyname, name, proto,
304 struct servent);
305 }
306
307 struct servent *
308 getservent(void)
309 {
310 GETENT(lu_getservent, _old_getservent, &s_state, struct servent);
311 }
312
313 void
314 setservent(int stayopen)
315 {
316 SETSTATE(lu_setservent, _old_setservent, &s_state, stayopen);
317 }
318
319 void
320 endservent(void)
321 {
322 UNSETSTATE(lu_endservent, _old_endservent, &s_state);
323 }