diff options
Diffstat (limited to 'usr/src/cmd/print/gateway/adaptor.c')
-rw-r--r-- | usr/src/cmd/print/gateway/adaptor.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/usr/src/cmd/print/gateway/adaptor.c b/usr/src/cmd/print/gateway/adaptor.c new file mode 100644 index 0000000000..ebe6aa97a0 --- /dev/null +++ b/usr/src/cmd/print/gateway/adaptor.c @@ -0,0 +1,360 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 (c) 1998-2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <string.h> +#include <errno.h> +#include <dlfcn.h> +#include <sys/systeminfo.h> + +#include <syslog.h> + +#include <adaptor.h> +#include <print/ns.h> + +#ifndef RTLD_GLOBAL /* for OSF/1 */ +#define RTLD_GLOBAL 0 +#endif + +/* + * This file contains the implementation of the API used by the front half + * of the BSD Print protocol adaptor to select and glue in the back half of + * the print protocol adaptor dynamically. Most of the functions in this + * file are hollow shells that pick a back end, load it, and call the "real" + * function from the loaded object, with the arguments passed in. The loaded + * functions have the naming convention {paradigm}_{function}. + * These functions are in NO WAY MT-Safe. They are intended to be used by + * a single threaded adaptor, that is/may be called via inetd concurrently. + */ + + +static void *paradigm_handle = NULL; +static char *paradigm_name = NULL; +static int paradigm_version = -1; +static ns_printer_t *printer_object = NULL; +static char *primary_name = NULL; + +static int +is_localhost(char *name) +{ + char buf[BUFSIZ]; + + if (name == NULL) + return (0); + + if (strcasecmp(name, "localhost") == 0) + return (0); + + (void) sysinfo(SI_HOSTNAME, buf, sizeof (buf)); + + return (strcasecmp(name, buf)); +} + +int +syn_name(const char *str) +{ + register char *p; + + if (!str || !*str) + return (0); + + if (strlen(str) > (size_t)14) + return (0); + + for (p = (char *)str; *p; p++) + if (!isalnum(*p) && *p != '_' && *p != '-') + return (0); + + return (1); +} + +/* + * A hack for performance. This will look for a local LP based printer in + * the most efficient manner. If found, it will circumvent all future + * adaptor resolution and load the default lpsched translation module. + */ +static int +lpsched_adaptor_available(const char *printer) +{ + char buf[BUFSIZ], buf2[BUFSIZ]; + + syslog(LOG_DEBUG, "in.lpd:lpsched_adaptor_available: entry\n"); + + if (!syn_name(printer)) + return (-1); + + (void) snprintf(buf, sizeof (buf), "/etc/lp/interfaces/%s", printer); + (void) snprintf(buf2, sizeof (buf2), "/etc/lp/classes/%s", printer); + syslog(LOG_DEBUG, + "in.lpd:lpsched_adaptor_available: printer is %s\n", + printer); + if ((access(buf, F_OK) < 0) && (access(buf2, F_OK) < 0)) + return (-1); + + syslog(LOG_DEBUG, + "in.lpd:lpsched_adaptor_available: printer %s local\n", + printer); + + paradigm_handle = dlopen("/usr/lib/print/bsd-adaptor/bsd_lpsched.so", + RTLD_NOW|RTLD_GLOBAL); + if (paradigm_handle == NULL) + return (-1); + + paradigm_name = LPSCHED; + return (0); +} + +/* + * adaptor_avaliable() takes in the name of a printer, looks it up in the + * name service, and dynamically loads backend support for the print paradigm + * the printer is defined in. If the printer is undefined, UNDEFINED is + * returned. If the spooling paradigm is not defined, and the printer is + * remote, a "cascade" capability is loaded. + */ +int +adaptor_available(const char *printer) +{ + char *path, + *dir, + *tmp, + *tmp_path; + ns_bsd_addr_t *addr; + + /* + * for performance, check lpsched first and foremost. This will + * hide any NS information if there is an LP configuration, valid + * or not. + */ + if (lpsched_adaptor_available(printer) == 0) + return (0); + + errno = 0; + if (((printer_object = ns_printer_get_name(printer, + NS_SVC_ETC)) == NULL) && + (endprinterentry() == 0) && + ((printer_object = ns_printer_get_name(printer, NULL)) == NULL)) { + errno = ENOENT; + return (-1); + } + + if ((addr = ns_get_value(NS_KEY_BSDADDR, printer_object)) != NULL) + primary_name = addr->printer; + + if ((paradigm_name = ns_get_value_string(NS_KEY_ADAPTOR_NAME, + printer_object)) == NULL) { + if ((addr != NULL) && (is_localhost(addr->server) == 0)) + paradigm_name = LPSCHED; + else + paradigm_name = CASCADE; + } + + if ((tmp = strrchr(paradigm_name, ',')) != NULL) { + *tmp++ = NULL; + paradigm_version = atoi(tmp); + } + + if ((path = ns_get_value_string(NS_KEY_ADAPTOR_PATH, printer_object)) + == NULL) + path = ADAPTOR_PATH; + + tmp_path = strdup(path); + for (dir = strtok(tmp_path, ":,"); dir != NULL; + dir = strtok(NULL, ":,")) { + static char object[BUFSIZ]; + + if (paradigm_version < 0) + (void) snprintf(object, sizeof (object), "%s/bsd_%s.so", + dir, paradigm_name); + else + (void) snprintf(object, sizeof (object), + "%s/bsd_%s.so.%d", dir, paradigm_name, + paradigm_version); + if ((paradigm_handle = dlopen(object, RTLD_NOW|RTLD_GLOBAL)) + != NULL) + break; +#ifdef DEBUG + syslog(LOG_DEBUG, "dlopen(%d): %s", object, dlerror()); +#endif + } + free(tmp_path); + + return (paradigm_handle == NULL); +} + + +static void * +adaptor_function(const char *paradigm, const char *function) +{ + char name[128]; + void *fpt = NULL; + + if (paradigm_handle == NULL) + return (NULL); + + (void) snprintf(name, sizeof (name), "%s_%s", paradigm, function); + if ((fpt = dlsym(paradigm_handle, name)) == NULL) + syslog(LOG_ERR, "could not locate function: %s()", name); + + return (fpt); +} + + +int +adaptor_spooler_available(const char *printer) +{ + static int (*fpt)() = NULL; + + if ((fpt != NULL) || + ((fpt = (int (*)())adaptor_function(paradigm_name, + "spooler_available")) != NULL)) + /* + * in the case of cascading, + * use the local name of the printer + */ + if (strcmp(paradigm_name, "cascade") == 0) + return ((int)(fpt)(printer)); + else + return ((int)(fpt) + (primary_name ? primary_name : printer)); + + return (-1); +} + + +int +adaptor_spooler_accepting_jobs(const char *printer) +{ + static int (*fpt)() = NULL; + + if ((fpt != NULL) || + ((fpt = (int (*)())adaptor_function(paradigm_name, + "spooler_accepting_jobs")) != NULL)) + return ((int)(fpt)(primary_name ? primary_name : printer)); + + return (-1); +} + + +int +adaptor_client_access(const char *printer, const char *host) +{ + static int (*fpt)() = NULL; + + if ((fpt != NULL) || + ((fpt = (int (*)())adaptor_function(paradigm_name, + "client_access")) != NULL)) + return ((int)(fpt)((primary_name ? primary_name : printer), + host)); + + return (-1); +} + + +int +adaptor_restart_printer(const char *printer) +{ + static int (*fpt)() = NULL; + + /* need a cast */ + if ((fpt != NULL) || + ((fpt = (int (*)())adaptor_function(paradigm_name, + "restart_printer")) != NULL)) + return ((int)(fpt)(primary_name ? primary_name : printer)); + + return (-1); +} + + +char * +adaptor_temp_dir(const char *printer, const char *host) +{ + static char *(*fpt)() = NULL; + + /* need a cast */ + if ((fpt != NULL) || + ((fpt = (char *(*)())adaptor_function(paradigm_name, + "temp_dir")) != NULL)) + return ((char *)(fpt)((primary_name ? primary_name : printer), + host)); + + return (NULL); +} + + +int +adaptor_submit_job(const char *printer, const char *host, char *cf, + char **df_list) +{ + static int (*fpt)() = NULL; + + /* need a cast */ + if ((fpt != NULL) || + ((fpt = (int (*)())adaptor_function(paradigm_name, + "submit_job")) != NULL)) + return ((int)(fpt)((primary_name ? primary_name : printer), + host, cf, df_list)); + + return (-1); +} + + +int +adaptor_show_queue(const char *printer, FILE *ofp, const int type, + char **list) +{ + static int (*fpt)() = NULL; + + /* need a cast */ + if ((fpt != NULL) || + ((fpt = (int (*)())adaptor_function(paradigm_name, + "show_queue")) != NULL)) + return ((int)(fpt)((primary_name ? primary_name : printer), + ofp, type, list)); + + return (-1); +} + + +int +adaptor_cancel_job(const char *printer, FILE *ofp, const char *user, + const char *host, char **list) +{ + static int (*fpt)() = NULL; + + /* need a cast */ + if ((fpt != NULL) || + ((fpt = (int (*)())adaptor_function(paradigm_name, + "cancel_job")) != NULL)) + return ((int)(fpt)((primary_name ? primary_name : printer), + ofp, user, host, list)); + + return (-1); +} |