diff options
Diffstat (limited to 'usr/src/cmd/lp/model/lp.tsol_separator.c')
| -rw-r--r-- | usr/src/cmd/lp/model/lp.tsol_separator.c | 528 |
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")); +} |
