|
|
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.