]> git.saurik.com Git - apple/libinfo.git/blob - lookup.subproj/lu_printer.c
Libinfo-173.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_printer.c
1 /*
2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Printer lookup
27 * Copyright (C) 1989 by NeXT, Inc.
28 */
29 #include <stdlib.h>
30 #include <mach/mach.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <rpc/types.h>
34 #include <rpc/xdr.h>
35 #include <pthread.h>
36
37 #include "_lu_types.h"
38 #include "lookup.h"
39 #include "printerdb.h"
40 #include "lu_utils.h"
41
42 static pthread_mutex_t _printer_lock = PTHREAD_MUTEX_INITIALIZER;
43
44 #define P_GET_NAME 1
45 #define P_GET_ENT 2
46
47 extern prdb_ent *_old_prdb_get();
48 extern prdb_ent *_old_prdb_getbyname();
49 extern void _old_prdb_set();
50 extern void _old_prdb_end();
51
52 static void
53 free_printer_data(prdb_ent *p)
54 {
55 char **names;
56 int i;
57
58 if (p == NULL) return;
59
60 names = p->pe_name;
61 if (names != NULL)
62 {
63 while (*names) free(*names++);
64 free(p->pe_name);
65 }
66
67 for (i = 0; i < p->pe_nprops; i++)
68 {
69 free(p->pe_prop[i].pp_key);
70 free(p->pe_prop[i].pp_value);
71 }
72
73 free(p->pe_prop);
74 }
75
76 static void
77 free_printer(prdb_ent *p)
78 {
79 if (p == NULL) return;
80 free_printer_data(p);
81 free(p);
82 }
83
84 static void
85 free_lu_thread_info_printer(void *x)
86 {
87 struct lu_thread_info *tdata;
88
89 if (x == NULL) return;
90
91 tdata = (struct lu_thread_info *)x;
92
93 if (tdata->lu_entry != NULL)
94 {
95 free_printer((prdb_ent *)tdata->lu_entry);
96 tdata->lu_entry = NULL;
97 }
98
99 _lu_data_free_vm_xdr(tdata);
100
101 free(tdata);
102 }
103
104 static prdb_ent *
105 extract_printer(XDR *xdr)
106 {
107 prdb_ent *p;
108 int i, j, nvals, nkeys, status;
109 char *key, **vals;
110
111 if (xdr == NULL) return NULL;
112
113 if (!xdr_int(xdr, &nkeys)) return NULL;
114
115 p = (prdb_ent *)calloc(1, sizeof(prdb_ent));
116
117 for (i = 0; i < nkeys; i++)
118 {
119 key = NULL;
120 vals = NULL;
121 nvals = 0;
122
123 status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
124 if (status < 0)
125 {
126 free_printer(p);
127 return NULL;
128 }
129
130 j = 0;
131
132 if ((p->pe_name == NULL) && (!strcmp("name", key)))
133 {
134 free(key);
135 p->pe_name = vals;
136 j = nvals;
137 vals = NULL;
138 }
139 else
140 {
141 if (p->pe_nprops == 0)
142 {
143 p->pe_prop = (prdb_property *)calloc(1, sizeof(prdb_property));
144 }
145 else
146 {
147 p->pe_prop = (prdb_property *)realloc(p->pe_prop, (p->pe_nprops + 1) * sizeof(prdb_property));
148 }
149 p->pe_prop[p->pe_nprops].pp_key = key;
150 p->pe_prop[p->pe_nprops].pp_value = NULL;
151 if (nvals > 0)
152 {
153 p->pe_prop[p->pe_nprops].pp_value = vals[0];
154 j = 1;
155 }
156 else
157 {
158 p->pe_prop[p->pe_nprops].pp_value = strdup("");
159 }
160 p->pe_nprops++;
161 }
162
163 if (vals != NULL)
164 {
165 for (; j < nvals; j++) free(vals[j]);
166 free(vals);
167 }
168 }
169
170 if (p->pe_name == NULL) p->pe_name = (char **)calloc(1, sizeof(char *));
171 if (p->pe_prop == NULL) p->pe_prop = (prdb_property *)calloc(1, sizeof(prdb_property));
172
173 return p;
174 }
175
176 static prdb_ent *
177 copy_printer(prdb_ent *in)
178 {
179 int i;
180 prdb_ent *p;
181
182 if (in == NULL) return NULL;
183
184 p = (prdb_ent *)calloc(1, sizeof(prdb_ent));
185
186 if (in->pe_name != NULL)
187 {
188 for (i = 0; in->pe_name[i] != NULL; i++);
189 p->pe_name = (char **)calloc(i, sizeof(char *));
190 for (i = 0; p->pe_name[i] != NULL; i++) p->pe_name[i] = strdup(in->pe_name[i]);
191 }
192 else
193 {
194 p->pe_name = (char **)calloc(1, sizeof(char *));
195 }
196
197 if (in->pe_nprops > 0)
198 {
199 p->pe_prop = (struct prdb_property *)calloc(in->pe_nprops, sizeof(struct prdb_property));
200
201 for (i = 0; in->pe_nprops; i++)
202 {
203 p->pe_prop[i].pp_key = strdup(in->pe_prop[i].pp_key);
204 p->pe_prop[i].pp_value = NULL;
205 if (in->pe_prop[i].pp_value != NULL) p->pe_prop[i].pp_value = strdup(in->pe_prop[i].pp_value);
206 }
207 }
208 else
209 {
210 p->pe_prop = (prdb_property *)calloc(1, sizeof(prdb_property));
211 }
212
213 return p;
214 }
215
216 static void
217 recycle_printer(struct lu_thread_info *tdata, struct prdb_ent *in)
218 {
219 struct prdb_ent *p;
220
221 if (tdata == NULL) return;
222 p = (struct prdb_ent *)tdata->lu_entry;
223
224 if (in == NULL)
225 {
226 free_printer(p);
227 tdata->lu_entry = NULL;
228 }
229
230 if (tdata->lu_entry == NULL)
231 {
232 tdata->lu_entry = in;
233 return;
234 }
235
236 free_printer_data(p);
237
238 p->pe_name = in->pe_name;
239 p->pe_nprops = in->pe_nprops;
240 p->pe_prop = in->pe_prop;
241
242 free(in);
243 }
244
245 static prdb_ent *
246 lu_prdb_getbyname(const char *name)
247 {
248 prdb_ent *p;
249 unsigned datalen;
250 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
251 XDR outxdr;
252 XDR inxdr;
253 static int proc = -1;
254 char *lookup_buf;
255 int count;
256
257 if (proc < 0)
258 {
259 if (_lookup_link(_lu_port, "prdb_getbyname", &proc) != KERN_SUCCESS)
260 {
261 return NULL;
262 }
263 }
264
265 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
266 if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
267 {
268 xdr_destroy(&outxdr);
269 return NULL;
270 }
271
272 datalen = 0;
273 lookup_buf = NULL;
274
275 if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS)
276 {
277 xdr_destroy(&outxdr);
278 return NULL;
279 }
280
281 xdr_destroy(&outxdr);
282
283 datalen *= BYTES_PER_XDR_UNIT;
284 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
285
286 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
287
288 count = 0;
289 if (!xdr_int(&inxdr, &count))
290 {
291 xdr_destroy(&inxdr);
292 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
293 return NULL;
294 }
295
296 if (count == 0)
297 {
298 xdr_destroy(&inxdr);
299 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
300 return NULL;
301 }
302
303 p = extract_printer(&inxdr);
304 xdr_destroy(&inxdr);
305 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
306
307 return p;
308 }
309
310 static void
311 lu_prdb_end()
312 {
313 struct lu_thread_info *tdata;
314
315 tdata = _lu_data_create_key(_lu_data_key_printer, free_lu_thread_info_printer);
316 _lu_data_free_vm_xdr(tdata);
317 }
318
319 static void
320 lu_prdb_set()
321 {
322 lu_prdb_end();
323 }
324
325 static prdb_ent *
326 lu_prdb_get()
327 {
328 prdb_ent *p;
329 static int proc = -1;
330 struct lu_thread_info *tdata;
331
332 tdata = _lu_data_create_key(_lu_data_key_printer, free_lu_thread_info_printer);
333 if (tdata == NULL)
334 {
335 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
336 _lu_data_set_key(_lu_data_key_printer, tdata);
337 }
338
339 if (tdata->lu_vm == NULL)
340 {
341 if (proc < 0)
342 {
343 if (_lookup_link(_lu_port, "prdb_get", &proc) != KERN_SUCCESS)
344 {
345 lu_prdb_end();
346 return NULL;
347 }
348 }
349
350 if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
351 {
352 lu_prdb_end();
353 return NULL;
354 }
355
356 /* mig stubs measure size in words (4 bytes) */
357 tdata->lu_vm_length *= 4;
358
359 if (tdata->lu_xdr != NULL)
360 {
361 xdr_destroy(tdata->lu_xdr);
362 free(tdata->lu_xdr);
363 }
364 tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
365
366 xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
367 if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
368 {
369 lu_prdb_end();
370 return NULL;
371 }
372 }
373
374 if (tdata->lu_vm_cursor == 0)
375 {
376 lu_prdb_end();
377 return NULL;
378 }
379
380 p = extract_printer(tdata->lu_xdr);
381 if (p == NULL)
382 {
383 lu_prdb_end();
384 return NULL;
385 }
386
387 tdata->lu_vm_cursor--;
388
389 return p;
390 }
391
392 static prdb_ent *
393 getprinter(const char *name, int source)
394 {
395 prdb_ent *res = NULL;
396 struct lu_thread_info *tdata;
397
398 tdata = _lu_data_create_key(_lu_data_key_printer, free_lu_thread_info_printer);
399 if (tdata == NULL)
400 {
401 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
402 _lu_data_set_key(_lu_data_key_printer, tdata);
403 }
404
405 if (_lu_running())
406 {
407 switch (source)
408 {
409 case P_GET_NAME:
410 res = lu_prdb_getbyname(name);
411 break;
412 case P_GET_ENT:
413 res = lu_prdb_get();
414 break;
415 default: res = NULL;
416 }
417 }
418 else
419 {
420 pthread_mutex_lock(&_printer_lock);
421 switch (source)
422 {
423 case P_GET_NAME:
424 res = copy_printer(_old_prdb_getbyname(name));
425 break;
426 case P_GET_ENT:
427 res = copy_printer(_old_prdb_get());
428 break;
429 default: res = NULL;
430 }
431 pthread_mutex_unlock(&_printer_lock);
432 }
433
434 recycle_printer(tdata, res);
435 return (prdb_ent *)tdata->lu_entry;
436 }
437
438 const prdb_ent *
439 prdb_getbyname(const char *name)
440 {
441 return (const prdb_ent *)getprinter(name, P_GET_NAME);
442 }
443
444 const prdb_ent *
445 prdb_get(void)
446 {
447 return (const prdb_ent *)getprinter(NULL, P_GET_ENT);
448 }
449
450 void
451 prdb_set(const char *name)
452 {
453 if (_lu_running()) lu_prdb_set();
454 else _old_prdb_set();
455 }
456
457 void
458 prdb_end(void)
459 {
460 if (_lu_running()) lu_prdb_end();
461 else _old_prdb_end();
462 }