Libinfo-278.0.3.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_rpc.c
1 /*
2 * Copyright (c) 1999-2006 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 * RPC lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28
29 #include <rpc/rpc.h>
30 #include <netdb.h>
31 #include <stdlib.h>
32 #include <mach/mach.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdint.h>
36 #include <netinet/in.h>
37 #include <pthread.h>
38 #include "lu_utils.h"
39 #include "lu_overrides.h"
40
41 static pthread_mutex_t _rpc_lock = PTHREAD_MUTEX_INITIALIZER;
42
43 #define RPC_GET_NAME 1
44 #define RPC_GET_NUM 2
45 #define RPC_GET_ENT 3
46
47 #define ENTRY_SIZE sizeof(struct rpcent)
48 #define ENTRY_KEY _li_data_key_rpc
49
50 static struct rpcent *
51 copy_rpc(struct rpcent *in)
52 {
53 if (in == NULL) return NULL;
54
55 return (struct rpcent *)LI_ils_create("s*4", in->r_name, in->r_aliases, in->r_number);
56 }
57
58 /*
59 * Extract the next rpc entry from a kvarray.
60 */
61 static void *
62 extract_rpc(kvarray_t *in)
63 {
64 struct rpcent tmp;
65 uint32_t d, k, kcount;
66 char *empty[1];
67
68 if (in == NULL) return NULL;
69
70 d = in->curr;
71 in->curr++;
72
73 if (d >= in->count) return NULL;
74
75 empty[0] = NULL;
76 memset(&tmp, 0, ENTRY_SIZE);
77
78 kcount = in->dict[d].kcount;
79
80 for (k = 0; k < kcount; k++)
81 {
82 if (!strcmp(in->dict[d].key[k], "r_name"))
83 {
84 if (tmp.r_name != NULL) continue;
85 if (in->dict[d].vcount[k] == 0) continue;
86
87 tmp.r_name = (char *)in->dict[d].val[k][0];
88 }
89 else if (!strcmp(in->dict[d].key[k], "r_number"))
90 {
91 if (in->dict[d].vcount[k] == 0) continue;
92 tmp.r_number = atoi(in->dict[d].val[k][0]);
93 }
94 else if (!strcmp(in->dict[d].key[k], "r_aliases"))
95 {
96 if (tmp.r_aliases != NULL) continue;
97 if (in->dict[d].vcount[k] == 0) continue;
98
99 tmp.r_aliases = (char **)in->dict[d].val[k];
100 }
101 }
102
103 if (tmp.r_name == NULL) tmp.r_name = "";
104 if (tmp.r_aliases == NULL) tmp.r_aliases = empty;
105
106 return copy_rpc(&tmp);
107 }
108
109 /*
110 * Send a query to the system information daemon.
111 */
112 static struct rpcent *
113 ds_getrpcbynumber(uint32_t number)
114 {
115 static int proc = -1;
116 char val[16];
117
118 snprintf(val, sizeof(val), "%u", number);
119 return (struct rpcent *)LI_getone("getrpcbynumber", &proc, extract_rpc, "number", val);
120 }
121
122 /*
123 * Send a query to the system information daemon.
124 */
125 static struct rpcent *
126 ds_getrpcbyname(const char *name)
127 {
128 static int proc = -1;
129
130 return (struct rpcent *)LI_getone("getrpcbyname", &proc, extract_rpc, "name", name);
131 }
132
133 /*
134 * Clean up / initialize / reinitialize the kvarray used to hold a list of all rpc entries.
135 */
136 static void
137 ds_endrpcent(void)
138 {
139 LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY));
140 }
141
142 static void
143 ds_setrpcent(void)
144 {
145 ds_endrpcent();
146 }
147
148 /*
149 * Get an entry from the getrpcent kvarray.
150 * Calls the system information daemon if the list doesn't exist (first call),
151 * or extracts the next entry if the list has been fetched.
152 */
153 static struct rpcent *
154 ds_getrpcent(void)
155 {
156 static int proc = -1;
157
158 return (struct rpcent *)LI_getent("getrpcent", &proc, extract_rpc, ENTRY_KEY, ENTRY_SIZE);
159 }
160
161 /*
162 * Checks if the system information daemon is running.
163 * If so, calls the appropriate fetch routine.
164 * If not, calls the appropriate "_old" routine.
165 * Places the result in thread-specific memory.
166 */
167 static struct rpcent *
168 getrpc(const char *name, uint32_t number, int source)
169 {
170 struct rpcent *res = NULL;
171 struct li_thread_info *tdata;
172
173 tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE);
174 if (tdata == NULL) return NULL;
175
176 if (_ds_running())
177 {
178 switch (source)
179 {
180 case RPC_GET_NAME:
181 res = ds_getrpcbyname(name);
182 break;
183 case RPC_GET_NUM:
184 res = ds_getrpcbynumber(number);
185 break;
186 case RPC_GET_ENT:
187 res = ds_getrpcent();
188 break;
189 default: res = NULL;
190 }
191 }
192 else
193 {
194 pthread_mutex_lock(&_rpc_lock);
195
196 switch (source)
197 {
198 case RPC_GET_NAME:
199 res = copy_rpc(_old_getrpcbyname(name));
200 break;
201 case RPC_GET_NUM:
202 res = copy_rpc(_old_getrpcbynumber(number));
203 break;
204 case RPC_GET_ENT:
205 res = copy_rpc(_old_getrpcent());
206 break;
207 default: res = NULL;
208 }
209
210 pthread_mutex_unlock(&_rpc_lock);
211 }
212
213 LI_data_recycle(tdata, res, ENTRY_SIZE);
214 return (struct rpcent *)tdata->li_entry;
215 }
216
217 struct rpcent *
218 getrpcbyname(const char *name)
219 {
220 return getrpc(name, -2, RPC_GET_NAME);
221 }
222
223 struct rpcent *
224 #ifdef __LP64__
225 getrpcbynumber(int number)
226 #else
227 getrpcbynumber(long number)
228 #endif
229 {
230 uint32_t n;
231
232 n = number;
233 return getrpc(NULL, n, RPC_GET_NUM);
234 }
235
236 struct rpcent *
237 getrpcent(void)
238 {
239 return getrpc(NULL, -2, RPC_GET_ENT);
240 }
241
242 void
243 setrpcent(int stayopen)
244 {
245 if (_ds_running()) ds_setrpcent();
246 else _old_setrpcent(stayopen);
247 }
248
249 void
250 endrpcent(void)
251 {
252 if (_ds_running()) ds_endrpcent();
253 else _old_endrpcent();
254 }