]>
Commit | Line | Data |
---|---|---|
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 |
41 | static pthread_mutex_t _printer_lock = PTHREAD_MUTEX_INITIALIZER; |
42 | ||
43 | #define P_GET_NAME 1 | |
44 | #define P_GET_ENT 2 | |
45 | ||
46 | extern prdb_ent *_old_prdb_get(); | |
47 | extern prdb_ent *_old_prdb_getbyname(); | |
03fb6eb0 A |
48 | extern void _old_prdb_set(); |
49 | extern void _old_prdb_end(); | |
50 | ||
03fb6eb0 | 51 | static void |
3b7c7bd7 | 52 | free_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 |
75 | static void |
76 | free_printer(prdb_ent *p) | |
77 | { | |
78 | if (p == NULL) return; | |
79 | free_printer_data(p); | |
80 | free(p); | |
81 | } | |
03fb6eb0 A |
82 | |
83 | static void | |
3b7c7bd7 | 84 | free_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 | ||
103 | static prdb_ent * | |
104 | extract_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 |
175 | static prdb_ent * |
176 | copy_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 | ||
215 | static void | |
3b7c7bd7 | 216 | recycle_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 | 244 | static prdb_ent * |
03fb6eb0 A |
245 | lu_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 |
309 | static void |
310 | lu_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 | ||
318 | static void | |
319 | lu_prdb_set() | |
320 | { | |
321 | lu_prdb_end(); | |
03fb6eb0 A |
322 | } |
323 | ||
324 | static prdb_ent * | |
325 | lu_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 | ||
391 | static prdb_ent * | |
392 | getprinter(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 | ||
437 | const prdb_ent * | |
438 | prdb_getbyname(const char *name) | |
439 | { | |
3b7c7bd7 | 440 | return (const prdb_ent *)getprinter(name, P_GET_NAME); |
03fb6eb0 A |
441 | } |
442 | ||
443 | const prdb_ent * | |
444 | prdb_get(void) | |
445 | { | |
3b7c7bd7 | 446 | return (const prdb_ent *)getprinter(NULL, P_GET_ENT); |
03fb6eb0 A |
447 | } |
448 | ||
449 | void | |
450 | prdb_set(const char *name) | |
451 | { | |
3b7c7bd7 A |
452 | if (_lu_running()) lu_prdb_set(); |
453 | else _old_prdb_set(); | |
03fb6eb0 A |
454 | } |
455 | ||
456 | void | |
457 | prdb_end(void) | |
458 | { | |
3b7c7bd7 A |
459 | if (_lu_running()) lu_prdb_end(); |
460 | else _old_prdb_end(); | |
03fb6eb0 | 461 | } |