|
|
1.1 root 1:
2: /******************************************************************************
3: lp. This is the Multiple-Line-Printer spooler interface to applications
4: and the Coherent user. Its job is to accept a print job and place it
5: into the spool queue. As part of this, a special filename is formed to
6: ensure that requests are printed in a prioritized-first-come-first-served
7: manner. The actual file is given a 192 byte header. Then the text of the
8: report is appended on the header. Much of the information stored in the
9: header is extracted from an environment variable called MLP_SPOOL. If a
10: printer is not specified, then the user name is used to derive the printer
11: name. This allows users to "route" their requests to various printers
12: on demmand.
13:
14: This program's command line interface is very similar to lp in Unix SV.
15:
16: One noteable difference: Output is ALWAYS copied into the spool directory.
17: This is to facilitate deferred de-spooling.
18:
19: Author: B.Blatchley (c) Magnetic Data Operation 1992
20: ******************************************************************************/
21:
22: #include "header.h"
23:
24: #define PRIORITY '2'
25: #define LONGEVITY 'S'
26:
27: static int input_from_stdin = FALSE;
28: static char priority = PRIORITY;
29: static char qstatus = 'R';
30: static char keep_status = LONGEVITY;
31: static int copies = 1;
32: static int mailme = FALSE;
33: static int writeme = FALSE;
34: static int silent = FALSE;
35: static char printer[15];
36: static char user[15];
37: static char title[WORKSTR];
38: static char path[WORKSTR];
39: static char message[WORKSTR];
40:
41: extern int curr_formlen;
42:
43:
44: /******************************************************************************
45: Return a new filename for the spool request.
46: ******************************************************************************/
47:
48: char *request_filename( when, priority)
49: char when;
50: char priority;
51: {
52: static char name[WORKSTR];
53: int seqnum;
54: char num[10];
55:
56: seqnum = get_seq_num();
57:
58: sprintf( name, "%c%c%05d", when, priority, seqnum);
59:
60: sprintf( num, "%d ", seqnum); strcat( message, num);
61:
62: return( name);
63: }
64:
65:
66:
67:
68: /******************************************************************************
69: Given the contents of the SPOOLER environment variable other things and
70: return a header string. This header will precede the actual printed-output.
71: ******************************************************************************/
72:
73: char *make_header()
74: {
75: static char header[ HEADER_SIZE+1];
76: char tmp[ WORKSTR], s[30];
77:
78: headerval( header, H_ENTIRE, " ");
79:
80: if ( input_from_stdin) headerval( header, H_DESC, "Standard Input");
81: if (path[0]) headerval( header, H_DESC, path);
82: if (title[0]) headerval( header, H_DESC, title);
83:
84: sprintf( s, "%03d", curr_formlen); headerval( header, H_FORMLEN, s);
85:
86: headerval( header, H_USER, user);
87: headerval( header, H_PRINTER, printer);
88:
89: if (printer[0]) headerval( header, H_PRINTER, printer);
90:
91: headerval( header, H_DSTAMP, datestamp());
92:
93: sprintf( tmp, "%02d", copies); headerval( header, H_COPIES, tmp);
94: sprintf( tmp, "%c", keep_status); headerval( header, H_LONGEVITY, tmp);
95:
96: if (mailme) headerval( header, H_MAILME, "M");
97: if (writeme) headerval( header, H_WRITEME, "W");
98:
99:
100: /* Fill from SPOOL Environment variable, if available */
101:
102: if (getenv(SPOOL_ENV)) {
103: strcpy( tmp, getenv( SPOOL_ENV));
104:
105: strncpy( s, &tmp[0], 10); headerval( header, H_TYPE, s);
106: strncpy( s, &tmp[10], 3); headerval( header, H_FORMLEN, s);
107: strncpy( s, &tmp[13], 14); headerval( header, H_DBASE, s);
108: strncpy( s, &tmp[27], 14); headerval( header, H_FORMAT, s);
109: strncpy( s, &tmp[41], 43); headerval( header, H_DESC, s);
110: }
111:
112: return( header);
113: }
114:
115:
116:
117:
118: /******************************************************************************
119: Create a spooled printout. Count the pages as they go by and
120: put this in the header for later use.
121: ******************************************************************************/
122:
123: spool_output()
124: {
125: char *qname, *header, buffer[256], tmp[WORKSTR];
126: int out, pages, n;
127:
128:
129: qname = request_filename( qstatus, priority);
130: header = make_header();
131:
132: if (!strcmp(LOCAL, printer) || !strcmp(DISPLAY, printer))
133: qname[0] = 'r';
134:
135: sprintf( buffer, "%s/%s", QUEUE_PATH, qname);
136:
137: if (( out = open( buffer, O_RDWR|O_CREAT|O_TRUNC, 0644))) {
138: write( out, header, HEADER_SIZE);
139:
140: pages = writeOut( 0, out, 0, 9999, curr_formlen, FALSE);
141:
142: sprintf( buffer, "%04d", pages); headerval( header, H_PAGES, buffer);
143:
144: lseek( out, 0L, 0); write( out, header, HEADER_SIZE);
145:
146: if (!strcmp(LOCAL, printer)) {
147: silent = TRUE;
148:
149: for ( n = 0; n < copies; n++)
150: local_print( out, 0, 0);
151: }
152:
153: close( out);
154:
155: if (!strcmp(DISPLAY, printer)) {
156: silent = TRUE;
157:
158: sprintf( tmp, "review %s/%s %d -mlp; clear", QUEUE_PATH, qname, curr_formlen);
159: system(tmp);
160: }
161: }
162: else
163: fatal("Cannot write request \"%s\" into the spool queue: %s", qname,
164: QUEUE_PATH);
165: }
166:
167:
168:
169:
170:
171: /******************************************************************************
172: Reprint a request that has already been spooled.
173: ******************************************************************************/
174:
175: reprint_request( seqnum, start, end)
176: int seqnum;
177: int start;
178: int end;
179: {
180: char *qname, *header, path[WORKSTR], tmp[WORKSTR], request[20];
181: int out, n;
182:
183: if ( start > end) {
184: n = end; end = start; start = n;
185: }
186:
187: if ( start > 0 && end == 0) end = 9999;
188:
189: sprintf( tmp, "%05d", seqnum);
190: strcpy( request, request_name( tmp));
191:
192: if (*request == 0) {
193: warning("Cannot open request #%05d to despool.", seqnum);
194: silent = TRUE;
195: return;
196: }
197:
198: if (!strcmp(LOCAL, printer)) {
199: silent = TRUE;
200: sprintf( path, "%s/%s", QUEUE_PATH, request);
201:
202: if ( (out = open( path, O_RDWR)) != BAD) {
203: lseek( out, (long) HEADER_SIZE, 0);
204:
205: for ( n = 0; n < copies; n++)
206: local_print( out, start, end);
207:
208: close( out);
209: }
210: }
211: if (!strcmp(DISPLAY, printer)) {
212: silent = TRUE;
213: sprintf( path, "review %s/%s %d -mlp; clear", QUEUE_PATH, request, curr_formlen);
214: system( path);
215: }
216: else {
217: qname = request_filename( qstatus, priority);
218: header = make_header();
219:
220: sprintf( path, "%s/%s", QUEUE_PATH, qname);
221:
222: if (( out = open( path, O_RDWR|O_CREAT|O_TRUNC, 0644))) {
223:
224: sprintf( tmp, "Reprint #%05u from page %04u to %04u",
225: seqnum, start, end);
226:
227: headerval( header, H_DESC, tmp);
228:
229: headerval( header, H_LONGEVITY, "R");
230:
231: write( out, header, HEADER_SIZE);
232:
233: close( out);
234: }
235: else
236: fatal("Cannot write request \"%s\" into the spool queue: %s", qname,
237: QUEUE_PATH);
238: }
239: }
240:
241:
242:
243: /****************************************************************************
244: Echo user's command
245: ****************************************************************************/
246:
247: void echo_command()
248: {
249: char *t, *u;
250:
251: if (silent) return;
252:
253: if (message[0]) {
254: t = strtok( message, " "); u = strtok( NULL, " ");
255:
256: if (u != NULL)
257: fprintf( stderr, "(MLP Spooled Requests: %s, %s", t, u);
258: else
259: fprintf( stderr, "(MLP Spooled Request: %s", t);
260:
261: while (t = strtok( NULL, " "))
262: fprintf( stderr, ", %s", t);
263: }
264:
265: fprintf( stderr, ")\n");
266: }
267:
268:
269:
270:
271: /******************************************************************************
272: Ask the despooler to shutdown. Remove the despooler's PID from the status
273: file. Then wakeup the despooler (which will read the newly changed status
274: file). When the despooler sees its PID removed, it will terminate.
275: ******************************************************************************/
276:
277: shutdown_despooler()
278: {
279: int pid;
280: char *value;
281:
282: if (getuid() == 0) {
283: value = status( DESPOOLER, ""); sscanf( value, "%d", &pid);
284:
285: status( DESPOOLER, " ");
286:
287: if ( pid > 0) kill( pid, SIGALRM);
288:
289: printf("MLP Despooler Shutdown.\n");
290: wakeup_despooler();
291: }
292: else
293: printf("\007\nSorry, you must be superuser to do this.\n\n");
294: }
295:
296:
297:
298:
299: /******************************************************************************
300: Find printer name "unknown" is assumed to be undefined in the route
301: directory--therefore the printer for unknown users will be the system
302: default. HOWEVER, if the route file "unknown" is filled with the name of
303: a printer, then these request will go to the this printer instead. Kind
304: of a freebe feature! Get the user's login name too.
305: ******************************************************************************/
306:
307: char *get_printer_and_user_name()
308: {
309: strcpy( user, "unknown");
310: strcpy( printer, "unknown");
311:
312: if ( getlogin())
313: strcpy( user, getlogin());
314:
315: strcpy( printer, route_request( user));
316:
317: if (!strcmp( SYSTEM, printer))
318: strcpy( printer, controls(DEFAULT,""));
319: }
320:
321:
322:
323:
324: /******************************************************************************
325: Check for environmental overides for the priority, form length and copies.
326: ******************************************************************************/
327:
328: char *get_environment()
329: {
330: char tmp[WORKSTR];
331: int tmpv;
332:
333: if (getenv(PRIORITY_ENV)) {
334: strcpy( tmp, getenv( PRIORITY_ENV)); tmp[1] = 0;
335:
336: if (*tmp < '0') *tmp = '0';
337: if (*tmp > '9') *tmp = '9';
338:
339: priority = *tmp;
340: }
341:
342: if (getenv(LONGEVITY_ENV)) {
343: strcpy( tmp, getenv( LONGEVITY_ENV)); tmp[1] = 0;
344:
345: switch (*tmp) {
346: case 'l':
347: case 'L': keep_status = 'L'; break;
348: case 't':
349: case 'T': keep_status = 'T'; break;
350: case 's':
351: case 'S':
352: default: keep_status = 'S';
353: }
354: }
355:
356:
357: curr_formlen = 66;
358:
359: if (getenv(FORMLEN_ENV))
360: if ( sscanf( getenv( FORMLEN_ENV), "%d", &tmpv))
361: curr_formlen = tmpv;
362:
363:
364: if (getenv(COPIES_ENV)) {
365: copies = 66;
366:
367: if ( sscanf( getenv( COPIES_ENV), "%d", &tmpv))
368: copies = tmpv;
369: }
370: }
371:
372:
373:
374:
375:
376: /******************************************************************************
377: Main Driver. Parse the arguments and spool each report named (otherwise
378: spool the contents of standard input). Then send the despooler a wakup
379: call.
380:
381: NOTE: This program does DIFFERENT things depending on what it is called.
382: 1) as "lp" it does lp kinds of things.
383: 2) as "lpshut" it shuts down the despooler.
384: 3) as "reprint" it reprints spooled requests
385: ******************************************************************************/
386:
387: void main( argc, argv)
388: int argc;
389: char *argv[];
390: {
391: extern char *optarg;
392: extern int optind;
393: extern char *progname;
394: char o;
395: int file, reprint, seqnum, start, end;
396:
397: reprint = FALSE;
398:
399: umask(FPERMS);
400:
401: progname = basename( argv[0]);
402:
403: get_printer_and_user_name();
404:
405:
406:
407: /******** As the lpshut command *************/
408:
409: if (!strcmp( progname, "lpshut")) {
410: shutdown_despooler();
411:
412: log("Shutdown Scheduler Daemon");
413:
414: /* cancel the currently running backend processes */
415:
416: if (argv[1] == NULL)
417: kill_printing_request( 0, R_KILL, CLEAR_ALL);
418: else
419: if (strcmp( argv[1], "-d"))
420: kill_printing_request( 0, R_KILL, CLEAR_ALL);
421:
422: exit(0);
423: }
424:
425:
426: /******** As the reprint command *************/
427:
428: if (!strcmp( progname, "reprint")) {
429: if ( argc == 1)
430: printf( "\nusage: reprint request_num [start_page] [end_page]\n\n");
431: else {
432: get_environment();
433:
434: seqnum = 0; sscanf( argv[1], "%d", &seqnum);
435: start = 0; sscanf( argv[2], "%d", &start);
436: end = 0; sscanf( argv[3], "%d", &end);
437:
438: reprint_request( seqnum, start, end);
439: wakeup_despooler();
440: }
441: exit(0);
442: }
443:
444:
445: /******** As the lp command *************/
446:
447: while ( (o = getopt( argc, argv, "bd:mn:t:wsSR")) != EOF) {
448: switch (o) {
449: case 'd': strncpy( printer, optarg, sizeof( printer)); break;
450: case 't': strncpy( title, optarg, sizeof( title)); break;
451: case 'n': sscanf( optarg, "%d", &copies); break;
452: case 'm': mailme = TRUE; break;
453: case 's': silent = TRUE; break;
454: case 'w': writeme = TRUE; break;
455: case 'R': reprint = TRUE; break;
456:
457: case 'S': shutdown_despooler(); exit(0);
458: }
459: }
460:
461: get_environment();
462:
463: if ( reprint) {
464: seqnum = 0; sscanf( argv[optind], "%d", &seqnum);
465: start = 0; sscanf( argv[optind+1], "%d", &start);
466: end = 0; sscanf( argv[optind+2], "%d", &end);
467:
468: reprint_request( seqnum, start, end);
469: }
470: else {
471: if ( optind < argc) {
472: while (optind < argc) {
473:
474: if (strcmp( argv[optind], "-"))
475: if ( ( file = open( argv[optind], O_RDONLY))) {
476: dup2( file, 0);
477: strncpy( path, argv[optind], strlen( argv[optind]));
478: spool_output();
479: }
480:
481: optind++;
482: }
483: }
484: else {
485: input_from_stdin = TRUE;
486: spool_output();
487: }
488: }
489:
490: echo_command();
491:
492: wakeup_despooler();
493: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.