Merge branch 'less_closed'
[unleashed.git] / usr / src / cmd / lp / model / lp.tsol_separator.c
bloba7ea55a1546fed8ccc481234b359fd7e356164c1
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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 */
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39 #include <limits.h>
40 #include <errno.h>
41 #include <signal.h>
42 #include <locale.h>
43 #include <tsol/label.h>
45 /* typedefs */
47 typedef int BOOL;
49 /* constants */
51 #ifndef FALSE
52 #define FALSE 0
53 #endif
54 #ifndef TRUE
55 #define TRUE 1
56 #endif
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"
63 #define MAXUSERLEN 32
64 #define MAXHOSTLEN 32
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;
93 static char *ArgUser;
94 static char *ArgTitle;
95 static char *ArgFile;
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[])
106 int err;
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"
120 #endif
121 (void) textdomain(TEXT_DOMAIN);
123 if (ProcessArgs(argc, argv) != 0)
124 exit(1);
126 if ((FileLabel = m_label_alloc(MAC_LABEL)) == NULL)
127 exit(1);
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
135 * from its pathname.
137 if ((remoteLabel = getenv("SLABEL")) != NULL) {
138 m_label_free(FileLabel);
139 FileLabel = NULL;
140 if (str_to_label(remoteLabel, &FileLabel, MAC_LABEL,
141 L_NO_CORRECTION, &err) == -1) {
142 perror("str_to_label");
143 exit(1);
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));
149 exit(1);
152 /* All of these functions exit if they encounter an error */
153 EmitJobData();
154 EmitPSFile(ArgSeparatorPS);
155 if (ArgReverse)
156 EmitPSFile(ArgTrailerPS);
157 else
158 EmitPSFile(ArgBannerPS);
159 CopyStdin();
160 if (ArgReverse)
161 EmitPSFile(ArgBannerPS);
162 else
163 EmitPSFile(ArgTrailerPS);
164 if (ArgDebugLevel >= 1)
165 (void) fprintf(ArgLogFile, gettext("Done.\n"));
166 m_label_free(FileLabel);
167 return (0);
170 static void
171 EmitJobData(void)
173 EmitPrologue();
174 EmitCommandLineInfo();
175 EmitClockBasedInfo();
176 EmitLabelInfo();
178 /* Emit ending PostScript code */
179 (void) printf("end\n\n");
180 (void) printf("%%%% End of code generated by lp.tsol_separator\n\n");
184 static void
185 EmitPrologue(void)
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 "
197 "info\n");
198 (void) printf("JobDict\n");
199 (void) printf("begin\n");
202 /* Emit parameters obtained from command line options */
204 static void
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");
218 (void) printf("\n");
221 /* Emit parameters generated from the system clock */
223 static void
224 EmitClockBasedInfo(void)
226 char timebuf[80];
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);
234 (void) printf("\n");
237 /* Emit parameters derived from the SL and IL of the file being printed. */
239 static void
240 EmitLabelInfo(void)
242 char *header = NULL; /* DIA banner page fields */
243 char *label = NULL;
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,
249 DEF_NAMES) != 0) {
250 (void) fprintf(ArgLogFile,
251 gettext("%s: label_to_str PRINTER_TOP_BOTTOM: %s.\n"),
252 ME, strerror(errno));
253 exit(1);
255 if (label_to_str(FileLabel, &label, PRINTER_LABEL,
256 DEF_NAMES) != 0) {
257 (void) fprintf(ArgLogFile,
258 gettext("%s: label_to_str PRINTER_LABEL: %s.\n"),
259 ME, strerror(errno));
260 exit(1);
262 if (label_to_str(FileLabel, &caveats, PRINTER_CAVEATS,
263 DEF_NAMES) != 0) {
264 (void) fprintf(ArgLogFile,
265 gettext("%s: label_to_str PRINTER_CAVEATS: %s.\n"),
266 ME, strerror(errno));
267 exit(1);
269 if (label_to_str(FileLabel, &channels, PRINTER_CHANNELS,
270 DEF_NAMES) != 0) {
271 (void) fprintf(ArgLogFile,
272 gettext("%s: label_to_str PRINTER_CHANNELS: %s.\n"),
273 ME, strerror(errno));
274 exit(1);
276 if (label_to_str(FileLabel, &page_label, M_LABEL,
277 LONG_NAMES) != 0) {
278 (void) fprintf(ArgLogFile,
279 gettext("%s: label_to_str M_LABEL: %s.\n"),
280 ME, strerror(errno));
281 exit(1);
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 */
291 free(header);
292 free(label);
293 free(caveats);
294 free(channels);
295 free(page_label);
299 * Parse input "host!user" to separate host and user names.
302 static void
303 ParseUsername(char *input, char *user, char *host)
305 char *cp;
307 if ((cp = strchr(input, '@')) != NULL) {
308 /* user@host */
309 (void) strlcpy(host, cp + 1, MAXHOSTLEN + 1);
310 *cp = '\0';
311 (void) strlcpy(user, input, MAXUSERLEN + 1);
312 *cp = '@';
313 } else if ((cp = strchr(input, '!')) != NULL) {
314 /* host!user */
315 (void) strlcpy(user, cp + 1, MAXUSERLEN + 1);
316 *cp = '\0';
317 (void) strlcpy(host, input, MAXHOSTLEN + 1);
318 *cp = '!';
319 } else {
320 /* user */
321 (void) strlcpy(user, input, MAXUSERLEN + 1);
322 host[0] = '\0';
327 static void
328 CopyStdin(void)
330 if (!EmitFile(stdin)) {
331 (void) fprintf(ArgLogFile,
332 gettext("%s: Error copying stdin to stdout\n"), ME);
333 exit(1);
338 static BOOL
339 EmitFile(FILE *file)
341 int len;
342 #define BUFLEN 1024
343 char buf[BUFLEN];
345 while ((len = fread(buf, 1, BUFLEN, file)) > 0) {
346 if (fwrite(buf, 1, len, stdout) != len)
347 return (FALSE);
349 if (!feof(file))
350 return (FALSE);
351 return (TRUE);
355 static void
356 EmitPSFile(const char *name)
358 char path[PATH_MAX];
359 FILE *file;
360 BOOL emitted;
362 if (name[0] != '/') {
363 (void) strlcpy(path, ArgPSLib, sizeof (path));
364 (void) strlcat(path, "/", sizeof (path));
365 (void) strlcat(path, name, sizeof (path));
366 } else {
367 (void) strlcpy(path, name, sizeof (path));
370 file = fopen(path, "r");
371 if (file == NULL) {
372 (void) fprintf(ArgLogFile,
373 gettext("%s: Error opening PostScript file %s. %s.\n"),
374 ME, path, strerror(errno));
375 exit(1);
378 emitted = EmitFile(file);
379 (void) fclose(file);
380 if (!emitted) {
381 (void) fprintf(ArgLogFile, gettext(
382 "%s: Error copying PostScript file %s to stdout.\n"),
383 ME, path);
384 exit(1);
389 static int
390 ProcessArgs(int argc, char *argv[])
392 int option_letter;
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;
401 ArgDebugLevel = 0;
402 ArgLogFile = stderr;
404 /* read switch arguments once to get error log file */
405 while ((option_letter = getopt(argc, argv, options_string)) != EOF) {
406 switch (option_letter) {
407 case 'd':
408 ArgDebugLevel = atoi(optarg);
409 break;
410 case 'e':
411 ArgLogFile = fopen(optarg, "a");
412 if (ArgLogFile == NULL) {
413 (void) fprintf(stderr,
414 gettext("Cannot open log file %s\n"),
415 optarg);
416 return (-1);
418 break;
419 case '?': /* ? or unrecognized option */
420 Usage();
421 return (-1);
425 if (ArgDebugLevel > 0)
426 (void) fprintf(ArgLogFile,
427 gettext("Processing switch arguments\n"));
429 /* re-read switch arguments */
430 optind = 1;
431 while ((option_letter = getopt(argc, argv, options_string)) != EOF) {
432 switch (option_letter) {
433 case 'd':
434 ArgDebugLevel = atoi(optarg);
435 break;
436 case 'e':
437 /* This was handled in earlier pass through args */
438 break;
439 case 'l':
440 ArgNoPageLabels = TRUE;
441 break;
442 case 'r':
443 ArgReverse = TRUE;
444 break;
445 case 's':
446 ArgSeparatorPS = optarg;
447 break;
448 case 'b':
449 ArgBannerPS = optarg;
450 break;
451 case 't':
452 ArgTrailerPS = optarg;
453 break;
454 case 'L':
455 ArgPSLib = optarg;
456 break;
457 case '?': /* ? or unrecognized option */
458 Usage();
459 return (-1);
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 */
467 if (argc != 5) {
468 (void) fprintf(ArgLogFile,
469 gettext("Wrong number of arguments.\n\n"));
470 Usage();
471 return (-1);
474 ArgPrinter = argv++[0];
475 ArgJobID = argv++[0];
476 ArgUser = argv++[0];
477 ArgTitle = argv++[0];
478 ArgFile = argv++[0];
480 if (ArgDebugLevel >= 1) {
481 (void) fprintf(ArgLogFile, gettext("Arguments processed\n"));
482 (void) fprintf(ArgLogFile, gettext("Printer: %s\n"),
483 ArgPrinter);
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);
490 return (0);
494 static void
495 Usage(void)
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"),
508 gettext("Banner"),
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"),
515 gettext("Trailer"),
516 gettext("PostScript program for trailer "
517 "(default tsol_trailer.ps)"));
518 (void) fprintf(ArgLogFile, OPTFMT, gettext("-L DIR"),
519 gettext("Library"),
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"));