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