home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / sources / misc / 3807 < prev    next >
Encoding:
Text File  |  1992-08-14  |  52.9 KB  |  2,567 lines

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