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