summaryrefslogtreecommitdiff
path: root/usr/src/cmd/print/lp/lp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/print/lp/lp.c')
-rw-r--r--usr/src/cmd/print/lp/lp.c1281
1 files changed, 0 insertions, 1281 deletions
diff --git a/usr/src/cmd/print/lp/lp.c b/usr/src/cmd/print/lp/lp.c
deleted file mode 100644
index dce11659f7..0000000000
--- a/usr/src/cmd/print/lp/lp.c
+++ /dev/null
@@ -1,1281 +0,0 @@
-/*
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/systeminfo.h>
-#include <sys/param.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <syslog.h>
-#include <termios.h>
-#include <libintl.h>
-#include <locale.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <print/ns.h>
-#include <print/network.h>
-#include <print/misc.h>
-#include <print/list.h>
-#include <print/job.h>
-
-/*
- * lpr/lp
- * This program will submit print jobs to a spooler using the BSD
- * printing protcol as defined in RFC1179, plus some extension for
- * support of additional lp functionality.
- */
-
-extern char *optarg;
-extern int optind, opterr, optopt;
-extern char *getenv(const char *);
-
-#define SEND_RETRY -1
-#define SEND_ABORT -2
-
-
-static int priority = -1,
- copies = 1,
- width = -1, /* pr width */
- indent = -1, /* pr indent */
- linked = 0,
- mail = 0,
- delete = 0,
- suppress = 1,
- banner = 1,
- connection_failed = 0;
-static char *printer = NULL,
- *form = NULL,
- *charset = NULL,
- *title = NULL, /* pr title */
- *class = NULL,
- *jobName = NULL,
- *notification = NULL,
- *handling = NULL,
- *pages = NULL,
- **mode = NULL,
- **s5options = NULL,
- *s5type = NULL,
- *internal_type = NULL,
- *fontR = NULL,
- *fontI = NULL,
- *fontB = NULL,
- *fontS = NULL,
- type = CF_PRINT_ASCII;
-
-static struct s5_types {
- char *name;
- char type;
-} output_types[] = { /* known LP "-T" types */
-/*
- * Switched to ASCII, because some BSD systems don't like the 'o' file
- * type.
- */
- { "postscript", CF_PRINT_ASCII },
- { "ps", CF_PRINT_ASCII },
- { "simple", CF_PRINT_ASCII },
- { "ascii", CF_PRINT_ASCII },
- { "raw", CF_PRINT_RAW },
- { "dvi", CF_PRINT_DVI },
- { "tex", CF_PRINT_DVI },
- { "raster", CF_PRINT_RAS },
- { "ditroff", CF_PRINT_DROFF },
- { "otroff", CF_PRINT_TROFF },
- { "troff", CF_PRINT_DROFF },
- { "cif", CF_PRINT_CIF },
- { "plot", CF_PRINT_PLOT },
- { "fortran", CF_PRINT_FORT },
- { "pr", CF_PRINT_PR },
- NULL
-};
-
-/*ARGSUSED*/
-static void sigbus_handler(int i)
-{
- (void) fprintf(stderr,
- gettext("No space in /var/spool/print to store job"));
- exit(-1);
-}
-
-/*ARGSUSED*/
-static void sigpipe_handler(int i)
-{
- syslog(LOG_ERR, "Warning: Received SIGPIPE; continuing");
- (void) signal(SIGPIPE, sigpipe_handler);
-}
-
-
-#define OLD_LP "/usr/lib/lp/local/lp" /* for local lpsched printers */
-#ifdef OLD_LP
-/*
- * this will submit the job to a local lpsched using the old interface.
- * the argument vector is rebuilt with a new destination, because
- * the old name may have been an alias or because it was actually
- * lpr(1b) that was called.
- */
-static void
-submit_local_lp(char *program, int ac, char *av[])
-{
- uid_t ruid = getuid();
- struct passwd *pw;
- int argc = 0;
- char **argv;
-
- /*
- * We allocate the space for ac+5 items, which include all the file
- * arguments(ac), generic arguments(OLD_LP, "-d" and "printer") and
- * "-s" option of lpr. The extra item is just a cushion.
- */
- if ((argv = (char **)calloc(ac + 5, sizeof (char *))) == NULL) {
- (void) fprintf(stderr,
- gettext("not enough memory for argument vector\n"));
- exit(1);
- }
- argv[argc++] = OLD_LP;
- argv[argc++] = "-d";
- argv[argc++] = printer;
-
- if (strcmp(program, "lp") == 0) {
- int i = 0;
-
- while (++i < ac)
- if (strncmp(av[i], "-d", 2) != 0) {
- argv[argc++] = av[i];
- } else if (strlen(av[i]) == 2)
- i++;
- } else { /* convert lpr options */
- argv[argc++] = "-s"; /* supress id message */
-
- if (linked == 0)
- argv[argc++] = "-c";
-
- if (copies > 1) {
- char buf[12];
- (void) sprintf(buf, "%d", copies);
- argv[argc++] = "-n";
- argv[argc++] = strdup(buf);
- }
- if (banner == 0) {
- argv[argc++] = "-o";
- argv[argc++] = "nobanner";
- }
- if (title != NULL) {
- char buf[BUFSIZ];
- (void) snprintf(buf, sizeof (buf), "prtitle='%s'",
- title);
- argv[argc++] = "-y";
- argv[argc++] = strdup(buf);
- }
- if (width > 0) {
- char buf[16];
- (void) sprintf(buf, "prwidth=%d", width);
- argv[argc++] = "-y";
- argv[argc++] = strdup(buf);
- }
- if (indent > 0) {
- char buf[16];
- (void) sprintf(buf, "indent=%d", indent);
- argv[argc++] = "-y";
- argv[argc++] = strdup(buf);
- }
- if (mail != 0)
- argv[argc++] = "-m";
- if ((jobName != NULL) || (class != NULL)) {
- char buf[128];
- snprintf(buf, sizeof (buf), "%s%s%s",
- (jobName ? jobName : ""),
- (jobName && class ? "\\n#####\\n#####\\t\\t "
- : ""), (class ? class : ""));
- argv[argc++] = "-t";
- argv[argc++] = strdup(buf);
- }
-
- if (type != CF_PRINT_ASCII) {
- struct s5_types *tmp;
-
- for (tmp = output_types; tmp->name != NULL; tmp++)
- if (tmp->type == type) {
- argv[argc++] = "-T";
- argv[argc++] = tmp->name;
- break;
- }
- }
-
- while (optind < ac)
- argv[argc++] = av[optind++];
-
- }
-
- ruid = getuid();
- if ((pw = getpwuid(ruid)) != NULL)
- (void) initgroups(pw->pw_name, pw->pw_gid);
- (void) setuid(ruid);
-
- argv[argc++] = NULL;
- (void) execv(OLD_LP, argv);
-}
-#endif
-
-
-/*
- * cheat and look in the LP interface to determine if a local printer is
- * rejecting. If so, don't queue the job. If the printer is remote or
- * accepting, queue it. This approximates behaviour of previous releases
- * The check is being done this way for performance.
- */
-static int
-rejecting(char *printer)
-{
- int rc = 0, found = 0;
- FILE *fp;
-
- if ((fp = fopen("/usr/spool/lp/system/pstatus", "r+")) != NULL) {
- char buf[BUFSIZ];
-
- while (fgets(buf, sizeof (buf), fp) != NULL) {
- buf[strlen(buf)-1] = NULL;
- if (strcmp(buf, printer) == 0) {
- char *ptr;
-
- found = 1;
- (void) fgets(buf, sizeof (buf), fp);
- buf[strlen(buf)-1] = NULL;
- ptr = strrchr(buf, ' ');
- if (ptr && (strcmp(++ptr, "rejecting") == 0)) {
- rc = 1;
- break;
- }
- }
- }
- }
- (void) fclose(fp);
-
- /* if we have'nt found the name it could be a class */
- if (!found) {
- if ((fp = fopen("/usr/spool/lp/system/cstatus",
- "r+")) != NULL) {
-
- char buf2[BUFSIZ];
-
- while (fgets(buf2, sizeof (buf2), fp) != NULL) {
- buf2[strlen(buf2)-1] = NULL;
- if (strcmp(buf2, printer) == 0) {
- fgets(buf2, sizeof (buf2), fp);
- buf2[strlen(buf2)-1] = NULL;
- if (strcmp(buf2, "rejecting") == 0) {
- rc = 1;
- break;
- }
- }
- }
-
- }
- }
-
- (void) fclose(fp);
- return (rc);
-}
-
-/*
- * Remove special characters before popen (change them into '_').
- */
-static void
-clean_string(char *ptr)
-{
- char *cp;
- wchar_t wc;
- int len;
-
- for (cp = ptr; *cp != NULL; ) {
- if ((len = mbtowc(&wc, cp, MB_CUR_MAX)) == -1) {
- cp++;
- continue;
- }
-
- if (len == 1 &&
- ((wc == L'`') || (wc == L'&') || (wc == L';') ||
- (wc == L'|') || (wc == L'>') || (wc == L'^') ||
- (wc == L'$') || (wc == L'(') || (wc == L')') ||
- (wc == L'<') || (wc == L'*') || (wc == L'?') ||
- (wc == L'[')))
- *cp = '_';
- cp += len;
- }
-}
-
-
-static int _notified = 0;
-
-static void
-error_notify(char *user, int id, char *msg, ...)
-{
- if (_notified++ == 0) {
- char *tmp;
- char cmd[BUFSIZ];
- FILE *fp;
- va_list ap;
-
- va_start(ap, msg);
- tmp = strdup(user);
- clean_string(tmp);
- (void) snprintf(cmd, sizeof (cmd),
- "/bin/write %s >/dev/null 2>&1", tmp);
- free(tmp);
- fp = popen(cmd, "w+");
- (void) fprintf(fp,
- gettext("\n\tError transfering print job %d\n"), id);
- (void) vfprintf(fp, msg, ap);
- (void) pclose(fp);
- va_end(ap);
- }
-}
-
-
-
-/*
- * bsd_options() parses the command line using the BSD lpr semantics and sets
- * several global variables for use in building the print request.
- */
-static void
-bsd_options(int ac, char *av[])
-{
- int c;
-
- while ((c = getopt(ac, av,
- "P:#:C:J:T:w:i:hplrstdgvcfmn1:2:3:4:")) != EOF)
- switch (c) {
- case 'P':
- printer = optarg;
- break;
- case '#':
- copies = atoi(optarg);
- break;
- case 'C':
- class = optarg;
- break;
- case 'J':
- jobName = optarg;
- break;
- case 'T':
- title = optarg;
- break;
- case 'w':
- width = atoi(optarg);
- break;
- case 'm':
- mail++;
- break;
- case 'i': /* this may or may not have an arguement */
- if (isdigit(optarg[0]) == 0) {
- indent = 8;
- optind--;
- } else
- indent = atoi(optarg);
- break;
- case 'h':
- banner = 0;
- break;
- case 'r':
- delete = 1;
- break;
- case 's':
- linked = 1;
- break;
- case 'l' :
- type = CF_PRINT_RAW;
- break;
- case 'd' :
- type = CF_PRINT_DVI;
- break;
- case 't' :
- type = CF_PRINT_TROFF;
- break;
- case 'g' :
- type = CF_PRINT_PLOT;
- break;
- case 'v' :
- type = CF_PRINT_RAS;
- break;
- case 'c' :
- type = CF_PRINT_CIF;
- break;
- case 'f' :
- type = CF_PRINT_FORT;
- break;
- case 'n' :
- type = CF_PRINT_DROFF;
- break;
- case 'o' :
- type = CF_PRINT_PS;
- break;
- case 'p' :
- type = CF_PRINT_PR;
- break;
- case '1' :
- fontR = optarg;
- break;
- case '2' :
- fontI = optarg;
- break;
- case '3' :
- fontB = optarg;
- break;
- case '4' :
- fontS = optarg;
- break;
- default:
- (void) fprintf(stderr,
- gettext("Usage: %s [-Pprinter] [-#num] "
- "[-Cclass] [-Jjob] [-Ttitle] [-i [indent]] "
- "[-1234 font] [-wcols] [-m] [-h] [-s] "
- "[-pltndgvcf] files ...\n"),
- av[0]);
- exit(1);
- }
-
- /*
- * The pr filter must be specified with the
- * title, width, and indent options
- */
- if ((title != NULL) && (type != CF_PRINT_PR))
- (void) fprintf(stderr, gettext(
- "Warning: title option ignored as the pr "
- "filter option was not specified\n"));
- if ((width > 0) && (type != CF_PRINT_PR))
- (void) fprintf(stderr, gettext(
- "Warning: width option ignored as the pr "
- "filter option was not specified\n"));
- if ((indent > 0) && (type != CF_PRINT_PR))
- (void) fprintf(stderr, gettext(
- "Warning: indent option ignored as the pr "
- "filter option was not specified\n"));
-}
-
-/*
- * sysv_options() parses the command line using the BSD lpr semantics and sets
- * several global variables for use in building the print request.
- */
-static void
-sysv_options(int ac, char *av[])
-{
- int c;
-
-#ifdef OLD_LP
- if ((ac > 2) && (strcmp(av[1], "-i") == 0)) {
- if (access(OLD_LP, F_OK) == 0) {
- /*
- * limit ourselves to real user's perms before exec'ing
- */
- (void) setuid(getuid());
- (void) execv(OLD_LP, av);
- perror("exec local modify");
- } else
- (void) printf(gettext(
- "job modification not supported on clients\n"));
- exit(-1);
- }
-#endif
-
- linked = 1;
- suppress = 0;
- while ((c = getopt(ac, av, "H:P:S:T:d:f:i:o:q:t:y:cmwn:prs")) != EOF)
- switch (c) {
- case 'q':
- priority = atoi(optarg);
- break;
- case 'H':
- handling = optarg;
- break;
- case 'f':
- form = optarg;
- break;
- case 'd':
- printer = optarg;
- break;
- case 'T':
- {
- struct s5_types *tmp;
- int flag = 0;
-
- for (tmp = output_types;
- ((flag == 0) && (tmp->name != NULL)); tmp++)
- if (strcasecmp(tmp->name, optarg) == 0) {
- type = tmp->type;
- flag++;
- }
- if (flag == 0)
- s5type = optarg;
- else
- internal_type = optarg;
- break;
- }
- case 'S':
- charset = optarg;
- break;
- case 'o':
- {
- char *p, *q = strdup(optarg);
-
- /*
- * -o nobanner will no longer generate a warning or
- * Onobanner in the control file. If "nobanner" is
- * embedded in an option list, the option list will
- * still generate a warning or 'O' message in the
- * control file.
- */
- if (strcmp("nobanner", optarg) != 0)
- s5options = (char **)list_append(
- (void**)s5options,
- (void *)strdup(optarg));
-
- for (p = strtok(q, "\t ,"); p != NULL;
- p = strtok(NULL, "\t ,"))
- if (strcmp(p, "nobanner") == 0) {
- banner = 0;
- break;
- }
- }
- break;
- case 'y':
- {
- char *p, *q = strdup(optarg);
-
- for (p = strtok(q, "\t ,"); p != NULL;
- p = strtok(NULL, "\t ,"))
- if (strcmp(p, "catv_filter") == 0)
- type = CF_PRINT_RAW;
- else
- mode = (char **)list_append(
- (void **)mode,
- (void *)p);
- }
- break;
- case 'P':
- pages = optarg;
- break;
- case 'i':
- (void) printf(gettext(
- "job modification (-i) only supported on server\n"));
- break;
- case 'c':
- linked = 0;
- break;
- case 'm':
- mail++;
- break;
- case 'w':
- mail++;
- break;
- case 'p':
- notification = optarg;
- break;
- case 'n':
- if ((optarg == 0) || (*optarg == '-')) {
- (void) fprintf(stderr, gettext(
- "-n requires a positive integer argument\n"));
- exit(1);
- }
- copies = atoi(optarg);
- break;
- case 's':
- suppress = 1;
- break;
- case 't':
- jobName = optarg;
- break;
- case 'r':
- /* not supported - raw */
- break;
- default:
- (void) fprintf(stderr,
- gettext("Usage: %s [-d dest] [-cmwsr] [-n num] "
- "[-t title] [-p notification] [-P page-list] "
- "[-i job-id] [y modes] [-o options] "
- "[-S char-set] [-T input-type] [H handling] "
- "[-q priority] files ...\n"),
- av[0]);
- exit(1);
- }
-}
-
-
-/*
- * stdin_to_file() reads standard input into a file and returns the file name
- * to the caller
- */
-static char *
-stdin_to_file()
-{
- int fd,
- rc;
- char *name,
- buf[BUFSIZ];
-
- (void) putenv("TMPDIR="); /* stop user moving the temp file */
-
- snprintf(buf, sizeof (buf), "/tmp/stdinXXXXXX");
- if ((fd = mkstemp(buf)) < 0)
- return (NULL);
- fchmod(fd, 0640);
- if ((name = strdup(buf)) == NULL) {
- close(fd);
- return (NULL);
- }
- syslog(LOG_DEBUG, "stdin_to_file: %s", name);
- while ((rc = read(0, buf, sizeof (buf))) > 0)
- (void) write(fd, buf, rc);
- (void) close(fd);
- return (name);
-}
-
-
-static int
-sendfile(jobfile_t *file, int nd, int type)
-{
- int rc = -1;
-
- syslog(LOG_DEBUG, "sendfile(%s, %d, %d)",
- ((file != NULL) ? file->jf_spl_path : "NULL"), nd, type);
- if (file && file->jf_spl_path) {
- rc = net_send_file(nd, file->jf_spl_path, file->jf_data,
- file->jf_size, type);
- }
- return (rc);
-}
-
-
-/*
- * send_job() sends a job to a remote print server.
- */
-static int
-send_job(job_t *job)
-{
- int lockfd,
- lock_size,
- nd,
- tmp,
- rc = 0;
- struct passwd *p = NULL;
- char buf[BUFSIZ];
-
- syslog(LOG_DEBUG, "send_job(%s, %s, %d): called", job->job_printer,
- job->job_server, job->job_id);
- if ((lockfd = get_lock(job->job_cf->jf_src_path, 0)) < 0) {
- (void) close(lockfd);
- return (SEND_RETRY);
- }
-
- /* is job complete ? */
-
- lock_size = file_size(job->job_cf->jf_src_path);
- (void) sprintf(buf, "%ld\n", getpid()); /* add pid to lock file */
- (void) lseek(lockfd, 0, SEEK_END);
- (void) write(lockfd, buf, strlen(buf));
-
- syslog(LOG_DEBUG, "send_job(%s, %s, %d): have lock", job->job_printer,
- job->job_server, job->job_id);
- connection_failed = 0;
- if ((nd = net_open(job->job_server, 5)) < 0) {
- connection_failed = 1;
- if ((nd != NETWORK_ERROR_UNKNOWN) && (nd != NETWORK_ERROR_PORT))
- job_destroy(job);
- else
- (void) ftruncate(lockfd, lock_size);
- (void) close(lockfd);
- return ((nd == NETWORK_ERROR_UNKNOWN) ||
- (nd == NETWORK_ERROR_PORT) ? SEND_RETRY : SEND_ABORT);
- }
-
- if (net_send_message(nd, "%c%s\n", XFER_REQUEST, job->job_printer)
- != 0) {
- (void) net_close(nd);
- syslog(LOG_WARNING,
- "send_job failed job %d (%s@%s) check status\n",
- job->job_id, job->job_printer, job->job_server);
- error_notify(job->job_user, job->job_id,
- gettext("\t\t check queue for (%s@%s)\n"),
- job->job_printer, job->job_server);
- (void) ftruncate(lockfd, lock_size);
- (void) close(lockfd);
- return (SEND_RETRY);
- }
-
- syslog(LOG_DEBUG, "send_job(%s, %s, %d): send data", job->job_printer,
- job->job_server, job->job_id);
-
- if ((p = getpwnam(job->job_user)) != NULL) {
- /*
- * attempt to become the job owner: uid, euid, gid, and
- * supplementary groups while we try to send the job data.
- * The real uid is changed with setreuid() separately from
- * changing the effective uid so that we retain the saved
- * uid to elevate privilege later. Combining these changes
- * would result in a change to the saved uid also and a loss
- * of the ability to elevate privilege later.
- */
- (void) setuid(0);
- (void) initgroups(job->job_user, p->pw_gid);
- (void) setgid(p->pw_gid);
- (void) setreuid(p->pw_uid, -1);
- (void) seteuid(p->pw_uid);
- }
-
- for (tmp = 0; job->job_df_list[tmp] != NULL; tmp++)
- if ((rc = sendfile(job->job_df_list[tmp], nd, XFER_DATA)) < 0)
- break; /* there was an error, quit now */
- tmp = errno;
- if (p != NULL) {
- /*
- * lose the supplemental groups and elevate our effective
- * uid to root so that we can destroy jobs and/or become
- * other job owners later on.
- */
- (void) seteuid(0);
- (void) initgroups("root", 1);
- }
- errno = tmp;
-
- if (rc < 0) {
- if (errno == ENOENT) {
- (void) net_close(nd);
- error_notify(job->job_user, job->job_id, gettext(
- "\t\tdata removed before transfer, job "
- "canceled.\n\t\tTry \"lp -c\" or \"lpr\"\n"));
- job_destroy(job);
- (void) close(lockfd);
- return (SEND_ABORT);
- } else if (errno == EACCES) {
- /* probably trying to circumvent file security */
- (void) net_close(nd);
- error_notify(job->job_user, job->job_id, gettext(
- "\t\tunable to read job data.\n"));
- job_destroy(job);
- (void) close(lockfd);
- return (SEND_ABORT);
- } else {
- (void) net_close(nd);
- (void) ftruncate(lockfd, lock_size);
- error_notify(job->job_user, job->job_id,
- gettext("\t\t check queue for (%s@%s)\n"),
- job->job_printer, job->job_server);
- (void) close(lockfd);
- return (SEND_RETRY);
- }
- }
-
- if (sendfile(job->job_cf, nd, XFER_CONTROL) < 0) {
- (void) net_send_message(nd, "%c\n", XFER_CLEANUP);
- (void) net_close(nd);
- (void) ftruncate(lockfd, lock_size);
- error_notify(job->job_user, job->job_id,
- gettext("\t\t check queue for (%s@%s)\n"),
- job->job_printer, job->job_server);
- (void) close(lockfd);
- return (SEND_RETRY);
- }
-
- syslog(LOG_DEBUG, "send_job(%s, %s, %d): complete", job->job_printer,
- job->job_server, job->job_id);
- (void) net_close(nd);
- job_destroy(job);
- (void) close(lockfd);
- return (0);
-}
-
-
-/*
- * xfer_daemon() attempts to start up a daemon for transfering jobs to a remote
- * print server. The daemon runs if it can get the master lock, and it
- * runs until there are no jobs waiting for transfer.
- */
-static void
-xfer_daemon()
-{
- job_t **list = NULL;
- int i,
- rc;
-
-
-
- closelog();
- closefrom(0);
-
- _notified = 1;
- (void) open("/dev/null", O_RDONLY);
- (void) open("/dev/null", O_WRONLY);
- (void) dup(1);
-
- (void) setuid(0);
- (void) setsid();
- openlog("printd", LOG_PID, LOG_LPR);
- if (fork() != 0)
- exit(0);
-
- if ((i = get_lock(MASTER_LOCK, 1)) < 0)
- exit(0);
-
- (void) chdir(SPOOL_DIR);
- while ((list = job_list_append(NULL, NULL, NULL, SPOOL_DIR)) != NULL) {
- job_t **tmp;
-
- syslog(LOG_DEBUG, "got the queue...");
- for (tmp = list; *tmp != NULL; tmp++) {
- /*
- * Bugid: 4133175 printd dies when data is removed or
- * permissions are changed. Memory is freed twice.
- * Fix: Do not process anything else in the list
- * if the return code is SEND_ABORT as the memory
- * has already been freed by job_destroy().
- */
- rc = send_job(*tmp);
- if ((rc != 0) && (rc != SEND_ABORT)) {
- char *s = strdup((*tmp)->job_server);
- char *p = strdup((*tmp)->job_printer);
-
- if (rc != SEND_ABORT) /* already free */
- job_free(*tmp);
-
- for (tmp++; ((*tmp != NULL) &&
- (strcmp(s, (*tmp)->job_server) == 0));
- tmp++)
- if ((connection_failed == 0) &&
- (strcmp(p,
- (*tmp)->job_printer) == 0))
- job_free(*tmp);
- else
- break;
- tmp--;
- free(s);
- free(p);
- }
- }
- free(list);
-
- /* look for more work to do before we sleep */
- if ((list = job_list_append(NULL, NULL, NULL,
- SPOOL_DIR)) != NULL) {
- (void) list_iterate((void **)list, (VFUNC_T)job_free);
- free(list);
- (void) sleep(60);
- }
- }
- syslog(LOG_DEBUG, "daemon exiting...");
-}
-
-static void
-append_string(char *s, va_list ap)
-{
- char *buf = va_arg(ap, char *);
-
- if (strlen(buf) != 0)
- (void) strcat(buf, " ");
- (void) strcat(buf, s);
-}
-
-
-static char *
-build_string(char **list)
-{
- int size = 0;
- char *buf = NULL;
-
- if (list != NULL) {
- size = list_iterate((void **)list, (VFUNC_T)strlen);
- size += 16;
- buf = malloc(size);
- (void) memset(buf, NULL, size);
- (void) list_iterate((void **)list, (VFUNC_T)append_string, buf);
- }
- return (buf);
-}
-
-
-#define ADD_PRIMATIVE(job, primative, value) \
- if ((job != NULL) && (value != NULL)) \
- (void) job_primative(job, primative, value);
-#define ADD_SVR4_PRIMATIVE(job, primative, value) \
- if ((job != NULL) && (value != NULL)) (void) job_svr4_primative(job, \
- primative, value);
-
-#define ADD_INT_PRIMATIVE(job, primative, value, ok) \
- if ((job != NULL) && (value != ok)) { \
- (void) sprintf(buf, "%d", value); \
- (void) job_primative(job, primative, buf); \
- }
-#define ADD_SVR4_INT_PRIMATIVE(job, primative, value, ok) \
- if ((job != NULL) && (value != ok)) { \
- (void) sprintf(buf, "%d", value); \
- (void) job_svr4_primative(job, primative, \
- buf); \
- }
-
-#define OPTION_ERROR(option, value) \
- if (value != NULL) \
- (void) fprintf(stderr, gettext("\tignoring: %s %s\n"), \
- option, value);
-
-#define OPTION_ERROR_INT(option, value) \
- if (value != -1) \
- (void) fprintf(stderr, gettext("\tignoring: %s %d\n"), \
- option, value);
-
-
-
-/*
- * Main program. if called with "lpr" use the BSD syntax, if called
- * with "lp", use the SYSV syntax. If called by any other name,
- * become a transfer daemon. In the lpr/lp case, build a job and
- * attempt to send it to the print server. If the server doesn't
- * respond, become a daemon if none is currently running and attempt
- * to xfer all waiting jobs.
- */
-int
-main(int ac, char *av[])
-{
- ns_bsd_addr_t *binding = NULL;
- int numFiles = 0,
- queueStdin = 0,
- exit_code = 0;
- char *program,
- *user,
- hostname[128],
- buf[BUFSIZ];
- job_t *job;
-
- (void) setlocale(LC_ALL, "");
-
-#if !defined(TEXT_DOMAIN)
-#define TEXT_DOMAIN "SYS_TEST"
-#endif
- (void) textdomain(TEXT_DOMAIN);
-
- if ((program = strrchr(av[0], '/')) == NULL)
- program = av[0];
- else
- program++;
-
- openlog(program, LOG_PID, LOG_LPR);
-
- /*
- * Bugid: 4013980 Application changed fd 1 to a pipe that has
- * no reader; we write to stdout and catch a sigpipe and exit.
- * Fix: catch signal, complain to syslog, and continue.
- */
- (void) signal(SIGPIPE, sigpipe_handler);
-
- if (check_client_spool(NULL) < 0) {
- (void) fprintf(stderr,
- gettext("couldn't validate local spool area (%s)\n"),
- SPOOL_DIR);
- return (-1);
- }
- if (strcmp(program, "lpr") == 0) {
- if ((printer = getenv((const char *)"PRINTER")) == NULL)
- printer = getenv((const char *)"LPDEST");
- bsd_options(ac, av);
- } else if (strcmp(program, "lp") == 0) {
- if ((printer = getenv((const char *)"LPDEST")) == NULL)
- printer = getenv((const char *)"PRINTER");
- sysv_options(ac, av);
- } else {
- xfer_daemon();
- return (0);
- }
-
- if (printer == NULL) {
- ns_printer_t *pobj = ns_printer_get_name(NS_NAME_DEFAULT, NULL);
-
- if (pobj != NULL) {
- printer = ns_get_value_string(NS_KEY_USE, pobj);
- ns_printer_destroy(pobj);
- }
-
- if (printer == NULL)
- printer = NS_NAME_DEFAULT;
- }
-
- if (printer == NULL) {
- (void) fprintf(stderr, gettext("No default destination\n"));
- return (1);
- }
-
- if ((binding = ns_bsd_addr_get_name(printer)) == NULL) {
- (void) fprintf(stderr, gettext("%s: unknown printer\n"),
- printer);
- return (1);
- }
-
- if (rejecting(binding->printer) != 0) {
- (void) fprintf(stderr, gettext(
- "%s: requests are not being accepted\n"),
- printer);
- return (1);
- }
-
- (void) sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
-#ifdef OLD_LP
- /*
- * If the server is local, there is lp server configuration, and
- * the old lp is still hanging around, use it to submit the job.
- */
- {
- char cpath[MAXPATHLEN],
- ppath[MAXPATHLEN];
-
- (void) snprintf(ppath, sizeof (ppath),
- "/etc/lp/printers/%s/configuration", binding->printer);
- (void) snprintf(cpath, sizeof (cpath),
- "/etc/lp/classes/%s", binding->printer);
- if (((strcasecmp(binding->server, hostname) == 0) ||
- (strcasecmp(binding->server, "localhost") == 0)) &&
- ((access(ppath, F_OK) == 0) ||
- (access(cpath, F_OK) == 0)) &&
- (access(OLD_LP, F_OK) == 0)) {
- printer = binding->printer;
- submit_local_lp(program, ac, av);
- }
- }
-#endif
-
- if ((job = job_create(strdup(binding->printer), strdup(binding->server),
- SPOOL_DIR)) == NULL) {
- syslog(LOG_ERR,
- "Error creating job: check spooling directory: %s",
- SPOOL_DIR);
- (void) fprintf(stderr, gettext(
- "Error creating job: check spooling directory: %s\n"),
- SPOOL_DIR);
- return (-1);
- }
-
- (void) umask(0);
- user = get_user_name();
-
- ADD_PRIMATIVE(job, CF_HOST, hostname);
- ADD_PRIMATIVE(job, CF_USER, user);
- ADD_PRIMATIVE(job, CF_TITLE, title);
-
-
- if (banner != 0) {
- if (jobName != NULL) {
- ADD_PRIMATIVE(job, CF_JOBNAME, jobName);
- } else if ((av[optind] == NULL) ||
- (strcmp(av[optind], "-") == 0)) {
- ADD_PRIMATIVE(job, CF_JOBNAME, "standard input");
- } else {
- ADD_PRIMATIVE(job, CF_JOBNAME, av[optind]);
- }
- ADD_PRIMATIVE(job, CF_CLASS, (class ? class : hostname));
- ADD_PRIMATIVE(job, CF_PRINT_BANNER, user);
- }
-
- if (mail != 0) {
- (void) snprintf(buf, sizeof (buf), "%s@%s", user, hostname);
- ADD_PRIMATIVE(job, CF_MAIL, buf);
- }
-
- ADD_INT_PRIMATIVE(job, CF_INDENT, indent, -1); /* ASCII */
- ADD_INT_PRIMATIVE(job, CF_WIDTH, width, -1);
-
- if ((type == CF_PRINT_DVI) || (type == CF_PRINT_DROFF) ||
- (type == CF_PRINT_TROFF)) {
- ADD_PRIMATIVE(job, CF_FONT_TROFF_R, fontR);
- ADD_PRIMATIVE(job, CF_FONT_TROFF_I, fontI);
- ADD_PRIMATIVE(job, CF_FONT_TROFF_B, fontB);
- ADD_PRIMATIVE(job, CF_FONT_TROFF_S, fontS);
- }
-
- if (binding->extension == NULL)
- binding->extension = "";
-
- if ((strcasecmp(binding->extension, NS_EXT_SOLARIS) == 0) ||
- (strcasecmp(binding->extension, NS_EXT_GENERIC) == 0)) {
- /* RFC1179 compliant don't get this */
- syslog(LOG_DEBUG, "main(): add Solaris extensions");
- ADD_PRIMATIVE(job, CF_SYSV_OPTION, build_string(s5options));
- ADD_SVR4_INT_PRIMATIVE(job, CF_SYSV_PRIORITY, priority, -1);
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_FORM, form);
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_CHARSET, charset);
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_NOTIFICATION, notification);
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_HANDLING, handling);
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_PAGES, pages);
- if (s5type != NULL) {
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_TYPE, s5type);
- } else if (internal_type != NULL)
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_TYPE, internal_type);
- ADD_SVR4_PRIMATIVE(job, CF_SYSV_MODE, build_string(mode));
- } else if (strcasecmp(binding->extension, NS_EXT_HPUX) == 0) {
- syslog(LOG_DEBUG, "main(): add HP-UX extensions");
- if (s5options != NULL) {
- char buf[BUFSIZ];
-
- (void) snprintf(buf, sizeof (buf), " O%s",
- build_string(s5options));
- ADD_PRIMATIVE(job, CF_SOURCE_NAME, buf);
- }
- } else {
- if ((s5options != NULL) || (form != NULL) || (pages != NULL) ||
- (charset != NULL) || (notification != NULL) ||
- (handling != NULL) || (s5type != NULL) || (mode != NULL) ||
- (priority != -1))
- (void) fprintf(stderr, gettext(
- "Warning: %s not configured to handle all lp options:\n"),
- printer);
- OPTION_ERROR("-o", build_string(s5options));
- OPTION_ERROR("-f", form);
- OPTION_ERROR("-P", pages);
- OPTION_ERROR("-S", charset);
- OPTION_ERROR("-p", notification);
- OPTION_ERROR("-H", handling);
- OPTION_ERROR("-T", s5type);
- OPTION_ERROR("-y", build_string(mode));
- OPTION_ERROR_INT("-q", priority);
- }
-
- syslog(LOG_DEBUG, "main(): add files");
- if (ac-optind > 0) {
- while (optind < ac)
- if (strcmp(av[optind++], "-") == 0)
- queueStdin++;
- else if (job_add_data_file(job, av[optind-1], title,
- type, copies, linked, delete) < 0) {
- switch (errno) {
- case EISDIR:
- (void) fprintf(stderr, gettext(
- "%s: not a regular file\n"),
- av[optind-1]);
- break;
- case ESRCH:
- (void) fprintf(stderr, gettext(
- "%s: empty file\n"),
- av[optind-1]);
- break;
- case ENFILE:
- (void) fprintf(stderr, gettext(
- "too many files, ignoring %s\n"),
- av[optind-1]);
- break;
- case EOVERFLOW:
- (void) fprintf(stderr, gettext(
- "%s: largefile (>= 2GB), ignoring\n"),
- av[optind-1]);
- break;
- default:
- perror(av[optind-1]);
- }
- exit_code = -1;
- } else
- numFiles++;
- } else
- queueStdin++;
-
- if (queueStdin != 0) {
- char *name;
-
- /* standard input */
- if ((name = stdin_to_file()) != NULL) {
- if (job_add_data_file(job, name,
- gettext("standard input"),
- type, copies, 0, 0) < 0) {
- switch (errno) {
- case ESRCH:
- (void) fprintf(stderr, gettext(
- "standard input empty\n"));
- break;
- case ENFILE:
- (void) fprintf(stderr, gettext(
- "too many files, ignoring standard input\n"));
- break;
- default:
- perror(name);
- }
- exit_code = -1;
- } else
- numFiles++;
- (void) unlink(name);
- free(name);
- }
- }
-
- if (numFiles == 0)
- return (-1);
-
- if (seteuid(0) < 0)
- perror("seteuid(0)");
-
- (void) signal(SIGBUS, sigbus_handler);
- (void) chdir(SPOOL_DIR);
- (void) job_store(job);
-
- if (suppress == 0)
- if (numFiles == 1)
- (void) printf(
- gettext("request id is %s-%d (%d file)\n"),
- printer, job->job_id, numFiles);
- else
- (void) printf(
- gettext("request id is %s-%d (%d files)\n"),
- printer, job->job_id, numFiles);
- (void) fflush(stdout);
-
- /*
- * bgolden 10/2/96
- * BUG 1264627
- * when executed from xemacs, a sighup will kill
- * the child before the job is sent. ignore the signal
- */
- (void) signal(SIGHUP, SIG_IGN);
-
- switch (fork()) { /* for immediate response */
- case -1:
- syslog(LOG_ERR, "fork() failed: %m");
- break;
- case 0:
- break;
- default:
- return (exit_code);
- }
-
- if (send_job(job) == SEND_RETRY) {
- syslog(LOG_DEBUG, "main(): transfer failed");
- start_daemon(0);
- }
- else
- syslog(LOG_DEBUG, "main(): transfer succeeded");
-
- return (0);
-}