12264Sjacobs /*
22264Sjacobs * CDDL HEADER START
32264Sjacobs *
42264Sjacobs * The contents of this file are subject to the terms of the
52264Sjacobs * Common Development and Distribution License (the "License").
62264Sjacobs * You may not use this file except in compliance with the License.
72264Sjacobs *
82264Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs * or http://www.opensolaris.org/os/licensing.
102264Sjacobs * See the License for the specific language governing permissions
112264Sjacobs * and limitations under the License.
122264Sjacobs *
132264Sjacobs * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs *
192264Sjacobs * CDDL HEADER END
202264Sjacobs */
212264Sjacobs
222264Sjacobs /*
239606SKeerthi.Kondaka@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
242264Sjacobs * Use is subject to license terms.
252264Sjacobs *
262264Sjacobs */
272264Sjacobs
282264Sjacobs /* $Id: in.lpd.c 170 2006-05-20 05:58:49Z njacobs $ */
292264Sjacobs
302264Sjacobs #include <stdio.h>
312264Sjacobs #include <stdlib.h>
323125Sjacobs #include <unistd.h>
333125Sjacobs #include <fcntl.h>
342264Sjacobs #include <stdarg.h>
352264Sjacobs #include <string.h>
366817Sjacobs #include <ctype.h>
372264Sjacobs #include <errno.h>
382264Sjacobs #include <syslog.h>
392264Sjacobs #include <libintl.h>
403125Sjacobs #include <pwd.h>
413125Sjacobs #include <grp.h>
423125Sjacobs #include <sys/types.h>
433125Sjacobs #include <sys/stat.h>
443125Sjacobs #include <sys/socket.h>
453125Sjacobs #include <netinet/in.h>
463125Sjacobs #include <arpa/inet.h>
473125Sjacobs #include <netdb.h>
483125Sjacobs #include <sys/systeminfo.h>
492264Sjacobs
502264Sjacobs #include <papi.h>
513125Sjacobs #include <uri.h>
522264Sjacobs #include "common.h"
532264Sjacobs
542264Sjacobs #define ACK(fp) { (void) fputc('\0', fp); (void) fflush(fp); }
552264Sjacobs #define NACK(fp) { (void) fputc('\1', fp); (void) fflush(fp); }
562264Sjacobs
572264Sjacobs /*
582264Sjacobs * This file contains the front-end of the BSD Print Protocol adaptor. This
592264Sjacobs * code assumes a BSD Socket interface to the networking side.
602264Sjacobs */
612264Sjacobs
623125Sjacobs static char *
remote_host_name(FILE * fp)633125Sjacobs remote_host_name(FILE *fp)
643125Sjacobs {
653125Sjacobs struct hostent *hp;
663125Sjacobs struct sockaddr_in6 peer;
673125Sjacobs socklen_t peer_len = sizeof (peer);
683125Sjacobs int fd = fileno(fp);
693125Sjacobs int error_num;
707132Sps29005 char tmp_buf[INET6_ADDRSTRLEN];
713125Sjacobs char *hostname;
723125Sjacobs
733125Sjacobs /* who is our peer ? */
743125Sjacobs if (getpeername(fd, (struct sockaddr *)&peer, &peer_len) < 0) {
753125Sjacobs if ((errno != ENOTSOCK) && (errno != EINVAL))
763125Sjacobs return (NULL);
773125Sjacobs else
783125Sjacobs return (strdup("localhost"));
793125Sjacobs }
803125Sjacobs
813125Sjacobs /* get their name or return a string containing their address */
823125Sjacobs if ((hp = getipnodebyaddr((const char *)&peer.sin6_addr,
8310472SSonam.Gupta@Sun.COM sizeof (struct in6_addr), AF_INET6,
8410472SSonam.Gupta@Sun.COM &error_num)) == NULL) {
853125Sjacobs return (strdup(inet_ntop(peer.sin6_family,
8610472SSonam.Gupta@Sun.COM &peer.sin6_addr, tmp_buf, sizeof (tmp_buf))));
873125Sjacobs }
883125Sjacobs
897132Sps29005 hostname = strdup(hp->h_name);
907132Sps29005 if (is_localhost(hp->h_name) != 0)
913125Sjacobs return (strdup("localhost"));
923125Sjacobs
933125Sjacobs /* It must be someone else */
943125Sjacobs return (hostname);
953125Sjacobs }
963125Sjacobs
973125Sjacobs static void
fatal(FILE * fp,char * fmt,...)982264Sjacobs fatal(FILE *fp, char *fmt, ...)
992264Sjacobs {
1002264Sjacobs va_list ap;
1012264Sjacobs
1022264Sjacobs va_start(ap, fmt);
1032264Sjacobs vsyslog(LOG_DEBUG, fmt, ap);
1042264Sjacobs vfprintf(fp, fmt, ap);
1052264Sjacobs va_end(ap);
1063125Sjacobs exit(1);
1072264Sjacobs }
1082264Sjacobs
1092264Sjacobs static void
cleanup(char *** files,char ** cf)1103125Sjacobs cleanup(char ***files, char **cf)
1113125Sjacobs {
1123125Sjacobs if (*files != NULL) {
1133125Sjacobs int i;
1143125Sjacobs
1153125Sjacobs for (i = 0; (*files)[i] != NULL; i++) {
1163125Sjacobs (void) unlink((*files)[i]);
1173125Sjacobs free((*files)[i]);
1183125Sjacobs }
1193125Sjacobs free(*files);
1203125Sjacobs *files = NULL;
1213125Sjacobs }
1223125Sjacobs
1233125Sjacobs if (*cf != NULL) {
1243125Sjacobs free(*cf);
1253125Sjacobs *cf = NULL;
1263125Sjacobs }
1273125Sjacobs }
1283125Sjacobs
1293125Sjacobs static papi_attribute_t **
parse_cf(papi_service_t svc,char * cf,char ** files)1303125Sjacobs parse_cf(papi_service_t svc, char *cf, char **files)
1312264Sjacobs {
1323125Sjacobs papi_attribute_t **list = NULL;
13310472SSonam.Gupta@Sun.COM char previous = NULL;
13410472SSonam.Gupta@Sun.COM char *entry;
13510472SSonam.Gupta@Sun.COM int copies_set = 0;
13610472SSonam.Gupta@Sun.COM int copies = 0;
1373125Sjacobs
1383125Sjacobs for (entry = strtok(cf, "\n"); entry != NULL;
1393125Sjacobs entry = strtok(NULL, "\n")) {
1403125Sjacobs char *format = NULL;
1413125Sjacobs
1423125Sjacobs /* count the copies */
1433125Sjacobs if ((entry[0] >= 'a') && (entry[0] <= 'z') &&
1443125Sjacobs (copies_set == 0) && (previous == entry[0]))
1453125Sjacobs copies++;
1463125Sjacobs else if ((previous >= 'a') && (previous <= 'z'))
1473125Sjacobs copies_set = 1;
1483125Sjacobs previous = entry[0];
1492264Sjacobs
1503125Sjacobs /* process the control message */
1513125Sjacobs switch (entry[0]) {
1523125Sjacobs /* RFC-1179 options */
1533125Sjacobs case 'J': /* RFC-1179 Banner Job Name */
1543125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
15510472SSonam.Gupta@Sun.COM "job-name", ++entry);
1563125Sjacobs break;
1573125Sjacobs case 'C': /* RFC-1179 Banner Class Name */
1583125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
15910472SSonam.Gupta@Sun.COM "rfc-1179-class", ++entry);
1603125Sjacobs break;
1613125Sjacobs case 'L': /* RFC-1179 Banner toggle */
1623125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
16310472SSonam.Gupta@Sun.COM "job-sheets", "standard");
1643125Sjacobs break;
1653125Sjacobs case 'T': /* RFC-1179 Title (pr) */
1663125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
16710472SSonam.Gupta@Sun.COM "pr-title", ++entry);
1683125Sjacobs break;
1693125Sjacobs case 'H': /* RFC-1179 Host */
1703125Sjacobs /*
1713125Sjacobs * use the host as known by us, not by them
1723125Sjacobs *
1733125Sjacobs * papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
1743125Sjacobs * "job-originating-host-name", ++entry);
1753125Sjacobs */
1763125Sjacobs break;
1773125Sjacobs case 'P': /* RFC-1179 User */
1783125Sjacobs ++entry;
1793125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
1809606SKeerthi.Kondaka@Sun.COM "job-originating-user-name", entry);
1813125Sjacobs papiServiceSetUserName(svc, entry);
1823125Sjacobs break;
1833125Sjacobs case 'M': /* RFC-1179 Mail to User */
1843125Sjacobs papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL,
18510472SSonam.Gupta@Sun.COM "rfc-1179-mail", 1);
1863125Sjacobs break;
1873125Sjacobs case 'W': /* RFC-1179 Width (pr) */
1883125Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL,
18910472SSonam.Gupta@Sun.COM "pr-width", atoi(++entry));
1903125Sjacobs break;
1913125Sjacobs case 'I': /* RFC-1179 Indent (pr) */
1923125Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL,
19310472SSonam.Gupta@Sun.COM "pr-indent", atoi(++entry));
1943125Sjacobs break;
1953125Sjacobs case 'N': /* RFC-1179 Filename */
1963125Sjacobs /* could have HPUX extension embedded */
1973125Sjacobs if (entry[1] != ' ') { /* real pathname */
1983125Sjacobs #ifdef DEBUG
1993125Sjacobs papiAttributeListAddString(&list,
20010472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL,
20110472SSonam.Gupta@Sun.COM "flist", ++entry);
2023125Sjacobs #endif
2033125Sjacobs } else if (entry[2] == 'O') /* HPUX lp -o options */
2043125Sjacobs papiAttributeListFromString(&list,
20510472SSonam.Gupta@Sun.COM PAPI_ATTR_APPEND, ++entry);
2063125Sjacobs break;
2073125Sjacobs case 'U': /* RFC-1179 Unlink */
2083125Sjacobs break; /* ignored */
2093125Sjacobs case '1': /* RFC-1179 TROFF Font R */
2103125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
21110472SSonam.Gupta@Sun.COM "rfc-1179-font-r", ++entry);
2123125Sjacobs break;
2133125Sjacobs case '2': /* RFC-1179 TROFF Font I */
2143125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
21510472SSonam.Gupta@Sun.COM "rfc-1179-font-i", ++entry);
2163125Sjacobs break;
2173125Sjacobs case '3': /* RFC-1179 TROFF Font B */
2183125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
21910472SSonam.Gupta@Sun.COM "rfc-1179-font-b", ++entry);
2203125Sjacobs break;
2213125Sjacobs case '4': /* RFC-1179 TROFF Font S */
2223125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
22310472SSonam.Gupta@Sun.COM "rfc-1179-font-s", ++entry);
2243125Sjacobs break;
2253125Sjacobs case 'f': /* RFC-1179 ASCII file (print) */
2263125Sjacobs format = "text/plain";
2273125Sjacobs if (is_postscript(files[0]) == 1)
2283125Sjacobs format = "application/postscript";
2293125Sjacobs break;
2303125Sjacobs case 'l': /* RFC-1179 CATV file (print) */
2313125Sjacobs format = "application/octet-stream";
2323125Sjacobs if (is_postscript(files[0]) == 1)
2333125Sjacobs format = "application/postscript";
2343125Sjacobs break;
2353125Sjacobs case 'o': /* RFC-1179 Postscript file (print) */
2363125Sjacobs format = "application/postscript";
2373125Sjacobs break;
2383125Sjacobs case 'p': /* RFC-1179 PR file (print) */
2393125Sjacobs format = "application/x-pr";
2403125Sjacobs papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL,
24110472SSonam.Gupta@Sun.COM "pr-filter", 1);
2423125Sjacobs break;
2433125Sjacobs case 't': /* RFC-1179 TROFF file (print) */
2443125Sjacobs format = "application/x-troff";
2453125Sjacobs break;
2463125Sjacobs case 'n': /* RFC-1179 DITROFF file (print) */
2473125Sjacobs format = "application/x-ditroff";
2483125Sjacobs break;
2493125Sjacobs case 'd': /* RFC-1179 DVI file (print) */
2503125Sjacobs format = "application/x-dvi";
2513125Sjacobs break;
2523125Sjacobs case 'g': /* RFC-1179 GRAPH file (print) */
2533125Sjacobs format = "application/x-plot";
2543125Sjacobs break;
2553125Sjacobs case 'c': /* RFC-1179 CIF file (print) */
2563125Sjacobs format = "application/x-cif";
2573125Sjacobs break;
2583125Sjacobs case 'v': /* RFC-1179 RASTER file (print) */
2593125Sjacobs format = "application/x-raster";
2603125Sjacobs break;
2613125Sjacobs case 'r': /* RFC-1179 FORTRAN file (print) */
2623125Sjacobs format = "application/x-fortran";
2633125Sjacobs break;
2643125Sjacobs /* Sun Solaris Extensions */
2653125Sjacobs case 'O':
2663125Sjacobs ++entry;
2677132Sps29005 {
2687132Sps29005 int rd, wr;
2697132Sps29005
2707132Sps29005 for (rd = wr = 0; entry[rd] != '\0'; rd++) {
2717132Sps29005 if (entry[rd] == '"')
2727132Sps29005 continue;
2737132Sps29005 if (rd != wr)
2747132Sps29005 entry[wr] = entry[rd];
2757132Sps29005 wr++;
2767132Sps29005 }
2777132Sps29005 entry[wr] = '\0';
2787132Sps29005
2797132Sps29005 papiAttributeListFromString(&list,
2807132Sps29005 PAPI_ATTR_APPEND, entry);
2817132Sps29005 }
2823125Sjacobs break;
2833125Sjacobs case '5':
2843125Sjacobs ++entry;
2853125Sjacobs switch (entry[0]) {
2863125Sjacobs case 'f': /* Solaris form */
2873125Sjacobs papiAttributeListAddString(&list,
28810472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL,
28910472SSonam.Gupta@Sun.COM "form", ++entry);
2903125Sjacobs break;
2913125Sjacobs case 'H': /* Solaris handling */
2923125Sjacobs ++entry;
2933125Sjacobs if (strcasecmp(entry, "hold") == 0)
2943125Sjacobs papiAttributeListAddString(&list,
29510472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL,
29610472SSonam.Gupta@Sun.COM "job-hold-until", "indefinite");
2976725Sjacobs else if (strcasecmp(entry, "immediate") == 0)
2983125Sjacobs papiAttributeListAddString(&list,
29910472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL,
30010472SSonam.Gupta@Sun.COM "job-hold-until", "no-hold");
3013125Sjacobs else
3023125Sjacobs papiAttributeListAddString(&list,
30310472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL,
30410472SSonam.Gupta@Sun.COM "job-hold-until", entry);
3053125Sjacobs break;
3063125Sjacobs case 'p': /* Solaris notification */
3073125Sjacobs papiAttributeListAddBoolean(&list,
30810472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL, "rfc-1179-mail", 1);
3093125Sjacobs break;
3106725Sjacobs case 'P': { /* Solaris page list */
3116725Sjacobs char buf[BUFSIZ];
3126725Sjacobs
3136725Sjacobs snprintf(buf, sizeof (buf), "page-ranges=%s",
31410472SSonam.Gupta@Sun.COM ++entry);
3156728Sjacobs papiAttributeListFromString(&list,
31610472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL, buf);
3176725Sjacobs }
3183125Sjacobs break;
3193125Sjacobs case 'q': { /* Solaris priority */
320*10635SSonam.Gupta@Sun.COM int i = atoi(++entry);
3213125Sjacobs
3226725Sjacobs i = 100 - (i * 2.5);
3233125Sjacobs if ((i < 1) || (i > 100))
3243125Sjacobs i = 50;
3253125Sjacobs papiAttributeListAddInteger(&list,
32610472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL, "job-priority", i);
3273125Sjacobs }
3283125Sjacobs break;
3293125Sjacobs case 'S': /* Solaris character set */
3303125Sjacobs papiAttributeListAddString(&list,
33110472SSonam.Gupta@Sun.COM PAPI_ATTR_EXCL, "lp-charset",
33210472SSonam.Gupta@Sun.COM ++entry);
3333125Sjacobs break;
3343125Sjacobs case 'T': /* Solaris type */
3353125Sjacobs format = lp_type_to_mime_type(++entry);
3363125Sjacobs break;
3373125Sjacobs case 'y': /* Solaris mode */
3383125Sjacobs papiAttributeListAddString(&list,
33910472SSonam.Gupta@Sun.COM PAPI_ATTR_APPEND, "lp-modes", ++entry);
3403125Sjacobs break;
3413125Sjacobs default:
3423125Sjacobs syslog(LOG_INFO|LOG_DEBUG,
34310472SSonam.Gupta@Sun.COM "Warning: cf message (%s) ignored",
34410472SSonam.Gupta@Sun.COM entry);
3453125Sjacobs break;
3463125Sjacobs }
3473125Sjacobs break;
3483125Sjacobs /* Undefined Extensions: SCO, Ultrix, AIX, ... */
3493125Sjacobs
3503125Sjacobs default:
3513125Sjacobs syslog(LOG_INFO|LOG_DEBUG,
35210472SSonam.Gupta@Sun.COM "Warning: cf message (%s) ignored", entry);
3533125Sjacobs break;
3543125Sjacobs }
3553125Sjacobs
3563125Sjacobs if (format != NULL)
3573125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
35810472SSonam.Gupta@Sun.COM "document-format", format);
3593125Sjacobs }
3603125Sjacobs
3613125Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL,
36210472SSonam.Gupta@Sun.COM "copies", ++copies);
3633125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
36410472SSonam.Gupta@Sun.COM "job-sheets", "none");
3653125Sjacobs
3663125Sjacobs return (list);
3673125Sjacobs }
3683125Sjacobs
3693125Sjacobs static papi_status_t
submit_job(papi_service_t svc,FILE * ifp,char * printer,int rid,char * cf,char ** files)3706817Sjacobs submit_job(papi_service_t svc, FILE *ifp, char *printer, int rid, char *cf,
3716817Sjacobs char **files)
3723125Sjacobs {
3733125Sjacobs papi_attribute_t **list = NULL;
3743125Sjacobs papi_status_t status;
3753125Sjacobs papi_job_t job = NULL;
3763125Sjacobs char *format = "";
3773125Sjacobs
3783125Sjacobs if ((list = parse_cf(svc, cf, files)) != NULL) {
3793125Sjacobs /* use the host as known by us, not by them */
3803125Sjacobs char *host = remote_host_name(ifp);
3813125Sjacobs
3823125Sjacobs if (host != NULL) {
3833125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_REPLACE,
38410472SSonam.Gupta@Sun.COM "job-originating-host-name", host);
3853125Sjacobs free(host);
3863125Sjacobs }
38710472SSonam.Gupta@Sun.COM if (rid >= 0) {
3886817Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL,
38910472SSonam.Gupta@Sun.COM "job-id-requested", rid);
3906817Sjacobs }
3913125Sjacobs }
3923125Sjacobs
3933125Sjacobs status = papiJobSubmit(svc, printer, list, NULL, files, &job);
3943125Sjacobs syslog(LOG_DEBUG, "submit: %s", papiStatusString(status));
3953125Sjacobs if (status != PAPI_OK) {
3963125Sjacobs char *tmp = papiServiceGetStatusMessage(svc);
3973125Sjacobs
3983125Sjacobs syslog(LOG_DEBUG, "submit-detail: %s", tmp ? tmp : "none");
3993125Sjacobs }
4003125Sjacobs papiJobFree(job);
4013125Sjacobs
4023125Sjacobs return (status);
4033125Sjacobs }
4043125Sjacobs
4053125Sjacobs static char *
receive_control_file(papi_service_t svc,FILE * ifp,FILE * ofp,int size)4063125Sjacobs receive_control_file(papi_service_t svc, FILE *ifp, FILE *ofp, int size)
4073125Sjacobs {
4083125Sjacobs char *ptr, *cf_data;
4093125Sjacobs
4103125Sjacobs if ((ptr = cf_data = calloc(1, size + 1)) == NULL) {
4113125Sjacobs NACK(ofp);
4123125Sjacobs return (NULL);
4133125Sjacobs } else
4143125Sjacobs ACK(ofp);
4153125Sjacobs
4163125Sjacobs while (size > 0) {
4173125Sjacobs int rc;
4183125Sjacobs
4193125Sjacobs if (((rc = fread(ptr, 1, size, ifp)) == 0) &&
4203125Sjacobs (feof(ifp) != 0)) {
4213125Sjacobs free(cf_data);
4223125Sjacobs return (NULL);
4233125Sjacobs } else {
4243125Sjacobs ptr += rc;
4253125Sjacobs size -= rc;
4263125Sjacobs }
4273125Sjacobs }
4283125Sjacobs syslog(LOG_DEBUG, "cf_data(%s)", cf_data);
4293125Sjacobs
4303125Sjacobs if (fgetc(ifp) != 0) {
4313125Sjacobs free(cf_data);
4323125Sjacobs return (NULL);
4333125Sjacobs }
4342264Sjacobs ACK(ofp);
4352264Sjacobs
4363125Sjacobs return (cf_data);
4373125Sjacobs }
4383125Sjacobs
4393125Sjacobs static char *
receive_data_file(FILE * ifp,FILE * ofp,int size)4403125Sjacobs receive_data_file(FILE *ifp, FILE *ofp, int size)
4413125Sjacobs {
4423125Sjacobs char file[] = "lpdXXXXXX";
4433125Sjacobs char buf[BUFSIZ];
4443125Sjacobs int fd;
4453125Sjacobs
4463125Sjacobs if ((fd = mkstemp(file)) < 0) {
4473125Sjacobs NACK(ofp);
4483125Sjacobs return (NULL);
4493125Sjacobs } else
4503125Sjacobs ACK(ofp);
4513125Sjacobs
4523125Sjacobs while (size > 0) {
4533125Sjacobs int rc = ((size > BUFSIZ) ? BUFSIZ : size);
4543125Sjacobs
4553125Sjacobs if (((rc = fread(buf, 1, rc, ifp)) == 0) &&
4563125Sjacobs (feof(ifp) != 0)) {
4573125Sjacobs close(fd);
4583125Sjacobs unlink(file);
4593125Sjacobs return (NULL);
4603125Sjacobs } else {
4613125Sjacobs char *ptr = buf;
4623125Sjacobs
4633125Sjacobs while (rc > 0) {
4643125Sjacobs int wrc = write(fd, ptr, rc);
4653125Sjacobs
4663125Sjacobs if (wrc < 0) {
4673125Sjacobs close(fd);
4683125Sjacobs unlink(file);
4693127Sjacobs return (NULL);
4703125Sjacobs }
4713125Sjacobs
4723125Sjacobs ptr += wrc;
4733125Sjacobs size -= wrc;
4743125Sjacobs rc -= wrc;
4753125Sjacobs }
4763125Sjacobs }
4773125Sjacobs }
4783125Sjacobs close(fd);
4793125Sjacobs if (fgetc(ifp) != 0) {
4803125Sjacobs unlink(file);
4813125Sjacobs return (NULL);
4823125Sjacobs }
4833125Sjacobs ACK(ofp);
4843125Sjacobs
4853125Sjacobs return (strdup(file));
4863125Sjacobs }
4873127Sjacobs
4883125Sjacobs static papi_status_t
berkeley_receive_files(papi_service_t svc,FILE * ifp,FILE * ofp,char * printer)4893125Sjacobs berkeley_receive_files(papi_service_t svc, FILE *ifp, FILE *ofp, char *printer)
4903125Sjacobs {
4913125Sjacobs papi_status_t status = PAPI_OK;
4923125Sjacobs char *file, **files = NULL; /* the job data files */
4933125Sjacobs char *cf = NULL;
4946817Sjacobs int rid = 0;
4953125Sjacobs char buf[BUFSIZ];
4963125Sjacobs
4973125Sjacobs while (fgets(buf, sizeof (buf), ifp) != NULL) {
4983125Sjacobs int size;
4993125Sjacobs
5003125Sjacobs syslog(LOG_DEBUG, "XFER CMD: (%d)%s\n", buf[0], &buf[1]);
5013125Sjacobs #ifdef DEBUG /* translate [1-3]... messages to \[1-3] to run by hand */
5023125Sjacobs if ((buf[0] > '0') && (buf[0] < '4'))
5033125Sjacobs buf[0] -= '0';
5043125Sjacobs #endif
5053125Sjacobs switch (buf[0]) {
5062264Sjacobs case 0x01: /* Abort */
5073125Sjacobs cleanup(&files, &cf);
5082264Sjacobs break;
5093125Sjacobs case 0x02: { /* Receive control file */
5106817Sjacobs if (((cf = strchr(buf, ' ')) != NULL) &&
5116817Sjacobs (strlen(cf) > 4)) {
5126817Sjacobs while ((*cf != NULL) && (isdigit(*cf) == 0))
5136817Sjacobs cf++;
5146817Sjacobs rid = atoi(cf);
5156817Sjacobs }
5163125Sjacobs cf = receive_control_file(svc, ifp, ofp, atoi(&buf[1]));
5173125Sjacobs if (cf == NULL) {
5183125Sjacobs cleanup(&files, &cf);
5193125Sjacobs return (PAPI_BAD_REQUEST);
5203125Sjacobs } else if (files != NULL) {
5216817Sjacobs status = submit_job(svc, ifp, printer, rid, cf,
52210472SSonam.Gupta@Sun.COM files);
5233125Sjacobs cleanup(&files, &cf);
5243125Sjacobs }
5253125Sjacobs }
5262264Sjacobs break;
5272264Sjacobs case 0x03: { /* Receive data file */
5283125Sjacobs file = receive_data_file(ifp, ofp, atoi(&buf[1]));
5293125Sjacobs if (file == NULL) {
5303125Sjacobs cleanup(&files, &cf);
5313125Sjacobs return (PAPI_TEMPORARY_ERROR);
5323125Sjacobs }
5333125Sjacobs list_append(&files, file);
5342264Sjacobs }
5352264Sjacobs break;
5362264Sjacobs default:
5373125Sjacobs cleanup(&files, &cf);
5382264Sjacobs fatal(ofp, "protocol screwup");
5392264Sjacobs break;
5402264Sjacobs }
5412264Sjacobs }
5422264Sjacobs
5433125Sjacobs if ((cf != NULL) && (files != NULL))
5446817Sjacobs status = submit_job(svc, ifp, printer, rid, cf, files);
5453125Sjacobs
5463125Sjacobs cleanup(&files, &cf);
5473125Sjacobs
5483125Sjacobs return (status);
5492264Sjacobs }
5502264Sjacobs
5513125Sjacobs static papi_status_t
berkeley_transfer_files(papi_service_t svc,FILE * ifp,FILE * ofp,char * printer)5522264Sjacobs berkeley_transfer_files(papi_service_t svc, FILE *ifp, FILE *ofp,
5532264Sjacobs char *printer)
5542264Sjacobs {
5552264Sjacobs papi_status_t status;
5562264Sjacobs papi_printer_t p = NULL;
5573125Sjacobs char *keys[] = { "printer-is-accepting-jobs", NULL };
5582264Sjacobs
5592264Sjacobs status = papiPrinterQuery(svc, printer, keys, NULL, &p);
5602264Sjacobs if ((status == PAPI_OK) && (p != NULL)) {
5612264Sjacobs papi_attribute_t **attrs = papiPrinterGetAttributeList(p);
5622264Sjacobs char accepting = PAPI_FALSE;
5632264Sjacobs
5642264Sjacobs papiAttributeListGetBoolean(attrs, NULL,
56510472SSonam.Gupta@Sun.COM "printer-is-accepting-jobs", &accepting);
5662264Sjacobs
5673125Sjacobs if (accepting == PAPI_TRUE) {
5683125Sjacobs ACK(ofp);
5693125Sjacobs status = berkeley_receive_files(svc, ifp, ofp, printer);
5703125Sjacobs } else
5712264Sjacobs NACK(ofp);
5722264Sjacobs
5732264Sjacobs papiPrinterFree(p);
5742264Sjacobs } else
5752264Sjacobs NACK(ofp);
5763125Sjacobs
5773125Sjacobs return (status);
5782264Sjacobs }
5792264Sjacobs
5803125Sjacobs static int
cyclical_service_check(char * svc_name)5813125Sjacobs cyclical_service_check(char *svc_name)
5823125Sjacobs {
5833125Sjacobs papi_attribute_t **list;
5843125Sjacobs uri_t *uri = NULL;
5853125Sjacobs char *s = NULL;
5863125Sjacobs
5873125Sjacobs /* was there a printer? */
5883125Sjacobs if (svc_name == NULL)
5893125Sjacobs return (0);
5903125Sjacobs
5913125Sjacobs if ((list = getprinterbyname(svc_name, NULL)) == NULL)
5923127Sjacobs return (0); /* if it doesnt' resolve, we will fail later */
5933125Sjacobs
5943125Sjacobs papiAttributeListGetString(list, NULL, "printer-uri-supported", &s);
5953125Sjacobs if ((s == NULL) || (strcasecmp(svc_name, s) != 0))
5963127Sjacobs return (0); /* they don't match */
5973125Sjacobs
5983125Sjacobs /* is it in uri form? */
5993125Sjacobs if (uri_from_string(s, &uri) < 0)
6003125Sjacobs return (0);
6013125Sjacobs
6023125Sjacobs if ((uri == NULL) || (uri->scheme == NULL) || (uri->host == NULL)) {
6033125Sjacobs uri_free(uri);
6043125Sjacobs return (0);
6053125Sjacobs }
6063125Sjacobs
6073125Sjacobs /* is it in lpd form? */
6083125Sjacobs if (strcasecmp(uri->scheme, "lpd") != 0) {
6093125Sjacobs uri_free(uri);
6103125Sjacobs return (0);
6113125Sjacobs }
6123125Sjacobs
6133125Sjacobs /* is it the local host? */
6147132Sps29005 if (is_localhost(uri->host) != 0) {
6153125Sjacobs uri_free(uri);
6163125Sjacobs return (0);
6173125Sjacobs }
6183125Sjacobs
6193125Sjacobs uri_free(uri);
6203125Sjacobs return (1);
6213125Sjacobs }
6223125Sjacobs
6233125Sjacobs
6242264Sjacobs /*
6252264Sjacobs * This is the entry point for this program. The program takes the
6262264Sjacobs * following options:
6272264Sjacobs * (none)
6282264Sjacobs */
6292264Sjacobs int
main(int ac,char * av[])6302264Sjacobs main(int ac, char *av[])
6312264Sjacobs {
6322264Sjacobs papi_status_t status;
6332264Sjacobs papi_service_t svc = NULL;
6342264Sjacobs papi_encryption_t encryption = PAPI_ENCRYPT_NEVER;
63510472SSonam.Gupta@Sun.COM FILE *ifp = stdin;
63610472SSonam.Gupta@Sun.COM FILE *ofp = stdout;
6372264Sjacobs int c;
63810472SSonam.Gupta@Sun.COM char buf[BUFSIZ];
63910472SSonam.Gupta@Sun.COM char **args;
64010472SSonam.Gupta@Sun.COM char *printer;
64110472SSonam.Gupta@Sun.COM char *run_dir = "/var/run/in.lpd";
64210472SSonam.Gupta@Sun.COM char *run_user = NULL;
6433125Sjacobs struct passwd *pw = NULL;
6442264Sjacobs
6453125Sjacobs (void) chdir("/tmp"); /* run in /tmp by default */
6462264Sjacobs openlog("bsd-gw", LOG_PID, LOG_LPR);
6472264Sjacobs
6483125Sjacobs while ((c = getopt(ac, av, "Ed:u:")) != EOF)
6492264Sjacobs switch (c) {
6502264Sjacobs case 'E':
6512264Sjacobs encryption = PAPI_ENCRYPT_ALWAYS;
6522264Sjacobs break;
6533125Sjacobs case 'd': /* run where they tell you */
6543125Sjacobs run_dir = optarg;
6553125Sjacobs break;
6563125Sjacobs case 'u': /* run as */
6573125Sjacobs run_user = optarg;
6583125Sjacobs break;
6592264Sjacobs default:
6602264Sjacobs ;
6612264Sjacobs }
6622264Sjacobs
6633125Sjacobs if (run_user != NULL) /* get the requested user info */
6643125Sjacobs pw = getpwnam(run_user);
6653127Sjacobs
6663125Sjacobs if (run_dir != NULL) { /* setup the run_dir */
6673125Sjacobs (void) mkdir(run_dir, 0700);
6683125Sjacobs if (pw != NULL)
6693125Sjacobs (void) chown(run_dir, pw->pw_uid, pw->pw_gid);
6703125Sjacobs }
6713125Sjacobs
6723125Sjacobs if (pw != NULL) { /* run as the requested user */
6733127Sjacobs syslog(LOG_DEBUG, "name: %s, uid: %d, gid: %d",
67410472SSonam.Gupta@Sun.COM pw->pw_name, pw->pw_uid, pw->pw_gid);
6753125Sjacobs initgroups(pw->pw_name, pw->pw_gid);
6763125Sjacobs setgid(pw->pw_gid);
6773125Sjacobs setuid(pw->pw_uid);
6783125Sjacobs }
6793125Sjacobs
6803125Sjacobs if (run_dir != NULL) /* move to the run_dir */
6813125Sjacobs if (chdir(run_dir) < 0) {
6823125Sjacobs syslog(LOG_DEBUG, "failed to chdir(%s)", run_dir);
6833125Sjacobs exit(1);
6843125Sjacobs }
6853125Sjacobs
6863125Sjacobs syslog(LOG_DEBUG, "$CWD = %s", getwd(NULL));
6873125Sjacobs
6882264Sjacobs if (fgets(buf, sizeof (buf), ifp) == NULL) {
6892264Sjacobs if (feof(ifp) == 0)
6902264Sjacobs syslog(LOG_ERR, "Error reading from connection: %s",
69110472SSonam.Gupta@Sun.COM strerror(errno));
6922264Sjacobs exit(1);
6932264Sjacobs }
6942264Sjacobs
6953125Sjacobs syslog(LOG_DEBUG, "CMD: (%d)%s\n", buf[0], &buf[1]);
6963125Sjacobs
6973125Sjacobs #ifdef DEBUG /* translate [1-5]... messages to \[1-5] to run by hand */
6983125Sjacobs if ((buf[0] > '0') && (buf[0] < '6'))
6993125Sjacobs buf[0] -= '0';
7003125Sjacobs #endif
7013125Sjacobs
7022264Sjacobs if ((buf[0] < 1) || (buf[0] > 5)) {
7032264Sjacobs fatal(ofp, "Invalid protocol request (%d): %c%s\n",
70410472SSonam.Gupta@Sun.COM buf[0], buf[0], buf);
7052264Sjacobs exit(1);
7062264Sjacobs }
7072264Sjacobs
7082264Sjacobs args = strsplit(&buf[1], "\t\n ");
7092264Sjacobs printer = *args++;
7102264Sjacobs
7112264Sjacobs if (printer == NULL) {
7122264Sjacobs fatal(ofp, "Can't determine requested printer");
7132264Sjacobs exit(1);
7142264Sjacobs }
7152264Sjacobs
7163125Sjacobs if (cyclical_service_check(printer) != 0) {
7173125Sjacobs fatal(ofp, "%s is cyclical\n", printer);
7183125Sjacobs exit(1);
7193125Sjacobs }
7203125Sjacobs
7212264Sjacobs status = papiServiceCreate(&svc, printer, NULL, NULL, NULL,
72210472SSonam.Gupta@Sun.COM encryption, NULL);
7232264Sjacobs if (status != PAPI_OK) {
7242264Sjacobs fatal(ofp, "Failed to contact service for %s: %s\n", printer,
72510472SSonam.Gupta@Sun.COM verbose_papi_message(svc, status));
7262264Sjacobs exit(1);
7272264Sjacobs }
7282264Sjacobs
7293125Sjacobs /*
7303125Sjacobs * Trusted Solaris can't be trusting of intermediaries. Pass
7313125Sjacobs * the socket connection to the print service to retrieve the
7323125Sjacobs * sensativity label off of a multi-level port.
7333125Sjacobs */
7343125Sjacobs (void) papiServiceSetPeer(svc, fileno(ifp));
7352264Sjacobs
7362264Sjacobs switch (buf[0]) {
7372264Sjacobs case '\1': /* restart printer */
7382264Sjacobs ACK(ofp); /* there is no equivalent */
7392264Sjacobs break;
7402264Sjacobs case '\2': /* transfer job(s) */
7413125Sjacobs status = berkeley_transfer_files(svc, ifp, ofp, printer);
7422264Sjacobs break;
7432264Sjacobs case '\3': /* show queue (short) */
7442264Sjacobs case '\4': { /* show queue (long) */
7452264Sjacobs int count;
7462264Sjacobs
74710472SSonam.Gupta@Sun.COM for (count = 0; args[count] != 0; count++) {}
7482264Sjacobs
7492264Sjacobs berkeley_queue_report(svc, ofp, printer, buf[0], count, args);
7502264Sjacobs }
7512264Sjacobs break;
7522264Sjacobs case '\5': { /* cancel job(s) */
7533125Sjacobs char *user = *args++;
7543125Sjacobs char *host = remote_host_name(ifp);
7552264Sjacobs int count;
7562264Sjacobs
7573125Sjacobs if (host != NULL) {
7583125Sjacobs char buf[BUFSIZ];
7593125Sjacobs
7603125Sjacobs snprintf(buf, sizeof (buf), "%s@%s", user, host);
7613125Sjacobs status = papiServiceSetUserName(svc, buf);
7623125Sjacobs } else
7633125Sjacobs status = papiServiceSetUserName(svc, user);
7643125Sjacobs
76510472SSonam.Gupta@Sun.COM for (count = 0; args[count] != 0; count++) {}
7662264Sjacobs
7672264Sjacobs berkeley_cancel_request(svc, ofp, printer, count, args);
7682264Sjacobs }
7692264Sjacobs break;
7702264Sjacobs default:
7712264Sjacobs fatal(ofp, "unsupported protocol request (%c), %s",
77210472SSonam.Gupta@Sun.COM buf[0], &buf[1]);
7732264Sjacobs }
7742264Sjacobs
7752264Sjacobs (void) fflush(ofp);
7762264Sjacobs
7772264Sjacobs syslog(LOG_DEBUG, "protocol request(%d) for %s completed: %s",
77810472SSonam.Gupta@Sun.COM buf[0], printer, papiStatusString(status));
7793125Sjacobs if (status != PAPI_OK)
7803125Sjacobs syslog(LOG_DEBUG, "detail: %s",
78110472SSonam.Gupta@Sun.COM verbose_papi_message(svc, status));
7822264Sjacobs
7832264Sjacobs papiServiceDestroy(svc);
7842264Sjacobs
7852264Sjacobs return (0);
7862264Sjacobs }
787