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 /*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 
35 #include <ns.h>
36 #include <list.h>
37 
38 /*
39  *	Commonly Used routines...
40  */
41 
42 /*
43  * FUNCTION:
44  *	kvp_create(const char *key, const void *value)
45  * INPUT(S):
46  *	const char *key
47  *		- key for key/value pair
48  *	const void *value
49  *		- value for key/value pair
50  * OUTPUT(S):
51  *	ns_kvp_t * (return value)
52  *		- pointer to structure containing the key/value pair
53  * DESCRIPTION:
54  */
55 ns_kvp_t *
ns_kvp_create(const char * key,const char * value)56 ns_kvp_create(const char *key, const char *value)
57 {
58 	ns_kvp_t *kvp;
59 
60 	if ((kvp = calloc(1, sizeof (*kvp))) != NULL) {
61 		kvp->key = strdup(key);
62 		kvp->value = (char *)value;
63 	}
64 	return (kvp);
65 }
66 
67 int
ns_kvp_destroy(void * arg,va_list arg1 __unused)68 ns_kvp_destroy(void *arg, va_list arg1 __unused)
69 {
70 	ns_kvp_t *kvp = arg;
71 
72 	if (kvp != NULL) {
73 		if (kvp->key != NULL)
74 			free(kvp->key);
75 		if (kvp->value != NULL)
76 			free(kvp->value);
77 		free(kvp);
78 	}
79 	return (0);
80 }
81 
82 
83 
84 
85 /*
86  * FUNCTION:
87  *	ns_kvp_match_key(const ns_kvp_t *kvp, const char *key)
88  * INPUT(S):
89  *	const ns_kvp_t *kvp
90  *		- key/value pair to check
91  *	const char *key
92  *		- key for matching
93  * OUTPUT(S):
94  *	int (return value)
95  *		- 0 if matched
96  * DESCRIPTION:
97  */
98 static int
ns_kvp_match_key(const ns_kvp_t * kvp,char * key)99 ns_kvp_match_key(const ns_kvp_t *kvp, char *key)
100 {
101 	if ((kvp != NULL) && (kvp->key != NULL) && (key != NULL))
102 		return (strcmp(kvp->key, key));
103 	return (-1);
104 }
105 
106 
107 /*
108  * FUNCTION:
109  *	ns_r_get_value(const char *key, const ns_printer_t *printer)
110  * INPUT(S):
111  *	const char *key
112  *		- key for matching
113  *	const ns_printer_t *printer
114  *		- printer to glean this from
115  * OUTPUT(S):
116  *	char * (return value)
117  *		- NULL, if not matched
118  * DESCRIPTION:
119  */
120 static void *
ns_r_get_value(const char * key,const ns_printer_t * printer,int level)121 ns_r_get_value(const char *key, const ns_printer_t *printer, int level)
122 {
123 	ns_kvp_t *kvp, **attrs;
124 
125 	if ((key == NULL) || (printer == NULL) ||
126 	    (printer->attributes == NULL))
127 		return (NULL);
128 
129 	if (level++ == 16)
130 		return (NULL);
131 
132 	/* find it right here */
133 	if ((kvp = list_locate((void **)printer->attributes,
134 	    (COMP_T)ns_kvp_match_key, (void *)key)) != NULL) {
135 		void *value = string_to_value(key, kvp->value);
136 
137 		/* fill in an empty printer for a bsdaddr */
138 		if (strcmp(key, NS_KEY_BSDADDR) == 0) {
139 			ns_bsd_addr_t *addr = value;
140 
141 			if (addr->printer == NULL)
142 				addr->printer = strdup(printer->name);
143 		}
144 		return (value);
145 	}
146 
147 	/* find it in a child */
148 	for (attrs = printer->attributes; attrs != NULL && *attrs != NULL;
149 	    attrs++) {
150 		void *value = NULL;
151 
152 		if ((strcmp((*attrs)->key, NS_KEY_ALL) == 0) ||
153 		    (strcmp((*attrs)->key, NS_KEY_GROUP) == 0)) {
154 			char **printers;
155 
156 			for (printers = string_to_value((*attrs)->key,
157 			    (*attrs)->value);
158 			    printers != NULL && *printers != NULL; printers++) {
159 				ns_printer_t *printer =
160 				    ns_printer_get_name(*printers, NULL);
161 
162 				value = ns_r_get_value(key, printer, level);
163 				if (value != NULL)
164 					return (value);
165 				ns_printer_destroy(printer);
166 			}
167 		} else if (strcmp((*attrs)->key, NS_KEY_LIST) == 0) {
168 			ns_printer_t **printers;
169 
170 			for (printers = string_to_value((*attrs)->key,
171 			    (*attrs)->value);
172 			    printers != NULL && *printers != NULL; printers++) {
173 				value = ns_r_get_value(key, *printers, level);
174 				if (value != NULL)
175 					return (value);
176 			}
177 		} else if (strcmp((*attrs)->key, NS_KEY_USE) == 0) {
178 			char *string = NULL;
179 			ns_printer_t *printer =
180 			    ns_printer_get_name((*attrs)->value, NULL);
181 			value = ns_r_get_value(key, printer, level);
182 			if (value != NULL)
183 				string = value_to_string(string, value);
184 			if (string != NULL)
185 				value = string_to_value(key, string);
186 			ns_printer_destroy(printer);
187 		}
188 
189 		if (value != NULL)
190 			return (value);
191 	}
192 
193 	return (NULL);
194 }
195 
196 
197 /*
198  * ns_get_value() gets the value of the passed in attribute from the passed
199  * in printer structure.  The value is returned in a converted format.
200  */
201 void *
ns_get_value(const char * key,const ns_printer_t * printer)202 ns_get_value(const char *key, const ns_printer_t *printer)
203 {
204 	return (ns_r_get_value(key, printer, 0));
205 }
206 
207 
208 /*
209  * ns_get_value_string() gets the value of the key passed in from the
210  * printer structure passed in.  The results is an ascii string.
211  */
212 char *
ns_get_value_string(const char * key,const ns_printer_t * printer)213 ns_get_value_string(const char *key, const ns_printer_t *printer)
214 {
215 	return ((char *)value_to_string(key, ns_get_value(key, printer)));
216 }
217 
218 
219 /*
220  * ns_set_value() sets the passed in kvp in the passed in printer structure,
221  * This is done by converting the value to a string first.
222  */
223 int
ns_set_value(const char * key,const void * value,ns_printer_t * printer)224 ns_set_value(const char *key, const void *value, ns_printer_t *printer)
225 {
226 	return (ns_set_value_from_string(key,
227 	    value_to_string(key, (void *)value), printer));
228 }
229 
230 
231 /*
232  * ns_set_value_from_string() sets the passed in kvp in the passed in printer
233  * structure.
234  */
235 int
ns_set_value_from_string(const char * key,const char * string,ns_printer_t * printer)236 ns_set_value_from_string(const char *key, const char *string,
237     ns_printer_t *printer)
238 {
239 	if (printer == NULL)
240 		return (-1);
241 
242 	if (key == NULL) {
243 		list_iterate((void **)printer->attributes, ns_kvp_destroy);
244 	} else {
245 		ns_kvp_t *kvp;
246 
247 		if (((kvp = list_locate((void **)printer->attributes,
248 		    (COMP_T)ns_kvp_match_key, (void *)key)) == NULL) &&
249 		    ((kvp = calloc(1, sizeof (*kvp))) != NULL)) {
250 			kvp->key = strdup(key);
251 			printer->attributes = (ns_kvp_t **)
252 			    list_append((void **)printer->attributes, kvp);
253 		}
254 		if (string != NULL)
255 			kvp->value = strdup(string);
256 		else
257 			kvp->value = NULL;
258 	}
259 
260 	return (0);
261 }
262