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