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