/* * 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. */ /* * Add TSOL banner, trailer, page header/footers to a print job */ /* system header files */ #include #include #include #include #include #include #include #include #include /* 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")); }