File:  [MW Coherent from dump] / coherent / g / usr / bin / mlp / lpstat.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:35 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/******************************************************************************
   lpstat.  MLP line-printer status a'la Unix V.
******************************************************************************/

#include "header.h"


extern char curr_printer[WORKSTR];
extern char curr_device[WORKSTR];
extern char curr_backend[WORKSTR];


/******************************************************************************
  Report the name of the system default printer
******************************************************************************/

void system_default_printer()
{
   char *c;
   c = controls( DEFAULT, "");

   printf("system default destination is: %s\n", c);
}



/******************************************************************************
  Report whether the scheduler is running or not
******************************************************************************/

void report_scheduler_status()
{
   if ( scheduler_status())
      printf("scheduler is running\n");
   else
      printf("scheduler is not running\n");
}





/******************************************************************************
  List the currently printing requests and the pending ones in Unix V style
******************************************************************************/

report_request_status()
{
   int   n, fd;
   char *requests, *entries, *name, header[HEADER_SIZE], path[WORKSTR];
   char  user[20], timestr[40], printer[20];
   long  rtime;
   struct passwd *p;

   p = getpwuid(getuid());

   requests = report_printer_status( REQUEST_DISPLAY);

   entries  = dirlist( QUEUE_PATH, FALSE);  /* return sorted spool queue list */
                                            /* This list is a two dimensional */
                                            /* array (entries x MAXNAMLEN) */
                                            /* Ascending order */

   for ( n = 0; *(name = (entries+(n * MAXNAMLEN))); n++) {
      if ( *name == 'r') break;

      if (strstr( requests, name) == NULL) {
         sprintf( path, "%s/%s", QUEUE_PATH, name);

         if ( (fd = open( path, O_RDONLY)) != BAD) {
             read( fd, header, HEADER_SIZE);
             close( fd);

             strcpy( user, headerval( header, H_USER, ""));
             unpadd( user);

             if ( (p && !strcmp( user, p->pw_name)) || (getuid(0) == 0)) {
                strcpy( printer, headerval( header, H_PRINTER, ""));
                unpadd( printer);

                strcpy( timestr, headerval( header, H_DSTAMP, ""));
                rtime = 0L; sscanf( timestr, "%ld", &rtime);
                strcpy( timestr, ctime(&rtime));
                timestr[strlen(timestr)-1] = 0;

                printf( "%s-%s\t\t%c\t%s", user,
                   (name+2), *(name+1), timestr);

                printf( "\tfor %s\n", printer);
             }
         }
      }
   }

   free( entries);
}





/******************************************************************************
  List the currently printing requests and the pending ones in MLP style
******************************************************************************/

report_mlp_request_status()
{
   int   n, fd, printing, val;
   char *requests, *entries, *name, header[HEADER_SIZE], path[WORKSTR];
   char  user[20], printer[20], title[100], tmp[WORKSTR];
   long  rtime;
   struct tm *tt;

   entries  = dirlist( QUEUE_PATH, TRUE);  /* return sorted spool queue list */
                                            /* This list is a two dimensional */
                                            /* array (entries x MAXNAMLEN) */
                                            /* Ascending order */

   printf("REQ # S P L #Pgs FL  #Cp   Date   Time  Description...\n");
   printf("----- - - - ---- --- --- -------- ----- -----------------------------------\n");

   for ( n = 0; *(name = (entries+(n * MAXNAMLEN))); n++) {
      printing = FALSE;

      if (strstr( requests, name)) printing = TRUE;

      sprintf( path, "%s/%s", QUEUE_PATH, name);

      if ( (fd = open( path, O_RDONLY)) != BAD) {
          read( fd, header, HEADER_SIZE);
          close( fd);

          printf("%-5s ", (name+2));  /* request sequence no. */

          /* Request Status */

          if (printing)
             printf("* ");  /* printing now */
          else
          if (*name == 'R')
             printf("P ");  /* waiting to print */
          else
          if (*name == 'r')
             printf("Q ");  /* held in queue print */
          else
             printf("? ");  /* don't know the status */

          printf("%c ", *(name+1));   /* priority */

          printf("%s ", unpadd( headerval( header, H_LONGEVITY, "")));

          val = 0;
          sscanf( unpadd( headerval( header, H_PAGES, "")), "%d", &val);
          printf("%4d ", val);
    
          val = 0;
          sscanf( unpadd( headerval( header, H_FORMLEN, "")), "%d", &val);
          printf("%3d ", val);
    
          val = 0;
          sscanf( unpadd( headerval( header, H_COPIES, "")), "%d", &val);
          printf("%3d ", val);


          sscanf( unpadd( headerval( header, H_DSTAMP, "")), "%ld", &rtime);

          tt = localtime( &rtime);

          printf( "%02d/%02d/%02d ", (tt->tm_mon+1), tt->tm_mday, tt->tm_year);
          printf( "%02d:%02d ", tt->tm_hour, tt->tm_min);
    
          strcpy( user,    unpadd( headerval( header, H_USER, "")));
          strcpy( printer, unpadd( headerval( header, H_PRINTER, "")));
          strcpy( title,   unpadd( headerval( header, H_DESC, "")));
   
          sprintf( tmp, "%s -by %s -on %s", title, user, printer);

          printf("%s\n", tmp);
      }
   }
}




/******************************************************************************
  Print a list of printers available for routine.
******************************************************************************/

list_printers( user)
char *user;
{
   char *list;

   printf("%s  ( ", route_request( user));

   each_printer( E_START);

   while (*(list = each_printer( E_NEXT)))
      printf( "%s ", strtok( list, SEP));

   each_printer( E_END);

   printf("system display local )\n");
}






/******************************************************************************
  Set the printer that the user wants to route to.
******************************************************************************/

set_route( user, printer)
char *user;
char *printer;
{
   FILE *fp;
   int   inlist;
   char *list, path[WORKSTR];

   each_printer( E_START);

   inlist = FALSE;

   while (*(list = each_printer( E_NEXT)))
      if (!strcmp( strtok( list, SEP), printer)) inlist = TRUE;

   each_printer( E_END);

   if (!strcmp( "local",   printer)) inlist = TRUE;
   if (!strcmp( "display", printer)) inlist = TRUE;
   if (!strcmp( "system",  printer)) inlist = TRUE;

   if (!inlist) {
      printf("\007\"%s\" is not a defined printer.\n", printer);
      return;
   }

   sprintf( path, "%s/%s", ROUTE_PATH, user);

   if ( fp = fopen( path, "w+")) {
      fprintf( fp, "%s\n", printer);
      fclose( fp);
      printf( "%s, your requests will now spool to the \"%s\" printer.\n", 
         user, printer);
   }
}




/******************************************************************************
   Reprioritize the requests
******************************************************************************/

void reprioritize_requests( argc, argv)
int   argc;
char *argv[];
{
   int   n, m, reqnum, filenum, fd;
   char *t, *name, prior, oldnam[WORKSTR], newnam[WORKSTR], *head, auser[30];
   struct passwd *p;

   p = getpwuid(getuid());

   prior = argv[1][2];

   if ( prior < '0') prior = '0';
   if ( prior > '9') prior = '9';


   MLP_lock( L_CANCEL);

   /* Not sure why I want to do this? */
   /* kill_printing_request( 0, R_CANCEL, CLEAR_ALL); */

   t = dirlist( QUEUE_PATH, FALSE);  /* return sorted spool queue list */
                                     /* This list is a two dimensional */
                                     /* (entries x MAXNAMLEN) */
                                     /* Ascending order */

   head = (char *) calloc( HEADER_SIZE, 1);

   for (n = 0; *(name = (t+(n * MAXNAMLEN))); n++) {

      if (sscanf( &name[2], "%d", &filenum) == 1) {

         for (m = 2; m <= argc; m++) {
            if (sscanf( argv[m], "%d", &reqnum) == 1) {
               if ( filenum == reqnum) {
                  sprintf( oldnam, "%s/%s", QUEUE_PATH, name);

                  if ( (fd = open( oldnam, O_RDONLY)) != BAD) {
                     read( fd, head, HEADER_SIZE);
                     close( fd);

                     strcpy( auser, headerval( head, H_USER, ""));
                     unpadd( auser);

                     if (p && !strcmp( auser, p->pw_name) ||
                        (getuid() == 0)) {

                        name[1] = prior;
                        sprintf( newnam, "%s/%s", QUEUE_PATH, name);
                        rename( oldnam, newnam);

                        if ( *name == 'R') {
                           /* make_inactive( name); */
                           kill_printing_request( reqnum, R_CANCEL, CLEAR_ONE);
                           warning( "Request #%d aborted due to a change in priority", 
                              reqnum);
                        }
                     }
                  }
               }
            }
         }
      }
   }

   free( head);

   MLP_unlock( L_CANCEL);

   free( t);
}






/******************************************************************************
   Change the longevity or the printer
******************************************************************************/

void adjust_requests( argc, argv, flag)
int   argc;
char *argv[];
int   flag;
{
   int   n, m, reqnum, filenum, fd;
   char *t, *name, nam[WORKSTR], oper[20], head[HEADER_SIZE], auser[30];
   struct passwd *p;

   p = getpwuid(getuid());

   strcpy( oper, &argv[1][2]);

   if (flag == A_LIFETIME) {
      oper[1] = 0;
      switch (*oper) {
         case 't':
         case 'T': *oper = 'T'; break;
         case 'l':
         case 'L': *oper = 'L'; break;
         case 's':
         case 'S':
         default:  *oper = 'S'; break;
      }
   }

   MLP_lock( L_CANCEL);

   /* Not sure why I want to do this? */
   /* kill_printing_request( 0, R_CANCEL, CLEAR_ALL); */

   t = dirlist( QUEUE_PATH, FALSE);  /* return sorted spool queue list */
                                     /* This list is a two dimensional */
                                     /* (entries x MAXNAMLEN) */
                                     /* Ascending order */

   for (n = 0; *(name = (t+(n * MAXNAMLEN))); n++) {

      if (sscanf( &name[2], "%d", &filenum) == 1) {

         for (m = 2; m <= argc; m++) {
            if (sscanf( argv[m], "%d", &reqnum) == 1) {

               if ( filenum == reqnum) {
                  sprintf( nam, "%s/%s", QUEUE_PATH, name);

                  if ( fd = open( nam, O_RDWR)) {
                     read( fd, head, HEADER_SIZE);

                     strcpy( auser, headerval( head, H_USER, ""));
                     unpadd( auser);

                     if ((p && !strcmp( auser, p->pw_name)) ||
                         (getuid() == 0)) {

                        if ( flag == A_PRINTER)
                           headerval( head, H_PRINTER, oper);
                        else
                           headerval( head, H_LONGEVITY, oper);

                        lseek( fd, 0L, 0);

                        write( fd, head, HEADER_SIZE);
                        close( fd);
 
                        if ( *name == 'R' && flag == A_PRINTER) {
                           /* make_inactive( name); */
                           kill_printing_request( reqnum, R_CANCEL, CLEAR_ONE);

                           warning( "Request #%d aborted because it was moved to a new printer", 
                              reqnum);
                        }
                     }
                  }
               }


            }
         }
      }
   }

   MLP_unlock( L_CANCEL);

   free( t);
}







/******************************************************************************
  Cancel all the requests in the list given.  This is a critical section--we
  cannot allow the despooler to reschedule a request that we just canceled
  before we are able to put the request in the inactive queue.  First we
  cancel the despooling of the request, if necessary.  Then we place the
  request in the inactive part of the queue.  The keyword "all" on the
  command line will cancel all printing and pending reports.
******************************************************************************/

void cancel_all_requests()
{
   int n, val;
   char *t, *name;

   MLP_lock( L_CANCEL);

   kill_printing_request( 0, R_CANCEL, CLEAR_ALL);

   t = dirlist( QUEUE_PATH, FALSE);  /* return sorted spool queue list */
                                     /* This list is a two dimensional */
                                     /* (entries x MAXNAMLEN) */
                                     /* Ascending order */




   for (n = 0; *(name = (t+(n * MAXNAMLEN))); n++)
      if ( *name == 'R') {
         if (do_i_own_it()) {
            make_inactive( name);
            sscanf( &name[2], "%d", &val);
            warning("Request #%d has been canceled.", val);
            printf("#%d canceled\n", val);
         }
      }

   MLP_unlock( L_CANCEL);

   free( t);
}




void cancel_requests( argc, argv)
int   argc;
char *argv[];
{
   int n, m, seqnum, Seqnum;
   char *c, *d, *t, *name, *head;

   if (!strcmp( argv[1], "all")) {
      cancel_all_requests();
      return;
   }


   MLP_lock( L_CANCEL);


   t = dirlist( QUEUE_PATH, FALSE);  /* return sorted spool queue list */
                                     /* This list is a two dimensional */
                                     /* (entries x MAXNAMLEN) */
                                     /* Ascending order */

   head = (char *) calloc( HEADER_SIZE, 1);

   for ( n = 1; n < argc; n++) {

      c = argv[n];

      if ( d = strrchr( c, '-')) c = (d+1);

      seqnum = 0; sscanf( c, "%d", &seqnum);

      if ( seqnum > 0) {

         if (!kill_printing_request( seqnum, R_CANCEL, CLEAR_ONE)) {

            for (m = 0; *(name = (t+(m * MAXNAMLEN))); m++)
               if ( *name == 'R') {
                  sscanf( &name[2], "%d", &Seqnum);

                  if ( Seqnum == seqnum) {

                     if (do_i_own_it()) {
                        make_inactive( name);
                        warning("Request #%d has been canceled.", Seqnum);
                        printf("#%d canceled\n", Seqnum);
                     }
                  }
               }
               else
                  break;
         }
      }
   }

   free( head);

   MLP_unlock( L_CANCEL);

   free( t);
}



/*****************************************************************************
   Print usage message.
*****************************************************************************/

void do_usage()
{
   printf("\nusages:  lpadmin -pprinter [-vdevice] [-mmodel]\n");
   printf("         lpadmin -ddestination\n");
   printf("         lpadmin -xdestination\n\n");
   printf("NOTE:  This utility modifies %s\n", CONTROL_PATH);
   printf("       Models are found in %s\n\n", BACKEND_PATH);
}




/*****************************************************************************
   Delete the given destination from the controls file.  This routine is in
   two parts inorder to reuse some of the code.
*****************************************************************************/

void _delete_destination( dest, newdest, device, backend)
char *dest;
char *newdest;
char *device;
char *backend;
{
   FILE *fp, *newfp;
   char  line[128], *t, tmppath[WORKSTR], tmp[WORKSTR];

   fp = (FILE *) each_printer( E_FILE);

   sprintf( tmppath, "%s.tmp", CONTROL_PATH);

   if ( newfp = fopen( tmppath, "w")) {

      while (fgets( line, sizeof(line), fp)) {
         strcpy( tmp, line);

         if (t = strtok( tmp, SEP)) {

            if (!strcmp( "PRINTER", uppercase( t))) {
               t = strtok( NULL, SEP);
               if (strcmp( dest, t))
                  fprintf( newfp, "%s", line);
            }
            else
               fprintf( newfp, "%s", line);
         }
         else
            fprintf( newfp, "%s", line);
      }


      if ( *newdest)
         fprintf( newfp, "printer = %s, %s, %s\n", newdest, device, backend);

      close( fp);  close( newfp);

      rename( tmppath, CONTROL_PATH);

      chmod( CONTROL_PATH, 0664);
   }
}


void delete_destination( dest)
char *dest;
{
    each_printer( E_START); 
   _delete_destination( dest, "", "", ""); 
    each_printer( E_UNLOCK);
    log( "Remove Printer: %s", dest); 
}





/*****************************************************************************
  Adds a new destination to the controls file.  Any current definition by
  the same name will be overwritten
*****************************************************************************/

add_destination( printer, device, backend)
char *printer;
char *device;
char *backend;
{
    each_printer( E_START);

   _delete_destination( printer, printer, device, backend);

    each_printer( E_UNLOCK);

    log( "Add Printer: %s, device=%s, backend=%s", printer, device, backend); 
}




/*****************************************************************************
   Change the system default destination, checking to see if the destination
   exists first.
*****************************************************************************/

change_destination( dest)
char *dest;
{
   int   ok = FALSE;
   char *list;

   each_printer( E_START);

   while (*(list = each_printer( E_NEXT)))
      if (!strcmp( strtok( list, SEP), dest)) ok = TRUE;

   each_printer( E_END);

   if (ok)
      controls( DEFAULT, dest);
   else
      printf("\007Destination \"%s\" does not exist.\n", dest);

   log( "Change System Default to: %s", dest); 
}




/*****************************************************************************
   Parse the arguments and figure out what function to do.
*****************************************************************************/

lpadmin( argc, argv)
int   argc;
char *argv[];
{
   int n, add, del, dest;
   char printer[20], backend[20], device[129];

   if ( argc == 1) { do_usage(); exit(0); }

   strcpy( printer, "main");
   strcpy( backend, "");
   strcpy( device,  "/dev/null");

   add = del = dest = FALSE;

   for ( n = 1; n < argc; n++) {
      if (!strncmp( argv[n], "-p", 2)) {
         strncpy( printer, &argv[n][2], sizeof( printer));
         add = TRUE;
      }
      else
      if (!strncmp( argv[n], "-x", 2)) {
         strncpy( printer, &argv[n][2], sizeof( printer));
         del = TRUE;
      }
      else
      if (!strncmp( argv[n], "-d", 2)) {
         strncpy( printer, &argv[n][2], sizeof( printer));
         dest = TRUE;
      }
      else
      if (!strncmp( argv[n], "-m", 2))
         strncpy( backend, &argv[n][2], sizeof( backend));
      else
      if (!strncmp( argv[n], "-v", 2))
         strncpy( device, &argv[n][2], sizeof( device));
   }




   if (add) {  /* Add a new printer */
      add_destination( printer, device, backend);
      exit(0);
   }
   
   if (del) {  /* Delete a printer definition */
      delete_destination( printer);
      exit(0);
   }
   
   if (dest) { /* Change the system default printer */
      change_destination( printer);
      exit(0);
   }
}






void main( argc, argv)
int   argc;
char *argv[];
{
   int    n;
   extern char progname[];
   char   user[15], *c;

   umask(FPERMS);

   c = basename( argv[0]);  if (c) strcpy( progname, c);


   /********* If program is called "lpadmin" ***********/

   if (!strcmp( progname, "lpadmin")) {
      if (getuid() == 0) {
         lpadmin( argc, argv);
         wakeup_despooler();
      }
      else
         printf("\007\nSorry, you must be superuser to do this.\n\n");

      exit(0);
   }


   /********* If program is called "cancel" ***********/

   if (!strcmp( progname, "cancel")) {
      if (argc == 1)
         printf("\nusage:  cancel request_num1 request_num2 ... request_numN\n\n");
      else
         cancel_requests( argc, argv);

      wakeup_despooler();

      exit(0);
   }


   /********* If program is called "chreq" ***********/

   if (!strcmp( progname, "chreq")) {
      if (!strncmp( argv[1], "-p", 2) && argc > 2)
         reprioritize_requests( argc, argv);
      else
      if (!strncmp( argv[1], "-d", 2) && argc > 2)
         adjust_requests( argc, argv, A_PRINTER);
      else
      if (!strncmp( argv[1], "-l", 2) && argc > 2)
         adjust_requests( argc, argv, A_LIFETIME);
      else {
         printf("\nusage: chreq -pNew_priority    reqests_num1 request_");
         printf("num2 ... request_numN\n\n");
         printf("             -dNew_destination request_num1 request_");
         printf("num2 ... request_numN\n\n");
         printf("             -lNew_lifetime    request_num1 request_");
         printf("num2 ... request_numN\n\n");
      }

      wakeup_despooler();
      exit(0);
   }



   /********* If program is called "route" ***********/

   if (!strcmp( progname, "route")) {
      strcpy( user, "unknown");

      if ( getlogin())
         strcpy( user, getlogin());

      if ( argc == 1) list_printers( user);
      else
      if ( argv[1] != NULL)
         set_route( user, argv[1]);

      wakeup_despooler();
      exit(0);
   }


   /********* If program is called "lpstat" ***********/
   if ( argc == 1) report_request_status();

   for ( n = 1; n < argc; n++) {
      if (!strcmp( argv[n], "-s")) { /* Summary */
         report_scheduler_status();
         system_default_printer();
         report_printer_status( DEVICE_DISPLAY);
      }
      else
      if (!strcmp( argv[n], "-v")) /* Devices */
         report_printer_status( DEVICE_DISPLAY);
      else
      if (!strcmp( argv[n], "-t")) { /* All */
         report_scheduler_status();
         system_default_printer();
         report_printer_status( DEVICE_DISPLAY);
         report_printer_status( PRINTER_DISPLAY);
         report_request_status();
      }
      else
      if (!strcmp( argv[n], "-q")) /* MLP Queue Status */
         report_mlp_request_status();
      else
      if (!strcmp( argv[n], "-r")) /* Scheduler Status */
         report_scheduler_status();
      else
      if (!strcmp( argv[n], "-p")) /* Printer Status */
         report_printer_status( PRINTER_DISPLAY);
      else
      if (!strcmp( argv[n], "-o")) /* Request Status */
         report_request_status();
      else
      if (!strcmp( argv[n], "-d")) /* Default Destination */
         system_default_printer();
   }

   wakeup_despooler();
}

unix.superglobalmegacorp.com

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