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