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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * "user" backend for nsswitch "printers" database. This module implements 27 * the ${HOME}/.printers naming support. This file provides users with a 28 * convenient method of aliasing and specifying an interest list. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #pragma weak _nss_user__printers_constr = _nss_user_printers_constr 34 35 #include <nss_dbdefs.h> 36 #include "user_common.h" 37 #include <string.h> 38 #include <stdlib.h> 39 #include <ctype.h> 40 41 static nss_status_t 42 _nss_user_printers_convert(char *entry, nss_XbyY_args_t *args) 43 { 44 nss_status_t res = NSS_NOTFOUND; 45 char *namelist = entry; 46 char *key = NULL; 47 char *value = NULL; 48 int length = 0; 49 50 if ((value = strpbrk(entry, "\t ")) != NULL) { 51 *value = NULL; value++; 52 53 while ((*value != NULL) && (isspace(*value) != 0)) 54 value++; 55 56 if ((key = strpbrk(value, "\n\t ")) != NULL) 57 *key = NULL; 58 } 59 60 args->buf.buffer[0] = NULL; 61 if ((value == NULL) || (*value == NULL)) { /* bad value */ 62 args->erange = 1; 63 return (res); 64 } 65 66 if (strcmp(namelist, "_all") == 0) 67 key = "all"; 68 else 69 key = "use"; 70 71 length = snprintf(args->buf.buffer, args->buf.buflen, "%s:%s=", 72 namelist, key); 73 74 /* append the value ':' must be escaped for posix style names */ 75 while ((length < args->buf.buflen) && (*value != NULL)) { 76 if (*value == ':') 77 args->buf.buffer[length++] = '\\'; 78 args->buf.buffer[length++] = *value++; 79 } 80 81 if (length >= args->buf.buflen) { /* the value was too big */ 82 args->erange = 1; 83 return (res); 84 } 85 86 args->buf.buffer[length] = NULL; /* terminate, just in case */ 87 args->returnval = args->buf.result; 88 res = NSS_SUCCESS; 89 90 return (res); 91 } 92 93 /* 94 * printers has the hostname as part of the data in the file, but the other 95 * backends don't include it in the data passed to the backend. For this 96 * reason, we process everything here and don't bother calling the backend. 97 */ 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 parsestat; 111 int namelen; 112 113 if (be->buf == 0 && 114 (be->buf = (char *)malloc(be->minbuf)) == 0) { 115 (void) _nss_user_endent(be, 0); 116 return (NSS_UNAVAIL); /* really panic, malloc failed */ 117 } 118 119 res = NSS_NOTFOUND; 120 namelen = strlen(args->key.name); 121 122 while (1) { 123 char *instr = be->buf; 124 char *p, *limit; 125 int linelen; 126 int found = 0; 127 char *key, *value; 128 129 /* 130 * _nss_user_read_line does process the '\' that are used 131 * in /etc/printers.conf for continuation and gives one long 132 * buffer. 133 * 134 * linelen counts the characters up to but excluding the '\n' 135 */ 136 if ((linelen = _nss_user_read_line(be->f, instr, 137 be->minbuf)) < 0) { 138 /* End of file */ 139 args->returnval = 0; 140 args->erange = 0; 141 break; 142 } 143 p = instr; 144 145 if (*p == '#') /* comment */ 146 continue; 147 148 /* 149 * find the name in the namelist a|b|c...: 150 */ 151 if ((limit = strpbrk(instr, "\t ")) == NULL) /* bad line */ 152 continue; 153 while ((p < limit) && (found == 0)) { 154 if ((strncmp(p, args->key.name, namelen) == 0) && 155 ((*(p+namelen) == '|') || 156 (isspace(*(p+namelen)) != 0))) 157 found++; 158 else { 159 if ((p = strchr(p, '|')) == NULL) 160 p = limit; 161 else /* skip the '|' */ 162 p++; 163 } 164 } 165 if (found == 0) 166 continue; 167 168 if ((res = _nss_user_printers_convert(be->buf, args)) 169 == NSS_SUCCESS) 170 break; 171 } 172 (void) _nss_user_endent(be, 0); 173 return (res); 174 } 175 176 static nss_status_t 177 getent(be, a) 178 user_backend_ptr_t be; 179 void *a; 180 { 181 nss_XbyY_args_t *args = (nss_XbyY_args_t *)a; 182 nss_status_t res = NSS_UNAVAIL; 183 184 if (be->buf == 0 && 185 (be->buf = (char *)malloc(be->minbuf)) == 0) { 186 return (NSS_UNAVAIL); /* really panic, malloc failed */ 187 } 188 189 if (be->f == 0) { 190 if ((res = _nss_user_setent(be, 0)) != NSS_SUCCESS) { 191 return (res); 192 } 193 } 194 195 res = NSS_NOTFOUND; 196 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 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 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