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 * "user" backend for nsswitch "printers" database. This module implements
26 * the ${HOME}/.printers naming support. This file provides users with a
27 * convenient method of aliasing and specifying an interest list.
28 */
29
30 #pragma weak _nss_user__printers_constr = _nss_user_printers_constr
31
32 #include <nss_dbdefs.h>
33 #include "user_common.h"
34 #include <string.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37
38 static nss_status_t
_nss_user_printers_convert(char * entry,nss_XbyY_args_t * args)39 _nss_user_printers_convert(char *entry, nss_XbyY_args_t *args)
40 {
41 nss_status_t res = NSS_NOTFOUND;
42 char *namelist = entry;
43 char *key = NULL;
44 char *value = NULL;
45 int length = 0;
46
47 if ((value = strpbrk(entry, "\t ")) != NULL) {
48 *value = '\0';
49 value++;
50
51 while ((*value != '\0') && (isspace(*value) != 0))
52 value++;
53
54 if ((key = strpbrk(value, "\n\t ")) != NULL)
55 *key = '\0';
56 }
57
58 args->buf.buffer[0] = '\0';
59 if ((value == NULL) || (*value == '\0')) { /* bad value */
60 args->erange = 1;
61 return (res);
62 }
63
64 if (strcmp(namelist, "_all") == 0)
65 key = "all";
66 else
67 key = "use";
68
69 length = snprintf(args->buf.buffer, args->buf.buflen, "%s:%s=",
70 namelist, key);
71
72 /* append the value ':' must be escaped for posix style names */
73 while ((length < args->buf.buflen) && (*value != '\0')) {
74 if (*value == ':')
75 args->buf.buffer[length++] = '\\';
76 args->buf.buffer[length++] = *value++;
77 }
78
79 if (length >= args->buf.buflen) { /* the value was too big */
80 args->erange = 1;
81 return (res);
82 }
83
84 args->buf.buffer[length] = '\0'; /* terminate, just in case */
85 args->returnval = args->buf.result;
86 res = NSS_SUCCESS;
87
88 return (res);
89 }
90
91 /*
92 * printers has the hostname as part of the data in the file, but the other
93 * backends don't include it in the data passed to the backend. For this
94 * reason, we process everything here and don't bother calling the backend.
95 */
96 /*ARGSUSED*/
97 static nss_status_t
_nss_user_XY_printers(be,args,filter)98 _nss_user_XY_printers(be, args, filter)
99 user_backend_ptr_t be;
100 nss_XbyY_args_t *args;
101 const char *filter;
102 /*
103 * filter not useful here since the key
104 * we are looking for is the first "word"
105 * on the line and we can be fast enough.
106 */
107 {
108 nss_status_t res;
109 int namelen;
110
111 if (be->buf == 0 &&
112 (be->buf = (char *)malloc(be->minbuf)) == 0) {
113 (void) _nss_user_endent(be, 0);
114 return (NSS_UNAVAIL); /* really panic, malloc failed */
115 }
116
117 res = NSS_NOTFOUND;
118 namelen = strlen(args->key.name);
119
120 /*CONSTCOND*/
121 while (1) {
122 char *instr = be->buf;
123 char *p, *limit;
124 int linelen;
125 int found = 0;
126
127 /*
128 * _nss_user_read_line does process the '\' that are used
129 * in /etc/printers.conf for continuation and gives one long
130 * buffer.
131 *
132 * linelen counts the characters up to but excluding the '\n'
133 */
134 if ((linelen = _nss_user_read_line(be->f, instr,
135 be->minbuf)) < 0) {
136 /* End of file */
137 args->returnval = 0;
138 args->erange = 0;
139 break;
140 }
141 p = instr;
142
143 if (*p == '#') /* comment */
144 continue;
145
146 /*
147 * find the name in the namelist a|b|c...:
148 */
149 if ((limit = strpbrk(instr, "\t ")) == NULL) /* bad line */
150 continue;
151 while ((p < limit) && (found == 0)) {
152 if ((strncmp(p, args->key.name, namelen) == 0) &&
153 ((*(p+namelen) == '|') ||
154 (isspace(*(p+namelen)) != 0)))
155 found++;
156 else {
157 if ((p = strchr(p, '|')) == NULL)
158 p = limit;
159 else /* skip the '|' */
160 p++;
161 }
162 }
163 if (found == 0)
164 continue;
165
166 if ((res = _nss_user_printers_convert(be->buf, args))
167 == NSS_SUCCESS)
168 break;
169 }
170 (void) _nss_user_endent(be, 0);
171 return (res);
172 }
173
174 static nss_status_t
getent(be,a)175 getent(be, a)
176 user_backend_ptr_t be;
177 void *a;
178 {
179 nss_XbyY_args_t *args = (nss_XbyY_args_t *)a;
180 nss_status_t res = NSS_UNAVAIL;
181
182 if (be->buf == 0 &&
183 (be->buf = (char *)malloc(be->minbuf)) == 0) {
184 return (NSS_UNAVAIL); /* really panic, malloc failed */
185 }
186
187 if (be->f == 0) {
188 if ((res = _nss_user_setent(be, 0)) != NSS_SUCCESS) {
189 return (res);
190 }
191 }
192
193 res = NSS_NOTFOUND;
194
195 /*CONSTCOND*/
196 while (1) {
197 char *instr = be->buf;
198 int linelen;
199
200 if ((linelen = _nss_user_read_line(be->f, instr,
201 be->minbuf)) < 0) {
202 /* End of file */
203 args->returnval = 0;
204 args->erange = 0;
205 break;
206 }
207
208 if (*(be->buf) == '#') /* comment */
209 continue;
210
211 if ((res = _nss_user_printers_convert(be->buf, args))
212 == NSS_SUCCESS)
213 break;
214 }
215 return (res);
216 }
217
218
219 static nss_status_t
getbyname(be,a)220 getbyname(be, a)
221 user_backend_ptr_t be;
222 void *a;
223 {
224 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
225 nss_status_t res;
226
227 /* printers_getbyname() has not set/endent; rewind on each call */
228 if ((res = _nss_user_setent(be, 0)) != NSS_SUCCESS) {
229 return (res);
230 }
231 return (_nss_user_XY_printers(be, argp, argp->key.name));
232 }
233
234 static user_backend_op_t printers_ops[] = {
235 _nss_user_destr,
236 _nss_user_endent,
237 _nss_user_setent,
238 getent,
239 getbyname
240 };
241
242 /*ARGSUSED*/
243 nss_backend_t *
_nss_user_printers_constr(dummy1,dummy2,dummy3)244 _nss_user_printers_constr(dummy1, dummy2, dummy3)
245 const char *dummy1, *dummy2, *dummy3;
246 {
247 char path[MAXPATHLEN], *home;
248
249 if ((home = getenv("HOME")) == NULL)
250 home = "";
251 (void) snprintf(path, sizeof (path), "%s/.printers", home);
252
253 return (_nss_user_constr(printers_ops,
254 sizeof (printers_ops) / sizeof (printers_ops[0]),
255 path, NSS_LINELEN_PRINTERS));
256 }
257