1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*LINTLIBRARY*/
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <syslog.h>
37
38 #include <ns.h>
39 #include <list.h>
40
41 static char **
strsplit(char * string,char * seperators)42 strsplit(char *string, char *seperators)
43 {
44 char **list = NULL;
45 char *where = NULL;
46 char *element;
47
48 for (element = strtok_r(string, seperators, &where); element != NULL;
49 element = strtok_r(NULL, seperators, &where))
50 list = (char **)list_append((void **)list, element);
51
52 return (list);
53 }
54
55 /*
56 * Manipulate bsd_addr structures
57 */
58 ns_bsd_addr_t *
bsd_addr_create(const char * server,const char * printer,const char * extension)59 bsd_addr_create(const char *server, const char *printer, const char *extension)
60 {
61 ns_bsd_addr_t *addr = NULL;
62
63 if ((server != NULL) &&
64 ((addr = calloc(1, sizeof (*addr))) != NULL)) {
65 addr->printer = (char *)printer;
66 addr->server = (char *)server;
67 addr->extension = (char *)extension;
68 }
69
70 return (addr);
71 }
72
73 static char *
bsd_addr_to_string(const ns_bsd_addr_t * addr)74 bsd_addr_to_string(const ns_bsd_addr_t *addr)
75 {
76 char buf[BUFSIZ];
77
78 if ((addr == NULL) || (addr->server == NULL))
79 return (NULL);
80
81 if (snprintf(buf, sizeof (buf), "%s", addr->server) >= sizeof (buf)) {
82 syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow");
83 return (NULL);
84 }
85
86 if ((addr->printer != NULL) || (addr->extension != NULL))
87 (void) strlcat(buf, ",", sizeof (buf));
88 if (addr->printer != NULL)
89 if (strlcat(buf, addr->printer, sizeof (buf)) >= sizeof (buf)) {
90 syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow");
91 return (NULL);
92 }
93 if (addr->extension != NULL) {
94 (void) strlcat(buf, ",", sizeof (buf));
95 if (strlcat(buf, addr->extension, sizeof (buf))
96 >= sizeof (buf)) {
97 syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow");
98 return (NULL);
99 }
100 }
101
102 return (strdup(buf));
103 }
104
105 ns_bsd_addr_t *
string_to_bsd_addr(const char * string)106 string_to_bsd_addr(const char *string)
107 {
108 char **list, *tmp, *printer = NULL, *extension = NULL;
109
110 if (string == NULL)
111 return (NULL);
112
113 tmp = strdup(string);
114 list = strsplit(tmp, ",");
115
116 if (list[1] != NULL) {
117 printer = list[1];
118 if (list[2] != NULL)
119 extension = list[2];
120 }
121
122 return (bsd_addr_create(list[0], printer, extension));
123 }
124
125 static char *
list_to_string(const char ** list)126 list_to_string(const char **list)
127 {
128 char buf[BUFSIZ];
129
130 if ((list == NULL) || (*list == NULL))
131 return (NULL);
132
133 if (snprintf(buf, sizeof (buf), "%s", *list) >= sizeof (buf)) {
134 syslog(LOG_ERR, "list_to_string: buffer overflow");
135 return (NULL);
136 }
137
138 while (*++list != NULL) {
139 (void) strlcat(buf, ",", sizeof (buf));
140 if (strlcat(buf, *list, sizeof (buf)) >= sizeof (buf)) {
141 syslog(LOG_ERR, "list_to_string: buffer overflow");
142 return (NULL);
143 }
144 }
145
146 return (strdup(buf));
147 }
148
149 static char *
internal_list_to_string(const ns_printer_t ** list)150 internal_list_to_string(const ns_printer_t **list)
151 {
152 char buf[BUFSIZ];
153
154 if ((list == NULL) || (*list == NULL))
155 return (NULL);
156
157 if (snprintf(buf, sizeof (buf), "%s", (*list)->name) >= sizeof (buf)) {
158 syslog(LOG_ERR, "internal_list_to_string:buffer overflow");
159 return (NULL);
160 }
161
162 while (*++list != NULL) {
163 (void) strlcat(buf, ",", sizeof (buf));
164 if (strlcat(buf, (*list)->name, sizeof (buf)) >= sizeof (buf)) {
165 syslog(LOG_ERR,
166 "internal_list_to_string:buffer overflow");
167 return (NULL);
168 }
169 }
170
171 return (strdup(buf));
172 }
173
174
175 char *
value_to_string(const char * key,void * value)176 value_to_string(const char *key, void *value)
177 {
178 char *string = NULL;
179
180 if ((key != NULL) && (value != NULL)) {
181 if (strcmp(key, NS_KEY_BSDADDR) == 0) {
182 string = bsd_addr_to_string(value);
183 } else if ((strcmp(key, NS_KEY_ALL) == 0) ||
184 (strcmp(key, NS_KEY_GROUP) == 0)) {
185 string = list_to_string(value);
186 } else if (strcmp(key, NS_KEY_LIST) == 0) {
187 string = internal_list_to_string(value);
188 } else {
189 string = strdup((char *)value);
190 }
191 }
192
193 return (string);
194 }
195
196
197 void *
string_to_value(const char * key,char * string)198 string_to_value(const char *key, char *string)
199 {
200 void *value = NULL;
201
202 if ((key != NULL) && (string != NULL) && (string[0] != NULL)) {
203 if (strcmp(key, NS_KEY_BSDADDR) == 0) {
204 value = (void *)string_to_bsd_addr(string);
205 } else if ((strcmp(key, NS_KEY_ALL) == 0) ||
206 (strcmp(key, NS_KEY_GROUP) == 0)) {
207 value = (void *)strsplit(string, ",");
208 } else {
209 value = (void *)string;
210 }
211 }
212
213 return (value);
214 }
215
216 static void
split_name(char * name,const char * delimiter,char ** p1,char ** p2,char ** p3)217 split_name(char *name, const char *delimiter, char **p1, char **p2, char **p3)
218 {
219 char *tmp, *junk = NULL;
220
221 if (p1 != NULL)
222 *p1 = NULL;
223 if (p2 != NULL)
224 *p2 = NULL;
225 if (p3 != NULL)
226 *p3 = NULL;
227
228 if ((name == NULL) || (delimiter == NULL)) {
229 syslog(LOG_DEBUG, "split_name(): name/delimter invalid\n");
230 return;
231 }
232
233 for (tmp = (char *)strtok_r(name, delimiter, &junk); tmp != NULL;
234 tmp = (char *)strtok_r(NULL, delimiter, &junk))
235 if ((p1 != NULL) && (*p1 == NULL))
236 *p1 = tmp;
237 else if ((p2 != NULL) && (*p2 == NULL)) {
238 *p2 = tmp;
239 if (p3 == NULL)
240 break;
241 } else if ((p3 != NULL) && (*p3 == NULL)) {
242 *p3 = tmp;
243 break;
244 }
245 }
246
247 /*
248 * This implements support for printer names that are fully resolvable
249 * on their own. These "complete" names are converted into a ns_printer_t
250 * structure containing an appropriate "bsdaddr" attribute. The supported
251 * formats are as follows:
252 * POSIX style (server:printer[:conformance]).
253 * This format is an adaptation of the format originally
254 * described in POSIX 1387.4. The POSIX draft has since been
255 * squashed, but this particular component lives on. The
256 * conformace field has been added to allow further identification
257 * of the the server.
258 */
259 ns_printer_t *
posix_name(const char * name)260 posix_name(const char *name)
261 {
262 ns_printer_t *printer = NULL;
263 char *tmp = NULL;
264
265 if ((name != NULL) && ((tmp = strpbrk(name, ":")) != NULL)) {
266 char *server = NULL;
267 char *queue = NULL;
268 char *extension = NULL;
269 char *addr = strdup(name);
270 char buf[BUFSIZ];
271
272 if (*tmp == ':')
273 split_name(addr, ": \t", &server, &queue, &extension);
274
275 memset(buf, 0, sizeof (buf));
276 if ((server != NULL) && (queue != NULL))
277 snprintf(buf, sizeof (buf), "%s,%s%s%s", server,
278 queue, (extension != NULL ? "," : ""),
279 (extension != NULL ? extension : ""));
280
281 /* build the structure here */
282 if (buf[0] != NULL) {
283 ns_kvp_t **list, *kvp;
284
285 kvp = ns_kvp_create(NS_KEY_BSDADDR, buf);
286 list = (ns_kvp_t **)list_append(NULL, kvp);
287 if (list != NULL)
288 printer = ns_printer_create(strdup(name), NULL,
289 "posix", list);
290 }
291 }
292
293 return (printer);
294 }
295
296 /*
297 * FUNCTION:
298 * int ns_bsd_addr_cmp(ns_bsd_addr_t *at, ns_bsd_addr_t *a2)
299 * INPUTS:
300 * ns_bsd_addr_t *a1 - a bsd addr
301 * ns_bsd_addr_t *21 - another bsd addr
302 * DESCRIPTION:
303 * This functions compare 2 bsd_addr structures to determine if the
304 * information in them is the same.
305 */
306 static int
ns_bsd_addr_cmp(ns_bsd_addr_t * a1,ns_bsd_addr_t * a2)307 ns_bsd_addr_cmp(ns_bsd_addr_t *a1, ns_bsd_addr_t *a2)
308 {
309 int rc;
310
311 if ((a1 == NULL) || (a2 == NULL))
312 return (1);
313
314 if ((rc = strcmp(a1->server, a2->server)) != 0)
315 return (rc);
316
317 if ((a1->printer == NULL) || (a2->printer == NULL))
318 return (a1->printer != a2->printer);
319
320 return (strcmp(a1->printer, a2->printer));
321 }
322
323
324
325
326 /*
327 * FUNCTION: ns_bsd_addr_cmp_local()
328 *
329 * DESCRIPTION: This function compares 2 bsd_addr structures to determine if
330 * the information in them is the same. It destinquishes between
331 * real printer names and alias names while doing the compare.
332 *
333 * INPUTS: ns_bsd_addr_t *a1 - a bsd addr
334 * ns_bsd_addr_t *21 - another bsd addr
335 */
336
337 static int
ns_bsd_addr_cmp_local(ns_bsd_addr_t * a1,ns_bsd_addr_t * a2)338 ns_bsd_addr_cmp_local(ns_bsd_addr_t *a1, ns_bsd_addr_t *a2)
339
340 {
341 int rc;
342
343 if ((a1 == NULL) || (a2 == NULL))
344 {
345 return (1);
346 }
347
348 if ((rc = strcmp(a1->server, a2->server)) != 0)
349 {
350 return (rc);
351 }
352
353 if ((a1->printer == NULL) || (a2->printer == NULL))
354 {
355 return (a1->printer != a2->printer);
356 }
357
358 rc = strcmp(a1->printer, a2->printer);
359 if (rc == 0)
360 {
361 /*
362 * The printer's real names are the same, but now check if
363 * their local names (alias) are the same.
364 */
365 rc = strcmp(a1->pname, a2->pname);
366 }
367
368 return (rc);
369 } /* ns_bsd_addr_cmp_local */
370
371
372
373 /*
374 * FUNCTION:
375 * ns_bsd_addr_t *ns_bsd_addr_get_name(char *name)
376 * INPUTS:
377 * char *name - name of printer to get address for
378 * OUTPUTS:
379 * ns_bsd_addr_t *(return) - the address of the printer
380 * DESCRIPTION:
381 * This function will get the BSD address of the printer specified.
382 * it fills in the printer name if none is specified in the "name service"
383 * as a convenience to calling functions.
384 */
385 ns_bsd_addr_t *
ns_bsd_addr_get_name(char * name)386 ns_bsd_addr_get_name(char *name)
387 {
388 ns_printer_t *printer;
389 ns_bsd_addr_t *addr = NULL;
390
391 endprinterentry();
392 if ((printer = ns_printer_get_name(name, NULL)) != NULL) {
393 addr = ns_get_value(NS_KEY_BSDADDR, printer);
394
395 if (addr != NULL && addr->printer == NULL)
396 addr->printer = strdup(printer->name);
397 if (addr != NULL) {
398 /*
399 * if the name given is not the same as that in the
400 * this is an alias/remote name so put that into the
401 * pname field otherwise duplicate the real printer
402 * name
403 */
404 if (strcmp(name, printer->name) != 0) {
405 addr->pname = strdup(name);
406 } else {
407 addr->pname = strdup(printer->name);
408 }
409 }
410 }
411
412 return (addr);
413 }
414
415
416 /*
417 * FUNCTION:
418 * ns_bsd_addr_t **ns_bsd_addr_get_list()
419 * OUTPUT:
420 * ns_bsd_addr_t **(return) - a list of bsd addresses for all printers
421 * in all "name services"
422 * DESCRIPTION:
423 * This function will gather a list of all printer addresses in all
424 * of the "name services". All redundancy is removed.
425 */
426 ns_bsd_addr_t **
ns_bsd_addr_get_list(int unique)427 ns_bsd_addr_get_list(int unique)
428
429 {
430 ns_printer_t **printers;
431 ns_bsd_addr_t **list = NULL;
432 char **aliases = NULL;
433
434 for (printers = ns_printer_get_list(NULL);
435 printers != NULL && *printers != NULL; printers++) {
436 ns_bsd_addr_t *addr;
437
438 if (strcmp(NS_NAME_ALL, (*printers)->name) == 0)
439 continue;
440
441 if ((addr = ns_get_value(NS_KEY_BSDADDR, *printers)) != NULL) {
442 if (addr->printer == NULL)
443 addr->printer = strdup((*printers)->name);
444 addr->pname = strdup((*printers)->name);
445 }
446
447 if (unique == UNIQUE)
448 list =
449 (ns_bsd_addr_t **)list_append_unique((void **)list,
450 (void *)addr, (COMP_T)ns_bsd_addr_cmp);
451 else
452 if (unique == LOCAL_UNIQUE)
453 list =
454 (ns_bsd_addr_t **)list_append_unique((void **)list,
455 (void *)addr, (COMP_T)ns_bsd_addr_cmp_local);
456 else
457 list = (ns_bsd_addr_t **)list_append((void **)list,
458 (void *)addr);
459
460 for (aliases = (*printers)->aliases;
461 (aliases != NULL) && (*aliases != NULL); aliases++)
462 {
463 /*
464 * Include any alias names that belong to the printer
465 */
466
467 if ((addr =
468 ns_get_value(NS_KEY_BSDADDR, *printers)) != NULL)
469 {
470 if (addr->printer == NULL)
471 {
472 addr->printer = strdup(*aliases);
473 }
474 addr->pname = strdup(*aliases);
475 }
476
477 if (unique == UNIQUE)
478 {
479 list = (ns_bsd_addr_t **)
480 list_append_unique((void **)list,
481 (void *)addr, (COMP_T)ns_bsd_addr_cmp);
482 }
483 else
484 if (unique == LOCAL_UNIQUE)
485 {
486 list = (ns_bsd_addr_t **)
487 list_append_unique((void **)list,
488 (void *)addr,
489 (COMP_T)ns_bsd_addr_cmp_local);
490 }
491 else
492 {
493 list = (ns_bsd_addr_t **)
494 list_append((void **)list, (void *)addr);
495 }
496 }
497 }
498
499 return (list);
500 }
501
502
503
504
505 /*
506 * FUNCTION:
507 * ns_bsd_addr_t **ns_bsd_addr_get_list()
508 * OUTPUT:
509 * ns_bsd_addr_t **(return) - a list of bsd addresses for "_all" printers
510 * in the "name service"
511 * DESCRIPTION:
512 * This function will use the "_all" entry to find a list of printers and
513 * addresses. The "default" printer is also added to the list.
514 * All redundancy is removed.
515 */
516 ns_bsd_addr_t **
ns_bsd_addr_get_all(int unique)517 ns_bsd_addr_get_all(int unique)
518 {
519 ns_printer_t *printer;
520 ns_bsd_addr_t **list = NULL;
521 char **printers;
522 char *def = NULL;
523
524 if (((def = (char *)getenv("PRINTER")) == NULL) &&
525 ((def = (char *)getenv("LPDEST")) == NULL))
526 def = NS_NAME_DEFAULT;
527
528 list = (ns_bsd_addr_t **)list_append((void **)list,
529 (void *)ns_bsd_addr_get_name(def));
530
531 endprinterentry();
532 if ((printer = ns_printer_get_name(NS_NAME_ALL, NULL)) == NULL)
533 return (ns_bsd_addr_get_list(unique));
534
535 for (printers = (char **)ns_get_value(NS_KEY_ALL, printer);
536 printers != NULL && *printers != NULL; printers++) {
537 ns_bsd_addr_t *addr;
538
539 addr = ns_bsd_addr_get_name(*printers);
540 if (addr != NULL)
541 addr->pname = *printers;
542 if (unique == UNIQUE)
543 list =
544 (ns_bsd_addr_t **)list_append_unique((void **)list,
545 (void *)addr, (COMP_T)ns_bsd_addr_cmp);
546 else
547 list = (ns_bsd_addr_t **)list_append((void **)list,
548 (void *)addr);
549 }
550
551 return (list);
552 }
553
554 ns_bsd_addr_t *
ns_bsd_addr_get_default()555 ns_bsd_addr_get_default()
556 {
557 char *def = NULL;
558 ns_bsd_addr_t *addr;
559
560 if (((def = (char *)getenv("PRINTER")) == NULL) &&
561 ((def = (char *)getenv("LPDEST")) == NULL)) {
562 def = NS_NAME_DEFAULT;
563 addr = ns_bsd_addr_get_name(def);
564 if (addr != NULL) {
565 addr->pname = def;
566 return (addr);
567 }
568 }
569
570 return (NULL);
571 }
572