|
|
1.1 root 1: /******************************************************************************
2: lpstat. MLP line-printer status a'la Unix V.
3: ******************************************************************************/
4:
5: #include "header.h"
6:
7:
8: extern char curr_printer[WORKSTR];
9: extern char curr_device[WORKSTR];
10: extern char curr_backend[WORKSTR];
11:
12:
13: /******************************************************************************
14: Report the name of the system default printer
15: ******************************************************************************/
16:
17: void system_default_printer()
18: {
19: char *c;
20: c = controls( DEFAULT, "");
21:
22: printf("system default destination is: %s\n", c);
23: }
24:
25:
26:
27: /******************************************************************************
28: Report whether the scheduler is running or not
29: ******************************************************************************/
30:
31: void report_scheduler_status()
32: {
33: if ( scheduler_status())
34: printf("scheduler is running\n");
35: else
36: printf("scheduler is not running\n");
37: }
38:
39:
40:
41:
42:
43: /******************************************************************************
44: List the currently printing requests and the pending ones in Unix V style
45: ******************************************************************************/
46:
47: report_request_status()
48: {
49: int n, fd;
50: char *requests, *entries, *name, header[HEADER_SIZE], path[WORKSTR];
51: char user[20], timestr[40], printer[20];
52: long rtime;
53: struct passwd *p;
54:
55: p = getpwuid(getuid());
56:
57: requests = report_printer_status( REQUEST_DISPLAY);
58:
59: entries = dirlist( QUEUE_PATH, FALSE); /* return sorted spool queue list */
60: /* This list is a two dimensional */
61: /* array (entries x MAXNAMLEN) */
62: /* Ascending order */
63:
64: for ( n = 0; *(name = (entries+(n * MAXNAMLEN))); n++) {
65: if ( *name == 'r') break;
66:
67: if (strstr( requests, name) == NULL) {
68: sprintf( path, "%s/%s", QUEUE_PATH, name);
69:
70: if ( (fd = open( path, O_RDONLY)) != BAD) {
71: read( fd, header, HEADER_SIZE);
72: close( fd);
73:
74: strcpy( user, headerval( header, H_USER, ""));
75: unpadd( user);
76:
77: if ( (p && !strcmp( user, p->pw_name)) || (getuid(0) == 0)) {
78: strcpy( printer, headerval( header, H_PRINTER, ""));
79: unpadd( printer);
80:
81: strcpy( timestr, headerval( header, H_DSTAMP, ""));
82: rtime = 0L; sscanf( timestr, "%ld", &rtime);
83: strcpy( timestr, ctime(&rtime));
84: timestr[strlen(timestr)-1] = 0;
85:
86: printf( "%s-%s\t\t%c\t%s", user,
87: (name+2), *(name+1), timestr);
88:
89: printf( "\tfor %s\n", printer);
90: }
91: }
92: }
93: }
94:
95: free( entries);
96: }
97:
98:
99:
100:
101:
102: /******************************************************************************
103: List the currently printing requests and the pending ones in MLP style
104: ******************************************************************************/
105:
106: report_mlp_request_status()
107: {
108: int n, fd, printing, val;
109: char *requests, *entries, *name, header[HEADER_SIZE], path[WORKSTR];
110: char user[20], printer[20], title[100], tmp[WORKSTR];
111: long rtime;
112: struct tm *tt;
113:
114: entries = dirlist( QUEUE_PATH, TRUE); /* return sorted spool queue list */
115: /* This list is a two dimensional */
116: /* array (entries x MAXNAMLEN) */
117: /* Ascending order */
118:
119: printf("REQ # S P L #Pgs FL #Cp Date Time Description...\n");
120: printf("----- - - - ---- --- --- -------- ----- -----------------------------------\n");
121:
122: for ( n = 0; *(name = (entries+(n * MAXNAMLEN))); n++) {
123: printing = FALSE;
124:
125: if (strstr( requests, name)) printing = TRUE;
126:
127: sprintf( path, "%s/%s", QUEUE_PATH, name);
128:
129: if ( (fd = open( path, O_RDONLY)) != BAD) {
130: read( fd, header, HEADER_SIZE);
131: close( fd);
132:
133: printf("%-5s ", (name+2)); /* request sequence no. */
134:
135: /* Request Status */
136:
137: if (printing)
138: printf("* "); /* printing now */
139: else
140: if (*name == 'R')
141: printf("P "); /* waiting to print */
142: else
143: if (*name == 'r')
144: printf("Q "); /* held in queue print */
145: else
146: printf("? "); /* don't know the status */
147:
148: printf("%c ", *(name+1)); /* priority */
149:
150: printf("%s ", unpadd( headerval( header, H_LONGEVITY, "")));
151:
152: val = 0;
153: sscanf( unpadd( headerval( header, H_PAGES, "")), "%d", &val);
154: printf("%4d ", val);
155:
156: val = 0;
157: sscanf( unpadd( headerval( header, H_FORMLEN, "")), "%d", &val);
158: printf("%3d ", val);
159:
160: val = 0;
161: sscanf( unpadd( headerval( header, H_COPIES, "")), "%d", &val);
162: printf("%3d ", val);
163:
164:
165: sscanf( unpadd( headerval( header, H_DSTAMP, "")), "%ld", &rtime);
166:
167: tt = localtime( &rtime);
168:
169: printf( "%02d/%02d/%02d ", (tt->tm_mon+1), tt->tm_mday, tt->tm_year);
170: printf( "%02d:%02d ", tt->tm_hour, tt->tm_min);
171:
172: strcpy( user, unpadd( headerval( header, H_USER, "")));
173: strcpy( printer, unpadd( headerval( header, H_PRINTER, "")));
174: strcpy( title, unpadd( headerval( header, H_DESC, "")));
175:
176: sprintf( tmp, "%s -by %s -on %s", title, user, printer);
177:
178: printf("%s\n", tmp);
179: }
180: }
181: }
182:
183:
184:
185:
186: /******************************************************************************
187: Print a list of printers available for routine.
188: ******************************************************************************/
189:
190: list_printers( user)
191: char *user;
192: {
193: char *list;
194:
195: printf("%s ( ", route_request( user));
196:
197: each_printer( E_START);
198:
199: while (*(list = each_printer( E_NEXT)))
200: printf( "%s ", strtok( list, SEP));
201:
202: each_printer( E_END);
203:
204: printf("system display local )\n");
205: }
206:
207:
208:
209:
210:
211:
212: /******************************************************************************
213: Set the printer that the user wants to route to.
214: ******************************************************************************/
215:
216: set_route( user, printer)
217: char *user;
218: char *printer;
219: {
220: FILE *fp;
221: int inlist;
222: char *list, path[WORKSTR];
223:
224: each_printer( E_START);
225:
226: inlist = FALSE;
227:
228: while (*(list = each_printer( E_NEXT)))
229: if (!strcmp( strtok( list, SEP), printer)) inlist = TRUE;
230:
231: each_printer( E_END);
232:
233: if (!strcmp( "local", printer)) inlist = TRUE;
234: if (!strcmp( "display", printer)) inlist = TRUE;
235: if (!strcmp( "system", printer)) inlist = TRUE;
236:
237: if (!inlist) {
238: printf("\007\"%s\" is not a defined printer.\n", printer);
239: return;
240: }
241:
242: sprintf( path, "%s/%s", ROUTE_PATH, user);
243:
244: if ( fp = fopen( path, "w+")) {
245: fprintf( fp, "%s\n", printer);
246: fclose( fp);
247: printf( "%s, your requests will now spool to the \"%s\" printer.\n",
248: user, printer);
249: }
250: }
251:
252:
253:
254:
255: /******************************************************************************
256: Reprioritize the requests
257: ******************************************************************************/
258:
259: void reprioritize_requests( argc, argv)
260: int argc;
261: char *argv[];
262: {
263: int n, m, reqnum, filenum, fd;
264: char *t, *name, prior, oldnam[WORKSTR], newnam[WORKSTR], *head, auser[30];
265: struct passwd *p;
266:
267: p = getpwuid(getuid());
268:
269: prior = argv[1][2];
270:
271: if ( prior < '0') prior = '0';
272: if ( prior > '9') prior = '9';
273:
274:
275: MLP_lock( L_CANCEL);
276:
277: /* Not sure why I want to do this? */
278: /* kill_printing_request( 0, R_CANCEL, CLEAR_ALL); */
279:
280: t = dirlist( QUEUE_PATH, FALSE); /* return sorted spool queue list */
281: /* This list is a two dimensional */
282: /* (entries x MAXNAMLEN) */
283: /* Ascending order */
284:
285: head = (char *) calloc( HEADER_SIZE, 1);
286:
287: for (n = 0; *(name = (t+(n * MAXNAMLEN))); n++) {
288:
289: if (sscanf( &name[2], "%d", &filenum) == 1) {
290:
291: for (m = 2; m <= argc; m++) {
292: if (sscanf( argv[m], "%d", &reqnum) == 1) {
293: if ( filenum == reqnum) {
294: sprintf( oldnam, "%s/%s", QUEUE_PATH, name);
295:
296: if ( (fd = open( oldnam, O_RDONLY)) != BAD) {
297: read( fd, head, HEADER_SIZE);
298: close( fd);
299:
300: strcpy( auser, headerval( head, H_USER, ""));
301: unpadd( auser);
302:
303: if (p && !strcmp( auser, p->pw_name) ||
304: (getuid() == 0)) {
305:
306: name[1] = prior;
307: sprintf( newnam, "%s/%s", QUEUE_PATH, name);
308: rename( oldnam, newnam);
309:
310: if ( *name == 'R') {
311: /* make_inactive( name); */
312: kill_printing_request( reqnum, R_CANCEL, CLEAR_ONE);
313: warning( "Request #%d aborted due to a change in priority",
314: reqnum);
315: }
316: }
317: }
318: }
319: }
320: }
321: }
322: }
323:
324: free( head);
325:
326: MLP_unlock( L_CANCEL);
327:
328: free( t);
329: }
330:
331:
332:
333:
334:
335:
336: /******************************************************************************
337: Change the longevity or the printer
338: ******************************************************************************/
339:
340: void adjust_requests( argc, argv, flag)
341: int argc;
342: char *argv[];
343: int flag;
344: {
345: int n, m, reqnum, filenum, fd;
346: char *t, *name, nam[WORKSTR], oper[20], head[HEADER_SIZE], auser[30];
347: struct passwd *p;
348:
349: p = getpwuid(getuid());
350:
351: strcpy( oper, &argv[1][2]);
352:
353: if (flag == A_LIFETIME) {
354: oper[1] = 0;
355: switch (*oper) {
356: case 't':
357: case 'T': *oper = 'T'; break;
358: case 'l':
359: case 'L': *oper = 'L'; break;
360: case 's':
361: case 'S':
362: default: *oper = 'S'; break;
363: }
364: }
365:
366: MLP_lock( L_CANCEL);
367:
368: /* Not sure why I want to do this? */
369: /* kill_printing_request( 0, R_CANCEL, CLEAR_ALL); */
370:
371: t = dirlist( QUEUE_PATH, FALSE); /* return sorted spool queue list */
372: /* This list is a two dimensional */
373: /* (entries x MAXNAMLEN) */
374: /* Ascending order */
375:
376: for (n = 0; *(name = (t+(n * MAXNAMLEN))); n++) {
377:
378: if (sscanf( &name[2], "%d", &filenum) == 1) {
379:
380: for (m = 2; m <= argc; m++) {
381: if (sscanf( argv[m], "%d", &reqnum) == 1) {
382:
383: if ( filenum == reqnum) {
384: sprintf( nam, "%s/%s", QUEUE_PATH, name);
385:
386: if ( fd = open( nam, O_RDWR)) {
387: read( fd, head, HEADER_SIZE);
388:
389: strcpy( auser, headerval( head, H_USER, ""));
390: unpadd( auser);
391:
392: if ((p && !strcmp( auser, p->pw_name)) ||
393: (getuid() == 0)) {
394:
395: if ( flag == A_PRINTER)
396: headerval( head, H_PRINTER, oper);
397: else
398: headerval( head, H_LONGEVITY, oper);
399:
400: lseek( fd, 0L, 0);
401:
402: write( fd, head, HEADER_SIZE);
403: close( fd);
404:
405: if ( *name == 'R' && flag == A_PRINTER) {
406: /* make_inactive( name); */
407: kill_printing_request( reqnum, R_CANCEL, CLEAR_ONE);
408:
409: warning( "Request #%d aborted because it was moved to a new printer",
410: reqnum);
411: }
412: }
413: }
414: }
415:
416:
417: }
418: }
419: }
420: }
421:
422: MLP_unlock( L_CANCEL);
423:
424: free( t);
425: }
426:
427:
428:
429:
430:
431:
432:
433: /******************************************************************************
434: Cancel all the requests in the list given. This is a critical section--we
435: cannot allow the despooler to reschedule a request that we just canceled
436: before we are able to put the request in the inactive queue. First we
437: cancel the despooling of the request, if necessary. Then we place the
438: request in the inactive part of the queue. The keyword "all" on the
439: command line will cancel all printing and pending reports.
440: ******************************************************************************/
441:
442: void cancel_all_requests()
443: {
444: int n, val;
445: char *t, *name;
446:
447: MLP_lock( L_CANCEL);
448:
449: kill_printing_request( 0, R_CANCEL, CLEAR_ALL);
450:
451: t = dirlist( QUEUE_PATH, FALSE); /* return sorted spool queue list */
452: /* This list is a two dimensional */
453: /* (entries x MAXNAMLEN) */
454: /* Ascending order */
455:
456:
457:
458:
459: for (n = 0; *(name = (t+(n * MAXNAMLEN))); n++)
460: if ( *name == 'R') {
461: if (do_i_own_it()) {
462: make_inactive( name);
463: sscanf( &name[2], "%d", &val);
464: warning("Request #%d has been canceled.", val);
465: printf("#%d canceled\n", val);
466: }
467: }
468:
469: MLP_unlock( L_CANCEL);
470:
471: free( t);
472: }
473:
474:
475:
476:
477: void cancel_requests( argc, argv)
478: int argc;
479: char *argv[];
480: {
481: int n, m, seqnum, Seqnum;
482: char *c, *d, *t, *name, *head;
483:
484: if (!strcmp( argv[1], "all")) {
485: cancel_all_requests();
486: return;
487: }
488:
489:
490: MLP_lock( L_CANCEL);
491:
492:
493: t = dirlist( QUEUE_PATH, FALSE); /* return sorted spool queue list */
494: /* This list is a two dimensional */
495: /* (entries x MAXNAMLEN) */
496: /* Ascending order */
497:
498: head = (char *) calloc( HEADER_SIZE, 1);
499:
500: for ( n = 1; n < argc; n++) {
501:
502: c = argv[n];
503:
504: if ( d = strrchr( c, '-')) c = (d+1);
505:
506: seqnum = 0; sscanf( c, "%d", &seqnum);
507:
508: if ( seqnum > 0) {
509:
510: if (!kill_printing_request( seqnum, R_CANCEL, CLEAR_ONE)) {
511:
512: for (m = 0; *(name = (t+(m * MAXNAMLEN))); m++)
513: if ( *name == 'R') {
514: sscanf( &name[2], "%d", &Seqnum);
515:
516: if ( Seqnum == seqnum) {
517:
518: if (do_i_own_it()) {
519: make_inactive( name);
520: warning("Request #%d has been canceled.", Seqnum);
521: printf("#%d canceled\n", Seqnum);
522: }
523: }
524: }
525: else
526: break;
527: }
528: }
529: }
530:
531: free( head);
532:
533: MLP_unlock( L_CANCEL);
534:
535: free( t);
536: }
537:
538:
539:
540: /*****************************************************************************
541: Print usage message.
542: *****************************************************************************/
543:
544: void do_usage()
545: {
546: printf("\nusages: lpadmin -pprinter [-vdevice] [-mmodel]\n");
547: printf(" lpadmin -ddestination\n");
548: printf(" lpadmin -xdestination\n\n");
549: printf("NOTE: This utility modifies %s\n", CONTROL_PATH);
550: printf(" Models are found in %s\n\n", BACKEND_PATH);
551: }
552:
553:
554:
555:
556: /*****************************************************************************
557: Delete the given destination from the controls file. This routine is in
558: two parts inorder to reuse some of the code.
559: *****************************************************************************/
560:
561: void _delete_destination( dest, newdest, device, backend)
562: char *dest;
563: char *newdest;
564: char *device;
565: char *backend;
566: {
567: FILE *fp, *newfp;
568: char line[128], *t, tmppath[WORKSTR], tmp[WORKSTR];
569:
570: fp = (FILE *) each_printer( E_FILE);
571:
572: sprintf( tmppath, "%s.tmp", CONTROL_PATH);
573:
574: if ( newfp = fopen( tmppath, "w")) {
575:
576: while (fgets( line, sizeof(line), fp)) {
577: strcpy( tmp, line);
578:
579: if (t = strtok( tmp, SEP)) {
580:
581: if (!strcmp( "PRINTER", uppercase( t))) {
582: t = strtok( NULL, SEP);
583: if (strcmp( dest, t))
584: fprintf( newfp, "%s", line);
585: }
586: else
587: fprintf( newfp, "%s", line);
588: }
589: else
590: fprintf( newfp, "%s", line);
591: }
592:
593:
594: if ( *newdest)
595: fprintf( newfp, "printer = %s, %s, %s\n", newdest, device, backend);
596:
597: close( fp); close( newfp);
598:
599: rename( tmppath, CONTROL_PATH);
600:
601: chmod( CONTROL_PATH, 0664);
602: }
603: }
604:
605:
606: void delete_destination( dest)
607: char *dest;
608: {
609: each_printer( E_START);
610: _delete_destination( dest, "", "", "");
611: each_printer( E_UNLOCK);
612: log( "Remove Printer: %s", dest);
613: }
614:
615:
616:
617:
618:
619: /*****************************************************************************
620: Adds a new destination to the controls file. Any current definition by
621: the same name will be overwritten
622: *****************************************************************************/
623:
624: add_destination( printer, device, backend)
625: char *printer;
626: char *device;
627: char *backend;
628: {
629: each_printer( E_START);
630:
631: _delete_destination( printer, printer, device, backend);
632:
633: each_printer( E_UNLOCK);
634:
635: log( "Add Printer: %s, device=%s, backend=%s", printer, device, backend);
636: }
637:
638:
639:
640:
641: /*****************************************************************************
642: Change the system default destination, checking to see if the destination
643: exists first.
644: *****************************************************************************/
645:
646: change_destination( dest)
647: char *dest;
648: {
649: int ok = FALSE;
650: char *list;
651:
652: each_printer( E_START);
653:
654: while (*(list = each_printer( E_NEXT)))
655: if (!strcmp( strtok( list, SEP), dest)) ok = TRUE;
656:
657: each_printer( E_END);
658:
659: if (ok)
660: controls( DEFAULT, dest);
661: else
662: printf("\007Destination \"%s\" does not exist.\n", dest);
663:
664: log( "Change System Default to: %s", dest);
665: }
666:
667:
668:
669:
670: /*****************************************************************************
671: Parse the arguments and figure out what function to do.
672: *****************************************************************************/
673:
674: lpadmin( argc, argv)
675: int argc;
676: char *argv[];
677: {
678: int n, add, del, dest;
679: char printer[20], backend[20], device[129];
680:
681: if ( argc == 1) { do_usage(); exit(0); }
682:
683: strcpy( printer, "main");
684: strcpy( backend, "");
685: strcpy( device, "/dev/null");
686:
687: add = del = dest = FALSE;
688:
689: for ( n = 1; n < argc; n++) {
690: if (!strncmp( argv[n], "-p", 2)) {
691: strncpy( printer, &argv[n][2], sizeof( printer));
692: add = TRUE;
693: }
694: else
695: if (!strncmp( argv[n], "-x", 2)) {
696: strncpy( printer, &argv[n][2], sizeof( printer));
697: del = TRUE;
698: }
699: else
700: if (!strncmp( argv[n], "-d", 2)) {
701: strncpy( printer, &argv[n][2], sizeof( printer));
702: dest = TRUE;
703: }
704: else
705: if (!strncmp( argv[n], "-m", 2))
706: strncpy( backend, &argv[n][2], sizeof( backend));
707: else
708: if (!strncmp( argv[n], "-v", 2))
709: strncpy( device, &argv[n][2], sizeof( device));
710: }
711:
712:
713:
714:
715: if (add) { /* Add a new printer */
716: add_destination( printer, device, backend);
717: exit(0);
718: }
719:
720: if (del) { /* Delete a printer definition */
721: delete_destination( printer);
722: exit(0);
723: }
724:
725: if (dest) { /* Change the system default printer */
726: change_destination( printer);
727: exit(0);
728: }
729: }
730:
731:
732:
733:
734:
735:
736: void main( argc, argv)
737: int argc;
738: char *argv[];
739: {
740: int n;
741: extern char progname[];
742: char user[15], *c;
743:
744: umask(FPERMS);
745:
746: c = basename( argv[0]); if (c) strcpy( progname, c);
747:
748:
749: /********* If program is called "lpadmin" ***********/
750:
751: if (!strcmp( progname, "lpadmin")) {
752: if (getuid() == 0) {
753: lpadmin( argc, argv);
754: wakeup_despooler();
755: }
756: else
757: printf("\007\nSorry, you must be superuser to do this.\n\n");
758:
759: exit(0);
760: }
761:
762:
763: /********* If program is called "cancel" ***********/
764:
765: if (!strcmp( progname, "cancel")) {
766: if (argc == 1)
767: printf("\nusage: cancel request_num1 request_num2 ... request_numN\n\n");
768: else
769: cancel_requests( argc, argv);
770:
771: wakeup_despooler();
772:
773: exit(0);
774: }
775:
776:
777: /********* If program is called "chreq" ***********/
778:
779: if (!strcmp( progname, "chreq")) {
780: if (!strncmp( argv[1], "-p", 2) && argc > 2)
781: reprioritize_requests( argc, argv);
782: else
783: if (!strncmp( argv[1], "-d", 2) && argc > 2)
784: adjust_requests( argc, argv, A_PRINTER);
785: else
786: if (!strncmp( argv[1], "-l", 2) && argc > 2)
787: adjust_requests( argc, argv, A_LIFETIME);
788: else {
789: printf("\nusage: chreq -pNew_priority reqests_num1 request_");
790: printf("num2 ... request_numN\n\n");
791: printf(" -dNew_destination request_num1 request_");
792: printf("num2 ... request_numN\n\n");
793: printf(" -lNew_lifetime request_num1 request_");
794: printf("num2 ... request_numN\n\n");
795: }
796:
797: wakeup_despooler();
798: exit(0);
799: }
800:
801:
802:
803: /********* If program is called "route" ***********/
804:
805: if (!strcmp( progname, "route")) {
806: strcpy( user, "unknown");
807:
808: if ( getlogin())
809: strcpy( user, getlogin());
810:
811: if ( argc == 1) list_printers( user);
812: else
813: if ( argv[1] != NULL)
814: set_route( user, argv[1]);
815:
816: wakeup_despooler();
817: exit(0);
818: }
819:
820:
821: /********* If program is called "lpstat" ***********/
822: if ( argc == 1) report_request_status();
823:
824: for ( n = 1; n < argc; n++) {
825: if (!strcmp( argv[n], "-s")) { /* Summary */
826: report_scheduler_status();
827: system_default_printer();
828: report_printer_status( DEVICE_DISPLAY);
829: }
830: else
831: if (!strcmp( argv[n], "-v")) /* Devices */
832: report_printer_status( DEVICE_DISPLAY);
833: else
834: if (!strcmp( argv[n], "-t")) { /* All */
835: report_scheduler_status();
836: system_default_printer();
837: report_printer_status( DEVICE_DISPLAY);
838: report_printer_status( PRINTER_DISPLAY);
839: report_request_status();
840: }
841: else
842: if (!strcmp( argv[n], "-q")) /* MLP Queue Status */
843: report_mlp_request_status();
844: else
845: if (!strcmp( argv[n], "-r")) /* Scheduler Status */
846: report_scheduler_status();
847: else
848: if (!strcmp( argv[n], "-p")) /* Printer Status */
849: report_printer_status( PRINTER_DISPLAY);
850: else
851: if (!strcmp( argv[n], "-o")) /* Request Status */
852: report_request_status();
853: else
854: if (!strcmp( argv[n], "-d")) /* Default Destination */
855: system_default_printer();
856: }
857:
858: wakeup_despooler();
859: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.