Annotation of coherent/g/usr/bin/mlp/lpsched.c, revision 1.1

1.1     ! root        1: /*****************************************************************************
        !             2:    MLP-Spool.  Search the print queue (/usr/spool/mlp/queue) for reports
        !             3:    to
        !             4:    print.  When necesarry, spawn processes to print these reports on the
        !             5:    proper printers observing the needs of concurent printing processes.
        !             6: 
        !             7:    Author: B.Blatchley (c) 1992 Magnetic Data Operation
        !             8: *****************************************************************************/
        !             9: 
        !            10: #include "header.h"
        !            11: #include <sys/param.h>
        !            12: #include <sys/stat.h>
        !            13: 
        !            14: #define SLEEPY 30
        !            15: 
        !            16: extern char curr_printer[WORKSTR];
        !            17: extern char curr_device[WORKSTR];
        !            18: extern char curr_backend[WORKSTR];
        !            19: extern char curr_desc[WORKSTR];
        !            20: extern char curr_user[20];
        !            21: extern char curr_name[20];
        !            22: extern char curr_longevity[2];
        !            23: extern int  curr_writeme;
        !            24: extern int  curr_mailme;
        !            25: extern int  curr_copies;
        !            26: extern int  curr_copy;
        !            27: extern int  curr_formlen;
        !            28: extern int  abort_write;
        !            29: extern int  kill_request;
        !            30: 
        !            31: int our_child;
        !            32: int pip[2];       /* backend pipe, global so cancel can close it */
        !            33: 
        !            34: 
        !            35: /*****************************************************************************
        !            36:   There are times when this program will sleep, while waiting for new things
        !            37:   to do.  This process is called when the program receives a "wakeup" signal
        !            38:   from another process (or from its internal alarm-clock).
        !            39: *****************************************************************************/
        !            40: 
        !            41: void wakeup()
        !            42: {
        !            43:    signal( SIGALRM, wakeup);
        !            44: }
        !            45: 
        !            46: 
        !            47: 
        !            48: 
        !            49: /*****************************************************************************
        !            50:    Kill the backend process without placing the request on hold
        !            51: *****************************************************************************/
        !            52: 
        !            53: void request_kill()
        !            54: {
        !            55:    abort_write = TRUE;
        !            56:    kill_request = TRUE;
        !            57:    signal( R_KILL, request_kill);
        !            58: }
        !            59: 
        !            60: 
        !            61: 
        !            62: /*****************************************************************************
        !            63:   Kill the backend process but keep the request current (will reprint when
        !            64:   the despooler scans the the queue).
        !            65: *****************************************************************************/
        !            66: 
        !            67: void request_cancel()
        !            68: {
        !            69:    abort_write = TRUE;
        !            70:    kill_request = FALSE;
        !            71:    signal( R_CANCEL, request_cancel);
        !            72: }
        !            73: 
        !            74: 
        !            75: 
        !            76: 
        !            77: /*****************************************************************************
        !            78:   Extract Header Values
        !            79: *****************************************************************************/
        !            80: 
        !            81: int extract_header( name)
        !            82: char *name;
        !            83: {
        !            84:    int  fd;
        !            85:    char path[WORKSTR], header[HEADER_SIZE], *t;
        !            86: 
        !            87:    sprintf( path, "%s/%s", QUEUE_PATH, name);
        !            88: 
        !            89:    if ( (fd = open( path, O_RDONLY)) != BAD) {
        !            90: 
        !            91:       read( fd, header, HEADER_SIZE);  close( fd); 
        !            92: 
        !            93:       strcpy( curr_name, name);
        !            94: 
        !            95:       t = headerval( header, H_USER, "");
        !            96:          strcpy( curr_user,    unpadd( t));
        !            97: 
        !            98:       t = headerval( header, H_PRINTER, ""); 
        !            99:          strcpy( curr_printer, unpadd( t));
        !           100: 
        !           101:       t = headerval( header, H_DESC, ""); 
        !           102:          strcpy( curr_desc,    unpadd( t));
        !           103: 
        !           104:       t = headerval( header, H_LONGEVITY, ""); 
        !           105:          strncpy( curr_longevity,  unpadd( t), 1);
        !           106: 
        !           107:       curr_mailme = FALSE; 
        !           108:       if ( *(headerval( header, H_MAILME, "")) != ' ')
        !           109:          curr_mailme = TRUE;
        !           110: 
        !           111:       curr_writeme = FALSE; 
        !           112:       if ( *(headerval( header, H_WRITEME, "")) != ' ')
        !           113:          curr_writeme = TRUE;
        !           114: 
        !           115:       sscanf( headerval( header, H_COPIES,  ""), "%d", &curr_copies);
        !           116: 
        !           117:       sscanf( headerval( header, H_FORMLEN, ""), "%d", &curr_formlen);
        !           118: 
        !           119:       return(1);
        !           120:    }
        !           121:    else
        !           122:       return(0);
        !           123: }
        !           124: 
        !           125: 
        !           126: 
        !           127: /*****************************************************************************
        !           128:    Return TRUE if the device specified in this request is available
        !           129: *****************************************************************************/
        !           130: 
        !           131: int device_available( name)
        !           132: char *name;
        !           133: {
        !           134:    int   id;
        !           135:    char *t, *c;
        !           136: 
        !           137:    if ( extract_header()) {
        !           138:       printer_device( curr_printer);
        !           139: 
        !           140:       if (!strcmp( curr_device, "")) {  /* No device? */
        !           141:          t = calloc(1000,1);
        !           142: 
        !           143:          scatf( t, "Printer \"%s\" has no device associated ", curr_printer);
        !           144:          scatf( t, "with it.\n\nRequest #%s has been suspended.  ", &name[2]);
        !           145:          scatf( t, "One way to resolve the problem\nwould be to define the ");
        !           146:          scatf( t, "printer in %s.  Another\nwould be to move ", CONTROL_PATH);
        !           147:          scatf( t, "the request to a different printer.\n\n");
        !           148:          scatf( t, "You may need to ask MLP to reprint the request.");
        !           149: 
        !           150:          warning( curr_user, t);
        !           151:          free( t);
        !           152: 
        !           153:          /* Put the request into the inactive queue */
        !           154: 
        !           155:          make_inactive( name);
        !           156: 
        !           157:          return(0);
        !           158:       }
        !           159: 
        !           160:       /* find out if the device is being used */
        !           161: 
        !           162:       if (*(t = status( curr_device, ""))) {
        !           163:          /* Who is using the device? */
        !           164: 
        !           165:          c = strtok( t, SEP);  sscanf( c, "%d", &id); 
        !           166: 
        !           167:          if (!kill( id, 0)) return(0);  /* process is still active */
        !           168:       }
        !           169: 
        !           170:       return(1);
        !           171:    }
        !           172: 
        !           173:    return(0);
        !           174: }
        !           175: 
        !           176: 
        !           177: 
        !           178: 
        !           179: /*****************************************************************************
        !           180:    Write Request.  Setup a pipeline and spawn a backend process to handle
        !           181:    the writing of the request.  We do this so that we can monitor to progress
        !           182:    of the request.
        !           183: *****************************************************************************/
        !           184: 
        !           185: write_request( name, backend, start, end)
        !           186: char *name;
        !           187: char *backend;
        !           188: int   start;
        !           189: int   end;
        !           190: {
        !           191:    int  source, sink, feed = FALSE, copy, docopies, tmpv;
        !           192:    char path[WORKSTR], tmp[WORKSTR], copies[10], *t, *u;
        !           193: 
        !           194:    signal( R_KILL,   request_kill);
        !           195:    signal( R_CANCEL, request_cancel);
        !           196: 
        !           197:    /* Open the print request and the device (data source & sink) */ 
        !           198: 
        !           199:    sprintf( path, "%s/%s", QUEUE_PATH, name);
        !           200: 
        !           201:    if ( ( source = open( path, O_RDONLY)) == BAD) {
        !           202:       warning_user(curr_user, "Cannot open request file: %s for request %s", path, &name[2]);
        !           203:       make_inactive( name);
        !           204:       return;
        !           205:    }
        !           206: 
        !           207:    if ( ( sink = open( curr_device, O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0644)) == BAD) {
        !           208:       warning_user(curr_user, "Cannot open device %s for request %s", curr_device, &name[2]);
        !           209:       make_inactive( name);
        !           210:       return;
        !           211:    }
        !           212: 
        !           213:    if( pipe( pip) == BAD) {
        !           214:       warning_user(curr_user, "Cannot create pipe to despool #%s", &name[2]);
        !           215:       make_inactive( name);
        !           216:       return;
        !           217:    }
        !           218: 
        !           219:    switch (fork()) {
        !           220:    case BAD: warning_user(curr_user, "Cannot fork to despool #%s", &name[2]);
        !           221:              close( source); close( sink); close( pip[0]); close( pip[1]);
        !           222:              make_inactive( name);
        !           223:              return;
        !           224: 
        !           225:    case   0: exit(0);
        !           226: 
        !           227:    default: setpgrp();  /* cut us loose from any control terminals! */
        !           228: 
        !           229:       /* The parent feeds the child, will noting the progress of the feeding
        !           230:          in the status file -- Inquiring Minds want to know! */
        !           231: 
        !           232:       switch ( our_child = fork()) {
        !           233:       case BAD: warning_user(curr_user, "Cannot fork to despool #%s", &name[2]); 
        !           234:                 close( source); close( sink); close( pip[0]); close( pip[1]);
        !           235:                 return;
        !           236: 
        !           237:       case   0: close( source); close( pip[1]); dup2( pip[0], 0); dup2( sink, 1);
        !           238: 
        !           239:                 signal( SIGTERM, SIG_IGN);
        !           240:                 signal( SIGINT,  SIG_IGN);
        !           241: 
        !           242: 
        !           243:                 sprintf( copies, "%d", curr_copies);
        !           244: 
        !           245:                 if (!strcmp( backend, DBACKEND))
        !           246:                    execl( backend, backend, NULL);
        !           247:                 else
        !           248:                 execl( "/bin/sh", "/bin/sh", backend, &name[2], curr_user,
        !           249:                    copies, NULL);
        !           250:       }
        !           251: 
        !           252: 
        !           253:       /* Parent feeds the child... */
        !           254: 
        !           255:       close( pip[0]); signal( SIGCLD, SIG_IGN);
        !           256: 
        !           257:    
        !           258:       t = controls( FEED, ""); 
        !           259:       if (!strcmp( t, "ON") || !strcmp( t, "on")) feed = TRUE;
        !           260: 
        !           261:       docopies = 1;
        !           262:       t = controls( DOCOPIES, "");
        !           263:       if (!strcmp( t, "ON") || !strcmp( t, "on")) docopies = curr_copies;
        !           264: 
        !           265: 
        !           266:       for ( copy = 0; copy < docopies; copy++) {
        !           267:          curr_copy = copy + 1;
        !           268: 
        !           269:          lseek( source, (long) HEADER_SIZE, 0);
        !           270: 
        !           271:          if (writeOut( source, pip[1], start, end, curr_formlen, TRUE) == BAD) {
        !           272:             
        !           273:             sscanf( &name[2], "%d", &tmpv);
        !           274: 
        !           275:             if ( kill_request) {
        !           276:                sprintf( tmp, "\n\n*** Request #%d Terminated ***\n\f", tmpv);
        !           277:                warning_user(curr_user, "The despooling of request #%d has been aborted.", tmpv);
        !           278:             }
        !           279:             else {
        !           280:                sprintf( tmp, "\n\n*** Request #%d Canceled ***\n\f", tmpv);
        !           281:                warning_user(curr_user, "Request #%d has been canceled.", tmpv);
        !           282:             }
        !           283:                
        !           284:             write( pip[1], tmp, strlen(tmp));
        !           285:             break;
        !           286:          }
        !           287: 
        !           288:          if ( feed) { *tmp = '\f'; write( pip[1], tmp, 1); }
        !           289:       }
        !           290: 
        !           291: 
        !           292:       close( source); close( pip[1]); close( sink);
        !           293:  
        !           294: 
        !           295:       /* If the request was aborted, keep it in the active
        !           296:          part of the queue.  Otherwise, retire it to the
        !           297:          inactive queue.  If the request is a reprint
        !           298:          then remove it from the queue. */
        !           299: 
        !           300:       if (!kill_request)
        !           301:            make_inactive( name);
        !           302: 
        !           303:       wait();
        !           304: 
        !           305: 
        !           306:       /* Send Messages if necessary */
        !           307: 
        !           308:       if (curr_writeme || curr_mailme) {
        !           309:          t = calloc(512,1);
        !           310:          u = calloc(512,1);
        !           311: 
        !           312:          strcpy( t, "echo \"\n`date`\n\"'\n*** MLP Spooler Reports");
        !           313:          strcat( t, " ***\n\nYour request, \"");
        !           314:          strcat( t, curr_desc);
        !           315:          strcat( t, ",\" ");
        !           316: 
        !           317:          if (strlen( curr_desc) > 15)
        !           318:             strcat( t, "\n");
        !           319: 
        !           320:          sprintf( tmp, "has been despooled on printer: %s", curr_printer);
        !           321:          strcat( t, tmp);
        !           322: 
        !           323:          if (curr_writeme) {
        !           324:             sprintf( u, "%s\n\n'| write %s >/dev/null", t, curr_user);
        !           325:             system( u);
        !           326:          }
        !           327: 
        !           328:          if ( curr_mailme) {
        !           329:             if (getenv("MLPLMAIL"))
        !           330:                sprintf( u, "%s\n\n'| lmail %s 2>/dev/null", t, curr_user);
        !           331:             else
        !           332:                sprintf( u, "%s\n\n'| mail %s 2>/dev/null", t, curr_user);
        !           333: 
        !           334:             system( u);
        !           335:          }
        !           336: 
        !           337:          free( t); free( u);
        !           338:       }
        !           339:    } 
        !           340: 
        !           341:    close( pip[0]);  close( pip[1]);          
        !           342: }
        !           343: 
        !           344: 
        !           345: 
        !           346: 
        !           347: /*****************************************************************************
        !           348:    De-spool a given file.
        !           349: *****************************************************************************/
        !           350: 
        !           351: despool_file( name, start, end)
        !           352: char *name;
        !           353: int   start;
        !           354: int   end;
        !           355: {
        !           356:    char path[WORKSTR], tmp[512], newname[20];
        !           357:    int  backend, r_copies;
        !           358: 
        !           359:    if ( *curr_longevity == 'R') { /* Is this a reprint? */
        !           360: 
        !           361:       /* sample description: "Reprint #00000 from page 0000 to page 0000"
        !           362:                                     10-|            26-|         34-|     */
        !           363: 
        !           364:       sscanf( &curr_desc[9], "%5s", tmp);
        !           365:       strcpy( newname, request_name( tmp));
        !           366: 
        !           367:       sscanf( &curr_desc[26], "%d", &start);  
        !           368:       sscanf( &curr_desc[34], "%d", &end);  
        !           369: 
        !           370:       sprintf( tmp, "%s/%s", QUEUE_PATH, name);
        !           371:       unlink( tmp);
        !           372: 
        !           373:       r_copies = curr_copies;  strcpy( tmp, curr_printer);
        !           374:       extract_header( newname);
        !           375:       curr_copies = r_copies;  strcpy( curr_printer, tmp);
        !           376:    }
        !           377:    else
        !           378:       strcpy( newname, name);
        !           379: 
        !           380: 
        !           381:    if (*curr_backend == 0) strcpy( curr_backend, DEFAULT);
        !           382: 
        !           383:    sprintf( path, "%s/%s", BACKEND_PATH, curr_backend);
        !           384: 
        !           385:    if ( (backend = open( path, O_RDONLY)) == BAD) {
        !           386:       sprintf( tmp, "Cannot find backend script (%s) for ", curr_backend);
        !           387:       scatf(   tmp, "the %s printer\nwhile trying to ", curr_printer);
        !           388:       scatf(   tmp, "despool request #%s\n\n", &newname[2]);
        !           389:       scatf(   tmp, "Despooling done with %s.\n", DBACKEND);
        !           390:       warning( tmp);
        !           391:       write_request( newname, DBACKEND, start, end);
        !           392:    }
        !           393:    else
        !           394:       write_request( newname, path, start, end);
        !           395: 
        !           396: 
        !           397:    log( "Despooled Request #%s", &name[2]);
        !           398: }
        !           399: 
        !           400: 
        !           401: 
        !           402: /*****************************************************************************
        !           403:    De-spool.   Check the queue for work, then process it.
        !           404: *****************************************************************************/
        !           405: 
        !           406: void despool()
        !           407: {
        !           408:    char *name, *t, *plist, tmp[WORKSTR];
        !           409:    int      n = 0, parent;
        !           410: 
        !           411: 
        !           412:    parent = getpid();
        !           413: 
        !           414:    plist = calloc(1024,1);    /* contains a list of printer in use during
        !           415:                                  this pass over the spool queue */
        !           416: 
        !           417:    t = dirlist( QUEUE_PATH, FALSE);  /* return sorted spool queue list */
        !           418:                                      /* This list is a two dimensional array */
        !           419:                                      /* (entries x MAXNAMLEN) */
        !           420:                                      /* Ascending order */
        !           421: 
        !           422:    while ( *(name = (t+(n * MAXNAMLEN)))) {
        !           423: 
        !           424:       if ( name[0] == 'R') {               /* despool the "ready" entries */
        !           425:          if ( device_available( name)) {
        !           426:             sprintf( tmp, "%s|", curr_device);
        !           427: 
        !           428:             if (!strstr( plist, tmp)) {
        !           429:                strcat( plist, tmp);
        !           430: 
        !           431:                switch (fork()) {
        !           432: 
        !           433:                case -1: warning("Cannot fork backend process for reqest #%s", &name[2]);
        !           434:                         break;
        !           435: 
        !           436:                case  0: /* claim the device */
        !           437: 
        !           438:                         sprintf( tmp, "%d, %s", getpid(), name);
        !           439:                         status( curr_device, tmp);
        !           440: 
        !           441:                         despool_file( name, 0, 0);
        !           442: 
        !           443:                         /* wakeup parent to rescan for work for this device */
        !           444:                         kill( parent, SIGALRM);
        !           445: 
        !           446:                         exit(0);
        !           447:                }
        !           448: 
        !           449:                signal( SIGCLD, SIG_IGN);
        !           450:             }
        !           451:          }
        !           452:       }
        !           453: 
        !           454:       n++;
        !           455:    }
        !           456: 
        !           457:    free( plist); free( t);
        !           458: }
        !           459: 
        !           460: 
        !           461: 
        !           462: 
        !           463: 
        !           464: /******************************************************************************
        !           465:    Roll the log over after a given time so that it does not grow
        !           466:    without bounds.
        !           467: ******************************************************************************/
        !           468: 
        !           469: #define RHOURS (7.0 * 24.0)
        !           470: 
        !           471: roll_log()
        !           472: {
        !           473:    long   rollover, current;
        !           474:    struct stat *s;
        !           475:    float  rhours;
        !           476:    char   tmp[WORKSTR];
        !           477: 
        !           478:    rhours = RHOURS; sscanf( controls( TLIFE, ""), "%f", &rhours);
        !           479: 
        !           480:    rollover = (long) 3600.0 * rhours;   time( &current);
        !           481: 
        !           482:    stat( LOG_PATH, s);
        !           483: 
        !           484:    if ((s->st_ctime + rollover) < current) {
        !           485:       sprintf( tmp, "%s.o", LOG_PATH);
        !           486: 
        !           487:       unlink( tmp); rename( LOG_PATH, tmp);
        !           488: 
        !           489:       warning("Logfile moved to log.o, starting new log.", "root");
        !           490:    }
        !           491: }
        !           492: 
        !           493: 
        !           494: 
        !           495: 
        !           496: /*****************************************************************************
        !           497:    Main Driver.   Tell the spooler how to find us.  Then process the queue
        !           498:    and sleep until something exciting happens ;)  First check to see if
        !           499:    the despooler is already running.
        !           500: *****************************************************************************/
        !           501: 
        !           502: void main()
        !           503: {
        !           504:    char tmp[10];
        !           505:    int  child, cycles;
        !           506: 
        !           507:    umask(FPERMS);
        !           508: 
        !           509:    if ( scheduler_status()) {
        !           510:       printf("MLP Scheduler already started.\n");
        !           511:       exit(0)        !           512:    }
        !           513: 
        !           514:    switch (child = fork()) {
        !           515:    case -1: fatal("Scheduler becoming a daemon.  Cannot fork()");
        !           516: 
        !           517:    case 0: /* I am in the background now, and will despool requests */
        !           518: 
        !           519:            chdir("/"); /* so we can dismount any mounted filesystems */
        !           520: 
        !           521:            /* for (fd = 0; fd < NOFILE; fd++) close(fd); */
        !           522: 
        !           523:            umask(0);
        !           524: 
        !           525:            setpgrp();  /* detatch me from my parent process */
        !           526: 
        !           527:            signal( SIGCLD,  SIG_IGN);
        !           528:            signal( SIGALRM, wakeup);
        !           529: 
        !           530:            sprintf( tmp, "%d", getpid());  status( DESPOOLER, tmp); 
        !           531: 
        !           532:            cycles = 0;
        !           533: 
        !           534:            while ( *(status( DESPOOLER, ""))) {
        !           535:               MLP_lock( L_CANCEL);
        !           536: 
        !           537:               despool();
        !           538:               
        !           539:               if (cycles++ > 10) {
        !           540:                  grim_reaper(); /* purge the inactive queue */ 
        !           541:                  cycles = 0;
        !           542:               }
        !           543: 
        !           544:               MLP_unlock( L_CANCEL);
        !           545: 
        !           546:               sleep( SLEEPY);
        !           547:            }
        !           548: 
        !           549:            fatal("Scheduler daemon expired gracefully"); 
        !           550:            break;
        !           551: 
        !           552:    default: printf("MLP Scheduler Started, PID: %d\n", child);
        !           553:             log("MLP Scheduler Started, PID: %d", child);
        !           554:             break;
        !           555:    }
        !           556: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.