4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Add TSOL banner, trailer, page header/footers to a print job
33 /* system header files */
43 #include <tsol/label.h>
58 #define ME "lp.tsol_separator"
59 #define POSTSCRIPTLIB "/usr/lib/lp/postscript"
60 #define SEPARATORPS "tsol_separator.ps"
61 #define BANNERPS "tsol_banner.ps"
62 #define TRAILERPS "tsol_trailer.ps"
66 /* external variables */
68 int optind
; /* Used by getopt */
69 char *optarg
; /* Used by getopt */
71 /* prototypes for static functions */
73 static int ProcessArgs(int argc
, char **argv
);
74 static void Usage(void);
75 static void ParseUsername(char *input
, char *user
, char *host
);
76 static void EmitPSFile(const char *name
);
77 static BOOL
EmitFile(FILE *file
);
78 static void EmitJobData(void);
79 static void EmitPrologue(void);
80 static void EmitCommandLineInfo(void);
81 static void EmitClockBasedInfo(void);
82 static void EmitLabelInfo(void);
83 static void CopyStdin(void);
85 /* static variables */
87 static char *ArgSeparatorPS
;
88 static char *ArgBannerPS
;
89 static char *ArgTrailerPS
;
90 static char *ArgPSLib
;
91 static char *ArgPrinter
;
92 static char *ArgJobID
;
94 static char *ArgTitle
;
96 static BOOL ArgReverse
;
97 static BOOL ArgNoPageLabels
;
98 static int ArgDebugLevel
;
99 static FILE *ArgLogFile
;
100 static m_label_t
*FileLabel
;
101 static char *remoteLabel
;
104 main(int argc
, char *argv
[])
108 * Run immune from typical interruptions, so that
109 * we stand a chance to get the fault message.
110 * EOF (or startup error) is the only way out.
112 (void) signal(SIGHUP
, SIG_IGN
);
113 (void) signal(SIGINT
, SIG_IGN
);
114 (void) signal(SIGQUIT
, SIG_IGN
);
115 (void) signal(SIGTERM
, SIG_IGN
);
117 (void) setlocale(LC_ALL
, "");
118 #if !defined(TEXT_DOMAIN)
119 #define TEXT_DOMAIN "SYS_TEST"
121 (void) textdomain(TEXT_DOMAIN
);
123 if (ProcessArgs(argc
, argv
) != 0)
126 if ((FileLabel
= m_label_alloc(MAC_LABEL
)) == NULL
)
129 * If the job was submitted via remotely, the label of the
130 * remote peer will be set in the SLABEL environment variable
131 * by copying it out of the SECURE structure.
133 * If there is no SLABEL value, the job was submitted locally
134 * via the named pipe, and the file label can be determined
137 if ((remoteLabel
= getenv("SLABEL")) != NULL
) {
138 m_label_free(FileLabel
);
140 if (str_to_label(remoteLabel
, &FileLabel
, MAC_LABEL
,
141 L_NO_CORRECTION
, &err
) == -1) {
142 perror("str_to_label");
145 } else if (getlabel(ArgFile
, FileLabel
) != 0) {
146 (void) fprintf(ArgLogFile
,
147 gettext("%1$s: cannot get label of %2$s: %3$s\n"),
148 ME
, ArgFile
, strerror(errno
));
152 /* All of these functions exit if they encounter an error */
154 EmitPSFile(ArgSeparatorPS
);
156 EmitPSFile(ArgTrailerPS
);
158 EmitPSFile(ArgBannerPS
);
161 EmitPSFile(ArgBannerPS
);
163 EmitPSFile(ArgTrailerPS
);
164 if (ArgDebugLevel
>= 1)
165 (void) fprintf(ArgLogFile
, gettext("Done.\n"));
166 m_label_free(FileLabel
);
174 EmitCommandLineInfo();
175 EmitClockBasedInfo();
178 /* Emit ending PostScript code */
179 (void) printf("end\n\n");
180 (void) printf("%%%% End of code generated by lp.tsol_separator\n\n");
187 /* Emit preliminary PostScript code */
188 (void) printf("%%!\n\n");
189 (void) printf("%%%% Begin code generated by lp.tsol_separator\n\n");
191 (void) printf("%%%% Create JobDict if it doesn't exist\n");
192 (void) printf("userdict /JobDict known not {\n");
193 (void) printf(" userdict /JobDict 100 dict put\n");
194 (void) printf("} if\n\n");
196 (void) printf("%%%% Define job parameters, including TSOL security "
198 (void) printf("JobDict\n");
199 (void) printf("begin\n");
202 /* Emit parameters obtained from command line options */
205 EmitCommandLineInfo(void)
207 char user
[MAXUSERLEN
+ 1];
208 char host
[MAXHOSTLEN
+ 1];
210 (void) printf("\t/Job_Printer (%s) def\n", ArgPrinter
);
211 ParseUsername(ArgUser
, user
, host
);
212 (void) printf("\t/Job_Host (%s) def\n", host
);
213 (void) printf("\t/Job_User (%s) def\n", user
);
214 (void) printf("\t/Job_JobID (%s) def\n", ArgJobID
);
215 (void) printf("\t/Job_Title (%s) def\n", ArgTitle
);
216 (void) printf("\t/Job_DoPageLabels (%s) def\n",
217 ArgNoPageLabels
? "NO" : "YES");
221 /* Emit parameters generated from the system clock */
224 EmitClockBasedInfo(void)
227 struct timeval clockval
;
229 (void) gettimeofday(&clockval
, NULL
);
230 (void) strftime(timebuf
, sizeof (timebuf
), NULL
,
231 localtime(&clockval
.tv_sec
));
232 (void) printf("\t/Job_Date (%s) def\n", timebuf
);
233 (void) printf("\t/Job_Hash (%ld) def\n", clockval
.tv_usec
% 100000L);
237 /* Emit parameters derived from the SL and IL of the file being printed. */
242 char *header
= NULL
; /* DIA banner page fields */
244 char *caveats
= NULL
;
245 char *channels
= NULL
;
246 char *page_label
= NULL
; /* interior pages label */
248 if (label_to_str(FileLabel
, &header
, PRINTER_TOP_BOTTOM
,
250 (void) fprintf(ArgLogFile
,
251 gettext("%s: label_to_str PRINTER_TOP_BOTTOM: %s.\n"),
252 ME
, strerror(errno
));
255 if (label_to_str(FileLabel
, &label
, PRINTER_LABEL
,
257 (void) fprintf(ArgLogFile
,
258 gettext("%s: label_to_str PRINTER_LABEL: %s.\n"),
259 ME
, strerror(errno
));
262 if (label_to_str(FileLabel
, &caveats
, PRINTER_CAVEATS
,
264 (void) fprintf(ArgLogFile
,
265 gettext("%s: label_to_str PRINTER_CAVEATS: %s.\n"),
266 ME
, strerror(errno
));
269 if (label_to_str(FileLabel
, &channels
, PRINTER_CHANNELS
,
271 (void) fprintf(ArgLogFile
,
272 gettext("%s: label_to_str PRINTER_CHANNELS: %s.\n"),
273 ME
, strerror(errno
));
276 if (label_to_str(FileLabel
, &page_label
, M_LABEL
,
278 (void) fprintf(ArgLogFile
,
279 gettext("%s: label_to_str M_LABEL: %s.\n"),
280 ME
, strerror(errno
));
284 (void) printf("\t/Job_Classification (%s) def\n", header
);
285 (void) printf("\t/Job_Protect (%s) def\n", label
);
286 (void) printf("\t/Job_Caveats (%s) def\n", caveats
);
287 (void) printf("\t/Job_Channels (%s) def\n", channels
);
288 (void) printf("\t/Job_SL_Internal (%s) def\n", page_label
);
290 /* Free memory allocated label_to_str */
299 * Parse input "host!user" to separate host and user names.
303 ParseUsername(char *input
, char *user
, char *host
)
307 if ((cp
= strchr(input
, '@')) != NULL
) {
309 (void) strlcpy(host
, cp
+ 1, MAXHOSTLEN
+ 1);
311 (void) strlcpy(user
, input
, MAXUSERLEN
+ 1);
313 } else if ((cp
= strchr(input
, '!')) != NULL
) {
315 (void) strlcpy(user
, cp
+ 1, MAXUSERLEN
+ 1);
317 (void) strlcpy(host
, input
, MAXHOSTLEN
+ 1);
321 (void) strlcpy(user
, input
, MAXUSERLEN
+ 1);
330 if (!EmitFile(stdin
)) {
331 (void) fprintf(ArgLogFile
,
332 gettext("%s: Error copying stdin to stdout\n"), ME
);
345 while ((len
= fread(buf
, 1, BUFLEN
, file
)) > 0) {
346 if (fwrite(buf
, 1, len
, stdout
) != len
)
356 EmitPSFile(const char *name
)
362 if (name
[0] != '/') {
363 (void) strlcpy(path
, ArgPSLib
, sizeof (path
));
364 (void) strlcat(path
, "/", sizeof (path
));
365 (void) strlcat(path
, name
, sizeof (path
));
367 (void) strlcpy(path
, name
, sizeof (path
));
370 file
= fopen(path
, "r");
372 (void) fprintf(ArgLogFile
,
373 gettext("%s: Error opening PostScript file %s. %s.\n"),
374 ME
, path
, strerror(errno
));
378 emitted
= EmitFile(file
);
381 (void) fprintf(ArgLogFile
, gettext(
382 "%s: Error copying PostScript file %s to stdout.\n"),
390 ProcessArgs(int argc
, char *argv
[])
393 char *options_string
= "lrd:e:s:b:t:L:";
395 /* set default values for arguments */
396 ArgSeparatorPS
= SEPARATORPS
;
397 ArgBannerPS
= BANNERPS
;
398 ArgTrailerPS
= TRAILERPS
;
399 ArgPSLib
= POSTSCRIPTLIB
;
400 ArgNoPageLabels
= ArgReverse
= FALSE
;
404 /* read switch arguments once to get error log file */
405 while ((option_letter
= getopt(argc
, argv
, options_string
)) != EOF
) {
406 switch (option_letter
) {
408 ArgDebugLevel
= atoi(optarg
);
411 ArgLogFile
= fopen(optarg
, "a");
412 if (ArgLogFile
== NULL
) {
413 (void) fprintf(stderr
,
414 gettext("Cannot open log file %s\n"),
419 case '?': /* ? or unrecognized option */
425 if (ArgDebugLevel
> 0)
426 (void) fprintf(ArgLogFile
,
427 gettext("Processing switch arguments\n"));
429 /* re-read switch arguments */
431 while ((option_letter
= getopt(argc
, argv
, options_string
)) != EOF
) {
432 switch (option_letter
) {
434 ArgDebugLevel
= atoi(optarg
);
437 /* This was handled in earlier pass through args */
440 ArgNoPageLabels
= TRUE
;
446 ArgSeparatorPS
= optarg
;
449 ArgBannerPS
= optarg
;
452 ArgTrailerPS
= optarg
;
457 case '?': /* ? or unrecognized option */
463 /* Adjust arguments to skip over options */
464 argc
-= optind
; /* Number of remaining(non-switch) args */
465 argv
+= optind
; /* argv[0] is first(non-switch) args */
468 (void) fprintf(ArgLogFile
,
469 gettext("Wrong number of arguments.\n\n"));
474 ArgPrinter
= argv
++[0];
475 ArgJobID
= argv
++[0];
477 ArgTitle
= argv
++[0];
480 if (ArgDebugLevel
>= 1) {
481 (void) fprintf(ArgLogFile
, gettext("Arguments processed\n"));
482 (void) fprintf(ArgLogFile
, gettext("Printer: %s\n"),
484 (void) fprintf(ArgLogFile
, gettext("Job ID: %s\n"), ArgJobID
);
485 (void) fprintf(ArgLogFile
, gettext("User: %s\n"), ArgUser
);
486 (void) fprintf(ArgLogFile
, gettext("Title: %s\n"), ArgTitle
);
487 (void) fprintf(ArgLogFile
, gettext("File: %s\n"), ArgFile
);
497 static const char *OPTFMT
= " %-8s %-9s %s\n";
499 (void) fprintf(ArgLogFile
,
500 gettext("Usage: lp.tsol_separator [OPTIONS] %s\n"),
501 gettext("PRINTER JOBID HOST!USER TITLE FILE"));
502 (void) fprintf(ArgLogFile
, gettext(" OPTIONS:\n"));
503 (void) fprintf(ArgLogFile
, OPTFMT
, "-r", gettext("Reverse"),
504 gettext("Reverse banner/trailer order"));
505 (void) fprintf(ArgLogFile
, OPTFMT
, "-l", gettext("Labels"),
506 gettext("Suppress page header/footer labels"));
507 (void) fprintf(ArgLogFile
, OPTFMT
, gettext("-b FILE"),
509 gettext("PostScript program for banner (default tsol_banner.ps)"));
510 (void) fprintf(ArgLogFile
, OPTFMT
, gettext("-s FILE"),
511 gettext("Separator"),
512 gettext("PostScript program for separator "
513 "(default tsol_separator.ps)"));
514 (void) fprintf(ArgLogFile
, OPTFMT
, gettext("-t FILE"),
516 gettext("PostScript program for trailer "
517 "(default tsol_trailer.ps)"));
518 (void) fprintf(ArgLogFile
, OPTFMT
, gettext("-L DIR"),
520 gettext("Directory to search for PostScript programs"));
521 (void) fprintf(ArgLogFile
, OPTFMT
, "", "",
522 gettext("(default /usr/lib/lp/postscript)"));
523 (void) fprintf(ArgLogFile
, OPTFMT
, gettext("-d N"), gettext("Debug"),
524 gettext("Set debug level to N"));
525 (void) fprintf(ArgLogFile
, OPTFMT
, gettext("-e FILE"),
526 gettext("Error File"),
527 gettext("Append error and debugging output to FILE"));