PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/cmd/lp/model/lp.tsol_separator.c

https://github.com/richlowe/illumos-gate
C | 528 lines | 398 code | 65 blank | 65 comment | 53 complexity | 3ec12b96f5eca77b10ea66bae9c3e869 MD5 | raw file
  1. /*
  2. * CDDL HEADER START
  3. *
  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.
  7. *
  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.
  12. *
  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]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. #pragma ident "%Z%%M% %I% %E% SMI"
  26. /*
  27. * Add TSOL banner, trailer, page header/footers to a print job
  28. */
  29. /* system header files */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <time.h>
  34. #include <limits.h>
  35. #include <errno.h>
  36. #include <signal.h>
  37. #include <locale.h>
  38. #include <tsol/label.h>
  39. /* typedefs */
  40. typedef int BOOL;
  41. /* constants */
  42. #ifndef FALSE
  43. #define FALSE 0
  44. #endif
  45. #ifndef TRUE
  46. #define TRUE 1
  47. #endif
  48. #define ME "lp.tsol_separator"
  49. #define POSTSCRIPTLIB "/usr/lib/lp/postscript"
  50. #define SEPARATORPS "tsol_separator.ps"
  51. #define BANNERPS "tsol_banner.ps"
  52. #define TRAILERPS "tsol_trailer.ps"
  53. #define MAXUSERLEN 32
  54. #define MAXHOSTLEN 32
  55. /* external variables */
  56. int optind; /* Used by getopt */
  57. char *optarg; /* Used by getopt */
  58. /* prototypes for static functions */
  59. static int ProcessArgs(int argc, char **argv);
  60. static void Usage(void);
  61. static void ParseUsername(char *input, char *user, char *host);
  62. static void EmitPSFile(const char *name);
  63. static BOOL EmitFile(FILE *file);
  64. static void EmitJobData(void);
  65. static void EmitPrologue(void);
  66. static void EmitCommandLineInfo(void);
  67. static void EmitClockBasedInfo(void);
  68. static void EmitLabelInfo(void);
  69. static void CopyStdin(void);
  70. /* static variables */
  71. static char *ArgSeparatorPS;
  72. static char *ArgBannerPS;
  73. static char *ArgTrailerPS;
  74. static char *ArgPSLib;
  75. static char *ArgPrinter;
  76. static char *ArgJobID;
  77. static char *ArgUser;
  78. static char *ArgTitle;
  79. static char *ArgFile;
  80. static BOOL ArgReverse;
  81. static BOOL ArgNoPageLabels;
  82. static int ArgDebugLevel;
  83. static FILE *ArgLogFile;
  84. static m_label_t *FileLabel;
  85. static char *remoteLabel;
  86. int
  87. main(int argc, char *argv[])
  88. {
  89. int err;
  90. /*
  91. * Run immune from typical interruptions, so that
  92. * we stand a chance to get the fault message.
  93. * EOF (or startup error) is the only way out.
  94. */
  95. (void) signal(SIGHUP, SIG_IGN);
  96. (void) signal(SIGINT, SIG_IGN);
  97. (void) signal(SIGQUIT, SIG_IGN);
  98. (void) signal(SIGTERM, SIG_IGN);
  99. (void) setlocale(LC_ALL, "");
  100. #if !defined(TEXT_DOMAIN)
  101. #define TEXT_DOMAIN "SYS_TEST"
  102. #endif
  103. (void) textdomain(TEXT_DOMAIN);
  104. if (ProcessArgs(argc, argv) != 0)
  105. exit(1);
  106. if ((FileLabel = m_label_alloc(MAC_LABEL)) == NULL)
  107. exit(1);
  108. /*
  109. * If the job was submitted via remotely, the label of the
  110. * remote peer will be set in the SLABEL environment variable
  111. * by copying it out of the SECURE structure.
  112. *
  113. * If there is no SLABEL value, the job was submitted locally
  114. * via the named pipe, and the file label can be determined
  115. * from its pathname.
  116. */
  117. if ((remoteLabel = getenv("SLABEL")) != NULL) {
  118. m_label_free(FileLabel);
  119. FileLabel = NULL;
  120. if (str_to_label(remoteLabel, &FileLabel, MAC_LABEL,
  121. L_NO_CORRECTION, &err) == -1) {
  122. perror("str_to_label");
  123. exit(1);
  124. }
  125. } else if (getlabel(ArgFile, FileLabel) != 0) {
  126. (void) fprintf(ArgLogFile,
  127. gettext("%1$s: cannot get label of %2$s: %3$s\n"),
  128. ME, ArgFile, strerror(errno));
  129. exit(1);
  130. }
  131. /* All of these functions exit if they encounter an error */
  132. EmitJobData();
  133. EmitPSFile(ArgSeparatorPS);
  134. if (ArgReverse)
  135. EmitPSFile(ArgTrailerPS);
  136. else
  137. EmitPSFile(ArgBannerPS);
  138. CopyStdin();
  139. if (ArgReverse)
  140. EmitPSFile(ArgBannerPS);
  141. else
  142. EmitPSFile(ArgTrailerPS);
  143. if (ArgDebugLevel >= 1)
  144. (void) fprintf(ArgLogFile, gettext("Done.\n"));
  145. m_label_free(FileLabel);
  146. return (0);
  147. }
  148. static void
  149. EmitJobData(void)
  150. {
  151. EmitPrologue();
  152. EmitCommandLineInfo();
  153. EmitClockBasedInfo();
  154. EmitLabelInfo();
  155. /* Emit ending PostScript code */
  156. (void) printf("end\n\n");
  157. (void) printf("%%%% End of code generated by lp.tsol_separator\n\n");
  158. }
  159. static void
  160. EmitPrologue(void)
  161. {
  162. /* Emit preliminary PostScript code */
  163. (void) printf("%%!\n\n");
  164. (void) printf("%%%% Begin code generated by lp.tsol_separator\n\n");
  165. (void) printf("%%%% Create JobDict if it doesn't exist\n");
  166. (void) printf("userdict /JobDict known not {\n");
  167. (void) printf(" userdict /JobDict 100 dict put\n");
  168. (void) printf("} if\n\n");
  169. (void) printf("%%%% Define job parameters, including TSOL security "
  170. "info\n");
  171. (void) printf("JobDict\n");
  172. (void) printf("begin\n");
  173. }
  174. /* Emit parameters obtained from command line options */
  175. static void
  176. EmitCommandLineInfo(void)
  177. {
  178. char user[MAXUSERLEN + 1];
  179. char host[MAXHOSTLEN + 1];
  180. (void) printf("\t/Job_Printer (%s) def\n", ArgPrinter);
  181. ParseUsername(ArgUser, user, host);
  182. (void) printf("\t/Job_Host (%s) def\n", host);
  183. (void) printf("\t/Job_User (%s) def\n", user);
  184. (void) printf("\t/Job_JobID (%s) def\n", ArgJobID);
  185. (void) printf("\t/Job_Title (%s) def\n", ArgTitle);
  186. (void) printf("\t/Job_DoPageLabels (%s) def\n",
  187. ArgNoPageLabels ? "NO" : "YES");
  188. (void) printf("\n");
  189. }
  190. /* Emit parameters generated from the system clock */
  191. static void
  192. EmitClockBasedInfo(void)
  193. {
  194. char timebuf[80];
  195. struct timeval clockval;
  196. (void) gettimeofday(&clockval, NULL);
  197. (void) strftime(timebuf, sizeof (timebuf), NULL,
  198. localtime(&clockval.tv_sec));
  199. (void) printf("\t/Job_Date (%s) def\n", timebuf);
  200. (void) printf("\t/Job_Hash (%ld) def\n", clockval.tv_usec % 100000L);
  201. (void) printf("\n");
  202. }
  203. /* Emit parameters derived from the SL and IL of the file being printed. */
  204. static void
  205. EmitLabelInfo(void)
  206. {
  207. char *header = NULL; /* DIA banner page fields */
  208. char *label = NULL;
  209. char *caveats = NULL;
  210. char *channels = NULL;
  211. char *page_label = NULL; /* interior pages label */
  212. if (label_to_str(FileLabel, &header, PRINTER_TOP_BOTTOM,
  213. DEF_NAMES) != 0) {
  214. (void) fprintf(ArgLogFile,
  215. gettext("%s: label_to_str PRINTER_TOP_BOTTOM: %s.\n"),
  216. ME, strerror(errno));
  217. exit(1);
  218. }
  219. if (label_to_str(FileLabel, &label, PRINTER_LABEL,
  220. DEF_NAMES) != 0) {
  221. (void) fprintf(ArgLogFile,
  222. gettext("%s: label_to_str PRINTER_LABEL: %s.\n"),
  223. ME, strerror(errno));
  224. exit(1);
  225. }
  226. if (label_to_str(FileLabel, &caveats, PRINTER_CAVEATS,
  227. DEF_NAMES) != 0) {
  228. (void) fprintf(ArgLogFile,
  229. gettext("%s: label_to_str PRINTER_CAVEATS: %s.\n"),
  230. ME, strerror(errno));
  231. exit(1);
  232. }
  233. if (label_to_str(FileLabel, &channels, PRINTER_CHANNELS,
  234. DEF_NAMES) != 0) {
  235. (void) fprintf(ArgLogFile,
  236. gettext("%s: label_to_str PRINTER_CHANNELS: %s.\n"),
  237. ME, strerror(errno));
  238. exit(1);
  239. }
  240. if (label_to_str(FileLabel, &page_label, M_LABEL,
  241. LONG_NAMES) != 0) {
  242. (void) fprintf(ArgLogFile,
  243. gettext("%s: label_to_str M_LABEL: %s.\n"),
  244. ME, strerror(errno));
  245. exit(1);
  246. }
  247. (void) printf("\t/Job_Classification (%s) def\n", header);
  248. (void) printf("\t/Job_Protect (%s) def\n", label);
  249. (void) printf("\t/Job_Caveats (%s) def\n", caveats);
  250. (void) printf("\t/Job_Channels (%s) def\n", channels);
  251. (void) printf("\t/Job_SL_Internal (%s) def\n", page_label);
  252. /* Free memory allocated label_to_str */
  253. free(header);
  254. free(label);
  255. free(caveats);
  256. free(channels);
  257. free(page_label);
  258. }
  259. /*
  260. * Parse input "host!user" to separate host and user names.
  261. */
  262. static void
  263. ParseUsername(char *input, char *user, char *host)
  264. {
  265. char *cp;
  266. if ((cp = strchr(input, '@')) != NULL) {
  267. /* user@host */
  268. (void) strlcpy(host, cp + 1, MAXHOSTLEN + 1);
  269. *cp = '\0';
  270. (void) strlcpy(user, input, MAXUSERLEN + 1);
  271. *cp = '@';
  272. } else if ((cp = strchr(input, '!')) != NULL) {
  273. /* host!user */
  274. (void) strlcpy(user, cp + 1, MAXUSERLEN + 1);
  275. *cp = '\0';
  276. (void) strlcpy(host, input, MAXHOSTLEN + 1);
  277. *cp = '!';
  278. } else {
  279. /* user */
  280. (void) strlcpy(user, input, MAXUSERLEN + 1);
  281. host[0] = '\0';
  282. }
  283. }
  284. static void
  285. CopyStdin(void)
  286. {
  287. if (!EmitFile(stdin)) {
  288. (void) fprintf(ArgLogFile,
  289. gettext("%s: Error copying stdin to stdout\n"), ME);
  290. exit(1);
  291. }
  292. }
  293. static BOOL
  294. EmitFile(FILE *file)
  295. {
  296. int len;
  297. #define BUFLEN 1024
  298. char buf[BUFLEN];
  299. while ((len = fread(buf, 1, BUFLEN, file)) > 0) {
  300. if (fwrite(buf, 1, len, stdout) != len)
  301. return (FALSE);
  302. }
  303. if (!feof(file))
  304. return (FALSE);
  305. return (TRUE);
  306. }
  307. static void
  308. EmitPSFile(const char *name)
  309. {
  310. char path[PATH_MAX];
  311. FILE *file;
  312. BOOL emitted;
  313. if (name[0] != '/') {
  314. (void) strlcpy(path, ArgPSLib, sizeof (path));
  315. (void) strlcat(path, "/", sizeof (path));
  316. (void) strlcat(path, name, sizeof (path));
  317. } else {
  318. (void) strlcpy(path, name, sizeof (path));
  319. }
  320. file = fopen(path, "r");
  321. if (file == NULL) {
  322. (void) fprintf(ArgLogFile,
  323. gettext("%s: Error opening PostScript file %s. %s.\n"),
  324. ME, path, strerror(errno));
  325. exit(1);
  326. }
  327. emitted = EmitFile(file);
  328. (void) fclose(file);
  329. if (!emitted) {
  330. (void) fprintf(ArgLogFile, gettext(
  331. "%s: Error copying PostScript file %s to stdout.\n"),
  332. ME, path);
  333. exit(1);
  334. }
  335. }
  336. static int
  337. ProcessArgs(int argc, char *argv[])
  338. {
  339. int option_letter;
  340. char *options_string = "lrd:e:s:b:t:L:";
  341. /* set default values for arguments */
  342. ArgSeparatorPS = SEPARATORPS;
  343. ArgBannerPS = BANNERPS;
  344. ArgTrailerPS = TRAILERPS;
  345. ArgPSLib = POSTSCRIPTLIB;
  346. ArgNoPageLabels = ArgReverse = FALSE;
  347. ArgDebugLevel = 0;
  348. ArgLogFile = stderr;
  349. /* read switch arguments once to get error log file */
  350. while ((option_letter = getopt(argc, argv, options_string)) != EOF) {
  351. switch (option_letter) {
  352. case 'd':
  353. ArgDebugLevel = atoi(optarg);
  354. break;
  355. case 'e':
  356. ArgLogFile = fopen(optarg, "a");
  357. if (ArgLogFile == NULL) {
  358. (void) fprintf(stderr,
  359. gettext("Cannot open log file %s\n"),
  360. optarg);
  361. return (-1);
  362. }
  363. break;
  364. case '?': /* ? or unrecognized option */
  365. Usage();
  366. return (-1);
  367. }
  368. }
  369. if (ArgDebugLevel > 0)
  370. (void) fprintf(ArgLogFile,
  371. gettext("Processing switch arguments\n"));
  372. /* re-read switch arguments */
  373. optind = 1;
  374. while ((option_letter = getopt(argc, argv, options_string)) != EOF) {
  375. switch (option_letter) {
  376. case 'd':
  377. ArgDebugLevel = atoi(optarg);
  378. break;
  379. case 'e':
  380. /* This was handled in earlier pass through args */
  381. break;
  382. case 'l':
  383. ArgNoPageLabels = TRUE;
  384. break;
  385. case 'r':
  386. ArgReverse = TRUE;
  387. break;
  388. case 's':
  389. ArgSeparatorPS = optarg;
  390. break;
  391. case 'b':
  392. ArgBannerPS = optarg;
  393. break;
  394. case 't':
  395. ArgTrailerPS = optarg;
  396. break;
  397. case 'L':
  398. ArgPSLib = optarg;
  399. break;
  400. case '?': /* ? or unrecognized option */
  401. Usage();
  402. return (-1);
  403. }
  404. }
  405. /* Adjust arguments to skip over options */
  406. argc -= optind; /* Number of remaining(non-switch) args */
  407. argv += optind; /* argv[0] is first(non-switch) args */
  408. if (argc != 5) {
  409. (void) fprintf(ArgLogFile,
  410. gettext("Wrong number of arguments.\n\n"));
  411. Usage();
  412. return (-1);
  413. }
  414. ArgPrinter = argv++[0];
  415. ArgJobID = argv++[0];
  416. ArgUser = argv++[0];
  417. ArgTitle = argv++[0];
  418. ArgFile = argv++[0];
  419. if (ArgDebugLevel >= 1) {
  420. (void) fprintf(ArgLogFile, gettext("Arguments processed\n"));
  421. (void) fprintf(ArgLogFile, gettext("Printer: %s\n"),
  422. ArgPrinter);
  423. (void) fprintf(ArgLogFile, gettext("Job ID: %s\n"), ArgJobID);
  424. (void) fprintf(ArgLogFile, gettext("User: %s\n"), ArgUser);
  425. (void) fprintf(ArgLogFile, gettext("Title: %s\n"), ArgTitle);
  426. (void) fprintf(ArgLogFile, gettext("File: %s\n"), ArgFile);
  427. }
  428. return (0);
  429. }
  430. static void
  431. Usage(void)
  432. {
  433. static const char *OPTFMT = " %-8s %-9s %s\n";
  434. (void) fprintf(ArgLogFile,
  435. gettext("Usage: lp.tsol_separator [OPTIONS] %s\n"),
  436. gettext("PRINTER JOBID HOST!USER TITLE FILE"));
  437. (void) fprintf(ArgLogFile, gettext(" OPTIONS:\n"));
  438. (void) fprintf(ArgLogFile, OPTFMT, "-r", gettext("Reverse"),
  439. gettext("Reverse banner/trailer order"));
  440. (void) fprintf(ArgLogFile, OPTFMT, "-l", gettext("Labels"),
  441. gettext("Suppress page header/footer labels"));
  442. (void) fprintf(ArgLogFile, OPTFMT, gettext("-b FILE"),
  443. gettext("Banner"),
  444. gettext("PostScript program for banner (default tsol_banner.ps)"));
  445. (void) fprintf(ArgLogFile, OPTFMT, gettext("-s FILE"),
  446. gettext("Separator"),
  447. gettext("PostScript program for separator "
  448. "(default tsol_separator.ps)"));
  449. (void) fprintf(ArgLogFile, OPTFMT, gettext("-t FILE"),
  450. gettext("Trailer"),
  451. gettext("PostScript program for trailer "
  452. "(default tsol_trailer.ps)"));
  453. (void) fprintf(ArgLogFile, OPTFMT, gettext("-L DIR"),
  454. gettext("Library"),
  455. gettext("Directory to search for PostScript programs"));
  456. (void) fprintf(ArgLogFile, OPTFMT, "", "",
  457. gettext("(default /usr/lib/lp/postscript)"));
  458. (void) fprintf(ArgLogFile, OPTFMT, gettext("-d N"), gettext("Debug"),
  459. gettext("Set debug level to N"));
  460. (void) fprintf(ArgLogFile, OPTFMT, gettext("-e FILE"),
  461. gettext("Error File"),
  462. gettext("Append error and debugging output to FILE"));
  463. }