summaryrefslogtreecommitdiff
path: root/usr/src/lib/print/libpapi-dynamic/common/nss.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/print/libpapi-dynamic/common/nss.c')
-rw-r--r--usr/src/lib/print/libpapi-dynamic/common/nss.c497
1 files changed, 497 insertions, 0 deletions
diff --git a/usr/src/lib/print/libpapi-dynamic/common/nss.c b/usr/src/lib/print/libpapi-dynamic/common/nss.c
new file mode 100644
index 0000000000..9a142827c4
--- /dev/null
+++ b/usr/src/lib/print/libpapi-dynamic/common/nss.c
@@ -0,0 +1,497 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ */
+
+/* $Id: nss.c 166 2006-05-20 05:48:55Z njacobs $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <papi.h>
+#include <uri.h>
+#include <papi_impl.h>
+#ifdef NSS_EMULATION
+#include <nss-emulation.h>
+#elif NSS_SOLARIS
+#include <nss_dbdefs.h>
+#endif
+#include <config-site.h>
+#if defined(__sun) && defined(__SVR4)
+#include <sys/systeminfo.h>
+#endif
+
+
+static char *
+bsdaddr_to_uri(char *bsdaddr)
+{
+ char *result = NULL;
+
+ if (bsdaddr != NULL) {
+ char *bsd[3], *tmp, *iter = NULL;
+ char buf[512];
+
+ tmp = strdup(bsdaddr);
+
+ bsd[0] = strtok_r(tmp, ":,", &iter);
+ bsd[1] = strtok_r(NULL, ":,", &iter);
+ bsd[2] = strtok_r(NULL, ":,", &iter);
+
+ snprintf(buf, sizeof (buf), "lpd://%s/%s%s%s", bsd[0], bsd[1],
+ (bsd[2] != NULL) ? "#" : "",
+ (bsd[2] != NULL) ? bsd[2] : "");
+
+ free(tmp);
+
+ result = strdup(buf);
+ }
+
+ return (result);
+}
+
+#if defined(__sun) && defined(__SVR4)
+/*
+ * This is an awful HACK to force the dynamic PAPI library to use the
+ * lpsched support when the destination apears to be a local lpsched
+ * queue on Solaris.
+ */
+static void
+solaris_lpsched_shortcircuit_hack(papi_attribute_t ***list)
+{
+ papi_attribute_t *attribute;
+ uri_t *uri = NULL;
+ char *printer = NULL;
+ char hostname[BUFSIZ];
+ char buf[128], buf2[128];
+
+ /* setting this in the calling env can be useful for debugging */
+ if (getenv("DISABLE_LPSCHED_SHORTCIRCUIT") != NULL)
+ return;
+
+ papiAttributeListGetString(*list, NULL,
+ "printer-uri-supported", &printer);
+ if (uri_from_string(printer, &uri) < 0)
+ return;
+
+ /* already an lpsched URI ? */
+ if (strcasecmp(uri->scheme, "lpsched") == 0)
+ return;
+
+ sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
+ if ((uri->host != NULL) &&
+ (strncasecmp(uri->host, hostname, strlen(hostname)) != 0) &&
+ (strncasecmp(uri->host, "localhost", 10) != 0))
+ return;
+
+ if ((printer = strrchr(uri->path, '/')) == NULL)
+ printer = uri->path;
+ else
+ printer++;
+
+ /* is there an lpsched queue (printer/class) */
+ snprintf(buf, sizeof (buf), "/etc/lp/interfaces/%s", printer);
+ snprintf(buf2, sizeof (buf2), "/etc/lp/classes/%s", printer);
+ if ((access(buf, F_OK) < 0) && (access(buf2, F_OK) < 0))
+ return;
+
+ snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s", printer);
+ papiAttributeListAddString(list, PAPI_ATTR_REPLACE,
+ "printer-uri-supported", buf);
+}
+#endif
+
+static void
+fill_printer_uri_supported(papi_attribute_t ***list)
+{
+ papi_attribute_t *attribute;
+ char *string = NULL;
+
+ /* do we have a printer-uri-supported */
+ attribute = papiAttributeListFind(*list, "printer-uri-supported");
+ if (attribute != NULL) /* we have what we need, return */
+ return;
+
+ /* do we have a printer-uri to rename */
+ attribute = papiAttributeListFind(*list, "printer-uri");
+ if (attribute != NULL) { /* rename it in place and return */
+ free(attribute->name);
+ attribute->name = strdup("printer-uri-supported");
+ return;
+ }
+
+ /* do we have a printers.conf(4) "bsdaddr" to convert */
+ papiAttributeListGetString(*list, NULL, "bsdaddr", &string);
+ if (string != NULL) { /* parse it, convert it, add it */
+ char *uri = bsdaddr_to_uri(string);
+
+ if (uri != NULL) {
+ papiAttributeListAddString(list, PAPI_ATTR_APPEND,
+ "printer-uri-supported", uri);
+ papiAttributeListDelete(list, "bsdaddr");
+ free(uri);
+ return;
+ }
+ }
+
+ /* do we have a printers.conf(4) "rm" (and "rp") to convert */
+ papiAttributeListGetString(*list, NULL, "rm", &string);
+ if (string != NULL) {
+ char *rp = NULL;
+
+ /* default to "printer-name", but use "rp" if we have it */
+ papiAttributeListGetString(*list, NULL, "printer-name", &rp);
+ papiAttributeListGetString(*list, NULL, "rp", &rp);
+
+ if (rp != NULL) { /* fill in the uri if we have the data */
+ char buf[BUFSIZ];
+
+ snprintf(buf, sizeof (buf), "lpd://%s/printers/%s",
+ string, rp);
+ papiAttributeListAddString(list, PAPI_ATTR_APPEND,
+ "printer-uri-supported", strdup(buf));
+ return;
+ }
+ }
+
+ /* if were are here, we don't have a printer-uri-supported */
+}
+
+#ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
+static void
+fill_printer_uri(papi_attribute_t ***list)
+{
+ papi_attribute_t *attribute;
+ char *uri = NULL;
+
+ if ((list == NULL) || (*list == NULL))
+ return;
+
+ /* do we have a printer-uri-supported */
+ attribute = papiAttributeListFind(*list, "printer-uri");
+ if (attribute != NULL) /* we have what we need, return */
+ return;
+
+ /*
+ * this is sufficient to fool libgnomeprintpapi, but not promote it's
+ * use in the future.
+ */
+ papiAttributeListAddString(list, PAPI_ATTR_EXCL, "printer-uri",
+ "broken printer-uri semantic");
+}
+#endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
+
+static void
+cvt_all_to_member_names(papi_attribute_t ***list)
+{
+ papi_status_t status;
+ void *iter = NULL;
+ char *string = NULL;
+
+ papiAttributeListGetString(*list, NULL, "member-names", &string);
+ if (string != NULL) /* already have a member-names */
+ return;
+
+ for (status = papiAttributeListGetString(*list, &iter, "all", &string);
+ status == PAPI_OK;
+ status = papiAttributeListGetString(*list, &iter, NULL, &string)) {
+ char *s_iter = NULL, *value, *tmp = strdup(string);
+
+ for (value = strtok_r(tmp, ", \t", &s_iter);
+ value != NULL;
+ value = strtok_r(NULL, ", \t", &s_iter))
+ papiAttributeListAddString(list, PAPI_ATTR_APPEND,
+ "member-names", value);
+ free(tmp);
+ }
+}
+
+static papi_attribute_t **
+_cvt_nss_entry_to_printer(char *entry)
+{
+ char *key = NULL,
+ *cp,
+ buf[BUFSIZ];
+ int in_namelist = 1, buf_pos = 0;
+ papi_attribute_t **list = NULL;
+
+ if (entry == NULL)
+ return (NULL);
+
+ memset(buf, 0, sizeof (buf));
+ for (cp = entry; *cp != '\0'; cp++) {
+ switch (*cp) {
+ case ':': /* end of kvp */
+ if (in_namelist != 0) {
+ papiAttributeListAddString(&list,
+ PAPI_ATTR_APPEND, "printer-name", buf);
+ in_namelist = 0;
+ } else if (key != NULL)
+ papiAttributeListAddString(&list,
+ PAPI_ATTR_APPEND, key, buf);
+ memset(buf, 0, sizeof (buf));
+ buf_pos = 0;
+ key = NULL;
+ break;
+ case '=': /* kvp seperator */
+ if (key == NULL) {
+ key = strdup(buf);
+ memset(buf, 0, sizeof (buf));
+ buf_pos = 0;
+ } else
+ buf[buf_pos++] = *cp;
+ break;
+ case '|': /* namelist seperator */
+ if (in_namelist != 0) {
+ papiAttributeListAddString(&list,
+ PAPI_ATTR_APPEND, "printer-name", buf);
+ memset(buf, 0, sizeof (buf));
+ buf_pos = 0;
+ } else /* add it to the buffer */
+ buf[buf_pos++] = *cp;
+ break;
+ case '\\': /* escape char */
+ buf[buf_pos++] = *(++cp);
+ break;
+ default:
+ buf[buf_pos++] = *cp;
+ }
+
+ }
+
+ if (key != NULL)
+ papiAttributeListAddString(&list, PAPI_ATTR_APPEND, key, buf);
+
+ /* resolve any "use" references in the configuration DB */
+ key = NULL;
+ papiAttributeListGetString(list, NULL, "use", &key);
+ if (key != NULL) {
+ papi_attribute_t **use_attrs = getprinterbyname(key, NULL);
+
+ list_concatenate(&list, use_attrs);
+ }
+
+ fill_printer_uri_supported(&list);
+#if defined(__sun) && defined(__SVR4)
+ solaris_lpsched_shortcircuit_hack(&list);
+#endif
+ cvt_all_to_member_names(&list); /* convert "all" to "member-names" */
+
+ return (list);
+}
+
+#if defined(NSS_SOLARIS) && !defined(NSS_EMULATION)
+
+#ifndef NSS_DBNAM__PRINTERS /* not in nss_dbdefs.h because it's private */
+#define NSS_DBNAM__PRINTERS "_printers"
+#endif
+
+static DEFINE_NSS_DB_ROOT(db_root);
+static DEFINE_NSS_GETENT(context);
+
+static char *private_ns = NULL;
+static char initialized = 0;
+
+static void
+_nss_initf_printers(p)
+ nss_db_params_t *p;
+{
+ if (private_ns != NULL) {
+ /*
+ * because we need to support a legacy interface that allows
+ * us to select a specific name service, we need to dummy up
+ * the parameters to use a private nsswitch database and set
+ * the * default_config entry to the name service we are
+ * looking into.
+ */
+ p->name = NSS_DBNAM__PRINTERS; /* "_printers" */
+ p->default_config = private_ns;
+ private_ns = NULL;
+ } else if (initialized == 0) {
+ /* regular behaviour */
+ p->name = NSS_DBNAM_PRINTERS; /* "printers" */
+ p->default_config = NSS_DEFCONF_PRINTERS;
+ initialized = 1;
+ }
+ syslog(LOG_DEBUG, "database: %s, services: %s",
+ (p->name ? p->name : "NULL"),
+ (p->default_config ? p->default_config : "NULL"));
+}
+
+/*
+ * Return values: 0 = success, 1 = parse error, 2 = erange ...
+ * The structure pointer passed in is a structure in the caller's space
+ * wherein the field pointers would be set to areas in the buffer if
+ * need be. instring and buffer should be separate areas.
+ */
+/* ARGSUSED */
+static int
+str2printer(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
+{
+ if (lenstr + 1 > buflen)
+ return (NSS_STR_PARSE_ERANGE);
+ /*
+ * We copy the input string into the output buffer
+ */
+ (void) memcpy(buffer, instr, lenstr);
+ buffer[lenstr] = '\0';
+
+ return (NSS_STR_PARSE_SUCCESS);
+}
+#endif /* NSS_SOLARIS */
+
+int
+setprinterentry(int stayopen, char *ns)
+{
+#ifdef NSS_EMULATION
+ emul_setprinterentry(stayopen);
+#elif NSS_SOLARIS
+ initialized = 0;
+ private_ns = ns;
+ nss_setent(&db_root, _nss_initf_printers, &context);
+#endif
+ return (0);
+}
+
+
+int
+endprinterentry(int i)
+{
+#ifdef NSS_EMULATION
+ emul_endprinterentry();
+#elif NSS_SOLARIS
+ initialized = 0;
+ nss_endent(&db_root, _nss_initf_printers, &context);
+ nss_delete(&db_root);
+#endif
+ return (0);
+}
+
+/* ARGSUSED2 */
+papi_attribute_t **
+getprinterentry(char *ns)
+{
+ papi_attribute_t **result = NULL;
+
+#if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
+ char buf[10240];
+ nss_status_t res = NSS_NOTFOUND;
+
+#ifdef NSS_EMULATION
+ res = emul_getprinterentry_r(buf, sizeof (buf));
+#elif NSS_SOLARIS
+ nss_XbyY_args_t arg;
+
+ NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
+ res = nss_getent(&db_root, _nss_initf_printers, &context, &arg);
+ (void) NSS_XbyY_FINI(&arg);
+#endif
+
+ if (res != NSS_SUCCESS)
+ buf[0] = '\0';
+
+ result = _cvt_nss_entry_to_printer(buf);
+#ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
+ fill_printer_uri(&result);
+#endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
+#endif
+
+#ifdef DEBUG
+ printf("getprinterentry(%s): 0x%8.8x\n", (ns ? ns : "NULL"), result);
+ if (result != NULL) {
+ char buf[4096];
+
+ papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
+ printf("\t%s\n", buf);
+ }
+#endif /* DEBUG */
+
+ return (result);
+}
+
+
+papi_attribute_t **
+getprinterbyname(char *name, char *ns)
+{
+ papi_attribute_t **result = NULL;
+
+ if (strstr(name, "://") != NULL) { /* shortcut for URI form */
+ papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
+ "printer-name", name);
+ papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
+ "printer-uri-supported", name);
+ } else if (strchr(name, ':') != NULL) { /* shortcut for POSIX form */
+ char *uri = bsdaddr_to_uri(name);
+
+ papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
+ "printer-name", name);
+ if (uri != NULL) {
+ papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
+ "printer-uri-supported", uri);
+ free(uri);
+ }
+ } else { /* anything else */
+#if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
+ char buf[10240];
+ nss_status_t res = NSS_NOTFOUND;
+
+#ifdef NSS_EMULATION
+ res = emul_getprinterbyname_r(name, buf, sizeof (buf));
+#elif NSS_SOLARIS
+ nss_XbyY_args_t arg;
+
+ private_ns = ns;
+ NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
+ arg.key.name = name;
+ res = nss_search(&db_root, _nss_initf_printers,
+ NSS_DBOP_PRINTERS_BYNAME, &arg);
+ (void) NSS_XbyY_FINI(&arg);
+
+ if (res != NSS_SUCCESS)
+ buf[0] = '\0';
+#endif
+
+ result = _cvt_nss_entry_to_printer(buf);
+#endif
+ }
+
+#ifdef DEBUG
+ printf("getprinterbyname(%s): %s = 0x%8.8x\n", (ns ? ns : "NULL"),
+ name, result);
+ if (result != NULL) {
+ char buf[4096];
+
+ papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
+ printf("\t%s\n", buf);
+ }
+#endif /* DEBUG */
+
+ return (result);
+}