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