summaryrefslogtreecommitdiff
path: root/usr/src/cmd/lp/model/lp.tsol_separator.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/lp/model/lp.tsol_separator.c')
-rw-r--r--usr/src/cmd/lp/model/lp.tsol_separator.c528
1 files changed, 528 insertions, 0 deletions
diff --git a/usr/src/cmd/lp/model/lp.tsol_separator.c b/usr/src/cmd/lp/model/lp.tsol_separator.c
new file mode 100644
index 0000000000..a7ea55a154
--- /dev/null
+++ b/usr/src/cmd/lp/model/lp.tsol_separator.c
@@ -0,0 +1,528 @@
+/*
+ * 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Add TSOL banner, trailer, page header/footers to a print job
+ */
+
+/* system header files */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <locale.h>
+#include <tsol/label.h>
+
+/* typedefs */
+
+typedef int BOOL;
+
+/* constants */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define ME "lp.tsol_separator"
+#define POSTSCRIPTLIB "/usr/lib/lp/postscript"
+#define SEPARATORPS "tsol_separator.ps"
+#define BANNERPS "tsol_banner.ps"
+#define TRAILERPS "tsol_trailer.ps"
+#define MAXUSERLEN 32
+#define MAXHOSTLEN 32
+
+/* external variables */
+
+int optind; /* Used by getopt */
+char *optarg; /* Used by getopt */
+
+/* prototypes for static functions */
+
+static int ProcessArgs(int argc, char **argv);
+static void Usage(void);
+static void ParseUsername(char *input, char *user, char *host);
+static void EmitPSFile(const char *name);
+static BOOL EmitFile(FILE *file);
+static void EmitJobData(void);
+static void EmitPrologue(void);
+static void EmitCommandLineInfo(void);
+static void EmitClockBasedInfo(void);
+static void EmitLabelInfo(void);
+static void CopyStdin(void);
+
+/* static variables */
+
+static char *ArgSeparatorPS;
+static char *ArgBannerPS;
+static char *ArgTrailerPS;
+static char *ArgPSLib;
+static char *ArgPrinter;
+static char *ArgJobID;
+static char *ArgUser;
+static char *ArgTitle;
+static char *ArgFile;
+static BOOL ArgReverse;
+static BOOL ArgNoPageLabels;
+static int ArgDebugLevel;
+static FILE *ArgLogFile;
+static m_label_t *FileLabel;
+static char *remoteLabel;
+
+int
+main(int argc, char *argv[])
+{
+ int err;
+ /*
+ * Run immune from typical interruptions, so that
+ * we stand a chance to get the fault message.
+ * EOF (or startup error) is the only way out.
+ */
+ (void) signal(SIGHUP, SIG_IGN);
+ (void) signal(SIGINT, SIG_IGN);
+ (void) signal(SIGQUIT, SIG_IGN);
+ (void) signal(SIGTERM, SIG_IGN);
+
+ (void) setlocale(LC_ALL, "");
+#if !defined(TEXT_DOMAIN)
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
+ (void) textdomain(TEXT_DOMAIN);
+
+ if (ProcessArgs(argc, argv) != 0)
+ exit(1);
+
+ if ((FileLabel = m_label_alloc(MAC_LABEL)) == NULL)
+ exit(1);
+ /*
+ * If the job was submitted via remotely, the label of the
+ * remote peer will be set in the SLABEL environment variable
+ * by copying it out of the SECURE structure.
+ *
+ * If there is no SLABEL value, the job was submitted locally
+ * via the named pipe, and the file label can be determined
+ * from its pathname.
+ */
+ if ((remoteLabel = getenv("SLABEL")) != NULL) {
+ m_label_free(FileLabel);
+ FileLabel = NULL;
+ if (str_to_label(remoteLabel, &FileLabel, MAC_LABEL,
+ L_NO_CORRECTION, &err) == -1) {
+ perror("str_to_label");
+ exit(1);
+ }
+ } else if (getlabel(ArgFile, FileLabel) != 0) {
+ (void) fprintf(ArgLogFile,
+ gettext("%1$s: cannot get label of %2$s: %3$s\n"),
+ ME, ArgFile, strerror(errno));
+ exit(1);
+ }
+
+ /* All of these functions exit if they encounter an error */
+ EmitJobData();
+ EmitPSFile(ArgSeparatorPS);
+ if (ArgReverse)
+ EmitPSFile(ArgTrailerPS);
+ else
+ EmitPSFile(ArgBannerPS);
+ CopyStdin();
+ if (ArgReverse)
+ EmitPSFile(ArgBannerPS);
+ else
+ EmitPSFile(ArgTrailerPS);
+ if (ArgDebugLevel >= 1)
+ (void) fprintf(ArgLogFile, gettext("Done.\n"));
+ m_label_free(FileLabel);
+ return (0);
+}
+
+static void
+EmitJobData(void)
+{
+ EmitPrologue();
+ EmitCommandLineInfo();
+ EmitClockBasedInfo();
+ EmitLabelInfo();
+
+ /* Emit ending PostScript code */
+ (void) printf("end\n\n");
+ (void) printf("%%%% End of code generated by lp.tsol_separator\n\n");
+
+}
+
+static void
+EmitPrologue(void)
+{
+ /* Emit preliminary PostScript code */
+ (void) printf("%%!\n\n");
+ (void) printf("%%%% Begin code generated by lp.tsol_separator\n\n");
+
+ (void) printf("%%%% Create JobDict if it doesn't exist\n");
+ (void) printf("userdict /JobDict known not {\n");
+ (void) printf(" userdict /JobDict 100 dict put\n");
+ (void) printf("} if\n\n");
+
+ (void) printf("%%%% Define job parameters, including TSOL security "
+ "info\n");
+ (void) printf("JobDict\n");
+ (void) printf("begin\n");
+}
+
+/* Emit parameters obtained from command line options */
+
+static void
+EmitCommandLineInfo(void)
+{
+ char user[MAXUSERLEN + 1];
+ char host[MAXHOSTLEN + 1];
+
+ (void) printf("\t/Job_Printer (%s) def\n", ArgPrinter);
+ ParseUsername(ArgUser, user, host);
+ (void) printf("\t/Job_Host (%s) def\n", host);
+ (void) printf("\t/Job_User (%s) def\n", user);
+ (void) printf("\t/Job_JobID (%s) def\n", ArgJobID);
+ (void) printf("\t/Job_Title (%s) def\n", ArgTitle);
+ (void) printf("\t/Job_DoPageLabels (%s) def\n",
+ ArgNoPageLabels ? "NO" : "YES");
+ (void) printf("\n");
+}
+
+/* Emit parameters generated from the system clock */
+
+static void
+EmitClockBasedInfo(void)
+{
+ char timebuf[80];
+ struct timeval clockval;
+
+ (void) gettimeofday(&clockval, NULL);
+ (void) strftime(timebuf, sizeof (timebuf), NULL,
+ localtime(&clockval.tv_sec));
+ (void) printf("\t/Job_Date (%s) def\n", timebuf);
+ (void) printf("\t/Job_Hash (%ld) def\n", clockval.tv_usec % 100000L);
+ (void) printf("\n");
+}
+
+/* Emit parameters derived from the SL and IL of the file being printed. */
+
+static void
+EmitLabelInfo(void)
+{
+ char *header = NULL; /* DIA banner page fields */
+ char *label = NULL;
+ char *caveats = NULL;
+ char *channels = NULL;
+ char *page_label = NULL; /* interior pages label */
+
+ if (label_to_str(FileLabel, &header, PRINTER_TOP_BOTTOM,
+ DEF_NAMES) != 0) {
+ (void) fprintf(ArgLogFile,
+ gettext("%s: label_to_str PRINTER_TOP_BOTTOM: %s.\n"),
+ ME, strerror(errno));
+ exit(1);
+ }
+ if (label_to_str(FileLabel, &label, PRINTER_LABEL,
+ DEF_NAMES) != 0) {
+ (void) fprintf(ArgLogFile,
+ gettext("%s: label_to_str PRINTER_LABEL: %s.\n"),
+ ME, strerror(errno));
+ exit(1);
+ }
+ if (label_to_str(FileLabel, &caveats, PRINTER_CAVEATS,
+ DEF_NAMES) != 0) {
+ (void) fprintf(ArgLogFile,
+ gettext("%s: label_to_str PRINTER_CAVEATS: %s.\n"),
+ ME, strerror(errno));
+ exit(1);
+ }
+ if (label_to_str(FileLabel, &channels, PRINTER_CHANNELS,
+ DEF_NAMES) != 0) {
+ (void) fprintf(ArgLogFile,
+ gettext("%s: label_to_str PRINTER_CHANNELS: %s.\n"),
+ ME, strerror(errno));
+ exit(1);
+ }
+ if (label_to_str(FileLabel, &page_label, M_LABEL,
+ LONG_NAMES) != 0) {
+ (void) fprintf(ArgLogFile,
+ gettext("%s: label_to_str M_LABEL: %s.\n"),
+ ME, strerror(errno));
+ exit(1);
+ }
+
+ (void) printf("\t/Job_Classification (%s) def\n", header);
+ (void) printf("\t/Job_Protect (%s) def\n", label);
+ (void) printf("\t/Job_Caveats (%s) def\n", caveats);
+ (void) printf("\t/Job_Channels (%s) def\n", channels);
+ (void) printf("\t/Job_SL_Internal (%s) def\n", page_label);
+
+ /* Free memory allocated label_to_str */
+ free(header);
+ free(label);
+ free(caveats);
+ free(channels);
+ free(page_label);
+}
+
+/*
+ * Parse input "host!user" to separate host and user names.
+ */
+
+static void
+ParseUsername(char *input, char *user, char *host)
+{
+ char *cp;
+
+ if ((cp = strchr(input, '@')) != NULL) {
+ /* user@host */
+ (void) strlcpy(host, cp + 1, MAXHOSTLEN + 1);
+ *cp = '\0';
+ (void) strlcpy(user, input, MAXUSERLEN + 1);
+ *cp = '@';
+ } else if ((cp = strchr(input, '!')) != NULL) {
+ /* host!user */
+ (void) strlcpy(user, cp + 1, MAXUSERLEN + 1);
+ *cp = '\0';
+ (void) strlcpy(host, input, MAXHOSTLEN + 1);
+ *cp = '!';
+ } else {
+ /* user */
+ (void) strlcpy(user, input, MAXUSERLEN + 1);
+ host[0] = '\0';
+ }
+}
+
+
+static void
+CopyStdin(void)
+{
+ if (!EmitFile(stdin)) {
+ (void) fprintf(ArgLogFile,
+ gettext("%s: Error copying stdin to stdout\n"), ME);
+ exit(1);
+ }
+}
+
+
+static BOOL
+EmitFile(FILE *file)
+{
+ int len;
+#define BUFLEN 1024
+ char buf[BUFLEN];
+
+ while ((len = fread(buf, 1, BUFLEN, file)) > 0) {
+ if (fwrite(buf, 1, len, stdout) != len)
+ return (FALSE);
+ }
+ if (!feof(file))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+static void
+EmitPSFile(const char *name)
+{
+ char path[PATH_MAX];
+ FILE *file;
+ BOOL emitted;
+
+ if (name[0] != '/') {
+ (void) strlcpy(path, ArgPSLib, sizeof (path));
+ (void) strlcat(path, "/", sizeof (path));
+ (void) strlcat(path, name, sizeof (path));
+ } else {
+ (void) strlcpy(path, name, sizeof (path));
+ }
+
+ file = fopen(path, "r");
+ if (file == NULL) {
+ (void) fprintf(ArgLogFile,
+ gettext("%s: Error opening PostScript file %s. %s.\n"),
+ ME, path, strerror(errno));
+ exit(1);
+ }
+
+ emitted = EmitFile(file);
+ (void) fclose(file);
+ if (!emitted) {
+ (void) fprintf(ArgLogFile, gettext(
+ "%s: Error copying PostScript file %s to stdout.\n"),
+ ME, path);
+ exit(1);
+ }
+}
+
+
+static int
+ProcessArgs(int argc, char *argv[])
+{
+ int option_letter;
+ char *options_string = "lrd:e:s:b:t:L:";
+
+ /* set default values for arguments */
+ ArgSeparatorPS = SEPARATORPS;
+ ArgBannerPS = BANNERPS;
+ ArgTrailerPS = TRAILERPS;
+ ArgPSLib = POSTSCRIPTLIB;
+ ArgNoPageLabels = ArgReverse = FALSE;
+ ArgDebugLevel = 0;
+ ArgLogFile = stderr;
+
+ /* read switch arguments once to get error log file */
+ while ((option_letter = getopt(argc, argv, options_string)) != EOF) {
+ switch (option_letter) {
+ case 'd':
+ ArgDebugLevel = atoi(optarg);
+ break;
+ case 'e':
+ ArgLogFile = fopen(optarg, "a");
+ if (ArgLogFile == NULL) {
+ (void) fprintf(stderr,
+ gettext("Cannot open log file %s\n"),
+ optarg);
+ return (-1);
+ }
+ break;
+ case '?': /* ? or unrecognized option */
+ Usage();
+ return (-1);
+ }
+ }
+
+ if (ArgDebugLevel > 0)
+ (void) fprintf(ArgLogFile,
+ gettext("Processing switch arguments\n"));
+
+ /* re-read switch arguments */
+ optind = 1;
+ while ((option_letter = getopt(argc, argv, options_string)) != EOF) {
+ switch (option_letter) {
+ case 'd':
+ ArgDebugLevel = atoi(optarg);
+ break;
+ case 'e':
+ /* This was handled in earlier pass through args */
+ break;
+ case 'l':
+ ArgNoPageLabels = TRUE;
+ break;
+ case 'r':
+ ArgReverse = TRUE;
+ break;
+ case 's':
+ ArgSeparatorPS = optarg;
+ break;
+ case 'b':
+ ArgBannerPS = optarg;
+ break;
+ case 't':
+ ArgTrailerPS = optarg;
+ break;
+ case 'L':
+ ArgPSLib = optarg;
+ break;
+ case '?': /* ? or unrecognized option */
+ Usage();
+ return (-1);
+ }
+ }
+
+ /* Adjust arguments to skip over options */
+ argc -= optind; /* Number of remaining(non-switch) args */
+ argv += optind; /* argv[0] is first(non-switch) args */
+
+ if (argc != 5) {
+ (void) fprintf(ArgLogFile,
+ gettext("Wrong number of arguments.\n\n"));
+ Usage();
+ return (-1);
+ }
+
+ ArgPrinter = argv++[0];
+ ArgJobID = argv++[0];
+ ArgUser = argv++[0];
+ ArgTitle = argv++[0];
+ ArgFile = argv++[0];
+
+ if (ArgDebugLevel >= 1) {
+ (void) fprintf(ArgLogFile, gettext("Arguments processed\n"));
+ (void) fprintf(ArgLogFile, gettext("Printer: %s\n"),
+ ArgPrinter);
+ (void) fprintf(ArgLogFile, gettext("Job ID: %s\n"), ArgJobID);
+ (void) fprintf(ArgLogFile, gettext("User: %s\n"), ArgUser);
+ (void) fprintf(ArgLogFile, gettext("Title: %s\n"), ArgTitle);
+ (void) fprintf(ArgLogFile, gettext("File: %s\n"), ArgFile);
+ }
+
+ return (0);
+}
+
+
+static void
+Usage(void)
+{
+ static const char *OPTFMT = " %-8s %-9s %s\n";
+
+ (void) fprintf(ArgLogFile,
+ gettext("Usage: lp.tsol_separator [OPTIONS] %s\n"),
+ gettext("PRINTER JOBID HOST!USER TITLE FILE"));
+ (void) fprintf(ArgLogFile, gettext(" OPTIONS:\n"));
+ (void) fprintf(ArgLogFile, OPTFMT, "-r", gettext("Reverse"),
+ gettext("Reverse banner/trailer order"));
+ (void) fprintf(ArgLogFile, OPTFMT, "-l", gettext("Labels"),
+ gettext("Suppress page header/footer labels"));
+ (void) fprintf(ArgLogFile, OPTFMT, gettext("-b FILE"),
+ gettext("Banner"),
+ gettext("PostScript program for banner (default tsol_banner.ps)"));
+ (void) fprintf(ArgLogFile, OPTFMT, gettext("-s FILE"),
+ gettext("Separator"),
+ gettext("PostScript program for separator "
+ "(default tsol_separator.ps)"));
+ (void) fprintf(ArgLogFile, OPTFMT, gettext("-t FILE"),
+ gettext("Trailer"),
+ gettext("PostScript program for trailer "
+ "(default tsol_trailer.ps)"));
+ (void) fprintf(ArgLogFile, OPTFMT, gettext("-L DIR"),
+ gettext("Library"),
+ gettext("Directory to search for PostScript programs"));
+ (void) fprintf(ArgLogFile, OPTFMT, "", "",
+ gettext("(default /usr/lib/lp/postscript)"));
+ (void) fprintf(ArgLogFile, OPTFMT, gettext("-d N"), gettext("Debug"),
+ gettext("Set debug level to N"));
+ (void) fprintf(ArgLogFile, OPTFMT, gettext("-e FILE"),
+ gettext("Error File"),
+ gettext("Append error and debugging output to FILE"));
+}