PageRenderTime 52ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://github.com/richlowe/illumos-gate
C | 501 lines | 376 code | 47 blank | 78 comment | 73 complexity | 226ead3092c5e7b6b1a972bee59a251c MD5 | raw file
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License, Version 1.0 only
  6. * (the "License"). You may not use this file except in compliance
  7. * with the License.
  8. *
  9. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10. * or http://www.opensolaris.org/os/licensing.
  11. * See the License for the specific language governing permissions
  12. * and limitations under the License.
  13. *
  14. * When distributing Covered Code, include this CDDL HEADER in each
  15. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16. * If applicable, add the following below this CDDL HEADER, with the
  17. * fields enclosed by brackets "[]" replaced with your own identifying
  18. * information: Portions Copyright [yyyy] [name of copyright owner]
  19. *
  20. * CDDL HEADER END
  21. */
  22. /*
  23. * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
  24. * Use is subject to license terms.
  25. */
  26. /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  27. /* All Rights Reserved */
  28. #pragma ident "%Z%%M% %I% %E% SMI"
  29. #include "signal.h"
  30. #include "stdio.h"
  31. #include "errno.h"
  32. #include "lp.h"
  33. #include "msgs.h"
  34. #include "string.h"
  35. void startup(),
  36. cleanup(),
  37. done();
  38. extern char *getenv(),
  39. *malloc(),
  40. *realloc();
  41. extern long atol();
  42. extern int atoi();
  43. static void wakeup();
  44. extern char *optarg;
  45. extern int optind, opterr, optopt;
  46. int optsw;
  47. #define PREFIX_STRING "%%["
  48. #define SUFFIX_STRING "]%%"
  49. #define PRINTER_ERROR_STRING "PrinterError:"
  50. #define STATUS_STRING "status:"
  51. #define JOB_STRING "job:"
  52. #define STATUS_OK_STRING "ready and printing"
  53. #define PAPER_CHANGED_STRING "paper changed:"
  54. /*
  55. * Some common postscript printer fault messages.
  56. * These strings are here so that they get l10ned and then lpstat will
  57. * be able to display them in the users language.
  58. * This seemed like a good place for them, since lp.tell knows about
  59. * postscript msgs.
  60. */
  61. char *ps_m1 = "unable to print: out of media (paper)";
  62. char *ps_m2 = "out of media (paper)";
  63. char *ps_m3 = "unable to print: tray not (properly) installed";
  64. char *ps_m4 = "tray not (properly) installed";
  65. char *ps_m5 = "unable to print: paper out for the selected tray";
  66. char *ps_m6 = "paper out for the selected tray";
  67. char *ps_m7 = "unable to print: cartridge life expiring";
  68. char *ps_m8 = "cartridge life expiring";
  69. char *ps_m9 = "unable to print: printer cover not locked";
  70. char *ps_m10 = "printer cover not locked";
  71. char *ps_m11 = "unable to print: media (paper) jam in exit path";
  72. char *ps_m12 = "media (paper) jam in exit path";
  73. char *ps_m13 = "unable to print: media (paper) jam in feed path";
  74. char *ps_m14 = "media (paper) jam in feed path";
  75. char *ps_m15 = "unable to print: drum assembly almost expended";
  76. char *ps_m16 = "drum assembly almost expended";
  77. char *ps_m17 = "unable to print: toner cartridge almost expended";
  78. char *ps_m18 = "toner cartridge almost expended";
  79. char *ps_m19 = "unable to print: drum assembly not (properly) installed";
  80. char *ps_m20 = "drum assembly not (properly) installed";
  81. char *ps_m21 = "unable to print: toner cartridge not (properly) installed";
  82. char *ps_m22 = "toner cartridge not (properly) installed";
  83. char *ps_m23 = "unable to print: drum assembly requires replacement";
  84. char *ps_m24 = "drum assembly requires replacement";
  85. char *ps_m25 = "unable to print: toner cartridge requires replacement";
  86. char *ps_m26 = "toner cartridge requires replacement";
  87. char *ps_m27 = "unable to print: fuser warming up";
  88. char *ps_m28 = "fuser warming up";
  89. char *ps_m29 = "unable to print: printer not responding";
  90. char *ps_m30 = "printer not responding";
  91. char *ps_m31 = "unable to print: fuser pausing";
  92. char *ps_m32 = "fuser pausing";
  93. char *ps_m33 = "unable to print: printer turned off";
  94. char *ps_m34 = "printer turned off";
  95. char *ps_m35 = "unable to print: printer warming up";
  96. char *ps_m36 = "printer warming up";
  97. char *ps_m37 = "unable to print: interlock open";
  98. char *ps_m38 = "interlock open";
  99. char *ps_m39 = "unable to print: selected tray out";
  100. char *ps_m40 = "selected tray out";
  101. char *ps_m41 = "unable to print: paper out for the manual tray";
  102. char *ps_m42 = "paper out for the manual tray";
  103. char *ps_m43 = "unable to print: paper exit jam";
  104. char *ps_m44 = "paper exit jam";
  105. char *ps_m45 = "unable to print: paper misfeed jam";
  106. char *ps_m46 = "paper misfeed jam";
  107. char *ps_m47 = "unable to print: paper jam between registration & heat rollers";
  108. char *ps_m48 = "paper jam between registration & heat rollers";
  109. char *ps_m49 = "unable to print: paper jam at registration roller";
  110. char *ps_m50 = "paper jam at registration roller";
  111. char *ps_m51 = "unable to print: no cartridge";
  112. char *ps_m52 = "no cartridge";
  113. char *ps_m53 = "unable to print: cartridge out";
  114. char *ps_m54 = "cartridge out";
  115. /**
  116. ** main()
  117. **/
  118. int
  119. main(int argc, char *argv[])
  120. {
  121. char *alert_text,
  122. buf[BUFSIZ],
  123. msgbuf[MSGMAX],
  124. *bufPtr,
  125. *printer,
  126. *s_key;
  127. char *printerErrorString = NULL;
  128. char *statusString = NULL;
  129. char *paperChangedString = NULL;
  130. char *suffixString = NULL;
  131. char *jobString = NULL;
  132. char *prefixString = NULL;
  133. char *statusOkString = NULL;
  134. int mtype,
  135. doStdOut,
  136. doDebug,
  137. first,
  138. oldalarm;
  139. short status;
  140. long key,clearKey;
  141. char *ptr1,*ptr2,*ptr3,*ptr4,*ptr5;
  142. int trayNum = 0;
  143. int mode = 0;
  144. int pagesPrinted = 0;
  145. char *paperType = NULL;
  146. short mesgRetType;
  147. int useLaserWriterMessages;
  148. int pLen,sLen,peLen,jLen,pcLen ;
  149. void (*oldsignal)();
  150. /*
  151. * Run immune from typical interruptions, so that
  152. * we stand a chance to get the fault message.
  153. * EOF (or startup error) is the only way out.
  154. */
  155. signal (SIGHUP, SIG_IGN);
  156. signal (SIGINT, SIG_IGN);
  157. signal (SIGQUIT, SIG_IGN);
  158. signal (SIGTERM, SIG_IGN);
  159. /*
  160. * Do we have a key?
  161. */
  162. if (
  163. argc < 2
  164. || !(s_key = getenv("SPOOLER_KEY"))
  165. || !*s_key
  166. || (key = atol(s_key)) <= 0
  167. ) {
  168. printf( "Usage: lptell [-lodk] [-X String] printer\n");
  169. printf("Options (where X is P,S,e,s, O or c )\n");
  170. printf(" environment variable SPOOLER_KEY: must be defined and > 0\n");
  171. printf(" printer: name of printer to give status for.\n");
  172. printf(" -l: expect laser writer type messages (NeWSprint does)\n");
  173. printf(" -o: send input to stdout\n");
  174. printf(" -d: send additional debugging output to stdout\n");
  175. printf(" -P String: string for prefix, default: '%%%%['\n");
  176. printf(" -S String: string for suffix, default: ']%%%%'\n");
  177. printf(" -e String: string to detect printer error,\n");
  178. printf(" default: 'PrinterError:', send S_SEND_FAULT to lpsched\n");
  179. printf(
  180. " -c String: string to detect paper change in context of printer error,\n");
  181. printf(" default: 'paper changed:', send S_PAPER_CHANGED to lpsched\n");
  182. printf(" -s String: string to detect printer ok status, \n");
  183. printf(" default: 'status:', send S_CLEAR_FAULT to lpsched\n");
  184. printf(" -k: do not use the key for making status ok\n");
  185. printf(" -O String: string sent as status message to lpsched,\n");
  186. printf(" default: 'ready and printing:'\n");
  187. exit (90);
  188. }
  189. doStdOut = 0;
  190. doDebug = 0;
  191. useLaserWriterMessages = 0;
  192. clearKey = key;
  193. prefixString = PREFIX_STRING; pLen = strlen(prefixString);
  194. suffixString = SUFFIX_STRING;
  195. printerErrorString = PRINTER_ERROR_STRING;
  196. peLen = strlen(printerErrorString);
  197. statusString = STATUS_STRING; sLen = strlen(statusString);
  198. jobString = JOB_STRING; jLen = strlen(jobString);
  199. paperChangedString = PAPER_CHANGED_STRING;
  200. pcLen = strlen(paperChangedString);
  201. statusOkString = STATUS_OK_STRING;
  202. while ((optsw = getopt(argc, argv, "le:s:c:okdO:S:P:")) != EOF) {
  203. switch ( optsw ) {
  204. case 'l':
  205. useLaserWriterMessages = 1;
  206. break;
  207. case 'P':
  208. prefixString = (optarg ? strdup(optarg) : NULL);
  209. pLen = strlen(prefixString );
  210. break;
  211. case 'S':
  212. suffixString = (optarg ? strdup(optarg) : NULL);
  213. break;
  214. case 'e':
  215. printerErrorString = (optarg ? strdup(optarg) : NULL);
  216. peLen = strlen(printerErrorString);
  217. break;
  218. case 's':
  219. statusString = (optarg ? strdup(optarg) : NULL);
  220. sLen = strlen(statusString);
  221. break;
  222. case 'O':
  223. statusOkString = (optarg ? strdup(optarg) : NULL);
  224. break;
  225. case 'c':
  226. paperChangedString = (optarg ? strdup(optarg) : NULL);
  227. pcLen = strlen(paperChangedString );
  228. break;
  229. case 'k':
  230. clearKey = -1;
  231. break;
  232. case 'o':
  233. doStdOut = 1;
  234. break;
  235. case 'd':
  236. doDebug = 1;
  237. break;
  238. }
  239. }
  240. /*
  241. * Which printer is this? Do we have a key?
  242. */
  243. if (
  244. !(printer = argv[optind])
  245. || !*printer
  246. ) {
  247. exit (90);
  248. }
  249. if (doDebug) {
  250. printf( "start lp.tell for %s key %d mode %s %s\n",
  251. printer,key,(useLaserWriterMessages ? "LW" : "standard"),
  252. (doStdOut ? "doStdOut" : "no output"));
  253. printf( "prefix (%s) suffix (%s) printerError (%s)\n",
  254. prefixString,suffixString,printerErrorString);
  255. printf( "paper_changed (%s) status (%s) key %d \n",
  256. paperChangedString,statusString , clearKey);
  257. fflush(stdout);
  258. }
  259. /*
  260. * Wait for a message on the standard input. When a single line
  261. * comes in, take a couple of more seconds to get any other lines
  262. * that may be ready, then send them to the Spooler.
  263. */
  264. while (fgets(buf, BUFSIZ, stdin)) {
  265. if (useLaserWriterMessages) {
  266. /* NeWSprint style processing (which simulates the LaserWriter
  267. *There are four types of messages:
  268. * 1) fault messages: printer error message from handler
  269. * 2) clear fault messages: printer ok messages from handler
  270. * 3) paper changed messages: printer handler detected paper change
  271. * 4) server messages: xnews problems
  272. */
  273. bufPtr = buf;
  274. if (strncmp(prefixString, bufPtr, pLen) == 0) {
  275. bufPtr += pLen;
  276. while (*bufPtr == ' ')
  277. bufPtr++;
  278. if (strncmp(printerErrorString, bufPtr,
  279. peLen) == 0) {
  280. bufPtr += peLen;
  281. while (*bufPtr == ' ')
  282. bufPtr++;
  283. if ((strncmp(bufPtr,paperChangedString,pcLen) == 0) &&
  284. (ptr1 = bufPtr +pcLen) &&
  285. (ptr2 = strchr(ptr1+1,':')) &&
  286. (ptr3 = strchr(ptr2+1,':')) &&
  287. (ptr4 = strchr(ptr3+1,':')) &&
  288. (ptr5 = strchr(ptr4+1,'\n'))) {
  289. if (doStdOut) printf("%s",buf);
  290. *ptr2 =0;
  291. *ptr3= 0;
  292. *ptr4= 0;
  293. *ptr5= 0;
  294. trayNum = atoi(ptr1+1);
  295. paperType = ptr2+1;
  296. mode = atoi(ptr3+1);
  297. pagesPrinted = atoi(ptr4+1);
  298. if (doDebug) {
  299. printf("Paper changed: %s tray %d paper %s md %d pages %d\n",
  300. printer,trayNum,paperType,mode,pagesPrinted);
  301. }
  302. startup ();
  303. mesgRetType = R_PAPER_CHANGED;
  304. (void)putmessage ( msgbuf, S_PAPER_CHANGED, printer, trayNum,
  305. paperType, mode, pagesPrinted);
  306. } else {
  307. if (doStdOut) printf("%s",buf);
  308. if (ptr1 = strstr(bufPtr,suffixString)) *ptr1 = 0;
  309. if ( doDebug ) {
  310. printf("Send fault: %s key %d (%s)\n",printer,key,bufPtr);
  311. }
  312. mesgRetType = R_SEND_FAULT;
  313. startup ();
  314. (void)putmessage (msgbuf,S_SEND_FAULT,printer,key,bufPtr);
  315. }
  316. } else if ((first = (strncmp(statusString,bufPtr,sLen) == 0)) ||
  317. (strncmp(jobString,bufPtr,jLen) == 0)) {
  318. bufPtr += (first ? sLen : jLen);
  319. if (doStdOut) printf("%s",buf);
  320. if (ptr1 = strstr(bufPtr,suffixString)) *ptr1 = 0;
  321. if ( doDebug ) {
  322. printf("Clear fault: %s key %d (%s)\n",printer, clearKey,
  323. bufPtr);
  324. }
  325. mesgRetType = R_CLEAR_FAULT;
  326. startup ();
  327. (void)putmessage( msgbuf,S_CLEAR_FAULT,printer,clearKey,
  328. statusOkString);
  329. } else {
  330. if (doStdOut) printf("%s",buf);
  331. if (ptr1 = strstr(bufPtr,suffixString)) *ptr1 = 0;
  332. if ( doDebug ) {
  333. printf("Server error: %s key %d (%s)\n",printer,key,
  334. buf);
  335. }
  336. mesgRetType = 0;
  337. }
  338. } else {
  339. if (doStdOut) printf("%s",buf);
  340. if (ptr1 = strstr(bufPtr,suffixString))
  341. *ptr1 = 0;
  342. if (doDebug) {
  343. printf("Server error: %s key %d (%s)\n",
  344. printer, key, buf);
  345. }
  346. mesgRetType = 0;
  347. }
  348. } else { /* not generic PostScript style messages */
  349. oldsignal = signal(SIGALRM, wakeup);
  350. oldalarm = alarm(2);
  351. alert_text = 0;
  352. do {
  353. if (alert_text)
  354. alert_text = realloc(alert_text,
  355. strlen(alert_text)+strlen(buf)+1
  356. );
  357. else {
  358. alert_text = malloc(strlen(buf) + 1);
  359. alert_text[0] = 0;
  360. }
  361. strcat (alert_text, buf);
  362. } while (fgets(buf, BUFSIZ, stdin));
  363. alarm (oldalarm);
  364. signal (SIGALRM, oldsignal);
  365. if (doStdOut) {
  366. if ( doDebug ) {
  367. printf("Send generic fault: %s key %d (%s)\n",printer,key,
  368. alert_text);
  369. }
  370. else {
  371. printf("%s\n",alert_text);
  372. }
  373. }
  374. if (strcmp(alert_text, "printer ok\n") == 0) {
  375. mesgRetType = R_CLEAR_FAULT;
  376. startup ();
  377. (void)putmessage(msgbuf, S_CLEAR_FAULT, printer,
  378. clearKey, statusOkString);
  379. } else {
  380. mesgRetType = R_SEND_FAULT;
  381. startup ();
  382. (void)putmessage(msgbuf, S_SEND_FAULT, printer,
  383. key, alert_text);
  384. }
  385. }
  386. if (mesgRetType) {
  387. if (msend(msgbuf) == -1)
  388. done (91);
  389. if (mrecv(msgbuf, sizeof(msgbuf)) == -1)
  390. done (92);
  391. mtype = getmessage(msgbuf, mesgRetType, &status);
  392. /*
  393. * check for R_CLEAR_FAULT here and 3 lines below
  394. * because older lpsched doesn't pass S_CLEAR_FAULT
  395. */
  396. if ((mtype != mesgRetType) &&
  397. (mesgRetType != R_CLEAR_FAULT))
  398. done (93);
  399. if ((status != MOK) && (mesgRetType != R_CLEAR_FAULT))
  400. done (94);
  401. }
  402. }
  403. done (0);
  404. return (0);
  405. }
  406. /**
  407. ** startup() - OPEN MESSAGE QUEUE TO SPOOLER
  408. ** cleanup() - CLOSE THE MESSAGE QUEUE TO THE SPOOLER
  409. **/
  410. static int have_contacted_spooler = 0;
  411. void startup ()
  412. {
  413. void catch();
  414. /*
  415. * Open a message queue to the Spooler.
  416. * An error is deadly.
  417. */
  418. if (!have_contacted_spooler) {
  419. if (mopen() == -1) {
  420. switch (errno) {
  421. case ENOMEM:
  422. case ENOSPC:
  423. break;
  424. default:
  425. break;
  426. }
  427. exit (1);
  428. }
  429. have_contacted_spooler = 1;
  430. }
  431. return;
  432. }
  433. void cleanup ()
  434. {
  435. if (have_contacted_spooler)
  436. mclose ();
  437. return;
  438. }
  439. /**
  440. ** wakeup() - TRAP ALARM
  441. **/
  442. static void wakeup ()
  443. {
  444. return;
  445. }
  446. /**
  447. ** done() - CLEANUP AND EXIT
  448. **/
  449. void done (ec)
  450. int ec;
  451. {
  452. cleanup ();
  453. exit (ec);
  454. }