home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / lprps / part02 < prev    next >
Encoding:
Text File  |  1992-08-13  |  52.7 KB  |  2,561 lines

  1. Newsgroups: comp.sources.misc
  2. From: jjc@jclark.com (James Clark)
  3. Subject:  v31i078:  lprps - interface lpr to a PostScript printer, Part02/02
  4. Message-ID: <1992Aug14.183713.21218@sparky.imd.sterling.com>
  5. X-Md4-Signature: aa87aad60cbd3c037340da1254ef0f93
  6. Date: Fri, 14 Aug 1992 18:37:13 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jjc@jclark.com (James Clark)
  10. Posting-number: Volume 31, Issue 78
  11. Archive-name: lprps/part02
  12. Environment: BSD, SUNOS
  13. Supersedes: lprps: Volume 21, Issue 25
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 2 (of 2)."
  22. # Contents:  psrev.c lprps.c psif.c textps.c psof.c
  23. # Wrapped by jjc@jclark on Fri Aug 14 17:43:04 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'psrev.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'psrev.c'\"
  27. else
  28. echo shar: Extracting \"'psrev.c'\" \(7543 characters\)
  29. sed "s/^X//" >'psrev.c' <<'END_OF_FILE'
  30. X/* psrev.c */
  31. X
  32. X#ifndef lint
  33. Xstatic char rcsid[] = "$Id: psrev.c,v 1.3 1991/07/14 14:11:01 jjc Exp $";
  34. X#endif
  35. X
  36. X#include <stdio.h>
  37. X#include <ctype.h>
  38. X#include <sys/types.h>
  39. X#include <sys/stat.h>
  40. X#include <errno.h>
  41. X
  42. Xchar *malloc();
  43. Xchar *realloc();
  44. X
  45. Xchar *xmalloc();
  46. Xchar *xrealloc();
  47. Xchar *prog;
  48. X
  49. Xvoid sys_error(message, arg)
  50. Xchar *message, *arg;
  51. X{
  52. X  extern char *sys_errlist[];
  53. X  extern int sys_nerr;
  54. X  int en;
  55. X
  56. X  en = errno;
  57. X  fprintf(stderr, "%s: ", prog);
  58. X  fprintf(stderr, message, arg);
  59. X  if (en > 0 && en < sys_nerr)
  60. X    fprintf(stderr, ": %s\n", sys_errlist[en]);
  61. X  else
  62. X    putc('\n', stderr);
  63. X  exit(1);
  64. X}
  65. X
  66. Xtypedef struct line_buf {
  67. X  char *buf;
  68. X  int len;
  69. X  int size;
  70. X} line_buf;
  71. X
  72. Xint get_line(lb, fp)
  73. Xline_buf *lb;
  74. XFILE *fp;
  75. X{
  76. X  int left;
  77. X  char *ptr;
  78. X  if (lb->buf == NULL) {
  79. X    lb->size = 16;
  80. X    lb->buf = xmalloc(16);
  81. X  }
  82. X  ptr = lb->buf;
  83. X  left = lb->size - 1;
  84. X  for (;;) {
  85. X    int c = getc(fp);
  86. X    if (c == EOF) {
  87. X      if (ferror(fp))
  88. X    sys_error("read error", (char *)0);
  89. X      if (ptr == lb->buf)
  90. X    return 0;
  91. X      lb->len = ptr - lb->buf;
  92. X      *ptr++ = '\0';
  93. X      return 1;
  94. X    }
  95. X    if (left <= 0) {
  96. X      int n = ptr - lb->buf;
  97. X      lb->size *= 2;
  98. X      lb->buf = xrealloc(lb->buf, lb->size);
  99. X      left = lb->size - n - 1;
  100. X      ptr = lb->buf + n;
  101. X    }
  102. X    *ptr++ = c;
  103. X    left -= 1;
  104. X    if (c == '\n') {
  105. X      lb->len = ptr - lb->buf;
  106. X      *ptr++ = '\0';
  107. X      return 1;
  108. X    }
  109. X  }
  110. X}
  111. X
  112. Xvoid put_line(lb, fp)
  113. Xline_buf *lb;
  114. XFILE *fp;
  115. X{
  116. X  if (fwrite(lb->buf, 1, lb->len, fp) != lb->len)
  117. X    sys_error("write error", (char *)0);
  118. X}
  119. X
  120. X/* is s2 a prefix of s1? */
  121. Xint strprefix(s1, s2)
  122. Xchar *s1, *s2;
  123. X{
  124. X  for (; *s1 != '\0' && *s1 == *s2; s1++, s2++)
  125. X    ;
  126. X  return *s2 == '\0';
  127. X}
  128. X
  129. Xvoid copy_and_exit(fp)
  130. XFILE *fp;
  131. X{
  132. X  int c;
  133. X  while ((c = getc(fp)) != EOF)
  134. X    if (putchar(c) == EOF)
  135. X      sys_error("write error", (char *)0);
  136. X  exit(0);
  137. X}
  138. X
  139. Xtypedef struct page_list {
  140. X  long pos;
  141. X  struct page_list *next;
  142. X} page_list;
  143. X
  144. Xvoid usage()
  145. X{
  146. X  fprintf(stderr, "usage: %s [file]\n", prog);
  147. X  exit(1);
  148. X}
  149. X
  150. Xmain(argc, argv)
  151. Xint argc;
  152. Xchar **argv;
  153. X{
  154. X  int dont_reverse = 0;
  155. X  int pageno;
  156. X  int pending_line = 0;
  157. X  int had_page_order = 0;
  158. X  int page_order_atend = 0;
  159. X  FILE *tempfp = NULL;
  160. X  page_list *pl = 0;
  161. X  long trailer_pos = -1;
  162. X  long prev_pos;
  163. X  int level = 0;
  164. X  line_buf lb;
  165. X  struct stat sb;
  166. X
  167. X  prog = argv[0];
  168. X  lb.buf = 0;
  169. X  if (argc > 2)
  170. X    usage();
  171. X  if (argc == 2) {
  172. X    errno = 0;
  173. X    if (!freopen(argv[1], "r", stdin))
  174. X      sys_error("can't open `%s'", argv[1]);
  175. X  }
  176. X  if (!get_line(&lb, stdin))
  177. X    exit(0);
  178. X  put_line(&lb, stdout);
  179. X  if (!strprefix(lb.buf, "%!PS-Adobe-"))
  180. X    copy_and_exit(stdin);
  181. X
  182. X  /* process the header section */
  183. X  while (get_line(&lb, stdin)) {
  184. X    int suppress = 0;
  185. X    if (!strprefix(lb.buf, "%%")) {
  186. X      pending_line = 1;
  187. X      break;
  188. X    }
  189. X    else if (strprefix(lb.buf, "%%PageOrder:")) {
  190. X      /* the first %%PageOrder comment is the significant one */
  191. X      if (had_page_order) 
  192. X    suppress = 1;
  193. X      else {
  194. X    char *ptr = lb.buf + sizeof("%%PageOrder:") - 1;
  195. X
  196. X    had_page_order = 1;
  197. X    while (*ptr == ' ')
  198. X      ptr++;
  199. X    if (strprefix(ptr, "(atend)"))
  200. X      page_order_atend = 1;
  201. X    else if (strprefix(ptr, "Ascend")) {
  202. X      fputs("%%PageOrder: Descend\n", stdout);
  203. X      suppress = 1;
  204. X    }
  205. X    else
  206. X      dont_reverse = 1;
  207. X      }
  208. X    }
  209. X    if (strprefix(lb.buf, "%%EndComments"))
  210. X      break;
  211. X    if (!suppress)
  212. X      put_line(&lb, stdout);
  213. X  }
  214. X
  215. X  if (!had_page_order)
  216. X    fputs("%%PageOrder: Descend\n", stdout);
  217. X  
  218. X  printf("%%%%EndComments\n");
  219. X
  220. X  if (dont_reverse)
  221. X    copy_and_exit(stdin);
  222. X
  223. X  /* process the prologue */
  224. X  while (pending_line || get_line(&lb, stdin)) {
  225. X    pending_line = 0;
  226. X    if (strprefix(lb.buf, "%%BeginDocument:"))
  227. X      ++level;
  228. X    else if (strprefix(lb.buf, "%%EndDocument")) {
  229. X      if (level > 0)
  230. X    --level;
  231. X    }
  232. X    else if (level == 0 && strprefix(lb.buf, "%%Page:")) {
  233. X      pending_line = 1;
  234. X      break;
  235. X    }
  236. X    put_line(&lb, stdout);
  237. X  }
  238. X
  239. X  /* if we didn't find any %%Page comments, we're done */
  240. X  if (!pending_line)
  241. X    exit(0);
  242. X
  243. X  /* open a temporary file if necessary */
  244. X  if (fstat(fileno(stdin), &sb) < 0)
  245. X    sys_error("cannot stat stdin", (char *)0);
  246. X  if ((sb.st_mode & S_IFMT) != S_IFREG) {
  247. X    tempfp = tmpfile();
  248. X    if (!tempfp)
  249. X      sys_error("can't open temporary file", (char *)0);
  250. X  }
  251. X
  252. X  /* process the body */
  253. X  while (pending_line || get_line(&lb, stdin)) {
  254. X    pending_line = 0;
  255. X    if (strprefix(lb.buf, "%%BeginDocument:"))
  256. X      ++level;
  257. X    else if (strprefix(lb.buf, "%%EndDocument")) {
  258. X      if (level > 0)
  259. X    --level;
  260. X    }
  261. X    else if (level == 0) {
  262. X      if (strprefix(lb.buf, "%%Page:")) {
  263. X    page_list *tem = (page_list *)xmalloc(sizeof(page_list));
  264. X    tem->next = pl;
  265. X    tem->pos = tempfp ? ftell(tempfp) : ftell(stdin) - lb.len;
  266. X    pl = tem;
  267. X      }
  268. X      else if (strprefix(lb.buf, "%%Trailer")) {
  269. X    pending_line = 1;
  270. X    break;
  271. X      }
  272. X    }
  273. X    if (tempfp != NULL)
  274. X      put_line(&lb, tempfp);
  275. X  }
  276. X
  277. X  /* process the trailer */
  278. X  if (pending_line) {
  279. X    trailer_pos = tempfp ? ftell(tempfp) : ftell(stdin) - lb.len;
  280. X    while (pending_line || get_line(&lb, stdin)) {
  281. X      pending_line = 0;
  282. X      if (page_order_atend && strprefix(lb.buf, "%%PageOrder:")) {
  283. X    char *p = lb.buf + sizeof("%%PageOrder:") - 1;
  284. X    while (*p == ' ')
  285. X      p++;
  286. X    dont_reverse = !strprefix(p, "Ascend");
  287. X      }
  288. X      if (tempfp != NULL)
  289. X    put_line(&lb, tempfp);
  290. X    }
  291. X  }
  292. X
  293. X  if (tempfp == NULL)
  294. X    tempfp = stdin;
  295. X
  296. X  if (dont_reverse) {
  297. X    long first_page_pos;
  298. X    if (pl == NULL)
  299. X      abort();
  300. X    /* find the position of the first page */
  301. X    while (pl != NULL) {
  302. X      page_list *tem = pl;
  303. X      first_page_pos = pl->pos;
  304. X      pl = pl->next;
  305. X      free((char *)tem);
  306. X    }
  307. X    if (fseek(tempfp, first_page_pos, 0) < 0)
  308. X      sys_error("seek error", (char *)0);
  309. X    copy_and_exit(tempfp);
  310. X  }
  311. X
  312. X  /* output each page */
  313. X  prev_pos = trailer_pos == -1 ? ftell(tempfp) : trailer_pos;
  314. X  pageno = 1;
  315. X  while (pl != NULL) {
  316. X    char *ptr, *label;
  317. X    int count = prev_pos - pl->pos;
  318. X    if (fseek(tempfp, pl->pos, 0) < 0)
  319. X      sys_error("seek error", (char *)0);
  320. X    if (!get_line(&lb, tempfp))
  321. X      abort();
  322. X    if (!strprefix(lb.buf, "%%Page:"))
  323. X      abort();
  324. X    ptr = lb.buf + 7;
  325. X    while (*ptr == ' ')
  326. X      ptr++;
  327. X    label = ptr;
  328. X    while (*ptr != '\0' && !(isascii(*ptr) && isspace(*ptr)))
  329. X      ptr++;
  330. X    *ptr = '\0';
  331. X    if (*label == '\0')
  332. X      label = "?";
  333. X    printf("%%%%Page: %s %d\n", label, pageno);
  334. X    pageno += 1;
  335. X    count -= lb.len;
  336. X    while (--count >= 0) {
  337. X      int c = getc(tempfp);
  338. X      if (c == EOF)
  339. X    abort();
  340. X      if (putc(c, stdout) == EOF)
  341. X    sys_error("write error", (char *)0);
  342. X    }
  343. X    prev_pos = pl->pos;
  344. X    pl = pl->next;
  345. X  }
  346. X
  347. X  /* output the trailer if there is one */
  348. X  if (trailer_pos != -1) {
  349. X    if (fseek(tempfp, trailer_pos, 0) < 0)
  350. X      sys_error("seek error", (char *)0);
  351. X    if (page_order_atend) {
  352. X      /* we need to change the %%PageOrder comment */
  353. X      while (get_line(&lb, tempfp)) {
  354. X    if (page_order_atend && strprefix(lb.buf, "%%PageOrder:"))
  355. X      fputs("%%PageOrder: Descend\n", stdout);
  356. X    else
  357. X      put_line(&lb, stdout);
  358. X      }
  359. X    }
  360. X    else
  361. X      copy_and_exit(tempfp);
  362. X  }
  363. X
  364. X  if (ferror(stdout))
  365. X    sys_error("write error", (char *)0);
  366. X
  367. X  exit(0);
  368. X}
  369. X
  370. Xchar *xmalloc(size)
  371. Xint size;
  372. X{
  373. X  char *tem;
  374. X  if ((tem = malloc(size)) == NULL) {
  375. X    fprintf(stderr, "%s: out of memory\n", prog);
  376. X    exit(1);
  377. X  }
  378. X  return tem;
  379. X}
  380. X
  381. Xchar *xrealloc(ptr, size)
  382. Xchar *ptr;
  383. Xint size;
  384. X{
  385. X  char *tem;
  386. X  if ((tem = realloc(ptr, size)) == NULL) {
  387. X    fprintf(stderr, "%s: out of memory\n", prog);
  388. X    exit(1);
  389. X  }
  390. X  return tem;
  391. X}
  392. END_OF_FILE
  393. if test 7543 -ne `wc -c <'psrev.c'`; then
  394.     echo shar: \"'psrev.c'\" unpacked with wrong size!
  395. fi
  396. # end of 'psrev.c'
  397. fi
  398. if test -f 'lprps.c' -a "${1}" != "-c" ; then 
  399.   echo shar: Will not clobber existing file \"'lprps.c'\"
  400. else
  401. echo shar: Extracting \"'lprps.c'\" \(20480 characters\)
  402. sed "s/^X//" >'lprps.c' <<'END_OF_FILE'
  403. X/* lprps.c */
  404. X
  405. X#ifndef lint
  406. Xstatic char rcsid[] = "$Id: lprps.c,v 1.16 1992/03/09 16:07:05 jjc Exp $";
  407. X#endif
  408. X
  409. X#include <stdio.h>
  410. X#include <ctype.h>
  411. X#include <strings.h>
  412. X#include <sys/types.h>
  413. X#include <sys/ioctl.h>
  414. X#include <sys/file.h>
  415. X#include <sys/stat.h>
  416. X#include <fcntl.h>
  417. X#include <sys/time.h>
  418. X#include <signal.h>
  419. X#include <syslog.h>
  420. X#include <errno.h>
  421. X
  422. X#define SENDMAIL "/usr/lib/sendmail"
  423. X
  424. X#define EXIT_SUCCESS 0
  425. X#define EXIT_REPRINT 1
  426. X#define EXIT_THROW_AWAY 2
  427. X
  428. X#define OBSIZE 1024
  429. X#define IBSIZE 1024
  430. X
  431. Xchar ctrl_d = '\004';
  432. Xchar ctrl_t = '\024';
  433. X
  434. Xchar *malloc();
  435. X
  436. X/* user's login name */
  437. Xchar *login = 0;
  438. X/* user's host */
  439. Xchar *host = 0;
  440. X/* name of accounting file */
  441. Xchar *accounting_file = 0;
  442. X/* stream to mailer process or log file */
  443. XFILE *mailfp = 0;
  444. X/* pid of the mailer process */
  445. Xint mail_pid = -1;
  446. X/* set to non-zero on interrupt */
  447. Xint interrupt_flag = 0;
  448. X/* set to non-zero on timeout */
  449. Xint timeout_flag = 0;
  450. X/* descriptor of printer device */
  451. Xint psfd = 1;
  452. X/* number of ^D's received from printer */
  453. Xint eof_count = 0;
  454. X/* if non-zero ignore all input from printer other than 004s */
  455. Xint ignore_input = 0;
  456. X/* are we currently printing the users job */
  457. Xint in_job = 0;
  458. X/* the contents of the status file at the beginning of the job */
  459. Xchar *status_file_contents = NULL;
  460. X/* name of the printer, or NULL if unknown */
  461. Xchar *printer_name = NULL;
  462. X/* non-zero if the contents of the status file are not status_file_contents */
  463. Xint status_file_changed = 0;
  464. X/* non-zero if we need to ask the printer for its status, so that we can tell
  465. Xwhen a printer error has been corrected */
  466. Xint want_status = 0;
  467. X/* name of the status file */
  468. Xchar *status_filename = "status";
  469. X/* name of the job, or NULL if unknown */
  470. Xchar *job_name = NULL;
  471. X/* non-zero if errors from the printer should be mailed back to the user */
  472. Xint mail_flag = 1;
  473. X
  474. Xenum {
  475. X  NORMAL,
  476. X  HAD_ONE_PERCENT,
  477. X  HAD_TWO_PERCENT,
  478. X  IN_MESSAGE,
  479. X  HAD_RIGHT_BRACKET,
  480. X  HAD_RIGHT_BRACKET_AND_PERCENT
  481. X  } parse_state;
  482. X
  483. Xenum {
  484. X  INVALID,
  485. X  UNKNOWN,
  486. X  IDLE,
  487. X  BUSY,
  488. X  WAITING,
  489. X  PRINTING
  490. X  } status = INVALID;
  491. X
  492. Xint start_pagecount = -1;
  493. Xint end_pagecount = -1;
  494. X
  495. Xstruct {
  496. X  char *ptr;
  497. X  int count;
  498. X  char buf[OBSIZE];
  499. X} out = { out.buf, OBSIZE };
  500. X
  501. X#define MBSIZE 1024
  502. X
  503. Xchar message_buf[MBSIZE];
  504. Xint message_buf_i;
  505. X
  506. Xstatic char pagecount_string[] = "(%%[ pagecount: ) print \
  507. Xstatusdict begin pagecount end 20 string cvs print \
  508. X( ]%%) print flush\n";
  509. X
  510. Xvoid process_input_char();
  511. Xvoid printer_flushing();
  512. Xvoid handle_interrupt();
  513. Xvoid do_exit();
  514. Xvoid print_status_file();
  515. Xvoid write_status_file();
  516. Xvoid restore_status_file();
  517. Xchar *xmalloc();
  518. Xchar *strsignal();
  519. X
  520. X
  521. Xvoid handle_timeout()
  522. X{
  523. X  syslog(LOG_ERR, "%s is not responding",
  524. X     printer_name ? printer_name : "printer");
  525. X  print_status_file("%s is not responding",
  526. X            printer_name ? printer_name : "printer");
  527. X  sleep(60);        /* it will take at least this long to warm up */
  528. X  do_exit(EXIT_REPRINT);
  529. X}
  530. X
  531. X/*VARARGS1*/
  532. Xvoid sys_error(s, a1, a2)
  533. Xchar *s;
  534. Xchar *a1, a2;
  535. X{
  536. X  char buf[BUFSIZ];
  537. X
  538. X  (void)sprintf(buf, s, a1, a2);
  539. X  if (printer_name)
  540. X    syslog(LOG_ERR, "%s: %s: %m", printer_name, buf);
  541. X  else
  542. X    syslog(LOG_ERR, "%s: %m", buf);
  543. X  exit(EXIT_THROW_AWAY);
  544. X}
  545. X
  546. X/*VARARGS1*/
  547. Xvoid error(s, a1, a2)
  548. Xchar *s;
  549. Xchar *a1, a2;
  550. X{
  551. X  char buf[BUFSIZ];
  552. X
  553. X  (void)sprintf(buf, s, a1, a2);
  554. X  if (printer_name)
  555. X    syslog(LOG_ERR, "%s: %s", printer_name, buf);
  556. X  else
  557. X    syslog(LOG_ERR, "%s", buf);
  558. X  exit(EXIT_THROW_AWAY);
  559. X}
  560. X
  561. Xint blocking_flag = 1;
  562. X
  563. Xvoid set_blocking()
  564. X{
  565. X  if (!blocking_flag) {
  566. X    if (fcntl(psfd, F_SETFL, 0) < 0)
  567. X      sys_error("fcntl");
  568. X    blocking_flag = 1;
  569. X  }
  570. X}
  571. X
  572. Xvoid set_non_blocking()
  573. X{
  574. X  if (blocking_flag) {
  575. X    if (fcntl(psfd, F_SETFL, FNDELAY) < 0)
  576. X      sys_error("fcntl");
  577. X    blocking_flag = 0;
  578. X  }
  579. X}
  580. X
  581. Xvoid blocking_write(s, n)
  582. Xchar *s;
  583. Xint n;
  584. X{
  585. X  set_blocking();
  586. X  if (write(psfd, s, n) < 0)
  587. X    sys_error("write");
  588. X}
  589. X
  590. Xvoid ioflush()
  591. X{
  592. X  int rw = FREAD|FWRITE;
  593. X  if (ioctl(psfd, TIOCFLUSH, (char *)&rw) < 0)
  594. X    sys_error("ioctl(TIOCFLUSH)");
  595. X}
  596. X
  597. Xvoid open_mailfp()
  598. X{
  599. X  if (mailfp == 0) {
  600. X    if (!login || !host || !mail_flag)
  601. X      mailfp = stderr;
  602. X    else {
  603. X      int fd[2];
  604. X      if (pipe(fd) < 0)
  605. X    sys_error("pipe");
  606. X      if ((mail_pid = fork()) == 0) {
  607. X    /* child */
  608. X    char buf[1024], *cp;
  609. X
  610. X    if (close(fd[1]) < 0)
  611. X      sys_error("close");
  612. X    if (dup2(fd[0], 0) < 0)
  613. X      sys_error("dup2");
  614. X    if (close(fd[0]) < 0)
  615. X      sys_error("close");
  616. X    /* don't leave stdout connected to the printer */
  617. X    if (close(1) < 0)
  618. X      sys_error("close");
  619. X    if (open("/dev/null", O_WRONLY) < 0)
  620. X      sys_error("can't open /dev/null");
  621. X    /* the parent catches SIGINT */
  622. X    if (signal(SIGINT, SIG_IGN) == BADSIG)
  623. X      sys_error("signal");
  624. X    (void)sprintf(buf, "%s@%s", login, host);
  625. X    if ((cp = rindex(SENDMAIL, '/')) != NULL)
  626. X      cp++;
  627. X    else
  628. X      cp = SENDMAIL;
  629. X    (void)execl(SENDMAIL, cp, buf, (char *)NULL);
  630. X    sys_error("can't exec %s", SENDMAIL);
  631. X      }
  632. X      else if (mail_pid < 0)
  633. X    sys_error("fork");
  634. X      /* parent */
  635. X      if (close(fd[0]) < 0)
  636. X    sys_error("close");
  637. X      mailfp = fdopen(fd[1], "w");
  638. X      if (!mailfp)
  639. X    sys_error("fdopen");
  640. X      (void)fprintf(mailfp, "To: %s@%s\nSubject: printer job\n\n", login, host);
  641. X    }
  642. X  }
  643. X}
  644. X
  645. Xvoid user_char(c)
  646. Xchar c;
  647. X{
  648. X  static int done_intro = 0;
  649. X  if (in_job && (done_intro || c != '\n')) {
  650. X    if (mailfp == 0)
  651. X      open_mailfp();
  652. X    if (!done_intro) {
  653. X      (void)fputs("Your printer job ", mailfp);
  654. X      if (job_name && *job_name)
  655. X    (void)fprintf(mailfp, "(%s) ", job_name);
  656. X      (void)fputs("produced the following output:\n", mailfp);
  657. X      done_intro = 1;
  658. X    }
  659. X    (void)putc(c, mailfp);
  660. X  }
  661. X}
  662. X
  663. X#if 0
  664. Xvoid init_tty()
  665. X{
  666. X  struct termios t;
  667. X  psfd = open("/dev/ttya", O_RDWR);
  668. X  if (psfd < 0)
  669. X    sys_error("open");
  670. X  if (ioctl(psfd, TCGETS, &t) < 0)
  671. X    sys_error("ioctl(TCGETS)");
  672. X  t.c_cflag = B38400|CS7|CSTOPB|CREAD|CLOCAL|PARENB;
  673. X  t.c_oflag &= ~OPOST;
  674. X  t.c_iflag = IXON|IXOFF|IGNBRK|ISTRIP|IGNCR;
  675. X  t.c_lflag = 0;
  676. X  t.c_cc[VMIN] = 1;
  677. X  t.c_cc[VTIME] = 0;
  678. X  if (ioctl(psfd, TCSETS, &t) < 0)
  679. X    sys_error("ioctl(TCSETS)");
  680. X}
  681. X#endif
  682. X
  683. X#if 0
  684. X#include <sys/termios.h>
  685. Xvoid debug_tty()
  686. X{
  687. X  struct termios t;
  688. X  if (ioctl(psfd, TCGETS, &t) < 0)
  689. X    sys_error("ioctl(TCGETS)");
  690. X  syslog(LOG_ERR, "cflag = %o", t.c_cflag);
  691. X  syslog(LOG_ERR, "oflag = %o", t.c_oflag);
  692. X  syslog(LOG_ERR, "lflag = %o", t.c_lflag);
  693. X  syslog(LOG_ERR, "iflag = %o", t.c_iflag);
  694. X}
  695. X#endif
  696. X
  697. Xvoid do_exit(exit_code)
  698. Xint exit_code;
  699. X{
  700. X  if (mailfp && mailfp != stderr) {
  701. X    int status;
  702. X    int ret;
  703. X
  704. X    if (fclose(mailfp) == EOF)
  705. X      sys_error("fclose");
  706. X    while ((ret = wait(&status)) != mail_pid)
  707. X      if (ret < 0)
  708. X    sys_error("wait");
  709. X    if ((status & 0377) == 0177)
  710. X      syslog(LOG_ERR, "%s stopped", SENDMAIL);
  711. X    else if ((status & 0377) != 0)
  712. X      syslog(LOG_ERR, "%s: %s%s", SENDMAIL, strsignal(status & 0177),
  713. X         (status & 0200) ? " (core dumped)" : "");
  714. X    else {
  715. X      int exit_code = (status >> 8) & 0377;
  716. X      if (exit_code != 0)
  717. X    syslog(LOG_ERR, "%s exited with status %d", SENDMAIL, exit_code);
  718. X    }
  719. X  }
  720. X  restore_status_file();
  721. X  exit(exit_code);
  722. X}
  723. X
  724. Xchar *strsignal(n)
  725. Xint n;
  726. X{
  727. X  extern char *sys_siglist[];
  728. X  static char buf[32];
  729. X  if (n >= 0 && n < NSIG)
  730. X    return sys_siglist[n];
  731. X  (void)sprintf(buf, "Signal %d", n);
  732. X  return buf;
  733. X}
  734. X
  735. Xvoid flush_output()
  736. X{
  737. X  char ibuf[IBSIZE];
  738. X  char *p = out.buf;
  739. X  int n = out.ptr - p;
  740. X  /* we daren't block on writes */
  741. X  set_non_blocking();
  742. X  while (n > 0) {
  743. X    fd_set rfds, wfds;
  744. X    FD_ZERO(&wfds);
  745. X    FD_ZERO(&rfds);
  746. X    FD_SET(psfd, &wfds);
  747. X    FD_SET(psfd, &rfds);
  748. X    if (interrupt_flag)
  749. X      handle_interrupt();
  750. X    while (select(psfd + 1, &rfds, &wfds, (fd_set *)NULL, (struct timeval *)NULL)
  751. X       < 0)
  752. X      if (errno == EINTR) {
  753. X    if (interrupt_flag)
  754. X      handle_interrupt();
  755. X      }
  756. X      else
  757. X    sys_error("select");
  758. X    if (FD_ISSET(psfd, &rfds)) {
  759. X      char *q = ibuf;
  760. X      int nread = read(psfd, ibuf, IBSIZE);
  761. X      if (nread < 0)
  762. X    sys_error("read");
  763. X      while (--nread >= 0)
  764. X    process_input_char(*q++);
  765. X    }
  766. X    else if (FD_ISSET(psfd, &wfds)) {
  767. X      if (want_status) {
  768. X    switch (write(psfd, &ctrl_t, 1)) {
  769. X    case 0:
  770. X      break;
  771. X    case 1:
  772. X      want_status = 0;
  773. X      break;
  774. X    case -1:
  775. X      sys_error("write");
  776. X    }
  777. X      }
  778. X      else {
  779. X    int nwritten = write(psfd, p, n);
  780. X    if (nwritten < 0)
  781. X      sys_error("write");
  782. X    n -= nwritten;
  783. X    p += nwritten;
  784. X      }
  785. X    }
  786. X  }
  787. X  out.ptr = out.buf;
  788. X  out.count = OBSIZE;
  789. X}
  790. X
  791. X  
  792. Xvoid output_char(c)
  793. Xchar c;
  794. X{
  795. X  if (out.count <= 0)
  796. X    flush_output();
  797. X  *out.ptr = c;
  798. X  out.ptr += 1;
  799. X  out.count -= 1;
  800. X}
  801. X
  802. Xvoid message_char(c)
  803. Xchar c;
  804. X{
  805. X  if (c != '\0' && message_buf_i < MBSIZE - 1)
  806. X    message_buf[message_buf_i++] = c;
  807. X}
  808. X
  809. Xvoid process_message()
  810. X{
  811. X  char *p = message_buf;
  812. X  message_buf[message_buf_i] = 0;
  813. X  
  814. X  while (*p != '\0') {
  815. X    char *key;
  816. X    char *nextp;
  817. X
  818. X    for (nextp = p; *nextp != '\0'; nextp++)
  819. X      if (*nextp == ';') {
  820. X    *nextp++ = '\0';
  821. X    break;
  822. X      }
  823. X    while (isspace(*p))
  824. X      p++;
  825. X    key = p;
  826. X    p = index(p, ':');
  827. X    if (p != NULL) {
  828. X      char *q;
  829. X      *p++ = '\0';
  830. X      while (isspace(*p))
  831. X    p++;
  832. X      q = index(p, '\0');
  833. X      while (q > p && isspace(q[-1]))
  834. X    --q;
  835. X      *q = '\0';
  836. X      if (strcmp(key, "Flushing") == 0)
  837. X    printer_flushing();
  838. X      else if (strcmp(key, "PrinterError") == 0) {
  839. X    syslog(LOG_ERR, "%s: %s",
  840. X           printer_name ? printer_name : "printer error",
  841. X           p);
  842. X    print_status_file("%s: %s",
  843. X              printer_name ? printer_name : "printer error",
  844. X              p);
  845. X    want_status = 1;
  846. X      }
  847. X      else if (strcmp(key, "exitserver") == 0) {
  848. X      }
  849. X      else if (strcmp(key, "Error") == 0) {
  850. X    if (in_job) {
  851. X      if (mailfp == NULL)
  852. X        open_mailfp();
  853. X      (void)fputs("Your printer job ", mailfp);
  854. X      if (job_name && *job_name)
  855. X        (void)fprintf(mailfp, "(%s) ", job_name);
  856. X      (void)fprintf(mailfp, "produced the PostScript error `%s'.\n", p);
  857. X    }
  858. X      }
  859. X      else if (strcmp(key, "status") == 0) {
  860. X    if (strcmp(p, "idle") == 0)
  861. X      status = IDLE;
  862. X    else if (strcmp(p, "busy") == 0)
  863. X      status = BUSY;
  864. X    else if (strcmp(p, "waiting") == 0)
  865. X      status = WAITING;
  866. X    else if (strcmp(p, "printing") == 0)
  867. X      status = PRINTING;
  868. X    else
  869. X      status = UNKNOWN;
  870. X    switch (status) {
  871. X    case BUSY:
  872. X    case WAITING:
  873. X    case PRINTING:
  874. X      restore_status_file();
  875. X      break;
  876. X    default:
  877. X      want_status = 1;
  878. X      break;
  879. X    }
  880. X      }
  881. X      else if (strcmp(key, "OffendingCommand") == 0) {
  882. X    if (in_job) {
  883. X      if (mailfp == NULL)
  884. X        open_mailfp();
  885. X      (void)fprintf(mailfp, "The offending command was `%s'.\n", p);
  886. X    }
  887. X      }
  888. X      else if (strcmp(key, "pagecount") == 0) {
  889. X    int n;
  890. X    if (sscanf(p, "%d", &n) == 1 && n >= 0) {
  891. X      if (start_pagecount < 0)
  892. X        start_pagecount = n;
  893. X      else
  894. X        end_pagecount = n;
  895. X    }
  896. X      }
  897. X    }
  898. X    p = nextp;
  899. X  }
  900. X}
  901. X
  902. X
  903. Xvoid process_input_char(c)
  904. Xchar c;
  905. X{
  906. X  if (c == '\004')
  907. X    ++eof_count;
  908. X  else if (ignore_input || c == '\r')
  909. X    ;
  910. X  else {
  911. X    switch (parse_state) {
  912. X    case NORMAL:
  913. X      if (c == '%')
  914. X    parse_state = HAD_ONE_PERCENT;
  915. X      else
  916. X    user_char(c);
  917. X      break;
  918. X    case HAD_ONE_PERCENT:
  919. X      if (c == '%')
  920. X    parse_state = HAD_TWO_PERCENT;
  921. X      else {
  922. X    user_char('%');
  923. X    user_char(c);
  924. X    parse_state = NORMAL;
  925. X      }
  926. X      break;
  927. X    case HAD_TWO_PERCENT:
  928. X      if (c == '[') {
  929. X    message_buf_i = 0;
  930. X    parse_state = IN_MESSAGE;
  931. X      }
  932. X      else {
  933. X    user_char('%');
  934. X    user_char('%');
  935. X    user_char(c);
  936. X    parse_state = NORMAL;
  937. X      }
  938. X      break;
  939. X    case IN_MESSAGE:
  940. X      if (c == ']')
  941. X    parse_state = HAD_RIGHT_BRACKET;
  942. X      else
  943. X    message_char(c);
  944. X      break;
  945. X    case HAD_RIGHT_BRACKET:
  946. X      if (c == '%')
  947. X    parse_state = HAD_RIGHT_BRACKET_AND_PERCENT;
  948. X      else {
  949. X    message_char(']');
  950. X    message_char(c);
  951. X    parse_state = IN_MESSAGE;
  952. X      }
  953. X      break;
  954. X    case HAD_RIGHT_BRACKET_AND_PERCENT:
  955. X      if (c == '%') {
  956. X    parse_state = NORMAL;
  957. X    process_message();
  958. X      }
  959. X      else {
  960. X    message_char(']');
  961. X    message_char('%');
  962. X    message_char(c);
  963. X    parse_state = IN_MESSAGE;
  964. X      }
  965. X      break;
  966. X    default:
  967. X      abort();
  968. X    }
  969. X  }
  970. X}
  971. X
  972. Xvoid process_some_input()
  973. X{
  974. X  char ibuf[IBSIZE];
  975. X  char *p = ibuf;
  976. X  int nread;
  977. X  fd_set rfds, wfds;
  978. X  set_non_blocking();
  979. X  FD_ZERO(&wfds);
  980. X  FD_ZERO(&rfds);
  981. X  FD_SET(psfd, &rfds);
  982. X  if (want_status)
  983. X    FD_SET(psfd, &wfds);
  984. X  if (interrupt_flag)
  985. X    handle_interrupt();
  986. X  if (timeout_flag)
  987. X    handle_timeout();
  988. X  while (select(psfd + 1, &rfds, &wfds, (fd_set *)NULL, (struct timeval *)NULL) 
  989. X     < 0)
  990. X    if (errno == EINTR) {
  991. X      if (timeout_flag)
  992. X    handle_timeout();
  993. X      else if (interrupt_flag)
  994. X    handle_interrupt();
  995. X    }
  996. X    else
  997. X      sys_error("select");
  998. X  if (FD_ISSET(psfd, &wfds)) {
  999. X    switch (write(psfd, &ctrl_t, 1)) {
  1000. X    case 0:
  1001. X      break;
  1002. X    case 1:
  1003. X      want_status = 0;
  1004. X      break;
  1005. X    case -1:
  1006. X      sys_error("write");
  1007. X    }
  1008. X    return;
  1009. X  }
  1010. X  nread = read(psfd, ibuf, IBSIZE);
  1011. X  if (nread < 0)
  1012. X    sys_error("read");
  1013. X  if (nread == 0)
  1014. X    sys_error("read returned 0");
  1015. X  while (--nread >= 0)
  1016. X    process_input_char(*p++);
  1017. X}
  1018. X
  1019. X
  1020. Xvoid do_accounting()
  1021. X{
  1022. X  FILE *fp;
  1023. X  if (end_pagecount > start_pagecount
  1024. X      && host != NULL
  1025. X      && login != NULL
  1026. X      && accounting_file != NULL
  1027. X      && (fp = fopen(accounting_file, "a")) != NULL) {
  1028. X    (void)fprintf(fp,
  1029. X          "%7.2f %s:%s\n", 
  1030. X          (double)(end_pagecount - start_pagecount),
  1031. X          host,
  1032. X          login);
  1033. X    if (fclose(fp) == EOF)
  1034. X      sys_error("fclose %s", accounting_file);
  1035. X  }
  1036. X}
  1037. X
  1038. Xvoid set_timeout_flag()
  1039. X{
  1040. X  timeout_flag = 1;
  1041. X}
  1042. X
  1043. Xvoid get_end_pagecount()
  1044. X{
  1045. X  int ec;
  1046. X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
  1047. X    sys_error("signal");
  1048. X  (void)alarm(30);
  1049. X  ioflush();
  1050. X  blocking_write(pagecount_string, sizeof(pagecount_string) - 1);
  1051. X  end_pagecount = -1;
  1052. X  ignore_input = 0;
  1053. X  in_job = 0;
  1054. X  parse_state = NORMAL;
  1055. X  while (end_pagecount < 0)
  1056. X    process_some_input();
  1057. X  blocking_write(&ctrl_d, 1);
  1058. X  ec = eof_count;
  1059. X  while (ec == eof_count)
  1060. X    process_some_input();
  1061. X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
  1062. X    sys_error("signal");
  1063. X}
  1064. X
  1065. Xvoid get_start_pagecount()
  1066. X{
  1067. X  int ec;
  1068. X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
  1069. X    sys_error("signal");
  1070. X  (void)alarm(30);
  1071. X  ioflush();
  1072. X  blocking_write(pagecount_string, sizeof(pagecount_string) - 1);
  1073. X  start_pagecount = -1;
  1074. X  parse_state = NORMAL;
  1075. X  in_job = 0;
  1076. X  ignore_input = 0;
  1077. X  while (start_pagecount < 0)
  1078. X    process_some_input();
  1079. X  blocking_write(&ctrl_d, 1);
  1080. X  ec = eof_count;
  1081. X  while (ec == eof_count)
  1082. X    process_some_input();
  1083. X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
  1084. X    sys_error("signal");
  1085. X}
  1086. X
  1087. Xvoid set_interrupt_flag()
  1088. X{
  1089. X  interrupt_flag = 1;
  1090. X}
  1091. X
  1092. Xvoid handle_interrupt()
  1093. X{
  1094. X  static char interrupt_string[] = "\003\004";
  1095. X  int ec;
  1096. X  interrupt_flag = 0;
  1097. X  if (signal(SIGINT, SIG_IGN) == BADSIG)
  1098. X    sys_error("signal");
  1099. X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
  1100. X    sys_error("signal");
  1101. X  (void)alarm(30);
  1102. X  ioflush();
  1103. X  blocking_write(interrupt_string, sizeof(interrupt_string)-1);
  1104. X  ignore_input = 1;
  1105. X  ec = eof_count;
  1106. X  while (eof_count == ec)
  1107. X    process_some_input();
  1108. X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
  1109. X    sys_error("signal");
  1110. X  get_end_pagecount();
  1111. X  do_accounting();
  1112. X  do_exit(EXIT_SUCCESS);
  1113. X}
  1114. X
  1115. Xvoid printer_flushing()
  1116. X{
  1117. X  int ec;
  1118. X  if (signal(SIGINT, SIG_IGN) == BADSIG)
  1119. X    sys_error("signal");
  1120. X  ioflush();
  1121. X  blocking_write(&ctrl_d, 1);
  1122. X  ignore_input = 1;
  1123. X  ec = eof_count;
  1124. X  while (eof_count == ec)
  1125. X    process_some_input();
  1126. X  get_end_pagecount();
  1127. X  do_accounting();
  1128. X  do_exit(EXIT_SUCCESS);
  1129. X}
  1130. X
  1131. Xvoid send_file()
  1132. X{
  1133. X  int ec;
  1134. X  int c;
  1135. X
  1136. X  in_job = 1;
  1137. X  parse_state = NORMAL;
  1138. X  ignore_input = 0;
  1139. X  if (signal(SIGINT, set_interrupt_flag) == BADSIG)
  1140. X    sys_error("signal");
  1141. X  while ((c = getchar()) != EOF)
  1142. X    if (c != '\004')
  1143. X      output_char(c);
  1144. X  flush_output();
  1145. X#ifdef IIg
  1146. X  /* rauletta@sitevax.gmu.edu says this works around the bug in the
  1147. X     serial driver of the Laserwriter IIf and IIg. */
  1148. X  (void)tcdrain(psfd);
  1149. X#endif
  1150. X  blocking_write(&ctrl_d, 1);
  1151. X  ec = eof_count;
  1152. X  while (ec == eof_count)
  1153. X    process_some_input();
  1154. X  restore_status_file();
  1155. X}
  1156. X
  1157. Xvoid get_status()
  1158. X{
  1159. X  if (signal(SIGALRM, set_timeout_flag) == BADSIG)
  1160. X    sys_error("signal");
  1161. X  ioflush();
  1162. X  (void)alarm(5);
  1163. X  blocking_write(&ctrl_t, 1);
  1164. X  in_job = 0;
  1165. X  parse_state = NORMAL;
  1166. X  ignore_input = 0;
  1167. X  while (status == INVALID)
  1168. X    process_some_input();
  1169. X  switch (status) {
  1170. X  case IDLE:
  1171. X    break;
  1172. X  case WAITING:
  1173. X    blocking_write(&ctrl_d, 1);
  1174. X    sleep(5);
  1175. X    exit(EXIT_REPRINT);
  1176. X  case BUSY:
  1177. X  case PRINTING:
  1178. X  case UNKNOWN:
  1179. X    sleep(15);
  1180. X    exit(EXIT_REPRINT);
  1181. X  }
  1182. X  if (signal(SIGALRM, SIG_IGN) == BADSIG)
  1183. X    sys_error("signal");
  1184. X}
  1185. X
  1186. X/* I know we ought to use varargs, but 4.3 doesn't have vsprintf. */
  1187. X
  1188. X/*VARARGS1*/
  1189. Xvoid print_status_file(s, a1, a2)
  1190. Xchar *s;
  1191. Xchar *a1, *a2;
  1192. X{
  1193. X  char buf[BUFSIZ];
  1194. X
  1195. X  (void)sprintf(buf, s, a1, a2);
  1196. X  (void)strcat(buf, "\n");
  1197. X  write_status_file(buf);
  1198. X  status_file_changed = 1;
  1199. X}
  1200. X
  1201. Xvoid restore_status_file()
  1202. X{
  1203. X  if (status_file_contents && status_file_changed) {
  1204. X    write_status_file(status_file_contents);
  1205. X    status_file_changed = 0;
  1206. X  }
  1207. X}
  1208. X
  1209. Xvoid write_status_file(s)
  1210. Xchar *s;
  1211. X{
  1212. X  int fd;
  1213. X
  1214. X  (void)umask(0);
  1215. X  fd = open(status_filename, O_WRONLY|O_CREAT, 0664);
  1216. X  if (fd < 0)
  1217. X    sys_error("can't open %s", status_filename);
  1218. X  if (flock(fd, LOCK_EX) < 0)
  1219. X    sys_error("flock %s", status_filename);
  1220. X  if (ftruncate(fd, (off_t)0) < 0)
  1221. X    sys_error("ftruncate %s", status_filename);
  1222. X  if (write(fd, s, strlen(s)) < 0)
  1223. X    sys_error("write %s", status_filename);
  1224. X  if (close(fd) < 0)
  1225. X    sys_error("close %s", status_filename);
  1226. X}
  1227. X
  1228. Xvoid read_status_file()
  1229. X{
  1230. X  struct stat sb;
  1231. X  int count;
  1232. X  char *ptr;
  1233. X
  1234. X  int fd = open(status_filename, O_RDONLY);
  1235. X  if (fd < 0)
  1236. X    sys_error("can't open %s", status_filename);
  1237. X  if (flock(fd, LOCK_SH) < 0)
  1238. X    sys_error("flock %s", status_filename);
  1239. X  if (fstat(fd, &sb) < 0)
  1240. X    sys_error("fstat %s", status_filename);
  1241. X  if ((sb.st_mode & S_IFMT) != S_IFREG)
  1242. X    error("%s is not a regular file", status_filename);
  1243. X  status_file_contents = xmalloc((int)sb.st_size + 1);
  1244. X  count = sb.st_size;
  1245. X  ptr = status_file_contents;
  1246. X  while (count > 0) {
  1247. X    int nread = read(fd, ptr, count);
  1248. X    if (nread < 0)
  1249. X      sys_error("read %s", status_file_contents);
  1250. X    if (nread == 0)
  1251. X      error("%s changed size (locking problem?)", status_filename);
  1252. X    count -= nread;
  1253. X    ptr += nread;
  1254. X  }
  1255. X  
  1256. X  if (close(fd) < 0)
  1257. X    sys_error("close %s", status_filename);
  1258. X  status_file_contents[sb.st_size] = '\0';
  1259. X
  1260. X  /* This is a grungy hack. */
  1261. X#define MESSAGE " is ready and printing\n"
  1262. X#define MESSAGE_LEN (sizeof(MESSAGE) - 1)
  1263. X  if (!printer_name
  1264. X      && sb.st_size > sizeof(MESSAGE)
  1265. X      && strcmp(status_file_contents + sb.st_size - MESSAGE_LEN, MESSAGE) == 0) {
  1266. X    int plen = sb.st_size - MESSAGE_LEN;
  1267. X    printer_name = xmalloc(plen + 1);
  1268. X    bcopy(status_file_contents, printer_name, plen);
  1269. X    printer_name[plen] = '\0';
  1270. X  }
  1271. X}
  1272. X
  1273. Xchar *xmalloc(n)
  1274. X     int n;
  1275. X{
  1276. X  char *p = malloc((unsigned)n);
  1277. X  if (!p)
  1278. X    error("out of memory");
  1279. X  return p;
  1280. X}
  1281. X
  1282. X#define usage() error("invalid arguments")    
  1283. X
  1284. Xint main(argc, argv)
  1285. Xint argc;
  1286. Xchar **argv;
  1287. X{
  1288. X  char *prog;
  1289. X  int i = 1;
  1290. X  int Uflag = 0;
  1291. X
  1292. X  if (argc > 0) {
  1293. X    prog = rindex(argv[0], '/');
  1294. X    if (prog)
  1295. X      prog++;
  1296. X    else
  1297. X      prog = argv[0];
  1298. X  }
  1299. X  else
  1300. X    prog = "lprps";
  1301. X  openlog(prog, LOG_PID, LOG_LPR);
  1302. X
  1303. X  for (i = 1; i < argc && argv[i][0] == '-'; i++)
  1304. X    switch (argv[i][1]) {
  1305. X    case 'c':
  1306. X      break;
  1307. X    case 'M':
  1308. X      /* don't mail errors back to user */
  1309. X      mail_flag = 0;
  1310. X      break;
  1311. X    case 'U':
  1312. X      /* argument is not a real user (eg daemon) */
  1313. X      Uflag++;
  1314. X      break;
  1315. X    case 'x':
  1316. X    case 'y':
  1317. X    case 'w':
  1318. X    case 'l':
  1319. X    case 'i':
  1320. X      /* not interested in these */
  1321. X      break;
  1322. X    case 'n':
  1323. X      if (++i == argc)
  1324. X    usage();
  1325. X      else
  1326. X    login = argv[i];
  1327. X      break;
  1328. X    case 'h':
  1329. X      if (++i == argc)
  1330. X    usage();
  1331. X      else
  1332. X    host = argv[i];
  1333. X      break;
  1334. X      /* 'j', 'p', and 's' are non-standard */
  1335. X    case 'j':
  1336. X      if (++i == argc)
  1337. X    usage();
  1338. X      else
  1339. X    job_name = argv[i];
  1340. X      break;
  1341. X    case 'p':
  1342. X      if (++i == argc)
  1343. X    usage();
  1344. X      else
  1345. X    printer_name = argv[i];
  1346. X      break;
  1347. X    case 's':
  1348. X      if (++i == argc)
  1349. X    usage();
  1350. X      else
  1351. X    status_filename = argv[i];
  1352. X      break;
  1353. X    default:
  1354. X      usage();
  1355. X    }
  1356. X  if (argc - i > 1)
  1357. X    usage();
  1358. X  if (i < argc)
  1359. X    accounting_file = argv[i];
  1360. X  if (Uflag && mail_flag && login) {
  1361. X    for (i = 1; i < argc && argv[i][0] == '-'; i++)
  1362. X      switch(argv[i][1]) {
  1363. X      case 'U':
  1364. X    if (strcmp(argv[i] + 2, login) == 0)
  1365. X      mail_flag = 0;
  1366. X    break;
  1367. X      case 'h':
  1368. X      case 'n':
  1369. X      case 'j':
  1370. X      case 'p':
  1371. X      case 's':
  1372. X    i++;
  1373. X    break;
  1374. X      }
  1375. X  }
  1376. X  read_status_file();
  1377. X  get_status();
  1378. X  get_start_pagecount();
  1379. X  send_file();
  1380. X  get_end_pagecount();
  1381. X  do_accounting();
  1382. X  do_exit(EXIT_SUCCESS);
  1383. X  /*NOTREACHED*/
  1384. X}
  1385. END_OF_FILE
  1386. if test 20480 -ne `wc -c <'lprps.c'`; then
  1387.     echo shar: \"'lprps.c'\" unpacked with wrong size!
  1388. fi
  1389. # end of 'lprps.c'
  1390. fi
  1391. if test -f 'psif.c' -a "${1}" != "-c" ; then 
  1392.   echo shar: Will not clobber existing file \"'psif.c'\"
  1393. else
  1394. echo shar: Extracting \"'psif.c'\" \(2326 characters\)
  1395. sed "s/^X//" >'psif.c' <<'END_OF_FILE'
  1396. X/* psif.c */
  1397. X
  1398. X#ifndef lint
  1399. Xstatic char rcsid[] = "$Id: psif.c,v 1.7 1992/02/01 12:40:34 jjc Exp $";
  1400. X#endif
  1401. X
  1402. X#include <stdio.h>
  1403. X#include <sys/types.h>
  1404. X#include <sys/stat.h>
  1405. X
  1406. Xoff_t lseek();
  1407. X
  1408. X#ifndef TEXT_FILTER
  1409. X#define TEXT_FILTER "/usr/local/lib/psif-text"
  1410. X#endif /* not TEXT_FILTER */
  1411. X
  1412. X#ifndef PS_FILTER
  1413. X#define PS_FILTER "/usr/local/lib/psif-ps"
  1414. X#endif /* not PS_FILTER */
  1415. X
  1416. X#define EXIT_SUCCESS 0
  1417. X#define EXIT_REPRINT 1
  1418. X#define EXIT_THROW_AWAY 2
  1419. X
  1420. Xchar *prog;
  1421. X
  1422. Xvoid sys_error(s)
  1423. Xchar *s;
  1424. X{
  1425. X  if (prog)
  1426. X    (void)fprintf(stderr, "%s: ", prog);
  1427. X  perror(s);
  1428. X  exit(EXIT_THROW_AWAY);
  1429. X}
  1430. X
  1431. X
  1432. X/* ARGSUSED */
  1433. Xmain(argc, argv)
  1434. Xint argc;
  1435. Xchar **argv;
  1436. X{
  1437. X  char buf[BUFSIZ];
  1438. X  char *command;
  1439. X  int nread = 0;
  1440. X  int eof = 0;
  1441. X  struct stat statb;
  1442. X  prog = argv[0];
  1443. X
  1444. X  /* Read the first block. */
  1445. X  while (nread < BUFSIZ) {
  1446. X    int ret = read(0, buf + nread, BUFSIZ - nread);
  1447. X    if (ret < 0)
  1448. X      sys_error("read");
  1449. X    if (ret == 0) {
  1450. X      eof = 1;
  1451. X      break;
  1452. X    }
  1453. X    nread += ret;
  1454. X  }
  1455. X  /* Assume a file is binary if it contains a NUL in the first block. */
  1456. X  if (memchr(buf, '\0', nread)) {
  1457. X    fprintf(stderr, "%s: binary file rejected\n", prog);
  1458. X    exit(EXIT_THROW_AWAY);
  1459. X  }
  1460. X  if (nread < 2 || buf[0] != '%' || buf[1] != '!')
  1461. X    command = TEXT_FILTER;
  1462. X  else
  1463. X    command = PS_FILTER;
  1464. X  if (fstat(0, &statb) < 0)
  1465. X    sys_error("fstat");
  1466. X  if ((statb.st_mode & S_IFMT) != S_IFREG) {
  1467. X    /* this happens with lpr -p */
  1468. X    int pid;
  1469. X    int fd[2];
  1470. X    if (pipe(fd) < 0)
  1471. X      sys_error("pipe");
  1472. X    if ((pid = fork()) < 0)
  1473. X      sys_error("fork");
  1474. X    else if (pid == 0) {
  1475. X      /* in the child */
  1476. X      int d;
  1477. X      if (close(fd[0]) < 0)
  1478. X    sys_error("close");
  1479. X      d = fd[1];
  1480. X      if (nread != 0) {
  1481. X    if (write(d, buf, nread) < 0)
  1482. X      sys_error("write");
  1483. X    if (!eof) {
  1484. X      while ((nread = read(0, buf, sizeof(buf))) > 0)
  1485. X        if (write(d, buf, nread) < 0)
  1486. X          sys_error("write");
  1487. X      if (nread < 0)
  1488. X        sys_error("read");
  1489. X    }
  1490. X      }
  1491. X      if (close(d) < 0)
  1492. X    sys_error("close");
  1493. X      exit(0);
  1494. X    }
  1495. X    if (close(fd[1]) < 0)
  1496. X      sys_error("close");
  1497. X    if (close(0) < 0)
  1498. X      sys_error("close");
  1499. X    if (dup(fd[0]) < 0)
  1500. X      sys_error("dup");
  1501. X    if (close(fd[0]) < 0)
  1502. X      sys_error("close");
  1503. X  }
  1504. X  else {
  1505. X    if (lseek(0, (off_t)-nread, 1) < 0)
  1506. X      sys_error("lseek");
  1507. X  }
  1508. X  execv(command, argv);
  1509. X  sys_error("execv");
  1510. X}
  1511. END_OF_FILE
  1512. if test 2326 -ne `wc -c <'psif.c'`; then
  1513.     echo shar: \"'psif.c'\" unpacked with wrong size!
  1514. fi
  1515. # end of 'psif.c'
  1516. fi
  1517. if test -f 'textps.c' -a "${1}" != "-c" ; then 
  1518.   echo shar: Will not clobber existing file \"'textps.c'\"
  1519. else
  1520. echo shar: Extracting \"'textps.c'\" \(12111 characters\)
  1521. sed "s/^X//" >'textps.c' <<'END_OF_FILE'
  1522. X/* textps.c */
  1523. X
  1524. X#ifndef lint
  1525. Xstatic char rcsid[] = "$Id: textps.c,v 1.8 1992/08/12 11:35:31 jjc Exp $";
  1526. X#endif
  1527. X
  1528. X#ifndef TAB_WIDTH
  1529. X#define TAB_WIDTH 8
  1530. X#endif /* not TAB_WIDTH */
  1531. X
  1532. X#ifndef LINES_PER_PAGE
  1533. X#define LINES_PER_PAGE 66
  1534. X#endif /* not LINES_PER_PAGE */
  1535. X
  1536. X#ifndef PAGE_LENGTH
  1537. X#ifdef A4
  1538. X#define PAGE_LENGTH 842.0
  1539. X#else /* not A4 */
  1540. X#define PAGE_LENGTH 792.0
  1541. X#endif /* not A4 */
  1542. X#endif /* not PAGE_LENGTH */
  1543. X
  1544. X#ifndef BASELINE_OFFSET
  1545. X#define BASELINE_OFFSET 8.0
  1546. X#endif /* not BASELINE_OFFSET */
  1547. X
  1548. X#ifndef VERTICAL_SPACING
  1549. X#define VERTICAL_SPACING 12.0
  1550. X#endif /* not VERTICAL_SPACING */
  1551. X
  1552. X#ifndef LEFT_MARGIN
  1553. X#define LEFT_MARGIN 18.0
  1554. X#endif /* not LEFT_MARGIN */
  1555. X
  1556. X#ifndef FONT
  1557. X#define FONT "Courier"
  1558. X#endif /* not FONT */
  1559. X
  1560. X#ifndef BOLD_FONT
  1561. X#define BOLD_FONT "Courier-Bold"
  1562. X#endif /* not BOLD_FONT */
  1563. X
  1564. X#include <stdio.h>
  1565. X#include <ctype.h>
  1566. X#include <string.h>
  1567. X
  1568. Xextern char *malloc();
  1569. Xextern char *optarg;
  1570. Xextern int optind;
  1571. X
  1572. Xtypedef struct output_char {
  1573. X  struct output_char *next;
  1574. X  char c;
  1575. X  char is_bold;
  1576. X  int pos;
  1577. X} output_char;
  1578. X
  1579. Xoutput_char *free_output_char_list = 0;
  1580. X
  1581. Xint tab_width = TAB_WIDTH;
  1582. Xint lines_per_page = LINES_PER_PAGE;
  1583. Xdouble page_length = PAGE_LENGTH; /* in points */
  1584. X/* distance in points from top of page to first baseline */
  1585. Xdouble baseline_offset = BASELINE_OFFSET;
  1586. Xdouble vertical_spacing = VERTICAL_SPACING; /* in points */
  1587. Xdouble left_margin = LEFT_MARGIN; /* in points */
  1588. Xchar *font = FONT;
  1589. Xchar *bold_font = BOLD_FONT;
  1590. X
  1591. Xdouble char_width;
  1592. X
  1593. Xint pageno = 0;
  1594. X
  1595. Xenum { NONE, ROMAN, BOLD } current_font;
  1596. X
  1597. Xvoid do_file();
  1598. Xvoid prologue();
  1599. Xvoid trailer();
  1600. Xchar *prog;
  1601. X
  1602. Xvoid usage()
  1603. X{
  1604. X  fprintf(stderr,
  1605. X      "usage: %s [-c n] [-l n] [-m n] [-t n] [-v n] [files ...]\n",
  1606. X      prog);
  1607. X  exit(1);
  1608. X}
  1609. X
  1610. Xmain(argc, argv)
  1611. Xint argc;
  1612. Xchar **argv;
  1613. X{
  1614. X  int bad_files = 0;
  1615. X  double cpi = 12.0;            /* characters per inch */
  1616. X  int opt;
  1617. X
  1618. X  prog = argv[0];
  1619. X
  1620. X  while ((opt = getopt(argc, argv, "c:l:m:t:v:")) != EOF)
  1621. X    switch (opt) {
  1622. X    case 'c':
  1623. X      if (sscanf(optarg, "%lf", &cpi) != 1)
  1624. X    usage();
  1625. X      break;
  1626. X    case 'l':
  1627. X      if (sscanf(optarg, "%d", &lines_per_page) != 1)
  1628. X    usage();
  1629. X      break;
  1630. X    case 'm':
  1631. X      if (sscanf(optarg, "%lf", &left_margin) != 1)
  1632. X    usage();
  1633. X      break;
  1634. X    case 't':
  1635. X      if (sscanf(optarg, "%lf", &baseline_offset) != 1)
  1636. X    usage();
  1637. X      break;
  1638. X    case 'v':
  1639. X      if (sscanf(optarg, "%lf", &vertical_spacing) != 1)
  1640. X    usage();
  1641. X      break;
  1642. X    case '?':
  1643. X      usage();
  1644. X    default:
  1645. X      abort();
  1646. X    }
  1647. X
  1648. X  char_width = 72.0/cpi;
  1649. X  prologue();
  1650. X  if (optind >= argc)
  1651. X    do_file(stdin);
  1652. X  else {
  1653. X    int i;
  1654. X    for (i = optind; i < argc; i++)
  1655. X      if (strcmp(argv[i], "-") != 0
  1656. X      && freopen(argv[i], "r", stdin) == NULL) {
  1657. X    perror(argv[i]);
  1658. X    bad_files++;
  1659. X      }
  1660. X      else
  1661. X    do_file();
  1662. X  }
  1663. X  trailer();
  1664. X  exit(bad_files);
  1665. X}
  1666. X
  1667. X
  1668. Xoutput_char *new_output_char()
  1669. X{
  1670. X  if (free_output_char_list) {
  1671. X    output_char *tem = free_output_char_list;
  1672. X    free_output_char_list = free_output_char_list->next;
  1673. X    return tem;
  1674. X  }
  1675. X  else {
  1676. X    output_char *tem;
  1677. X    if ((tem = (output_char *)malloc(sizeof(output_char))) == NULL) {
  1678. X      fprintf(stderr, "%s: out of memory\n", prog);
  1679. X      exit(1);
  1680. X    }
  1681. X    return tem;
  1682. X  }
  1683. X}
  1684. X
  1685. Xvoid delete_output_char(p)
  1686. Xoutput_char *p;
  1687. X{
  1688. X  p->next = free_output_char_list;
  1689. X  free_output_char_list = p;
  1690. X}
  1691. X
  1692. Xvoid pschar(c)
  1693. Xint c;
  1694. X{
  1695. X  if (!isascii(c) || iscntrl(c))
  1696. X    printf("\\%03o", c & 0377);
  1697. X  else if (c == '(' || c == ')' || c == '\\') {
  1698. X    putchar('\\');
  1699. X    putchar(c);
  1700. X  }
  1701. X  else
  1702. X    putchar(c);
  1703. X}
  1704. X
  1705. Xvoid psnum(f)
  1706. Xdouble f;
  1707. X{
  1708. X  static char buf[100];
  1709. X  char *p;
  1710. X  sprintf(buf, "%f", f);
  1711. X  for (p = buf + strlen(buf) - 1; *p != '.';  --p)
  1712. X    if (*p != '0') {
  1713. X      p++;
  1714. X      break;
  1715. X    }
  1716. X  *p = '\0';
  1717. X  fputs(buf, stdout);
  1718. X}
  1719. X
  1720. X/* output_line is ordered greatest position first */
  1721. X
  1722. Xvoid print_line(output_line, vpos)
  1723. Xoutput_char *output_line;
  1724. Xint vpos;
  1725. X{
  1726. X  output_char *rev = output_line;
  1727. X  output_line = 0;
  1728. X  while (rev != 0) {
  1729. X    output_char *tem = rev;
  1730. X    rev = rev->next;
  1731. X    tem->next = output_line;
  1732. X    output_line = tem;
  1733. X  }
  1734. X  while (output_line != NULL) {
  1735. X    output_char *tem;
  1736. X    output_char **p = &output_line;
  1737. X    int start_pos = output_line->pos;
  1738. X    int is_bold = output_line->is_bold;
  1739. X    int pos;
  1740. X    if (is_bold) {
  1741. X      if (current_font != BOLD) {
  1742. X    printf("B");
  1743. X    current_font = BOLD;
  1744. X      }
  1745. X    }
  1746. X    else {
  1747. X      if (current_font != ROMAN) {
  1748. X    printf("R");
  1749. X    current_font = ROMAN;
  1750. X      }
  1751. X    }
  1752. X    putchar('(');
  1753. X    pschar(output_line->c);
  1754. X    pos = output_line->pos + 1;
  1755. X    tem = output_line;
  1756. X    output_line = output_line->next;
  1757. X    delete_output_char(tem);
  1758. X    for (;;) {
  1759. X      while (*p != NULL
  1760. X         && ((*p)->pos < pos || (*p)->is_bold != is_bold))
  1761. X    p = &(*p)->next;
  1762. X      if (*p == NULL)
  1763. X    break;
  1764. X      while (pos < (*p)->pos) {
  1765. X    pschar(' ');
  1766. X    pos++;
  1767. X      }
  1768. X      pschar((*p)->c);
  1769. X      pos++;
  1770. X      tem = *p;
  1771. X      *p = tem->next;
  1772. X      delete_output_char(tem);
  1773. X    }
  1774. X    putchar(')');
  1775. X    psnum(left_margin + start_pos*char_width);
  1776. X    putchar(' ');
  1777. X    psnum(page_length - baseline_offset - vpos*vertical_spacing);
  1778. X    fputs(" L\n", stdout);
  1779. X  }
  1780. X}
  1781. X
  1782. Xvoid page_start()
  1783. X{
  1784. X  printf("%%%%Page: ? %d\n%%%%BeginPageSetup\nPS\n%%%%EndPageSetup\n",
  1785. X     ++pageno);
  1786. X  current_font = NONE;
  1787. X}
  1788. X
  1789. Xvoid page_end()
  1790. X{
  1791. X  printf("PE\n");
  1792. X}
  1793. X
  1794. Xchar *defs[] = {
  1795. X  "/L { moveto show } bind def",
  1796. X  "/PS { /level0 save def } bind def",
  1797. X  "/PE { level0 restore showpage } bind def",
  1798. X  "/RE {",
  1799. X  "\tfindfont",
  1800. X  "\tdup maxlength dict begin",
  1801. X  "\t{",
  1802. X  "\t\t1 index /FID ne { def } { pop pop } ifelse",
  1803. X  "\t} forall",
  1804. X  "\t/Encoding exch def",
  1805. X  "\tdup /FontName exch def",
  1806. X  "\tcurrentdict end definefont pop",
  1807. X  "} bind def",
  1808. X};
  1809. X
  1810. Xchar *latin1[] = {
  1811. X  ".notdef",
  1812. X  ".notdef",
  1813. X  ".notdef",
  1814. X  ".notdef",
  1815. X  ".notdef",
  1816. X  ".notdef",
  1817. X  ".notdef",
  1818. X  ".notdef",
  1819. X  ".notdef",
  1820. X  ".notdef",
  1821. X  ".notdef",
  1822. X  ".notdef",
  1823. X  ".notdef",
  1824. X  ".notdef",
  1825. X  ".notdef",
  1826. X  ".notdef",
  1827. X  ".notdef",
  1828. X  ".notdef",
  1829. X  ".notdef",
  1830. X  ".notdef",
  1831. X  ".notdef",
  1832. X  ".notdef",
  1833. X  ".notdef",
  1834. X  ".notdef",
  1835. X  ".notdef",
  1836. X  ".notdef",
  1837. X  ".notdef",
  1838. X  ".notdef",
  1839. X  ".notdef",
  1840. X  ".notdef",
  1841. X  ".notdef",
  1842. X  ".notdef",
  1843. X  "space",
  1844. X  "exclam",
  1845. X  "quotedbl",
  1846. X  "numbersign",
  1847. X  "dollar",
  1848. X  "percent",
  1849. X  "ampersand",
  1850. X  "quoteright",
  1851. X  "parenleft",
  1852. X  "parenright",
  1853. X  "asterisk",
  1854. X  "plus",
  1855. X  "comma",
  1856. X  "hyphen",  /* this should be `minus', but not all PS printers have it */
  1857. X  "period",
  1858. X  "slash",
  1859. X  "zero",
  1860. X  "one",
  1861. X  "two",
  1862. X  "three",
  1863. X  "four",
  1864. X  "five",
  1865. X  "six",
  1866. X  "seven",
  1867. X  "eight",
  1868. X  "nine",
  1869. X  "colon",
  1870. X  "semicolon",
  1871. X  "less",
  1872. X  "equal",
  1873. X  "greater",
  1874. X  "question",
  1875. X  "at",
  1876. X  "A",
  1877. X  "B",
  1878. X  "C",
  1879. X  "D",
  1880. X  "E",
  1881. X  "F",
  1882. X  "G",
  1883. X  "H",
  1884. X  "I",
  1885. X  "J",
  1886. X  "K",
  1887. X  "L",
  1888. X  "M",
  1889. X  "N",
  1890. X  "O",
  1891. X  "P",
  1892. X  "Q",
  1893. X  "R",
  1894. X  "S",
  1895. X  "T",
  1896. X  "U",
  1897. X  "V",
  1898. X  "W",
  1899. X  "X",
  1900. X  "Y",
  1901. X  "Z",
  1902. X  "bracketleft",
  1903. X  "backslash",
  1904. X  "bracketright",
  1905. X  "asciicircum",
  1906. X  "underscore",
  1907. X  "quoteleft",
  1908. X  "a",
  1909. X  "b",
  1910. X  "c",
  1911. X  "d",
  1912. X  "e",
  1913. X  "f",
  1914. X  "g",
  1915. X  "h",
  1916. X  "i",
  1917. X  "j",
  1918. X  "k",
  1919. X  "l",
  1920. X  "m",
  1921. X  "n",
  1922. X  "o",
  1923. X  "p",
  1924. X  "q",
  1925. X  "r",
  1926. X  "s",
  1927. X  "t",
  1928. X  "u",
  1929. X  "v",
  1930. X  "w",
  1931. X  "x",
  1932. X  "y",
  1933. X  "z",
  1934. X  "braceleft",
  1935. X  "bar",
  1936. X  "braceright",
  1937. X  "asciitilde",
  1938. X  ".notdef",
  1939. X  ".notdef",
  1940. X  ".notdef",
  1941. X  ".notdef",
  1942. X  ".notdef",
  1943. X  ".notdef",
  1944. X  ".notdef",
  1945. X  ".notdef",
  1946. X  ".notdef",
  1947. X  ".notdef",
  1948. X  ".notdef",
  1949. X  ".notdef",
  1950. X  ".notdef",
  1951. X  ".notdef",
  1952. X  ".notdef",
  1953. X  ".notdef",
  1954. X  ".notdef",
  1955. X  "dotlessi",
  1956. X  "grave",
  1957. X  "acute",
  1958. X  "circumflex",
  1959. X  "tilde",
  1960. X  "macron",
  1961. X  "breve",
  1962. X  "dotaccent",
  1963. X  "dieresis",
  1964. X  ".notdef",
  1965. X  "ring",
  1966. X  "cedilla",
  1967. X  ".notdef",
  1968. X  "hungarumlaut",
  1969. X  "ogonek",
  1970. X  "caron",
  1971. X  ".notdef",
  1972. X  "exclamdown",
  1973. X  "cent",
  1974. X  "sterling",
  1975. X  "currency",
  1976. X  "yen",
  1977. X  "brokenbar",
  1978. X  "section",
  1979. X  "dieresis",
  1980. X  "copyright",
  1981. X  "ordfeminine",
  1982. X  "guilsinglleft",
  1983. X  "logicalnot",
  1984. X  "hyphen",
  1985. X  "registered",
  1986. X  "macron",
  1987. X  "degree",
  1988. X  "plusminus",
  1989. X  "twosuperior",
  1990. X  "threesuperior",
  1991. X  "acute",
  1992. X  "mu",
  1993. X  "paragraph",
  1994. X  "periodcentered",
  1995. X  "cedilla",
  1996. X  "onesuperior",
  1997. X  "ordmasculine",
  1998. X  "guilsinglright",
  1999. X  "onequarter",
  2000. X  "onehalf",
  2001. X  "threequarters",
  2002. X  "questiondown",
  2003. X  "Agrave",
  2004. X  "Aacute",
  2005. X  "Acircumflex",
  2006. X  "Atilde",
  2007. X  "Adieresis",
  2008. X  "Aring",
  2009. X  "AE",
  2010. X  "Ccedilla",
  2011. X  "Egrave",
  2012. X  "Eacute",
  2013. X  "Ecircumflex",
  2014. X  "Edieresis",
  2015. X  "Igrave",
  2016. X  "Iacute",
  2017. X  "Icircumflex",
  2018. X  "Idieresis",
  2019. X  "Eth",
  2020. X  "Ntilde",
  2021. X  "Ograve",
  2022. X  "Oacute",
  2023. X  "Ocircumflex",
  2024. X  "Otilde",
  2025. X  "Odieresis",
  2026. X  "multiply",
  2027. X  "Oslash",
  2028. X  "Ugrave",
  2029. X  "Uacute",
  2030. X  "Ucircumflex",
  2031. X  "Udieresis",
  2032. X  "Yacute",
  2033. X  "Thorn",
  2034. X  "germandbls",
  2035. X  "agrave",
  2036. X  "aacute",
  2037. X  "acircumflex",
  2038. X  "atilde",
  2039. X  "adieresis",
  2040. X  "aring",
  2041. X  "ae",
  2042. X  "ccedilla",
  2043. X  "egrave",
  2044. X  "eacute",
  2045. X  "ecircumflex",
  2046. X  "edieresis",
  2047. X  "igrave",
  2048. X  "iacute",
  2049. X  "icircumflex",
  2050. X  "idieresis",
  2051. X  "eth",
  2052. X  "ntilde",
  2053. X  "ograve",
  2054. X  "oacute",
  2055. X  "ocircumflex",
  2056. X  "otilde",
  2057. X  "odieresis",
  2058. X  "divide",
  2059. X  "oslash",
  2060. X  "ugrave",
  2061. X  "uacute",
  2062. X  "ucircumflex",
  2063. X  "udieresis",
  2064. X  "yacute",
  2065. X  "thorn",
  2066. X  "ydieresis",
  2067. X};
  2068. X  
  2069. Xvoid prologue()
  2070. X{
  2071. X  int col, i;
  2072. X
  2073. X  printf("%%!PS-Adobe-3.0\n");
  2074. X  printf("%%%%DocumentNeededResources: font %s\n", font);
  2075. X  printf("%%%%+ font %s\n", bold_font);
  2076. X  printf("%%%%Pages: (atend)\n");
  2077. X  printf("%%%%EndComments\n");
  2078. X  printf("%%%%BeginProlog\n");
  2079. X  printf("/textps 10 dict def textps begin\n");
  2080. X  for (i = 0; i < sizeof(defs)/sizeof(defs[0]); i++)
  2081. X    printf("%s\n", defs[i]);
  2082. X  printf("/ISOLatin1Encoding where{pop}{/ISOLatin1Encoding[\n");
  2083. X
  2084. X  col = 0;
  2085. X  for (i = 0; i < 256; i++) {
  2086. X    int len = strlen(latin1[i]) + 1;
  2087. X    col += len;
  2088. X    if (col > 79) {
  2089. X      putchar('\n');
  2090. X      col = len;
  2091. X    }
  2092. X    printf("/%s", latin1[i]);
  2093. X  }
  2094. X  printf("\n] def}ifelse\nend\n");
  2095. X  printf("%%%%BeginSetup\n");
  2096. X  printf("%%%%IncludeResource: font %s\n", font);
  2097. X  printf("%%%%IncludeResource: font %s\n", bold_font);
  2098. X  printf("textps begin\n");
  2099. X  printf("/__%s ISOLatin1Encoding /%s RE\n", font, font);
  2100. X  printf("/R [ /__%s findfont %f scalefont /setfont load ] cvx def\n",
  2101. X     font, char_width/.6);
  2102. X  printf("/__%s ISOLatin1Encoding /%s RE\n", bold_font, bold_font);
  2103. X  printf("/B [ /__%s findfont %f scalefont /setfont load ] cvx def\n", 
  2104. X     bold_font, char_width/.6);
  2105. X  printf("%%%%EndSetup\n");
  2106. X  printf("%%%%EndProlog\n");
  2107. X}
  2108. X
  2109. Xvoid trailer()
  2110. X{
  2111. X  printf("%%%%Trailer\nend\n%%%%Pages: %d\n", pageno);
  2112. X}
  2113. X
  2114. X/* p is ordered greatest position first */
  2115. X
  2116. Xvoid add_char(c, pos, p)
  2117. Xint c;
  2118. Xint pos;
  2119. Xoutput_char **p;
  2120. X{
  2121. X  for (;; p = &(*p)->next) {
  2122. X    if (*p == NULL || (*p)->pos < pos) {
  2123. X      output_char *tem = new_output_char();
  2124. X      tem->next = *p;
  2125. X      *p = tem;
  2126. X      tem->c = c;
  2127. X      tem->is_bold = 0;
  2128. X      tem->pos = pos;
  2129. X      break;
  2130. X    }
  2131. X    else if ((*p)->pos == pos) {
  2132. X      if (c == (*p)->c) {
  2133. X    (*p)->is_bold = 1;
  2134. X    break;
  2135. X      }
  2136. X    }
  2137. X  }
  2138. X}
  2139. X
  2140. Xvoid do_file()
  2141. X{
  2142. X  int c;
  2143. X  int vpos = 0;
  2144. X  int hpos = 0;
  2145. X  int page_started = 0;
  2146. X  int esced = 0;
  2147. X  output_char *output_line = 0;
  2148. X  while ((c = getchar()) != EOF)
  2149. X    if (esced)
  2150. X      switch(c) {
  2151. X      case '7':
  2152. X    if (vpos > 0) {
  2153. X      if (output_line != NULL) {
  2154. X        if (!page_started) {
  2155. X          page_started = 1;
  2156. X          page_start();
  2157. X        }
  2158. X        print_line(output_line, vpos);
  2159. X        output_line = 0;
  2160. X      }
  2161. X      vpos -= 1;
  2162. X    }
  2163. X    /* hpos = 0; */
  2164. X    esced = 0;
  2165. X    break;
  2166. X      default:
  2167. X    /* silently ignore */
  2168. X    esced = 0;
  2169. X    break;
  2170. X      }
  2171. X    else
  2172. X      switch (c) {
  2173. X      case '\033':
  2174. X    esced = 1;
  2175. X    break;
  2176. X      case '\b':
  2177. X    if (hpos > 0)
  2178. X      hpos--;
  2179. X    break;
  2180. X      case '\f':
  2181. X    if (!page_started)
  2182. X      page_start();
  2183. X    print_line(output_line, vpos);
  2184. X    output_line = 0;
  2185. X    page_end();
  2186. X    hpos = 0;        /* ?? */
  2187. X    vpos = 0;
  2188. X    page_started = 0;
  2189. X    break;
  2190. X      case '\r':
  2191. X    hpos = 0;
  2192. X    break;
  2193. X      case '\n':
  2194. X    if (output_line != NULL) {
  2195. X      if (!page_started) {
  2196. X        page_started = 1;
  2197. X        page_start();
  2198. X      }
  2199. X      print_line(output_line, vpos);
  2200. X      output_line = 0;
  2201. X    }
  2202. X    vpos += 1;
  2203. X    if (vpos >= lines_per_page) {
  2204. X      if (!page_started)
  2205. X        page_start();
  2206. X      page_end();
  2207. X      page_started = 0;
  2208. X      vpos = 0;
  2209. X    }
  2210. X    hpos = 0;
  2211. X    break;
  2212. X      case ' ':
  2213. X    hpos++;
  2214. X    break;
  2215. X      case '\t':
  2216. X    hpos = ((hpos + tab_width)/tab_width)*tab_width;
  2217. X    break;
  2218. X      default:
  2219. X    if (!(isascii(c) && iscntrl(c))) {
  2220. X      add_char(c, hpos, &output_line);
  2221. X      hpos++;
  2222. X    }
  2223. X    break;
  2224. X      }
  2225. X  if (output_line != NULL) {
  2226. X    if (!page_started) {
  2227. X      page_started = 1;
  2228. X      page_start();
  2229. X    }
  2230. X    print_line(output_line, vpos);
  2231. X    output_line = 0;
  2232. X  }
  2233. X  if (page_started)
  2234. X    page_end();
  2235. X}
  2236. END_OF_FILE
  2237. if test 12111 -ne `wc -c <'textps.c'`; then
  2238.     echo shar: \"'textps.c'\" unpacked with wrong size!
  2239. fi
  2240. # end of 'textps.c'
  2241. fi
  2242. if test -f 'psof.c' -a "${1}" != "-c" ; then 
  2243.   echo shar: Will not clobber existing file \"'psof.c'\"
  2244. else
  2245. echo shar: Extracting \"'psof.c'\" \(5933 characters\)
  2246. sed "s/^X//" >'psof.c' <<'END_OF_FILE'
  2247. X/* psof.c - lprps `of' filter for banner printing */
  2248. X
  2249. X/* Assumes sb is set, sh is not set, and that there is also an if
  2250. Xfilter. */
  2251. X
  2252. X/* TODO: parse height and width command line arguments and pass them
  2253. Xas definitions to banner prog */
  2254. X
  2255. X#ifndef lint
  2256. Xstatic char rcsid[] = "$Id: psof.c,v 1.1 1992/02/01 12:36:01 jjc Exp $";
  2257. X#endif
  2258. X
  2259. X#include <stdio.h>
  2260. X#include <strings.h>
  2261. X#include <signal.h>
  2262. X#include <syslog.h>
  2263. X#include <errno.h>
  2264. X#include <ctype.h>
  2265. X
  2266. X#ifndef LPRPS
  2267. X#define LPRPS "/usr/local/lib/lprps"
  2268. X#endif /* not LPRPS */
  2269. X
  2270. X#ifndef BANNER
  2271. X#define BANNER "/usr/local/lib/banner.ps"
  2272. X#endif /* not BANNER */
  2273. X
  2274. X#define JOB_PREFIX "  Job: "
  2275. X#define DATE_PREFIX "  Date: "
  2276. X#define LINE_MAX 1024
  2277. X
  2278. Xstatic char class[32];
  2279. Xstatic char user[32];
  2280. Xstatic char job[100];
  2281. Xstatic char date[100];
  2282. X
  2283. Xstatic void sys_error();
  2284. Xstatic void error();
  2285. Xstatic int parse_banner();
  2286. Xstatic int define_string();
  2287. Xstatic int do_banner();
  2288. Xstatic void print_banner();
  2289. X
  2290. Xstatic char *xstrstr();
  2291. X
  2292. Xint main(argc, argv)
  2293. Xint argc;
  2294. Xchar **argv;
  2295. X{
  2296. X  char buf[LINE_MAX];
  2297. X  char *prog;
  2298. X
  2299. X  if (argc > 0) {
  2300. X    if ((prog = rindex(argv[0], '/')) == 0)
  2301. X      prog = argv[0];
  2302. X    else
  2303. X      prog++;
  2304. X  }
  2305. X  else
  2306. X    prog = "psof";
  2307. X  openlog(prog, LOG_PID, LOG_LPR);
  2308. X  for (;;) {
  2309. X    int i = 0;
  2310. X    int c = getchar();
  2311. X    if (c == EOF)
  2312. X      break;
  2313. X    for (;;) {
  2314. X      if (c == '\n')
  2315. X    break;
  2316. X      if (i >= LINE_MAX - 1 || c == '\0' || c == EOF || c == '\031')
  2317. X    error("bad banner line");
  2318. X      buf[i++] = c;
  2319. X      c = getchar();
  2320. X    }
  2321. X    buf[i++] = '\0';
  2322. X    if (!parse_banner(buf))
  2323. X      error("bad banner line");
  2324. X    print_banner();
  2325. X    c = getchar();
  2326. X    if (c == EOF)
  2327. X      break;
  2328. X    if (c != '\031' || getchar() != '\001')
  2329. X      error("more than one banner line");
  2330. X    if (kill(getpid(), SIGSTOP) < 0)
  2331. X      sys_error("kill");
  2332. X  }
  2333. X  exit(0);
  2334. X  /*NOTREACHED*/
  2335. X}
  2336. X
  2337. Xstatic int parse_banner(s)
  2338. X     char *s;
  2339. X{
  2340. X  char *p, *q;
  2341. X
  2342. X  class[0] = date[0] = user[0] = job[0] = '\0';
  2343. X  
  2344. X  p = xstrstr(s, JOB_PREFIX);
  2345. X  if (!p)
  2346. X    return 0;
  2347. X  *p = 0;
  2348. X  q = index(s, ':');
  2349. X  if (q == 0) {
  2350. X    if (strlen(s) + 1 > sizeof(user))
  2351. X      return 0;
  2352. X    (void)strcpy(user, s);
  2353. X  }
  2354. X  else {
  2355. X    if (strlen(q + 1) + 1 > sizeof(user))
  2356. X      return 0;
  2357. X    (void)strcpy(user, q + 1);
  2358. X    if (q - s + 1 > sizeof(class))
  2359. X      return 0;
  2360. X    bcopy(s, class, q - s);
  2361. X    class[q - s] = '\0';
  2362. X  }
  2363. X  p += sizeof(JOB_PREFIX) - 1;
  2364. X  q = xstrstr(p, DATE_PREFIX);
  2365. X  if (!q)
  2366. X    return 0;
  2367. X  if (q - p + 1 > sizeof(job))
  2368. X    return 0;
  2369. X  bcopy(p, job, q - p);
  2370. X  job[q - p] = '\0';
  2371. X  q += sizeof(DATE_PREFIX) - 1;
  2372. X  if (strlen(q) + 1 > sizeof(date))
  2373. X    return 0;
  2374. X  (void)strcpy(date, q);
  2375. X  return 1;
  2376. X}
  2377. X
  2378. Xstatic void print_banner()
  2379. X{
  2380. X  int fd[2];
  2381. X  FILE *psfp;
  2382. X  int status;
  2383. X  int pid;
  2384. X  int ret;
  2385. X  int write_error = 0;
  2386. X
  2387. X  if (signal(SIGPIPE, SIG_IGN) == BADSIG) /* in case lprps dies */
  2388. X    sys_error("signal");
  2389. X  for (;;) {
  2390. X    if (pipe(fd) < 0)
  2391. X      sys_error("pipe");
  2392. X    if ((pid = fork()) < 0)
  2393. X      sys_error("fork");
  2394. X    else if (pid == 0) {
  2395. X      /* child */
  2396. X      if (close(fd[1]) < 0)
  2397. X    sys_error("close");
  2398. X      if (dup2(fd[0], 0) < 0)
  2399. X    sys_error("dup2");
  2400. X      if (close(fd[0]) < 0)
  2401. X    sys_error("close");
  2402. X      (void)execl(LPRPS, LPRPS, (char *)0);
  2403. X      sys_error("exec");
  2404. X    }
  2405. X    /* parent */
  2406. X    if (close(fd[0]) < 0)
  2407. X      sys_error("close");
  2408. X    if ((psfp = fdopen(fd[1], "w")) == NULL)
  2409. X      sys_error("fdopen");
  2410. X    if (do_banner(psfp) < 0) {
  2411. X      if (errno != EPIPE)
  2412. X    sys_error("write");
  2413. X      write_error = 1;
  2414. X      clearerr(psfp);
  2415. X      (void)fclose(psfp);
  2416. X    }
  2417. X    if (fclose(psfp) < 0) {
  2418. X      if (errno != EPIPE)
  2419. X    sys_error("fclose");
  2420. X      write_error = 1;
  2421. X    }
  2422. X    while ((ret = wait(&status)) != pid)
  2423. X      if (ret < 0)
  2424. X    sys_error("wait");
  2425. X    status &= 0xffff;        /* anal */
  2426. X    if ((status & 0xff) != 0) {
  2427. X      int sig = status & 0x7f;
  2428. X      if (sig < NSIG) {
  2429. X    extern char *sys_siglist[];
  2430. X    syslog(LOG_ERR, "%s: %s%s", LPRPS, sys_siglist[sig],
  2431. X           (status & 0x80) ? " (core dumped)" : "");
  2432. X      }
  2433. X      else
  2434. X    syslog(LOG_ERR, "%s: signal %d%s", LPRPS, sig,
  2435. X          (status & 0x80) ? " (core dumped)" : "");
  2436. X      return;
  2437. X    }
  2438. X    else {
  2439. X      int exit_status = (status >> 8) & 0xff;
  2440. X      switch (exit_status) {
  2441. X      case 0:
  2442. X    if (write_error)
  2443. X      syslog(LOG_ERR, "got EPIPE but exit status was 0");
  2444. X    return;
  2445. X      case 1:
  2446. X    /* this will happen if the printer's not turned on */
  2447. X    continue;
  2448. X      case 2:
  2449. X    return;
  2450. X      default:
  2451. X    syslog(LOG_ERR, "`%s' exited with status %d", LPRPS, exit_status);
  2452. X    return;
  2453. X      }
  2454. X    }
  2455. X  }
  2456. X}
  2457. X
  2458. X/* Return -1 for a write error, 0 otherwise. */
  2459. X
  2460. Xstatic int do_banner(psfp)
  2461. X     FILE *psfp;
  2462. X{
  2463. X  FILE *infp;
  2464. X  int c;
  2465. X
  2466. X  infp = fopen(BANNER, "r");
  2467. X  if (!infp)
  2468. X    sys_error(BANNER);
  2469. X  if (fputs("%!\n", psfp) < 0)
  2470. X    return -1;
  2471. X  if (define_string("Job", job, psfp) < 0
  2472. X      || define_string("Class", class, psfp) < 0
  2473. X      || define_string("User", user, psfp) < 0
  2474. X      || define_string("Date", date, psfp) < 0)
  2475. X    return -1;
  2476. X  
  2477. X  while ((c = getc(infp)) != EOF)
  2478. X    if (putc(c, psfp) < 0)
  2479. X      return -1;
  2480. X  return 0;
  2481. X}
  2482. X
  2483. X/* Return -1 for a write error, 0 otherwise. */
  2484. X
  2485. Xstatic int define_string(name, str, psfp)
  2486. X     char *name, *str;
  2487. X     FILE *psfp;
  2488. X{
  2489. X  if (fprintf(psfp, "/%s (", name) < 0)
  2490. X    return -1; 
  2491. X  for (; *str; str++) {
  2492. X    if (*str == ')' || *str == '(' || *str == '\\') {
  2493. X      if (fprintf(psfp, "\\%c", *str) < 0)
  2494. X    return -1;
  2495. X    }
  2496. X    else if (isascii(*str) && isprint(*str)) {
  2497. X      if (putc(*str, psfp) < 0)
  2498. X    return -1;
  2499. X    }
  2500. X    else  {
  2501. X      if (fprintf(psfp, "\\%03o", (unsigned char)*str) < 0)
  2502. X    return -1;
  2503. X    }
  2504. X  }
  2505. X  if (fprintf(psfp, ") def\n") < 0)
  2506. X    return -1;
  2507. X  return 0;
  2508. X}
  2509. X
  2510. Xstatic void sys_error(s)
  2511. Xchar *s;
  2512. X{
  2513. X  syslog(LOG_ERR, "%s: %m", s);
  2514. X  exit(1);
  2515. X}
  2516. X
  2517. Xstatic void error(s)
  2518. Xchar *s;
  2519. X{
  2520. X  syslog(LOG_ERR, "%s", s);
  2521. X  exit(1);
  2522. X}
  2523. X
  2524. X/* same as ANSI strstr */
  2525. X
  2526. Xstatic char *xstrstr(p, q)
  2527. X     char *p, *q;
  2528. X{
  2529. X  int len = strlen(q);
  2530. X  do {
  2531. X    if (strncmp(p, q, len) == 0)
  2532. X      return p;
  2533. X  } while (*p++ != '\0');
  2534. X  return 0;
  2535. X}
  2536. END_OF_FILE
  2537. if test 5933 -ne `wc -c <'psof.c'`; then
  2538.     echo shar: \"'psof.c'\" unpacked with wrong size!
  2539. fi
  2540. # end of 'psof.c'
  2541. fi
  2542. echo shar: End of archive 2 \(of 2\).
  2543. cp /dev/null ark2isdone
  2544. MISSING=""
  2545. for I in 1 2 ; do
  2546.     if test ! -f ark${I}isdone ; then
  2547.     MISSING="${MISSING} ${I}"
  2548.     fi
  2549. done
  2550. if test "${MISSING}" = "" ; then
  2551.     echo You have unpacked both archives.
  2552.     rm -f ark[1-9]isdone
  2553. else
  2554.     echo You still need to unpack the following archives:
  2555.     echo "        " ${MISSING}
  2556. fi
  2557. ##  End of shell archive.
  2558. exit 0
  2559.  
  2560. exit 0 # Just in case...
  2561.