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 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 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 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 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 * 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