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 /*
29  * This file contains routines necessary to convert a string buffer into
30  * a printer object.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <string.h>
38 #include <stdarg.h>
39 #include <syslog.h>
40 
41 #include <ns.h>
42 #include <list.h>
43 #include <misc.h>
44 
45 #define	ESCAPE_CHARS	"\\\n=:"	/* \, \n, =, : */
46 
47 /*
48  * Just like strncat(3C), but escapes the supplied characters.
49  * This allows the escape character '\' and seperators to be part of the
50  * keys or values.
51  */
52 char *
53 strncat_escaped(char *d, char *s, int len, char *escape)
54 {
55 	char *t = d;
56 
57 	while ((*t != NULL) && (len > 0))
58 		len--, t++;
59 
60 	if (escape == NULL)
61 		escape = "\\";
62 
63 	while ((*s != NULL) && (len > 0)) {
64 		if (strchr(escape, *s) != NULL)
65 			len--, *t++ = '\\';
66 		len--, *t++ = *s++;
67 	}
68 	*t = NULL;
69 
70 	return (d);
71 }
72 
73 
74 
75 char *
76 _cvt_printer_to_entry(ns_printer_t *printer, char *buf, int buflen)
77 {
78 	int i, len;
79 	int bufferok = 1;
80 
81 	(void) memset(buf, NULL, buflen);
82 
83 	if ((printer == NULL) || (printer->attributes == NULL))
84 		return (NULL);
85 
86 	if (snprintf(buf, buflen, "%s", printer->name) >= buflen) {
87 		(void) memset(buf, NULL, buflen);
88 		syslog(LOG_ERR, "_cvt_printer_to_entry: buffer overflow");
89 		return (NULL);
90 	}
91 
92 	if ((printer->aliases != NULL) && (printer->aliases[0] != NULL)) {
93 		char **alias = printer->aliases;
94 
95 		while (*alias != NULL) {
96 			(void) strlcat(buf, "|", buflen);
97 			(void) strncat_escaped(buf, *alias++, buflen,
98 			    ESCAPE_CHARS);
99 		}
100 	}
101 
102 	if (strlcat(buf, ":", buflen) >= buflen) {
103 		(void) memset(buf, NULL, buflen);
104 		syslog(LOG_ERR, "_cvt_printer_to_entry: buffer overflow");
105 		return (NULL);
106 	}
107 
108 	len = strlen(buf);
109 
110 	for (i = 0; printer->attributes[i] != NULL && bufferok; i++) {
111 		ns_kvp_t *kvp = printer->attributes[i];
112 
113 		if (kvp->value == NULL)
114 			continue;
115 		(void) strlcat(buf, "\\\n\t:", buflen);
116 		(void) strncat_escaped(buf, kvp->key, buflen, ESCAPE_CHARS);
117 		(void) strlcat(buf, "=", buflen);
118 		(void) strncat_escaped(buf, kvp->value, buflen, ESCAPE_CHARS);
119 		if (strlcat(buf, ":", buflen) >= buflen) {
120 			bufferok = 0;
121 		}
122 	}
123 
124 	if (!bufferok) {
125 		(void) memset(buf, NULL, buflen);
126 		syslog(LOG_ERR, "_cvt_printer_to_entry: buffer overflow");
127 		return (NULL);
128 	}
129 
130 	if (strlen(buf) == len) {	/* there were no attributes */
131 		(void) memset(buf, NULL, buflen);
132 		buf = NULL;
133 	}
134 
135 	return (buf);
136 }
137 
138 
139 ns_printer_t *
140 _cvt_nss_entry_to_printer(char *entry, char *ns)
141 {
142 	char	*name = NULL,
143 		*key = NULL,
144 		**aliases = NULL,
145 		*cp,
146 		buf[BUFSIZ];
147 	int in_namelist = 1, buf_pos = 0;
148 	ns_printer_t *printer = NULL;
149 
150 	if (entry == NULL)
151 		return (NULL);
152 
153 	(void) memset(buf, NULL, sizeof (buf));
154 	for (cp = entry; *cp != NULL; cp++) {
155 		switch (*cp) {
156 		case ':':	/* end of kvp */
157 			if (in_namelist != 0) {
158 				if (name == NULL)
159 					name = strdup(buf);
160 				else
161 					aliases = (char **)list_append(
162 							(void **)aliases,
163 							(void *)strdup(buf));
164 				printer = (ns_printer_t *)ns_printer_create(
165 						name, aliases, ns, NULL);
166 				in_namelist = 0;
167 			} else if (key != NULL)
168 				(void) ns_set_value_from_string(key, buf,
169 				    printer);
170 			(void) memset(buf, NULL, sizeof (buf));
171 			buf_pos = 0;
172 			key = NULL;
173 			break;
174 		case '=':	/* kvp seperator */
175 			if (key == NULL) {
176 				key = strdup(buf);
177 				(void) memset(buf, NULL, sizeof (buf));
178 				buf_pos = 0;
179 			} else
180 				buf[buf_pos++] = *cp;
181 			break;
182 		case '|':	/* namelist seperator */
183 			if (in_namelist != 0) {
184 				if (name == NULL)
185 					name = strdup(buf);
186 				else
187 					aliases = (char **)list_append(
188 							(void **)aliases,
189 							(void *)strdup(buf));
190 				(void) memset(buf, NULL, sizeof (buf));
191 				buf_pos = 0;
192 			} else	/* add it to the buffer */
193 				buf[buf_pos++] = *cp;
194 			break;
195 		case '\\':	/* escape char */
196 			buf[buf_pos++] = *(++cp);
197 			break;
198 		default:
199 			buf[buf_pos++] = *cp;
200 		}
201 
202 	}
203 
204 	if (key != NULL)
205 		(void) ns_set_value_from_string(key, buf, printer);
206 
207 	return (printer);
208 }
209