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

1.1     ! root        1: /******************************************************************************
        !             2:    Various routines used by the MLP spooler system.
        !             3: ******************************************************************************/
        !             4: 
        !             5: #include "header.h"
        !             6: 
        !             7: char progname[16];
        !             8: 
        !             9: static char  caparea[WORKSTR];
        !            10: static char *PS, *PN;
        !            11: 
        !            12: char curr_printer[WORKSTR];
        !            13: char curr_device[WORKSTR];
        !            14: char curr_backend[WORKSTR];
        !            15: char curr_desc[WORKSTR];
        !            16: char curr_user[20];
        !            17: char curr_name[20];
        !            18: char curr_longevity[2];
        !            19: int  curr_mailme;
        !            20: int  curr_writeme;
        !            21: int  curr_copies;
        !            22: int  curr_copy;
        !            23: int  curr_formlen;
        !            24: int  abort_write = FALSE;
        !            25: int  kill_request = FALSE;
        !            26: 
        !            27: 
        !            28: /******************************************************************************
        !            29:    Scatf works like sprintf except the target string has the newly formated
        !            30:    string appended to the end of it.  Be sure the target is big enough to 
        !            31:    hold the new string as well as its current contents.  Returns a pointer
        !            32:    to the target string.
        !            33: ******************************************************************************/
        !            34: 
        !            35: char *scatf( va_alist)
        !            36: va_dcl
        !            37: {
        !            38:     va_list  args;
        !            39:     char    *dest, *tmp;
        !            40: 
        !            41:     tmp = malloc(512);
        !            42:     va_start( args);
        !            43: 
        !            44:     dest = va_arg( args, char *);
        !            45: 
        !            46:     sprintf( tmp, "%r", args);
        !            47: 
        !            48:     strcat( dest, tmp);
        !            49: 
        !            50:     va_end( args);
        !            51:     free( tmp);
        !            52: 
        !            53:     return( dest);
        !            54: }
        !            55: 
        !            56: 
        !            57: 
        !            58: /******************************************************************************
        !            59:    fatal.  Handles fatal errors with "astonishing" grace.  It sends a formated
        !            60:    messages to root's mailbox and terminates the program.  Warning sends a 
        !            61:    formated message to the user's mailbox and returns to caller.
        !            62: ******************************************************************************/
        !            63: 
        !            64: void warning( va_alist)
        !            65: va_dcl
        !            66: {
        !            67:    va_list  args;
        !            68:    char    *i, *j, user[20];
        !            69: 
        !            70:    strcpy( user, "root");  if ( i = (char *) getlogin())  strcpy( user, i);
        !            71: 
        !            72:    i = calloc(1024,1);  j = calloc(1024,1);
        !            73: 
        !            74:    strcpy(  i, "/bin/echo \"\n`date`\n\"");
        !            75:    strcat(  i, "'\n*** Message From The MLP Spooler ***\n\n");
        !            76: 
        !            77:    va_start( args);  
        !            78:    sprintf( j, "%r", args);
        !            79:    va_end( args);
        !            80: 
        !            81:    strcat( i, j); 
        !            82: 
        !            83:    if (getenv("MLPLMAIL"))
        !            84:       strcat( i, "\n\n' | lmail ");
        !            85:    else
        !            86:       strcat( i, "\n\n' | mail ");
        !            87: 
        !            88:    strcat( i, user);
        !            89: 
        !            90:    log( "%s", j);  system( i);
        !            91: 
        !            92:    free( i);  free( j);
        !            93: }
        !            94: 
        !            95: void warning_user( va_alist)
        !            96: va_dcl
        !            97: {
        !            98:    va_list  args;
        !            99:    char    *i, *j, *user;
        !           100: 
        !           101:    i = calloc(1024,1);  j = calloc(1024,1);
        !           102: 
        !           103:    strcpy(  i, "/bin/echo \"\n`date`\n\"");
        !           104:    strcat(  i, "'\n*** Message From The MLP Spooler ***\n\n");
        !           105: 
        !           106:    va_start( args);  
        !           107:    user = va_arg( args, char *);  sprintf( j, "%r", args);
        !           108:    va_end( args);
        !           109: 
        !           110:    strcat( i, j); 
        !           111: 
        !           112:    if (getenv("MLPLMAIL"))
        !           113:       strcat( i, "\n\n' | lmail ");
        !           114:    else
        !           115:       strcat( i, "\n\n' | mail ");
        !           116: 
        !           117:    strcat( i, user);
        !           118: 
        !           119:    log( "%s", j);  system( i);
        !           120: 
        !           121:    free( i);  free( j);
        !           122: }
        !           123: 
        !           124: 
        !           125: 
        !           126: void fatal( va_alist)
        !           127: va_dcl
        !           128: {
        !           129:    va_list  args;
        !           130:    char    *i, *j;
        !           131: 
        !           132:    i = calloc(1024,1);  j = calloc(1024,1);
        !           133: 
        !           134:    strcpy(  i, "/bin/echo \"\n`date`\n\"");
        !           135:    strcat(  i, "'\n*** Message From The MLP Spooler ***\n\n");
        !           136: 
        !           137:    va_start( args);  
        !           138:    sprintf( j, "%r", args);
        !           139:    va_end( args);
        !           140: 
        !           141:    strcat( i, j); 
        !           142: 
        !           143:    if (getenv("MLPLMAIL"))
        !           144:       strcat( i, "\n\n' | lmail root");
        !           145:    else
        !           146:       strcat( i, "\n\n' | mail root");
        !           147: 
        !           148:    log( "%s", j);  system( i);
        !           149: 
        !           150:    free( i);  free( j);
        !           151:    exit(0);
        !           152: }
        !           153: 
        !           154: 
        !           155: /******************************************************************************
        !           156:    Removes the leading and trailing spaces from the given string.  First
        !           157:    scan to the end of the string. Then eat the right hand spaces.  Then
        !           158:    eat the left hand spaces.  Then copy the unpadded string back into its
        !           159:    original place.
        !           160: ******************************************************************************/
        !           161: 
        !           162: char *unpadd( str)
        !           163: char *str;
        !           164: {
        !           165:    int   len = 0;
        !           166:    char *t, *u;
        !           167: 
        !           168:    for (t = str; *t; t++) len++;    t--;
        !           169: 
        !           170:    while ( t != str && *t == ' ') { *t = 0; t--; len--;} 
        !           171: 
        !           172:    for (t = str; *t && *t == ' '; t++) len--;
        !           173: 
        !           174:    u = calloc((len+1), 1); strncpy( u, t, len); strcpy( str, u); free( u);
        !           175: 
        !           176:    return( str);
        !           177: }
        !           178: 
        !           179: 
        !           180: /******************************************************************************
        !           181:    Rename a file.
        !           182: ******************************************************************************/
        !           183: 
        !           184: int rename( old, new)
        !           185: char *old;
        !           186: char *new;
        !           187: {
        !           188:    unlink( new);
        !           189: 
        !           190:    if ( link( old, new) == BAD) return(2);
        !           191: 
        !           192:    if ( unlink( old) == BAD)    return(3);
        !           193: 
        !           194:    return(0);
        !           195: }
        !           196: 
        !           197: 
        !           198: 
        !           199: 
        !           200: 
        !           201: /*****************************************************************************
        !           202:    Put a request in the inactive queue
        !           203: *****************************************************************************/
        !           204: 
        !           205: void make_inactive( name)
        !           206: char *name;
        !           207: {
        !           208:    char newname[20], path[WORKSTR], newpath[WORKSTR];
        !           209: 
        !           210:    if (*name == 'r') return;  /* already inactive */
        !           211: 
        !           212:    strcpy( newname, name); newname[0] = 'r';
        !           213: 
        !           214:    sprintf( path,    "%s/%s", QUEUE_PATH, name);
        !           215:    sprintf( newpath, "%s/%s", QUEUE_PATH, newname);     
        !           216: 
        !           217:    rename( path, newpath);
        !           218: } 
        !           219: 
        !           220: 
        !           221: 
        !           222: 
        !           223: 
        !           224: /******************************************************************************
        !           225:    Get/Set header information
        !           226: ******************************************************************************/
        !           227: 
        !           228: char *headerval( header, opt, value)
        !           229: char *header;
        !           230: int   opt;
        !           231: char *value;
        !           232: {
        !           233:    static char s[HEADER_SIZE];
        !           234:    int         offset, length, n;
        !           235: 
        !           236:    switch (opt) {
        !           237:       case H_USER:      offset =  0; length =  14; break;
        !           238:       case H_PRINTER:   offset = 14; length =  14; break;
        !           239:       case H_TYPE:      offset = 28; length =  10; break;
        !           240:       case H_FORMLEN:   offset = 38; length =   3; break;
        !           241:       case H_PAGES:     offset = 41; length =   4; break;
        !           242:       case H_COPIES:    offset = 45; length =   2; break;
        !           243:       case H_LONGEVITY: offset = 47; length =   1; break;
        !           244:       case H_MAILME:    offset = 48; length =   1; break;
        !           245:       case H_WRITEME:   offset = 49; length =   1; break;
        !           246:       case H_DBASE:     offset = 50; length =  14; break;
        !           247:       case H_FORMAT:    offset = 64; length =  14; break;
        !           248:       case H_DSTAMP:    offset = 78; length =  10; break;
        !           249:       case H_DESC:      offset = 88; length =  60; break;
        !           250: 
        !           251:       case H_ENTIRE:    offset =  0; length = HEADER_SIZE-2; 
        !           252:                         header[HEADER_SIZE-1] = '\n';
        !           253:                         header[HEADER_SIZE] = 0;
        !           254:                         break;
        !           255:    }
        !           256: 
        !           257:    if (value[0]) {
        !           258:       for (n = 0; n < length; n++) header[offset+n] = ' ';
        !           259:       for (n = 0; value[n] && n < length; n++) header[offset+n] = value[n]; 
        !           260:    }
        !           261: 
        !           262:    strncpy( s, &header[offset], length); s[length] = 0;
        !           263: 
        !           264:    return( s);
        !           265: }
        !           266: 
        !           267: 
        !           268: 
        !           269: 
        !           270: /******************************************************************************
        !           271:    Log text messages into the log file.
        !           272: ******************************************************************************/
        !           273: 
        !           274: log( va_alist)
        !           275: va_dcl
        !           276: {
        !           277:    va_list    args;
        !           278:    FILE      *fp;
        !           279:    long       clock;
        !           280:    struct tm *tt;
        !           281:    char       message[1200];
        !           282: 
        !           283: 
        !           284:    va_start( args);  sprintf( message, "%r", args);  va_end( args); 
        !           285: 
        !           286:    MLP_lock( L_LOG);
        !           287: 
        !           288:    time( &clock); tt = localtime( &clock);
        !           289: 
        !           290:    if ( fp = fopen( LOG_PATH, "a+")) {
        !           291:       fprintf( fp, "%02d/%02d/%02d ", (tt->tm_mon+1), tt->tm_mday, tt->tm_year);
        !           292:       fprintf( fp, "%02d:%02d - ", (tt->tm_hour), tt->tm_min);
        !           293:       fprintf( fp, "%s\n", message);
        !           294:       fflush( fp);
        !           295:       close( fp);
        !           296:    }
        !           297: 
        !           298:    MLP_unlock( L_LOG);
        !           299: }
        !           300: 
        !           301: 
        !           302: 
        !           303: /******************************************************************************
        !           304:    Get Termcap Information.  If we've already filled PS then don't bother again.
        !           305: ******************************************************************************/
        !           306: 
        !           307: void get_termcap()
        !           308: {
        !           309:    extern char *tgetstr();
        !           310:    extern int   tgetent();
        !           311:    char *buff, *term, *ptr;
        !           312: 
        !           313:    if ( PS) return;
        !           314: 
        !           315:    ptr = buff = calloc( 1024, 1);
        !           316: 
        !           317:    if ( buff == NULL) fatal("Not enough memory to local print");
        !           318: 
        !           319:    if ( (term = getenv("TERM")) == NULL)
        !           320:       fatal("Trying to local print.  TERM must be defined.");
        !           321: 
        !           322:    if ( tgetent( buff, term) == BAD)
        !           323:       fatal("Trying to local print.  Cannot find %s in /etc/termcap", term);
        !           324: 
        !           325:    ptr = caparea;
        !           326: 
        !           327:    PS = tgetstr( "PS", &ptr);
        !           328:    PN = tgetstr( "PN", &ptr);
        !           329: 
        !           330:    if ( PS == NULL || PN == NULL)
        !           331:       fatal("Trying to local print.\n\nBoth PS and PN need to be defined for terminal %s in /etc/termcap", term);
        !           332: }
        !           333: 
        !           334: 
        !           335: 
        !           336: 
        !           337: 
        !           338: 
        !           339: 
        !           340: /******************************************************************************
        !           341:    Return a datestamp string (actually it is the long-int in text form)
        !           342: ******************************************************************************/
        !           343: 
        !           344: char *datestamp()
        !           345: {
        !           346:    static char stamp[11];
        !           347:    time_t      t;
        !           348: 
        !           349:    time( &t);  sprintf( stamp, "%010lu", t);
        !           350: 
        !           351:    return( stamp);
        !           352: }
        !           353: 
        !           354: 
        !           355: 
        !           356: /******************************************************************************
        !           357:    Given a string, convert it to uppercase.
        !           358: ******************************************************************************/
        !           359: 
        !           360: char *uppercase( str)
        !           361: char *str;
        !           362: {
        !           363:    char *c = str;
        !           364: 
        !           365:    while (*c) {
        !           366:       if (islower(*c)) *c = toupper(*c);
        !           367:       c++;
        !           368:    }
        !           369: 
        !           370:    return( str);
        !           371: }
        !           372: 
        !           373: 
        !           374: 
        !           375: /******************************************************************************
        !           376:   Given the name of a control-file parameter, return its value.  Lock the
        !           377:   file so we can read/write it without it changing on us.  If the value of the
        !           378:   string "newval", is non-null then assign the parameter this new new value.
        !           379: ******************************************************************************/
        !           380: 
        !           381: char *parameters( param, newval, pathname, locktype)
        !           382: char *param;
        !           383: char *newval;
        !           384: char *pathname;
        !           385: int  locktype;
        !           386: {
        !           387:    static  char value[ WORKSTR];
        !           388:    FILE   *fp, *ofp;
        !           389:    char    tmp[WORKSTR], tmp1[WORKSTR], parameter[30], *c, tmppath[WORKSTR];
        !           390: 
        !           391:    sprintf( tmppath, "%s.tmp", pathname);
        !           392: 
        !           393:    strncpy( parameter, param, sizeof( parameter));  uppercase( parameter);
        !           394: 
        !           395:    strcpy( value, "");
        !           396: 
        !           397:    MLP_lock( locktype); 
        !           398:  
        !           399:    if ( (fp = fopen( pathname, "r"))) {
        !           400: 
        !           401:       if (!strcmp( newval, "")) {
        !           402: 
        !           403:          while (!feof( fp)) {
        !           404:             fgets( tmp, sizeof( tmp), fp);
        !           405: 
        !           406:             for (c = tmp; *c && *c != '#'; c++); /* look for comment */
        !           407: 
        !           408:             if ( *tmp && !*c) {
        !           409:                c = strtok( tmp, SEP);  uppercase( c);
        !           410: 
        !           411:              
        !           412:                if ( !strcmp( c, parameter)) {
        !           413:                   c = strtok( NULL, "\n");
        !           414:                   while (*c && (*c == ' ' || *c == '\t' || *c == '=')) c++;
        !           415:                   strcpy( value, c);
        !           416:                   break;
        !           417:                }
        !           418:             }
        !           419:          }
        !           420:          fclose( fp);
        !           421:       }
        !           422:       else { 
        !           423:          if ( (ofp = fopen( tmppath, "w"))) {
        !           424: 
        !           425:             while (!feof( fp)) {
        !           426:                fgets( tmp, sizeof( tmp), fp);  strcpy( tmp1, tmp);
        !           427: 
        !           428:                if ( *tmp && *tmp != '#') {
        !           429:                   c = strtok( tmp, SEP);  uppercase( c);
        !           430: 
        !           431:                   if ( strcmp( c, parameter)) 
        !           432:                      fprintf( ofp, "%s", tmp1);
        !           433:                }
        !           434:                else
        !           435:                   fprintf( ofp, "%s", tmp1);
        !           436:             }
        !           437: 
        !           438:             fprintf( ofp, "%s = %s\n", param, newval);
        !           439: 
        !           440:             fclose( ofp);  fclose( fp);
        !           441: 
        !           442:             rename( tmppath, pathname);
        !           443:          }
        !           444:          else {
        !           445:             fclose( fp);
        !           446:             fatal("Cannot create %s", tmppath);
        !           447:          }
        !           448:       }
        !           449:    }
        !           450:    else
        !           451:    if ( errno == EACCES) 
        !           452:          fatal("Permission Problem with \"%s\".  It should have the suid bit set.", progname);
        !           453:    else
        !           454:    if ( rename( tmppath, pathname) == 0) {
        !           455:       MLP_unlock( locktype);
        !           456:       return( parameters( param, newval, pathname, locktype));
        !           457:    }
        !           458:    else {
        !           459:       if ( (fp = fopen( pathname, "w"))) {
        !           460:          fclose( fp);
        !           461:          MLP_unlock( locktype);
        !           462:          return( parameters( param, newval, pathname, locktype));
        !           463:       }
        !           464:       else
        !           465:          fatal("Cannot create control file: %s", pathname);
        !           466:    }
        !           467:    
        !           468: 
        !           469:    MLP_unlock( locktype);
        !           470: 
        !           471:    return( value);
        !           472: }
        !           473: 
        !           474: 
        !           475: 
        !           476: 
        !           477: /******************************************************************************
        !           478:   Given the name of a printer-setup parameter, return its value. 
        !           479:   If the value of the string "newval", is non-null then assign the parameter
        !           480:   this new new value.
        !           481: ******************************************************************************/
        !           482: 
        !           483: char *controls( param, newval)
        !           484: char *param;
        !           485: char *newval;
        !           486: {
        !           487:    return( parameters( param, newval, CONTROL_PATH, L_CONTROL));
        !           488: }
        !           489: 
        !           490: 
        !           491: /******************************************************************************
        !           492:   Given the name of a printer-status parameter, return its value.  
        !           493:   If the value of the string "newval", is non-null then assign the parameter
        !           494:   this new new value.
        !           495: ******************************************************************************/
        !           496: 
        !           497: char *status( param, newval)
        !           498: char *param;
        !           499: char *newval;
        !           500: {
        !           501:    return( parameters( param, newval, STATUS_PATH, L_STATUS));
        !           502: }
        !           503: 
        !           504: 
        !           505: 
        !           506: 
        !           507: /*****************************************************************************
        !           508:    Given the name of a printer, return the name of its device.  The controls
        !           509:    line for a printer looks like this:
        !           510: 
        !           511:    printer = name, device, backend
        !           512: *****************************************************************************/
        !           513: 
        !           514: char *printer_device( newprinter)
        !           515: char *newprinter;
        !           516: {
        !           517:    char  line[WORKSTR], tmp[40], *c, tmppath[WORKSTR], printer[WORKSTR];
        !           518:    FILE *fp;
        !           519: 
        !           520:    strcpy( printer, newprinter);
        !           521: 
        !           522:    sprintf( tmppath, "%s.tmp", CONTROL_PATH);
        !           523: 
        !           524:    MLP_lock( L_CONTROL);
        !           525: 
        !           526:    if ( (fp = fopen( CONTROL_PATH, "r"))) {
        !           527: 
        !           528:       while ( fgets( line, sizeof( line), fp)) {
        !           529: 
        !           530:          *tmp = *curr_device = *curr_backend = 0;   
        !           531: 
        !           532:          c = strtok( line, SEP);  if (c) strncpy( tmp, c, sizeof(tmp));
        !           533: 
        !           534:          if (!strcmp( "PRINTER", uppercase( tmp))) {
        !           535:             c = strtok( NULL, SEP);
        !           536: 
        !           537:             if (!strcmp( printer, c)) {
        !           538:                c = strtok( NULL, SEP); if (c) strncpy( curr_device,  c, WORKSTR);
        !           539:                c = strtok( NULL, SEP); if (c) strncpy( curr_backend, c, WORKSTR);
        !           540:                break;
        !           541:             }
        !           542:          }
        !           543:       }
        !           544: 
        !           545:       fclose( fp);
        !           546:    }
        !           547:    else
        !           548:    if ( errno == EACCES) {
        !           549:          /* fprintf(stderr,"permission problem (%s)\n", progname); fflush(stderr); */
        !           550:          fatal("Permission Problem with \"%s\".  It should have the suid bit set.", progname);
        !           551:    }
        !           552:    else
        !           553:    if ( rename( tmppath, CONTROL_PATH) == 0) {
        !           554:       MLP_unlock( L_CONTROL);
        !           555:       return( printer_device( newprinter));
        !           556:    }
        !           557:    else
        !           558:       fatal( "Missing control file: %s", CONTROL_PATH);
        !           559: 
        !           560:    MLP_unlock( L_CONTROL);
        !           561: 
        !           562:    return( curr_device);   
        !           563: }
        !           564: 
        !           565: 
        !           566: 
        !           567: 
        !           568: 
        !           569: /******************************************************************************
        !           570:    Given a user name, return the name of the printer to which they are cur-
        !           571:    rently routed.
        !           572: ******************************************************************************/
        !           573: 
        !           574: char *route_request( user)
        !           575: char *user;
        !           576: {
        !           577:    static  char printer[15];
        !           578:    FILE   *fp;
        !           579:    char         path[WORKSTR], *c;
        !           580: 
        !           581:    sprintf( path, "%s/%s", ROUTE_PATH, user);
        !           582: 
        !           583: 
        !           584:    strcpy( printer, "");
        !           585: 
        !           586:    if ( (fp = fopen( path, "r"))) {
        !           587:       fgets( printer, sizeof( printer), fp);
        !           588:       fclose( fp);
        !           589:    }
        !           590:    else {
        !           591:       strcpy( printer, controls( DEFAULT,""));
        !           592: 
        !           593:       if (!strcmp( printer, ""))
        !           594:          fatal( "Controls file (%s) needs a default printer entry", CONTROL_PATH);
        !           595:    }
        !           596: 
        !           597:    if ( c = strchr( printer, '\n')) *c = 0;
        !           598: 
        !           599:    return( printer);
        !           600: }
        !           601: 
        !           602: 
        !           603: 
        !           604: 
        !           605: 
        !           606: /******************************************************************************
        !           607:    Return a new report sequence number.
        !           608: ******************************************************************************/
        !           609: 
        !           610: int get_seq_num()
        !           611: {
        !           612:    char *v, newnum[10];
        !           613:    int   n;
        !           614: 
        !           615:    v = status("seqnum","");          if ( v[0] == 0)  v = "00001";
        !           616:    
        !           617:    sscanf( v, "%d", &n);               if ( n >= 32001) n = 1;
        !           618: 
        !           619:    sprintf( newnum, "%05u", (n+1));    status( SEQNUM, newnum);
        !           620: 
        !           621:    return(n);
        !           622: }
        !           623: 
        !           624: 
        !           625: 
        !           626: 
        !           627: /******************************************************************************
        !           628:    Local print.  Send the contents of the spool file (less the header)
        !           629:    to the printer connected to the user's terminal.  We assume that we are
        !           630:    positioned past the header.
        !           631: ******************************************************************************/
        !           632: 
        !           633: void local_print( fd, start, end)
        !           634: int fd;
        !           635: int start;
        !           636: int end;
        !           637: {
        !           638:    char *c, k;
        !           639:    long here;
        !           640: 
        !           641: 
        !           642:    here = lseek( fd, 0L, 1);
        !           643: 
        !           644:    get_termcap();
        !           645: 
        !           646:    write( 1, PN, strlen( PN));
        !           647: 
        !           648:    writeOut( fd, 1, start, end, curr_formlen, FALSE);
        !           649: 
        !           650:    c = controls( LOCALFEED, "");
        !           651: 
        !           652:    if (!strcmp( c, "ON") || !strcmp( c, "on")) { k = '\f'; write( 1, &k, 1); }
        !           653: 
        !           654:    write( 1, PS, strlen( PS));
        !           655: 
        !           656:    lseek( fd, here, 0);
        !           657: }
        !           658: 
        !           659: 
        !           660: 
        !           661: /*****************************************************************************
        !           662:    Return a sorted list of the spool queue.  The data structure returned is
        !           663:    a two dimensional array ( entries x MAXNAMLEN).
        !           664: *****************************************************************************/
        !           665: 
        !           666: char *dirlist( dirname, descend)
        !           667: char *dirname;
        !           668: int   descend;
        !           669: {
        !           670:    extern char *realloc();
        !           671:    DIR *dr;
        !           672:    struct dirent *dp;
        !           673:    char *t, tmp[MAXNAMLEN];
        !           674:    int   size, top, swapit, i, j, gap, comp;
        !           675: 
        !           676:    dr = opendir( dirname);  t = calloc( MAXNAMLEN, 1);  size = 0;
        !           677: 
        !           678:    while ( ( dp = readdir( dr)) != NULL)
        !           679:       if (!strcmp( ".", dp->d_name) || !strcmp( "..", dp->d_name))
        !           680:          continue;
        !           681:       else {
        !           682:          strncpy( (t+(size * MAXNAMLEN)), dp->d_name, MAXNAMLEN);
        !           683:          size++;
        !           684:          t = realloc( t, ((size+1) * MAXNAMLEN));
        !           685:       }
        !           686: 
        !           687:    closedir( dr);
        !           688: 
        !           689:    strcpy( (t+(size * MAXNAMLEN)), "");
        !           690: 
        !           691: 
        !           692:    /* Use a COMBsort to sort the items in this directory */
        !           693:    /* This sort is like a bubble sort only MUCH faster */
        !           694: 
        !           695:    gap = size;
        !           696: 
        !           697:    do {
        !           698:       gap = gap * 10 / 13;    if (gap == 0) gap = 1;
        !           699: 
        !           700:       top = size - gap;       swapit = 0;
        !           701: 
        !           702:       for ( i = 0; i < top; i++) {
        !           703:          j = i + gap;
        !           704:         
        !           705:          comp = strcmp( (t+(i * MAXNAMLEN)), (t+(j * MAXNAMLEN)));
        !           706: 
        !           707:          if (descend) {      /* Reverse the sort order */
        !           708:             if ( comp > 0)
        !           709:                comp = 0;
        !           710:             else
        !           711:                comp = 1;
        !           712:          }
        !           713:        
        !           714:          if ( comp > 0) {
        !           715:             strcpy( tmp, (t+(i * MAXNAMLEN)));
        !           716:             strcpy( (t+(i * MAXNAMLEN)), (t+(j * MAXNAMLEN)));
        !           717:             strcpy( (t+(j * MAXNAMLEN)), tmp);
        !           718: 
        !           719:             swapit++;
        !           720:          } 
        !           721:       }
        !           722:    } while ( swapit || gap > 1);
        !           723:    return( t);
        !           724: }
        !           725: 
        !           726: 
        !           727: 
        !           728: /******************************************************************************
        !           729:    Wakeup The Despooler by sending it an alarm signal.  The despooler's PID
        !           730:    will be found in the controls database.
        !           731: ******************************************************************************/
        !           732: 
        !           733: void wakeup_despooler()
        !           734: {
        !           735:    char  *v;
        !           736:    int    pid = 0;
        !           737: 
        !           738:    v = status( DESPOOLER,"");
        !           739: 
        !           740:    sscanf( v, "%d", &pid);
        !           741: 
        !           742:    if ( pid > 0) kill( pid, SIGALRM);
        !           743: }
        !           744: 
        !           745: 
        !           746: 
        !           747: 
        !           748: 
        !           749: /******************************************************************************
        !           750:    Basename.  Strip the leading path information from a pathname.
        !           751: ******************************************************************************/
        !           752: 
        !           753: char *basename( path)
        !           754: char *path;
        !           755: {
        !           756:    char *c;
        !           757: 
        !           758:    if (path == NULL) return("");
        !           759: 
        !           760:    for (c = path; *c; c++); c--;           /* go to the end of the string */
        !           761: 
        !           762:    while (c != path && *(c-1) != '/') c--; /* step back til we see a slash */
        !           763: 
        !           764:    return( c);
        !           765: }
        !           766: 
        !           767: 
        !           768: 
        !           769: 
        !           770: /******************************************************************************
        !           771:    Return TRUE if the scheduler is running, FALSE if not.
        !           772: ******************************************************************************/
        !           773: 
        !           774: int scheduler_status()
        !           775: {
        !           776:    char *t;
        !           777:    int   pid;
        !           778: 
        !           779:    t = status( DESPOOLER, "");  sscanf( t, "%d", &pid);
        !           780:    
        !           781:    if ( pid > 1 && !kill( pid, 0))
        !           782:       return( TRUE);
        !           783:    else
        !           784:       return( FALSE);
        !           785: }
        !           786: 
        !           787: 
        !           788: 
        !           789: 
        !           790: /******************************************************************************
        !           791:    This routine does all the actual I/O to the device.  The tricky part is
        !           792:    counting the pages and (optionally printing only the desired range of pages).
        !           793:    It is used in several places.  Source and Sink are the input and output
        !           794:    file descriptors.  The source's file pointer is expected to be at the
        !           795:    start of the user's data; that is, seek past the header, if there is one.
        !           796:    Start and end are the starting and ending page numbers for the reqeuest.
        !           797:    If both of these are zero then we will send all of the source data to the
        !           798:    sink, otherwise we send source to sink only when we are within the page
        !           799:    range.  Counting pages depends heavily on the form length (curr_formlen)
        !           800:    and the nature of the source data.  If you are sending bitmaps to a laser
        !           801:    printer though this routine, the page numbers will probably be wildly
        !           802:    skewed!  At this point, I know of no convienent way around this.  You'd
        !           803:    have to parse the input for ALL known laser printers. Then the next new
        !           804:    one could possibly make your effort moot.  Maybe this could be done for
        !           805:    HPCL and Postscript?  If the flag "report" is TRUE then the routine's
        !           806:    progress will be reported in the status file.  This routine returns the
        !           807:    number of pages that it has processed.
        !           808: ******************************************************************************/
        !           809: 
        !           810: #define IOBUFF 1024
        !           811: 
        !           812: int writeOut( source, sink, start, end, formlen, report)
        !           813: int source;
        !           814: int sink;
        !           815: int start;
        !           816: int end;
        !           817: int formlen;
        !           818: int report;
        !           819: {
        !           820:    int   result, lines, progress;
        !           821:    int   pages;
        !           822:    long  rsize, oldpos;
        !           823:    char  tmp[WORKSTR];
        !           824:    char *i, *ibuff, *imax;  /* input buffer pointers */
        !           825:    char *o, *obuff, *omax;  /* output buffer pointers */
        !           826: 
        !           827:    /* how big is the source file? */
        !           828:  
        !           829:    oldpos = lseek( source, 0L, 1);
        !           830:    rsize  = lseek( source, 0L, 2);  lseek( source, oldpos, 0);
        !           831: 
        !           832:    
        !           833:    ibuff = malloc( IOBUFF);  obuff = malloc( IOBUFF);
        !           834: 
        !           835:    o = obuff;  omax = obuff + IOBUFF;
        !           836: 
        !           837:    lines = 0;  pages = 1;
        !           838:  
        !           839:    while ( result = read( source, ibuff, IOBUFF)) {
        !           840:       if (abort_write) {
        !           841:          o = obuff;
        !           842:          pages = -1;
        !           843:          break;
        !           844:       }
        !           845: 
        !           846:       if ( start == 0 && end == 0)
        !           847:          write( sink, ibuff, result);   /* print entire request */
        !           848:       else {
        !           849: 
        !           850:          /* print from start to end page of request */
        !           851: 
        !           852:          for ( i = ibuff, imax = ibuff + result; i < imax; i++) {
        !           853: 
        !           854:             if ( *i == '\n') {
        !           855:                lines++;
        !           856: 
        !           857:                if ( lines > formlen) {
        !           858:                   lines = 0;
        !           859:                   /* lines -= formlen; */
        !           860:                   pages++;
        !           861:                }
        !           862:             }
        !           863:             else
        !           864:             if ( *i == '\f') {
        !           865:                pages++;
        !           866:                lines = 0;
        !           867:             }
        !           868: 
        !           869:             if ( pages >= start && pages <= end) {
        !           870: 
        !           871:                *o++ = *i;
        !           872: 
        !           873:                if ( o >= omax) {
        !           874: 
        !           875:                   write( sink, obuff, IOBUFF);
        !           876:                   o = obuff;
        !           877:                }
        !           878:             }
        !           879:          }
        !           880:       }
        !           881: 
        !           882: 
        !           883:       /* Report Progress to the status file */
        !           884: 
        !           885:       if (report) {
        !           886:          progress = (int) (lseek( source, 0L, 1) * 100L / rsize);
        !           887: 
        !           888:          sprintf( tmp, "%d, %s, %s, %d, %d of %d", getpid(), curr_name, 
        !           889:             curr_printer, progress, curr_copy, curr_copies);
        !           890: 
        !           891:          status( curr_device, tmp);
        !           892:       }
        !           893:    }
        !           894: 
        !           895:    /* write anything leftover in the output buffer */
        !           896: 
        !           897:    if ( o != obuff) write( sink, obuff, (int) (o - obuff)); 
        !           898: 
        !           899: 
        !           900:    free( ibuff);  free( obuff);
        !           901: 
        !           902:    return( pages);
        !           903: }
        !           904: 
        !           905: 
        !           906: 
        !           907: /******************************************************************************
        !           908:    Given the sequence number of a request, return the full file name of
        !           909:    the request.
        !           910: ******************************************************************************/
        !           911: 
        !           912: char *request_name( seqnum)
        !           913: char *seqnum;
        !           914: {
        !           915:    DIR *dr;
        !           916:    struct dirent *dp;
        !           917:    int val;
        !           918:    char tvalue[15];
        !           919:    static char value[15];
        !           920: 
        !           921: 
        !           922:    val = 0;  sscanf( seqnum, "%d", &val);   sprintf( tvalue, "%05u", val);
        !           923: 
        !           924:    dr = opendir( QUEUE_PATH);  value[0] = 0;
        !           925: 
        !           926: 
        !           927:    while ( ( dp = readdir( dr)) != NULL)
        !           928:       if (!strcmp( ".", dp->d_name) || !strcmp( "..", dp->d_name))
        !           929:          continue;
        !           930:       else {
        !           931:          if (!strncmp( tvalue, &dp->d_name[2], 5)) {
        !           932:             sprintf( value, "%s", dp->d_name);
        !           933:             break;
        !           934:          }
        !           935:       }
        !           936: 
        !           937:    closedir( dr);
        !           938: 
        !           939:    return( value);
        !           940: }
        !           941: 
        !           942: 
        !           943: 
        !           944: 
        !           945: /****************************************************************************
        !           946:    Given the report sequence number, return the owner's name
        !           947: ****************************************************************************/
        !           948: 
        !           949: char *request_owner( seqnum)
        !           950: char *seqnum;
        !           951: {
        !           952:    static char owner[20];
        !           953:    char path[WORKSTR], head[HEADER_SIZE];
        !           954:    int  fd;
        !           955: 
        !           956:    strcpy( owner, request_name( seqnum));
        !           957: 
        !           958:    if (*owner) {
        !           959:       sprintf( path, "%s/%s", QUEUE_PATH, owner);
        !           960: 
        !           961:       if ( (fd = open( path, O_RDONLY)) != BAD) {
        !           962:          read( fd, head, HEADER_SIZE);
        !           963:          close( fd);
        !           964: 
        !           965:          strcpy( owner, headerval( head, H_USER, ""));
        !           966:          unpadd( owner);
        !           967:       }
        !           968:    }
        !           969:    else
        !           970:       *owner = 0;
        !           971: 
        !           972:    return( owner);
        !           973: }
        !           974: 
        !           975: 
        !           976: 
        !           977: 
        !           978: /****************************************************************************
        !           979:   Return 1 if I (the program's user) own the request, 0 otherwise. If I'm
        !           980:   superuser, then I own it all.
        !           981: ****************************************************************************/
        !           982: 
        !           983: int do_i_own_it( seqnum)
        !           984: char *seqnum;
        !           985: {
        !           986:    struct passwd *p;
        !           987:    
        !           988:    p = getpwuid( getuid());
        !           989: 
        !           990:    if ((p && !strcmp( p->pw_name, request_owner( seqnum))) ||
        !           991:       (getuid() == 0))
        !           992:       return(1);
        !           993:    else
        !           994:       return(0);
        !           995: }
        !           996: 
        !           997: 
        !           998: 
        !           999: 
        !          1000: 
        !          1001: /******************************************************************************
        !          1002:    Report the status of all the printers defined in the control file.
        !          1003: ******************************************************************************/
        !          1004: 
        !          1005: char *each_printer( command)
        !          1006: int command;
        !          1007: {
        !          1008:    static FILE *fp;
        !          1009:    static char  line[WORKSTR];
        !          1010:    char         tmp[WORKSTR], *t;
        !          1011: 
        !          1012:    *line = 0;
        !          1013: 
        !          1014:    switch (command) {
        !          1015:       case E_START: MLP_lock( L_CONTROL);
        !          1016: 
        !          1017:                     if ( (fp = fopen( CONTROL_PATH, "r+")) == NULL) {
        !          1018:                        sprintf( tmp, "%s.tmp", CONTROL_PATH);
        !          1019: 
        !          1020:                        if ( errno == EACCES)
        !          1021:                           fatal("Permission Problem with \"%s\".  It should have the suid bit set.", progname);
        !          1022:                        else
        !          1023:                        if ( rename( tmp, CONTROL_PATH) == 0) {
        !          1024:                           MLP_unlock( L_CONTROL);
        !          1025:                           return( each_printer( command));
        !          1026:                        }
        !          1027:                        else
        !          1028:                           fatal( "Missing control file: %s", CONTROL_PATH);
        !          1029:                     }
        !          1030:                     break;
        !          1031: 
        !          1032:       case E_NEXT:  while (fgets( tmp, sizeof(tmp), fp)) {
        !          1033: 
        !          1034:                        t = strtok( tmp, SEP); uppercase( t);
        !          1035:                        if (!strcmp( "PRINTER", t)) {
        !          1036:                           for (t = tmp; *t; t++); t++;
        !          1037:                           while (strchr(SEP, *t)) t++;
        !          1038:                           strcpy( line, t);
        !          1039:                           break;
        !          1040:                        }
        !          1041:                     }
        !          1042:                     break;
        !          1043: 
        !          1044:       case E_REWIND: fseek( fp, 0L, SEEK_SET); break;
        !          1045: 
        !          1046:       case E_END:    fclose( fp);
        !          1047:       case E_UNLOCK: MLP_unlock( L_CONTROL); break;
        !          1048: 
        !          1049:       case E_FILE:   return( (char *) fp);
        !          1050:    }
        !          1051: 
        !          1052:    return( line);
        !          1053: }
        !          1054: 
        !          1055: 
        !          1056: 
        !          1057: 
        !          1058: char *report_printer_status( display_type)
        !          1059: {
        !          1060:    static char request_list[WORKSTR];
        !          1061:    int    pid, req;
        !          1062:    char   tmp[40], *t, *c, *d, *header, rpath[WORKSTR];
        !          1063:    char   request[20], user[20], timestr[40];
        !          1064:    long   rtime;
        !          1065: 
        !          1066:    request_list[0] = 0;  /* will contain a list of all the request that are
        !          1067:                             currently printing.  This is so we can skip these
        !          1068:                             when we go over the list of all pending requests.*/
        !          1069: 
        !          1070: 
        !          1071:    each_printer( E_START);
        !          1072: 
        !          1073:    while ( *(t = each_printer( E_NEXT))) {
        !          1074: 
        !          1075:          *tmp = *curr_printer = *curr_device = *curr_backend = 0;   
        !          1076: 
        !          1077:          c = strtok( t   , SEP); if (c) strncpy( curr_printer, c, WORKSTR);
        !          1078:          c = strtok( NULL, SEP); if (c) strncpy( curr_device,  c, WORKSTR);
        !          1079:          c = strtok( NULL, SEP); if (c) strncpy( curr_backend, c, WORKSTR);
        !          1080: 
        !          1081: 
        !          1082:          /*** Now look at this printer from the status database ***/
        !          1083: 
        !          1084:          strcpy( tmp, status( curr_device, ""));
        !          1085: 
        !          1086: 
        !          1087:          c = strtok( tmp, SEP);  pid = 0; sscanf( c, "%d", &pid);
        !          1088: 
        !          1089:          if (pid > 0 && kill( pid, 0)) c = NULL;
        !          1090: 
        !          1091:          switch (display_type) {
        !          1092:          case PID_DISPLAY:
        !          1093:             if (c != NULL) {
        !          1094:                c = strtok( NULL, SEP);
        !          1095:                if (c) sprintf( timestr, "%d|%s ", pid, (c+2));
        !          1096: 
        !          1097:                if ((strlen( request_list)+strlen( timestr))
        !          1098:                      < sizeof( request_list))
        !          1099:                   strcat( request_list, timestr);
        !          1100:             }
        !          1101:          break;
        !          1102: 
        !          1103:          case DEVICE_DISPLAY:
        !          1104:             printf("device for %s: %s\n", curr_printer, curr_device);
        !          1105:          break;
        !          1106: 
        !          1107:          case PRINTER_DISPLAY:
        !          1108:             *request = 0; if ( d = strtok( NULL, SEP)) strcpy( request, d);
        !          1109: 
        !          1110:             d = strtok( NULL, SEP);
        !          1111: 
        !          1112:             if ( c == NULL || d == NULL || strcmp(d, curr_printer))
        !          1113:                printf("printer %s is idle\n", curr_printer);
        !          1114:             else {
        !          1115:                printf("printer %s is printing request #", curr_printer);
        !          1116:                printf("%s, ", &request[2]);
        !          1117: 
        !          1118:                if ( c = strtok( NULL, SEP))
        !          1119:                   printf("%s%% sent to device", c);
        !          1120: 
        !          1121:                if ( c = strtok( NULL, ","))
        !          1122:                   printf(", copy %s", c);
        !          1123:    
        !          1124:                printf("\n");
        !          1125:             }
        !          1126:          break;
        !          1127: 
        !          1128:          case REQUEST_DISPLAY:
        !          1129:             if ( c != NULL) {
        !          1130:                strcpy( request, strtok( NULL, SEP));
        !          1131:                sprintf( rpath, "%s/%s", QUEUE_PATH, request);
        !          1132: 
        !          1133:                if ((c = strtok( NULL, SEP)) && !strcpy( c, curr_printer)) {   
        !          1134:               
        !          1135:                   if ( (req = open( rpath, O_RDONLY)) != BAD) {
        !          1136:                      header = calloc( HEADER_SIZE, 1);
        !          1137:                      read( req, header, HEADER_SIZE);
        !          1138:                      close( req);
        !          1139: 
        !          1140:                      strcpy( user, headerval( header, H_USER, ""));
        !          1141:                      unpadd( user);
        !          1142: 
        !          1143:                      strcpy( timestr, headerval( header, H_DSTAMP, ""));
        !          1144:                      rtime = 0L; sscanf( timestr, "%ld", &rtime);
        !          1145:                      strcpy( timestr, ctime(&rtime));
        !          1146:                      timestr[strlen(timestr)-1] = 0;
        !          1147: 
        !          1148:                      free( header);
        !          1149: 
        !          1150:                      printf( "%s-%s\t\t%c\t%s", user,
        !          1151:                         (request+2), *(request+1), timestr);
        !          1152: 
        !          1153:                      printf( "\ton %s\n", curr_printer);
        !          1154: 
        !          1155: 
        !          1156:                      sprintf( timestr, "%s|", request);
        !          1157:                      if ((strlen( request_list)+strlen( timestr))
        !          1158:                           < sizeof( request_list))
        !          1159:                         strcat( request_list, timestr);
        !          1160:                   }
        !          1161:                }                  
        !          1162:             }
        !          1163: 
        !          1164:          break;
        !          1165:          }
        !          1166:    }
        !          1167: 
        !          1168:    each_printer( E_END);
        !          1169: 
        !          1170:    return( request_list);
        !          1171: }
        !          1172: 
        !          1173: 
        !          1174: 
        !          1175: /******************************************************************************
        !          1176:    Cancel currently printing requests (not pending ones!).  Kill only the ones
        !          1177:    I own.  If I'm superuser, then I own it all.
        !          1178: ******************************************************************************/
        !          1179: 
        !          1180: int kill_printing_request( seqnum, sig, flag)
        !          1181: int  seqnum;
        !          1182: int  sig;
        !          1183: int  flag;
        !          1184: {
        !          1185:    int   pid, seq, sucessfull = FALSE;
        !          1186:    char *list, *t;
        !          1187: 
        !          1188:    list = report_printer_status( PID_DISPLAY);
        !          1189: 
        !          1190:    t = strtok( list, " ");
        !          1191: 
        !          1192:    do {
        !          1193:       if (t) {
        !          1194:          sscanf( t, "%d|%d", &pid, &seq);
        !          1195: 
        !          1196:          if ( flag || (seq == seqnum)) 
        !          1197:             if (do_i_own_it( seqnum)) {
        !          1198:                kill( pid, sig);
        !          1199:                sucessfull = TRUE;
        !          1200:             }
        !          1201: 
        !          1202:          t = strtok( NULL, " ");
        !          1203:       }
        !          1204:    } while (t);
        !          1205: 
        !          1206:    if (flag) log("Abort Currently Printing Requests");
        !          1207: 
        !          1208:    return( sucessfull);
        !          1209: }
        !          1210: 
        !          1211: 
        !          1212: 
        !          1213: 
        !          1214: /*****************************************************************************
        !          1215:    This routine scans the spool queue looking for request that need to be
        !          1216:    removed.  That is, they need to die of old age!  There are four classes
        !          1217:    of longevity: (R) reprint, (T) temporary, (S) shortterm, and (L) longterm.
        !          1218:    R requests are really just headers and they are deleted as soon as they
        !          1219:    have despooled.  This routine handles the other three classes.
        !          1220: *****************************************************************************/
        !          1221: 
        !          1222: #define THOURS 0.5
        !          1223: #define SHOURS 24.0
        !          1224: #define LHOURS (7.0 * 24.0)
        !          1225: 
        !          1226: void grim_reaper()
        !          1227: {
        !          1228:    long   temporary, shortterm, longterm, current, dstamp, elapst;
        !          1229:    float  thours, shours, lhours;
        !          1230:    char  *entries, *name, header[HEADER_SIZE], path[WORKSTR], life[2];
        !          1231:    char   desc[WORKSTR];
        !          1232:    int    n, fd, die;
        !          1233: 
        !          1234:    thours = THOURS; sscanf( controls( TLIFE, ""), "%f", &thours);
        !          1235:    shours = SHOURS; sscanf( controls( SLIFE, ""), "%f", &shours);
        !          1236:    lhours = LHOURS; sscanf( controls( LLIFE, ""), "%f", &lhours);
        !          1237: 
        !          1238:    temporary = (long) 3600.0 * thours;
        !          1239:    shortterm = (long) 3600.0 * shours;
        !          1240:    longterm  = (long) 3600.0 * lhours;
        !          1241: 
        !          1242:    time( &current);
        !          1243: 
        !          1244:    entries  = dirlist( QUEUE_PATH, FALSE);  /* return sorted spool queue list */
        !          1245:                                             /* This list is a two dimensional */
        !          1246:                                             /* array (entries x MAXNAMLEN) */
        !          1247:                                             /* Ascending order */
        !          1248: 
        !          1249:    for ( n = 0; *(name = (entries+(n * MAXNAMLEN))); n++) {
        !          1250:       if ( *name == 'R') continue;
        !          1251: 
        !          1252:       sprintf( path, "%s/%s", QUEUE_PATH, name);
        !          1253: 
        !          1254:       if ( fd = open( path, O_RDONLY)) {
        !          1255:          read( fd, header, HEADER_SIZE);
        !          1256:          dstamp = 0L; 
        !          1257:          sscanf( headerval( header, H_DSTAMP,    ""), "%ld", &dstamp);
        !          1258:          sscanf( headerval( header, H_LONGEVITY, ""), "%1s", life);
        !          1259:          strcpy( desc, headerval( header, H_DESC, ""));
        !          1260:          unpadd( desc);
        !          1261:          close( fd);
        !          1262: 
        !          1263:          elapst = current - dstamp;    die = FALSE;
        !          1264: 
        !          1265:          switch (*life) {
        !          1266:             case 'T': if (elapst > temporary) die = TRUE; break;
        !          1267:             case 'S': if (elapst > shortterm) die = TRUE; break;
        !          1268:             case 'L': if (elapst > longterm)  die = TRUE; break;
        !          1269:          }
        !          1270: 
        !          1271:          if (die) { 
        !          1272:             log( "Request #%s \"%s\" expired.", &name[2], desc);
        !          1273:             unlink( path);
        !          1274:             /* printf("unlink %s\n", path); */
        !          1275:          }
        !          1276:       }
        !          1277:    }
        !          1278: 
        !          1279:    free( entries);
        !          1280: }
        !          1281: 
        !          1282: 
        !          1283: 
        !          1284: /******************************************************************************
        !          1285:   ftok() implements Unix's function of the same name.  Given a valid pathname
        !          1286:   and a project identifier, return a "unique" handle.  This handle is used by
        !          1287:   the Unix IPC.  If the path is not found, a -1 is returned.  For some reason,
        !          1288:   Coherent does not implement this function.
        !          1289: ******************************************************************************/
        !          1290: 
        !          1291: key_t ftok( path, proj)
        !          1292: char *path;
        !          1293: char  proj;
        !          1294: {
        !          1295:    struct stat s;
        !          1296: 
        !          1297:    if (stat( path, &s) == BAD) return( (key_t) -1L);
        !          1298: 
        !          1299:    return( (key_t) (s.st_ino | (proj << 16) | (s.st_dev << 24)));
        !          1300: }
        !          1301: 
        !          1302: 
        !          1303: /******************************************************************************
        !          1304:    MLP_Lock.  This routine can lock several critical sections involving MLP
        !          1305:    process.  These are: Cancel, Controls and Status.  The controls and status
        !          1306:    files need to be locked while they are modified.  The Cancel lock keeps
        !          1307:    processes that cancel requests out of the hair of the despooler and vice-
        !          1308:    versa.
        !          1309: 
        !          1310:    ***NOTE***
        !          1311:    Because Mark Williams has not implemented SEM_UNDO, we will fall back to
        !          1312:    lockfiles for safety reasons.
        !          1313: ******************************************************************************/
        !          1314: 
        !          1315: int locks[IPC_SEMS];    /* contains lockfile fd's */
        !          1316: 
        !          1317: void MLP_lock( which)
        !          1318: int which;
        !          1319: {
        !          1320:    char path[WORKSTR];
        !          1321: 
        !          1322:    sprintf( path, "%s/LCK..%d", QUEUE_PATH, which);
        !          1323: 
        !          1324:    locks[which] = open( path, O_RDWR); lockf( locks[which], F_LOCK, 0L);
        !          1325: 
        !          1326: /* SEM_UNDO is not yet implemented...
        !          1327: 
        !          1328:    static struct sembuf lcancel[2]  = { 0,0,0,  0,1,SEM_UNDO };
        !          1329:    static struct sembuf lcontrol[2] = { 1,0,0,  1,1,SEM_UNDO };
        !          1330:    static struct sembuf lstatus[2]  = { 2,0,0,  2,1,SEM_UNDO };
        !          1331:    static struct sembuf llog[2]     = { 3,0,0,  3,1,SEM_UNDO };
        !          1332: 
        !          1333:    struct sembuf *s;
        !          1334:    key_t k;
        !          1335:    int   sID;
        !          1336: 
        !          1337:    k = ftok( IPC_NAME, 1);
        !          1338: 
        !          1339:    if ((sID = semget( k, IPC_SEMS, IPC_PERMS|IPC_CREAT|IPC_EXCL)) == BAD) {
        !          1340:       if ((sID = semget( k, IPC_SEMS, 0)) == BAD) {
        !          1341:          return;
        !          1342:       }
        !          1343:    }
        !          1344: 
        !          1345:    switch (which) {
        !          1346:       case L_CANCEL:  semop( sID, lcancel,  2); break;
        !          1347:       case L_CONTROL: semop( sID, lcontrol, 2); break;
        !          1348:       case L_STATUS:  semop( sID, lstatus,  2); break;
        !          1349:       case L_LOG:     semop( sID, llog,     2); break;
        !          1350:    }
        !          1351: */
        !          1352: }
        !          1353: 
        !          1354: 
        !          1355: 
        !          1356: void MLP_unlock( which)
        !          1357: int which;
        !          1358: {
        !          1359:    char path[WORKSTR];
        !          1360: 
        !          1361:    sprintf( path, "%s/LCK..%d", QUEUE_PATH, which);
        !          1362: 
        !          1363:    lockf( locks[which], F_ULOCK, 0L); close( locks[which]); unlink( path);
        !          1364: 
        !          1365: /* SEM_UNDO is not yet implemented...
        !          1366: 
        !          1367:    static struct sembuf lcancel[1]  = { 0,-1, IPC_NOWAIT|SEM_UNDO };
        !          1368:    static struct sembuf lcontrol[1] = { 1,-1, IPC_NOWAIT|SEM_UNDO };
        !          1369:    static struct sembuf lstatus[1]  = { 2,-1, IPC_NOWAIT|SEM_UNDO };
        !          1370:    static struct sembuf llog[1]  =    { 3,-1, IPC_NOWAIT|SEM_UNDO };
        !          1371: 
        !          1372:    key_t k;
        !          1373:    int   sID;
        !          1374: 
        !          1375:    k = ftok( IPC_NAME, 1);
        !          1376: 
        !          1377:    if ((sID = semget( k, IPC_SEMS, IPC_PERMS|IPC_CREAT|IPC_EXCL)) == BAD) {
        !          1378:       if ((sID = semget( k, IPC_SEMS, 0)) == BAD) {
        !          1379:          return;
        !          1380:       }
        !          1381:    }
        !          1382: 
        !          1383:    switch (which) {
        !          1384:       case L_CANCEL:  semop( sID, lcancel,  1); break;
        !          1385:       case L_CONTROL: semop( sID, lcontrol, 1); break;
        !          1386:       case L_STATUS:  semop( sID, lstatus,  1); break;
        !          1387:       case L_LOG:     semop( sID, llog,     1); break;
        !          1388:    }
        !          1389: */
        !          1390: }

unix.superglobalmegacorp.com

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