2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A *
2N/A * "user" backend for nsswitch "printers" database. This module implements
2N/A * the ${HOME}/.printers naming support. This file provides users with a
2N/A * convenient method of aliasing and specifying an interest list.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#pragma weak _nss_user__printers_constr = _nss_user_printers_constr
2N/A
2N/A#include <nss_dbdefs.h>
2N/A#include "user_common.h"
2N/A#include <string.h>
2N/A#include <stdlib.h>
2N/A#include <ctype.h>
2N/A
2N/Astatic nss_status_t
2N/A_nss_user_printers_convert(char *entry, nss_XbyY_args_t *args)
2N/A{
2N/A nss_status_t res = NSS_NOTFOUND;
2N/A char *namelist = entry;
2N/A char *key = NULL;
2N/A char *value = NULL;
2N/A int length = 0;
2N/A
2N/A if ((value = strpbrk(entry, "\t ")) != NULL) {
2N/A *value = NULL; value++;
2N/A
2N/A while ((*value != NULL) && (isspace(*value) != 0))
2N/A value++;
2N/A
2N/A if ((key = strpbrk(value, "\n\t ")) != NULL)
2N/A *key = NULL;
2N/A }
2N/A
2N/A args->buf.buffer[0] = NULL;
2N/A if ((value == NULL) || (*value == NULL)) { /* bad value */
2N/A args->erange = 1;
2N/A return (res);
2N/A }
2N/A
2N/A if (strcmp(namelist, "_all") == 0)
2N/A key = "all";
2N/A else
2N/A key = "use";
2N/A
2N/A length = snprintf(args->buf.buffer, args->buf.buflen, "%s:%s=",
2N/A namelist, key);
2N/A
2N/A /* append the value ':' must be escaped for posix style names */
2N/A while ((length < args->buf.buflen) && (*value != NULL)) {
2N/A if (*value == ':')
2N/A args->buf.buffer[length++] = '\\';
2N/A args->buf.buffer[length++] = *value++;
2N/A }
2N/A
2N/A if (length >= args->buf.buflen) { /* the value was too big */
2N/A args->erange = 1;
2N/A return (res);
2N/A }
2N/A
2N/A args->buf.buffer[length] = NULL; /* terminate, just in case */
2N/A args->returnval = args->buf.result;
2N/A res = NSS_SUCCESS;
2N/A
2N/A return (res);
2N/A}
2N/A
2N/A/*
2N/A * printers has the hostname as part of the data in the file, but the other
2N/A * backends don't include it in the data passed to the backend. For this
2N/A * reason, we process everything here and don't bother calling the backend.
2N/A */
2N/A/*ARGSUSED*/
2N/Astatic nss_status_t
2N/A_nss_user_XY_printers(be, args, filter)
2N/A user_backend_ptr_t be;
2N/A nss_XbyY_args_t *args;
2N/A const char *filter;
2N/A /*
2N/A * filter not useful here since the key
2N/A * we are looking for is the first "word"
2N/A * on the line and we can be fast enough.
2N/A */
2N/A{
2N/A nss_status_t res;
2N/A int namelen;
2N/A
2N/A if (be->buf == 0 &&
2N/A (be->buf = (char *)malloc(be->minbuf)) == 0) {
2N/A (void) _nss_user_endent(be, 0);
2N/A return (NSS_UNAVAIL); /* really panic, malloc failed */
2N/A }
2N/A
2N/A res = NSS_NOTFOUND;
2N/A namelen = strlen(args->key.name);
2N/A
2N/A /*CONSTCOND*/
2N/A while (1) {
2N/A char *instr = be->buf;
2N/A char *p, *limit;
2N/A int linelen;
2N/A int found = 0;
2N/A
2N/A /*
2N/A * _nss_user_read_line does process the '\' that are used
2N/A * in /etc/printers.conf for continuation and gives one long
2N/A * buffer.
2N/A *
2N/A * linelen counts the characters up to but excluding the '\n'
2N/A */
2N/A if ((linelen = _nss_user_read_line(be->f, instr,
2N/A be->minbuf)) < 0) {
2N/A /* End of file */
2N/A args->returnval = 0;
2N/A args->erange = 0;
2N/A break;
2N/A }
2N/A p = instr;
2N/A
2N/A if (*p == '#') /* comment */
2N/A continue;
2N/A
2N/A /*
2N/A * find the name in the namelist a|b|c...:
2N/A */
2N/A if ((limit = strpbrk(instr, "\t ")) == NULL) /* bad line */
2N/A continue;
2N/A while ((p < limit) && (found == 0)) {
2N/A if ((strncmp(p, args->key.name, namelen) == 0) &&
2N/A ((*(p+namelen) == '|') ||
2N/A (isspace(*(p+namelen)) != 0)))
2N/A found++;
2N/A else {
2N/A if ((p = strchr(p, '|')) == NULL)
2N/A p = limit;
2N/A else /* skip the '|' */
2N/A p++;
2N/A }
2N/A }
2N/A if (found == 0)
2N/A continue;
2N/A
2N/A if ((res = _nss_user_printers_convert(be->buf, args))
2N/A == NSS_SUCCESS)
2N/A break;
2N/A }
2N/A (void) _nss_user_endent(be, 0);
2N/A return (res);
2N/A}
2N/A
2N/Astatic nss_status_t
2N/Agetent(be, a)
2N/A user_backend_ptr_t be;
2N/A void *a;
2N/A{
2N/A nss_XbyY_args_t *args = (nss_XbyY_args_t *)a;
2N/A nss_status_t res = NSS_UNAVAIL;
2N/A
2N/A if (be->buf == 0 &&
2N/A (be->buf = (char *)malloc(be->minbuf)) == 0) {
2N/A return (NSS_UNAVAIL); /* really panic, malloc failed */
2N/A }
2N/A
2N/A if (be->f == 0) {
2N/A if ((res = _nss_user_setent(be, 0)) != NSS_SUCCESS) {
2N/A return (res);
2N/A }
2N/A }
2N/A
2N/A res = NSS_NOTFOUND;
2N/A
2N/A /*CONSTCOND*/
2N/A while (1) {
2N/A char *instr = be->buf;
2N/A int linelen;
2N/A
2N/A if ((linelen = _nss_user_read_line(be->f, instr,
2N/A be->minbuf)) < 0) {
2N/A /* End of file */
2N/A args->returnval = 0;
2N/A args->erange = 0;
2N/A break;
2N/A }
2N/A
2N/A if (*(be->buf) == '#') /* comment */
2N/A continue;
2N/A
2N/A if ((res = _nss_user_printers_convert(be->buf, args))
2N/A == NSS_SUCCESS)
2N/A break;
2N/A }
2N/A return (res);
2N/A}
2N/A
2N/A
2N/Astatic nss_status_t
2N/Agetbyname(be, a)
2N/A user_backend_ptr_t be;
2N/A void *a;
2N/A{
2N/A nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
2N/A nss_status_t res;
2N/A
2N/A /* printers_getbyname() has not set/endent; rewind on each call */
2N/A if ((res = _nss_user_setent(be, 0)) != NSS_SUCCESS) {
2N/A return (res);
2N/A }
2N/A return (_nss_user_XY_printers(be, argp, argp->key.name));
2N/A}
2N/A
2N/Astatic user_backend_op_t printers_ops[] = {
2N/A _nss_user_destr,
2N/A _nss_user_endent,
2N/A _nss_user_setent,
2N/A getent,
2N/A getbyname
2N/A};
2N/A
2N/A/*ARGSUSED*/
2N/Anss_backend_t *
2N/A_nss_user_printers_constr(dummy1, dummy2, dummy3)
2N/A const char *dummy1, *dummy2, *dummy3;
2N/A{
2N/A char path[MAXPATHLEN], *home;
2N/A
2N/A if ((home = getenv("HOME")) == NULL)
2N/A home = "";
2N/A (void) snprintf(path, sizeof (path), "%s/.printers", home);
2N/A
2N/A return (_nss_user_constr(printers_ops,
2N/A sizeof (printers_ops) / sizeof (printers_ops[0]),
2N/A path, NSS_LINELEN_PRINTERS));
2N/A}