home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume16
/
plp
/
part16
< prev
next >
Wrap
Text File
|
1988-09-22
|
31KB
|
1,019 lines
Subject: v16i029: Public lineprinter spooler package, Part16/16
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: papowell@julius.cs.umn.edu
Posting-number: Volume 16, Issue 29
Archive-name: plp/part16
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 16 (of 16)."
# Contents: src/control_ops.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/control_ops.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/control_ops.c'\"
else
echo shar: Extracting \"'src/control_ops.c'\" \(28050 characters\)
sed "s/^X//" >'src/control_ops.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: Control_ops.c
X ***************************************************************************
X * Revision History: Created Mon Jan 18 07:48:12 CST 1988
X * $Log: control_ops.c,v $
X * Revision 3.2 88/06/24 17:55:14 papowell
X * MODS for VAX 4.3BSD UNIX
X *
X * Revision 3.1 88/06/18 09:34:02 papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X *
X * Revision 2.2 88/05/14 10:21:23 papowell
X * Modified -X flag handling
X *
X * Revision 2.1 88/05/09 10:07:50 papowell
X * PLP: Released Version
X *
X * Revision 1.9 88/04/28 11:02:11 papowell
X * removed unused variables, shuts up lint
X *
X * Revision 1.8 88/04/27 17:59:14 papowell
X * Added debugging statements to C_lpq, C_lprm
X *
X * Revision 1.7 88/04/07 12:31:32 papowell
X *
X * Revision 1.6 88/04/06 12:12:24 papowell
X * Minor updates, changes in error message formats.
X * Elimination of the AF_UNIX connections, use AF_INET only.
X * Better error messages.
X *
X * Revision 1.5 88/03/25 14:59:13 papowell
X * Debugged Version:
X * 1. Added the PLP control file first transfer
X * 2. Checks for MX during file transfers
X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
X * apparently they open files and then assume that they will stay
X * open.
X * 4. Made sure that stdin, stdout, stderr was available at all times.
X *
X * Revision 1.4 88/03/12 10:03:38 papowell
X * *** empty log message ***
X *
X * Revision 1.3 88/03/11 19:29:57 papowell
X * Minor Changes, Updates
X *
X * Revision 1.2 88/03/05 15:01:56 papowell
X * Minor Corrections, Lint Problems
X *
X * Revision 1.1 88/03/01 11:08:19 papowell
X * Initial revision
X *
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X "$Header: control_ops.c,v 3.2 88/06/24 17:55:14 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X
X#include "lp.h"
X
X/***************************************************************************
X * Control_ops()
X * 1. get the printcap entries
X * 2. check for permissions
X * 3. determine the function to be carried out
X * 4. carry out the function
X ***************************************************************************/
static int op_init; /* flag for operation initialization */
X
X
X/*
X * dispatch is a data structure that contains the names and flagss
X * of control commands.
X */
struct dispatch{
X char *name;
X int distinct;
X int (*routine)();
X int flags;
X char *summary;
X};
X
int C_bad(), C_help(), C_abort(), C_clean(), C_disable(),
X C_enable(), C_exit(), C_kill(), C_restart(), C_lpq(), C_lprm(),
X C_start(), C_status(), C_stop(), C_topq(), C_remote(), C_lpd();
X
X#define NEED_OPT 1 /* we check for other options */
X#define ALL_ALLOWED 2 /* check for all */
X#define NEED_PRIV 4 /* privileged operation */
X#define ALL_DEF 8 /* if no parameter, all is default */
X#define NO_PR_LIST 0x10 /* printer list */
X#define REMOTE_OP 0x20 /* remote allowed */
X#define SERVER_OP 0x40 /* server allowed */
X#define ON_REMOTE 0x80 /* not if you have RM and NW */
X#define IS_OPT(x) ((x)&NEED_OPT)
X#define IS_ALL(x) ((x)&ALL_ALLOWED)
X#define IS_PRIV(x) ((x)&NEED_PRIV)
X#define IS_ALL_DEF(x) ((x)&ALL_DEF)
X#define IS_NO_PR_LIST(x) ((x)&NO_PR_LIST)
X#define IS_REMOTE(x) ((x)&REMOTE_OP)
X#define IS_SERVER(x) ((x)&SERVER_OP)
X#define IS_ON_REMOTE(x) ((x)&ON_REMOTE)
X
static struct dispatch
dispatch[] = {
X{ "", 0, 0, 0, "not a command" },
X{ "?", 1, C_help, 0, "? is same as 'help'" },
X{ "abort", 1, C_abort,
X NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
X "abort ( all | Printer ): kill off server and disable printing" },
X{ "clean", 1, C_clean, NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |ON_REMOTE,
X "clean ( all | Printer ): remove all crud from queue (dangerous!)"},
X{ "disable", 1, C_disable, NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |ON_REMOTE,
X "disable ( all | Printer ): disable queueing"},
X{ "enable", 2, C_enable, NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |ON_REMOTE,
X "enable ( all | Printer ): enable queuing"},
X{ "exit", 2, C_exit, 0, "exit: terminate" },
X{ "help", 1, C_help, 0 ,"help [all] [command]: print command summary"},
X{ "kill", 1, C_kill,
X NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
X "kill ( all | Printer ): kill off server and then restart printing" },
X{ "lpd", 3, C_lpd, 0,
X "lpd : check out lpd process"},
X{ "lpq", 3, C_lpq, 0,
X "lpq ( parms ) : call lpq"},
X{ "lprm", 3, C_lprm, 0,
X "lprm ( parms ) : call lpq"},
X{ "quit", 1, C_exit, 0, "quit (same as exit): terminate" },
X{ "remote", 3, C_remote, 0,
X "remote command: do the action on remote printer"},
X{ "restart", 3, C_restart, NEED_OPT | ALL_ALLOWED |REMOTE_OP |SERVER_OP,
X "restart ( all | Printer ): start a server"},
X{ "start", 4, C_start,
X NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
X "start ( all | Printer ): enable printing and start server"},
X{ "status", 4, C_status, ALL_DEF |ALL_ALLOWED | NEED_OPT,
X "status [all] [Printer]: print status"},
X{ "stop", 3, C_stop,
X NEED_OPT | NEED_PRIV |ALL_ALLOWED |REMOTE_OP |SERVER_OP |ON_REMOTE,
X "stop ( all | Printer ): disable further printing"},
X{ "topq", 1, C_topq, NO_PR_LIST | NEED_OPT |REMOTE_OP | ON_REMOTE| NEED_PRIV,
X "topq Printer (Host | jobnumber)*: move job to top of queue"},
X};
int ncmds = sizeof(dispatch)/sizeof(struct dispatch);
X
X/***************************************************************************
X * Control_ops()
X * This routine is called with the parameters in the Parms[] array.
X * It will check to see if the command is valid, and if so, will
X * do any other actions.
X ***************************************************************************/
int
Control_ops()
X{
X int command; /* command we are going to do */
X char **list; /* list of Printers */
X int i, all; /* doing for all Printers */
X
X /*
X * set the flagss needed
X */
X Is_local = ( strcmp( From, Host ) == 0 );
X Is_root = ( strcmp( Person, "root" ) == 0);
X op_init = 0;
X command = 0;
X all = 0;
X /*
X * check to see that we have a valid command
X */
X if(Debug>4)Show_ops();
X if( Parmcount < 1 ){
X (void)fprintf( stdout, "no command\n" );
X return( 0 );
X }
X command = find_command( Parms[0].str );
X if( command == 0 ){
X (void)fprintf( stdout, "unknown command %s\n", Parms[0].str );
X return( 0 );
X }
X if(Debug>3)log(XLOG_DEBUG,"Control_ops: command %s, flags 0x%x, %s",
X dispatch[command].name,dispatch[command].flags,dispatch[command].summary);
X if( !Is_local && !IS_REMOTE(dispatch[command].flags) ){
X log(XLOG_INFO,"command %s cannot be done remotely", Parms[0].str);
X return( 0 );
X }
X
X /*
X * call the appropriate routine
X */
X Shift_parms(1);
X /*
X * If no option processing just dispatch
X */
X if( !IS_OPT(dispatch[command].flags) ){
X return( (*dispatch[command].routine)(&dispatch[command]));
X }
X /*
X * if no options and IS_ALL is the default, set up the all flag
X */
X if( Parmcount == 0 ){
X if( IS_ALL_DEF(dispatch[command].flags) ){
X all = 1;
X } else {
X (void)fprintf( stdout, "no parameters, use: %s\n",
X dispatch[command].summary);
X return( 0 );
X }
X } else if( strcmp( Parms[0].str, "all" ) == 0 ){
X if( IS_ALL(dispatch[command].flags) ){
X all = 1;
X } else {
X (void)fprintf( stdout, "'all' not allowed, use: %s\n",
X dispatch[command].summary);
X return( 0 );
X }
X }
X /*
X * set up Printer from parameters
X */
X if( all ){
X if(Debug>2)log(XLOG_DEBUG,"'all' parameter" );
X for( list = All_printers(); *list; ++list ){
X Printer = *list;
X if( service( &dispatch[command] ) == 0 ){
X return( 0 );
X }
X }
X } else {
X for( i = 0; i < Parmcount; ++i ){
X Printer = Parms[0].str;
X Shift_parms(1);
X if( service( &dispatch[command] ) == 0 ){
X return( 0 );
X }
X if( IS_NO_PR_LIST(dispatch[command].flags) ){
X break;
X }
X }
X }
X return( 1 );
X}
X
X/***************************************************************************
X * service( struct dispatch *cmd );
X * 1. check on the printcap entry
X * 2. chdir to the spool directory
X * 3. dispatch the particular routine
X ***************************************************************************/
X
service( cmd )
X struct dispatch *cmd;
X{
X char *st, *ps;
X int perms = 'C'; /* Permission Checking */
X
X if(Debug>4)log(XLOG_DEBUG,"service: printer '%s', cmd '%s'",
X Printer, cmd->name );
X if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){
X log(XLOG_INFO,"service: Printer %s does not have printcap entry", Printer);
X return( 0 );
X }
X if( RM && NW && IS_ON_REMOTE(cmd->flags) ){
X (void)fprintf( stdout,
X "remote printer and network file system, use \'remote %s %s\'\n",
X cmd->name, Printer );
X return( 0 );
X }
X /*
X * we may have a server specified
X */
X if( SS && *SS ){
X ps = PS;
X st = ST;
X if( Set_pc_entry(SS, Status_pc_vars, Status_pc_len) == 0){
X log(XLOG_INFO,"service: Server %s queue %s does not have printcap entry",
X Printer,SS);
X return( 0 );
X }
X PS = ps;
X ST = st;
X LO = Printer;
X SV = 0;
X }
X if( SD == 0 || *SD == 0 ){
X log( XLOG_INFO,"service: Printer %s does not have spool directory", Printer);
X return( 0 );
X }
X /* chdir to spool directory */
X if (chdir(SD) < 0) {
X logerr( XLOG_INFO,"service: cannot chdir to %s", SD);
X return( 0 );
X }
X /*
X * check on the privileges needed
X * You have to be local and root OR have C privs
X */
X if( IS_PRIV(cmd->flags) && !( Is_local && Is_root )
X && !( Permfile && *Permfile
X && Checkperm(Permfile,From,Person,First_name,&perms,(int *)0,0))){
X (void)fprintf(stdout,
X "You do not have Printer control perms on '%s'\n", Printer);
X return( 0 );
X }
X return( (*cmd->routine)(cmd));
X}
X
X/***************************************************************************
X * int find_command( char *str )
X * look in the command table for a match. The "distinct" entry is used
X * to determine the numbers of characters for a match.
X ***************************************************************************/
X
int
find_command( str )
X char *str;
X{
X int i;
X
X for( i = 1; i < ncmds; ++ i ){
X if( strncmp( str, dispatch[i].name, dispatch[i].distinct ) == 0
X && strncmp( str, dispatch[i].name, strlen(str)) == 0 ){
X return( i );
X }
X }
X return( 0 );
X}
X
X/***************************************************************************
X * C_bad()
X * Cannot decide what to do with the command
X ***************************************************************************/
int
C_bad()
X{
X (void)fprintf(stdout, "bad command %s\n", Parms[0].str );
X return( 1 );
X}
X/***************************************************************************
X * C_help()
X * Print a help message for each command listed,
X * or a simple list of commands
X ***************************************************************************/
int
C_help()
X{
X int i, cmd;
X
X if( Parmcount < 2 || strcmp( Parms[1].str, "all" ) == 0 ){
X for( i = 1; i < ncmds; ++i ){
X Print_sum( i );
X }
X } else {
X for( i = 1; i < Parmcount; ++i ){
X cmd = find_command( Parms[i].str );
X if( cmd > 0 ){
X Print_sum( cmd );
X } else {
X (void)fprintf(stdout, "not a command: %s", Parms[i].str );
X }
X }
X }
X}
X
X/***************************************************************************
X * Print_sum( cmd )
X * prints the command summary line
X ***************************************************************************/
Print_sum( cmd )
X{
X (void)fprintf(stdout, "%s\n", dispatch[cmd].summary );
X}
X
X
X/***************************************************************************
X * C_exit()
X * terminate gracefully
X ***************************************************************************/
C_exit()
X{
X exit( 0 );
X}
X/***************************************************************************
X * C_stop()
X * Sets the DISABLE_PRINT perm bit in the lockfile perms
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_stop()
X{
X int s;
X
X if(Debug>4)log(XLOG_DEBUG,"C_stop: printer %s, lock '%s'", Printer, LO );
X (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
X if((s=chmod_daemon(LO,(int)(LO_statb.st_mode&0777) |DISABLE_PRINT)) < 0){
X logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
X } else {
X (void)fprintf(stdout,"%s: printing disabled\n", Printer);
X }
X return( s >= 0 );
X}
X/***************************************************************************
X * C_start()
X * 1. Clears the DISABLE_PRINT perm bit in the lockfile perms
X * 2. Starts the Printer
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_start()
X{
X int s;
X
X if(Debug>4)log(XLOG_DEBUG,"C_start: printer %s, lock '%s'", Printer, LO );
X (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
X if((s=chmod_daemon(LO, (int)(LO_statb.st_mode & ENABLE_PRINT))) < 0){
X logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
X } else {
X (void)fprintf(stdout,"%s: printing enabled\n", Printer);
X }
X /*
X * start the server
X */
X if( s >= 0 ){
X s = C_restart();
X }
X return( s >= 0 );
X}
X/***************************************************************************
X * C_disable()
X * Sets the DISABLE_QUEUE perm bit in the lockfile perms
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_disable()
X{
X int s;
X
X if(Debug>4)log(XLOG_DEBUG,"C_disable: printer %s, lock '%s'", Printer, LO );
X (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
X if((s=chmod_daemon(LO,(int)(LO_statb.st_mode&0777) | DISABLE_QUEUE)) < 0){
X logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
X } else {
X (void)fprintf(stdout,"%s: queueing disabled\n", Printer);
X }
X return( s >= 0 );
X}
X/***************************************************************************
X * C_enable()
X * 1. Clears the DISABLE_QUEUE perm bit in the lockfile perms
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_enable()
X{
X int s;
X
X if(Debug>4)log(XLOG_DEBUG,"C_enable: printer %s, lock '%s'", Printer, LO );
X (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
X if((s=chmod_daemon(LO, (int)(LO_statb.st_mode & ENABLE_QUEUE))) < 0){
X logerr(XLOG_INFO,"cannot chmod lockfile %s", LO);
X } else {
X (void)fprintf(stdout,"%s: queueing enabled\n", Printer);
X }
X return( s >= 0 );
X}
X/***************************************************************************
X * C_restart()
X * 1. Attempts to fire up the server
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_restart()
X{
X /*
X * start the server
X */
X
X if(Debug>4)log(XLOG_DEBUG,"C_restart: printer %s, lock '%s'", Printer, LO );
X (void)Startserver();
X return( 1 );
X}
X
X/*
X * killserver(): kills the current server to stop printing
X */
static int
killserver()
X{
X int s; /* Success of operation */
X int pid; /* server PID */
X /*
X * Kill the current server to stop printing now.
X */
X s = 1;
X if( Checklockfile( LO, &pid, (char *)0, 0,&LO_statb )){
X if( kill(pid, SIGINT) < 0 ){
X (void)logerr(XLOG_INFO,"server (pid %d) not killed", pid);
X s = 0;
X } else {
X (void)fprintf(stdout,"%s: server (pid %d) killed\n",
X Printer, pid);
X }
X } else {
X (void)fprintf(stdout,"%s: no server present\n", Printer);
X }
X return(s);
X}
X/***************************************************************************
X * C_abort()
X * 1. Does C_stop()
X * 2. kills off server if there is one
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_abort()
X{
X int s; /* Success of operation */
X
X if(Debug>4)log(XLOG_DEBUG,"C_abort: printer %s, lock '%s'", Printer, LO );
X s = C_stop();
X if( s ){
X s = killserver();
X }
X return( s );
X}
X/***************************************************************************
X * C_kill()
X * 1. Does C_abort()
X * 2. Does C_start()
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_kill()
X{
X int s; /* Success of operation */
X
X if(Debug>4)log(XLOG_DEBUG,"C_kill: printer %s, lock '%s'", Printer, LO );
X s = C_abort();
X if( s ){
X s = C_start();
X }
X return( s );
X}
X
X/***************************************************************************
X * C_clean()
X * 1. Removes all entries in the specified spool directory.
X * Returns: 1 if successful, 0 if not;
X ***************************************************************************/
C_clean()
X{
X int c; /* ACME Integers, Inc. */
X DIR *dirp;
X struct direct *d;
X
X if(Debug>4)log(XLOG_DEBUG,"C_clean: printer %s, lock '%s'", Printer, LO );
X if ((dirp = opendir(SD)) == NULL) {
X logerr(XLOG_INFO,"cannot examine spool directory %s");
X return( 0 );
X }
X while ((d = readdir(dirp)) != NULL) {
X c = d->d_name[0];
X if ((c == 'c' || c == 't' || c == 'd') && d->d_name[1]=='f') {
X if (unlink_daemon(d->d_name) < 0){
X (void)fprintf(stdout,"cannot remove %s\n", d->d_name);
X } else {
X (void)fprintf(stdout,"removed %s\n", d->d_name);
X }
X }
X }
X closedir(dirp);
X return( 1 );
X}
X/*
X * Print the status of each queue listed or all the queues.
X */
static char *hdr_format = "%-12.12s %-4s %-10s %s\n";
static char *data_format = "%-12.12s %4d %-10s %s%s%s\n";
C_status()
X{
X int active, pid; /* active server and its pid */
X char buf[BUFSIZ]; /* buffer */
X char *prstat, *actstat, *qstat, *rqstat; /* Printer and queue status */
X char *st, *ps;
X char sbuf[BUFSIZ]; /* status buffer */
X char servers[BUFSIZ];
X char *sp, *ep, *sr; /* ACME Pointers, Inc. */
X
X if(Debug>3)log(XLOG_INFO,"C_status: printer %s", Printer);
X if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){
X log(XLOG_INFO,"Printer %s does not have printcap entry", Printer);
X return( 0 );
X }
X /* we have a server here */
X if( SS && *SS ){
X ps = PS;
X st = ST;
X if( Set_pc_entry(SS, Status_pc_vars, Status_pc_len) == 0){
X log(XLOG_INFO,"Server %s queue %s does not have printcap entry",
X Printer,SS);
X return( 0 );
X }
X PS = ps;
X ST = st;
X LO = Printer;
X SV = 0;
X }
X if( SD == 0 || *SD == 0 ){
X log( XLOG_INFO,"Printer %s does not have spool directory", Printer);
X return( 0 );
X }
X /* chdir to spool directory */
X if (chdir(SD) < 0) {
X logerr( XLOG_INFO,"cannot chdir to %s", SD);
X return( 0 );
X }
X /*
X * start by getting active server information
X */
X buf[0] = 0;
X active = Checklockfile( LO, &pid, buf, sizeof( buf),&LO_statb);
X
X /*
X * get numbers of jobs in queue
X */
X
X Jobcount = Getq();
X
X /*
X * now format the info appropriately
X */
X qstat = (LO_statb.st_mode & DISABLE_QUEUE) ? "disabled " : "enabled ";
X prstat = ( LO_statb.st_mode & DISABLE_PRINT) ? "disabled " : "enabled ";
X /*
X * get active server
X */
X if(Debug>4)log(XLOG_DEBUG,"C_status: active '%d', Jobcount '%d', '%s'",
X active, Jobcount, buf );
X if( SV == 0 || *SV == 0 ){
X if( Jobcount == 0 && active == 0 ){
X (void)sprintf( sbuf,"" );
X } else if( Jobcount == 0 && active ){
X (void)sprintf( sbuf,"(server %d)", pid, buf );
X } else if( Jobcount && active == 0 ){
X (void)sprintf( sbuf,"(no server)" );
X } else {
X (void)sprintf( sbuf,"(server %d, job %s)", pid, buf );
X }
X actstat = sbuf;
X } else {
X (void)strcpy( servers, SV );
X (void)sprintf( sbuf, hdr_format, "", "", "X", "" );
X if( (sp = index( sbuf, 'X' ) ) == 0 ){
X fatal(XLOG_INFO,"C_status: header format bad" );
X }
X *sp = 0;
X for( sp = servers; sp; sp = ep ){
X ep = index( sp, ',');
X if( ep ){
X *ep = 0;
X ep = ep + 1;
X }
X active = Checklockfile( sp, &pid,buf,sizeof(buf),&LO_statb );
X if( LO_statb.st_mode & DISABLE_PRINT){
X sr = "dis";
X } else {
X sr = "enb";
X }
X if( active == 0 ){
X (void)sprintf( sbuf+strlen(sbuf),"(%s: %s, no server)",sp, sr);
X } else {
X (void)sprintf( sbuf+strlen(sbuf),"(%s: %s, %d, job %s)",
X sp, sr, pid, buf );
X }
X }
X actstat = sbuf;
X }
X if( LO_statb.st_mode & FORCE_REQUE ){
X rqstat = ", reorder requested";
X } else {
X rqstat = "";
X }
X /* displays heading if not already displayed */
X if (!op_init) {
X (void)fprintf(stdout,hdr_format,
X SS ? "Server" : "Queue", "Jobs", "Queueing", "Printing" );
X op_init = 1;
X }
X /* prints the queue status */
X (void)fprintf(stdout,data_format, Printer, Jobcount, qstat,
X prstat,rqstat,actstat);
X /* prints the Printer status */
X printstatus();
X (void)fflush(stdout);
X return(1);
X}
X
X/*
X * Put the specified jobs at the top of Printer queue.
X */
C_topq()
X{
X int i; /* ACME Integer, Inc. */
X int changed; /* We changed the queue */
X char *cfname; /* control file name */
X
X (void)fprintf(stdout,"%s:\n", Printer);
X
X /*
X * put the parameters in the list in the correct position
X */
X if( Parmcount == 0 ){
X if(Debug>4)log(XLOG_DEBUG,"C_topq: no parameters" );
X return( 0 );
X }
X if(Debug>4)log(XLOG_DEBUG,"C_topq: '%s'(%d)", Parms[0].str, Parms[0].num );
X /* get number of jobs in the queue */
X Jobcount = Getq();
X /*
X * go through the queue and find the jobs to be promoted
X */
X changed = 0;
X for( i = 0; i < Jobcount; ++i ){
X if(Match_entry( &Queue[i] )){
X /*
X * Reposition the job by setting its priority to high level
X * and then fix the control file
X */
X if(promote(Queue[i].q_name)) {
X changed++;
X Queue[i].q_name[0] = 0;
X }
X }
X }
X /*
X * Put the other high priority jobs lower
X */
X if( !changed ){
X return( 1 );
X }
X for( i = 0; i < Jobcount; i++) {
X cfname = Queue[i].q_name;
X if(*cfname && cfname[2] == 'A'){
X touch(cfname);
X }
X }
X (void)fprintf(stdout, "queue order changed\n");
X /*
X * Turn on the public execute bit of the lock file to
X * get lpd to rebuild the queue after the current job.
X */
X (void)Checklockfile( LO, (int *)0,(char *)0,0,&LO_statb );
X if( chmod_daemon(LO, (int)(LO_statb.st_mode & 0777) | FORCE_REQUE) < 0 ){
X logerr( XLOG_INFO, "cannot force requeue on lockfile %s", LO );
X return( 0 );
X }
X return( 1 );
X}
X
X/***************************************************************************
X * promote( char *cfname )
X * promote a file to the A priority, and head of the list.
X ***************************************************************************/
promote(cfname)
X char *cfname;
X{
X char buf[BUFSIZ];
X
X (void)strcpy( buf, cfname);
X buf[STARTPR] = 'A';
X if(Debug>0)log( XLOG_DEBUG, "renaming %s to %s", cfname, buf );
X if( strcmp( buf, cfname) && rename( cfname, buf ) < 0 ){
X logerr( XLOG_INFO,"cannot rename %s to %s", cfname, buf );
X return(0);
X }
X (void)fprintf( stdout, "promoting %s to %s\n", cfname, buf );
X return( 1 );
X}
X
X
X/*
X * Change the modification time of the file.
X * Returns boolean if successful.
X */
touch(cfname)
X char *cfname;
X{
X FILE *fp;
X int i;
X
X if( (fp = Lockcf(cfname)) == NULL ){
X logerr(XLOG_INFO,"cannot open %s\n", cfname);
X } else if( (i = getc(fp)) == EOF ){
X logerr(XLOG_INFO,"cannot read %s\n", cfname);
X } else if(fseek(fp, 0L, 0) < 0 ){;
X /* set pointer back to top of file */
X logerr(XLOG_INFO,"cannot seek %s\n", cfname);
X } else if( putc( i, fp) == EOF ){
X logerr(XLOG_INFO,"cannot write %s\n", cfname);
X } else if( fflush( fp ) == EOF ){
X logerr(XLOG_INFO,"cannot flush %s\n", cfname);
X }
X if( fp != NULL ){
X (void)fclose(fp);
X }
X}
X
X/*
X * Show_ops()
X * show the values of the local options
X */
X
Show_ops()
X{
X int i;
X (void)fprintf(stdout,"From: %s, Host %s, Person %s\n",From,Host,Person);
X (void)fprintf(stdout,"Is_local %d, Is_root %d\n", Is_local, Is_root );
X (void)fprintf(stdout,"Parmcount %d ", Parmcount );
X for( i = 0; i < Parmcount; ++i ){
X (void)fprintf(stdout, " '%s'(%d)", Parms[i].str, Parms[i].num );
X }
X (void)fprintf(stdout,"\n");
X (void)fflush(stdout);
X}
X
X/***************************************************************************
X * C_lpq()
X * invoke Lpq with parameters.
X * use the "system()" facility to do this.
X ***************************************************************************/
C_lpq()
X{
X char buf[BUFSIZ];
X char *bp, *ep; /* ACME Pointers, Inc. */
X int i;
X
X ep = buf+sizeof(buf);
X bp = estrcp( buf, "lpq", ep );
X for( i = 0; i < Parmcount; ++i ){
X bp = estrcp( bp, " ", ep );
X bp = estrcp( bp, Parms[i].str, ep );
X }
X if(Debug>4)log(XLOG_DEBUG,"C_lpq: '%s'", buf );
X i = system( buf );
X if(Debug>4)log(XLOG_DEBUG,"C_lpq: status %d", i );
X return( i );
X}
X
X/***************************************************************************
X * C_lprm()
X * invoke Lprm with parameters.
X * use the "system()" facility to do this.
X ***************************************************************************/
C_lprm()
X{
X char buf[BUFSIZ];
X char *bp, *ep; /* ACME Pointers, Inc. */
X int i;
X
X ep = buf+sizeof(buf);
X bp = estrcp( buf, "lprm", ep );
X for( i = 0; i < Parmcount; ++i ){
X bp = estrcp( bp, " ", ep );
X bp = estrcp( bp, Parms[i].str, ep );
X }
X if(Debug>4)log(XLOG_DEBUG,"C_lprm: '%s'", buf );
X i = system( buf );
X if(Debug>4)log(XLOG_DEBUG,"C_lprm: status %d", i );
X return( i );
X}
X
X/***************************************************************************
X * C_remote()
X * do the indicated command on the remote host
X * command has the form: "remote op printer"
X * 1. get the command and see if it can be done remotely
X * Parms[0] will be op, Parms[1] will be printer
X * 2. check the printer and make sure that it is a remote printer
X * 3. send the remote command to the far end, and get the information
X * sent back.
X ***************************************************************************/
X
C_remote(cmd)
X struct dispatch *cmd;
X{
X char **list; /* list of printers */
X int i; /* ACME Integers and Bearings, Inc. */
X int command; /* command we are going to do */
X
X if( Parmcount < 2 ){
X (void)fprintf( stdout, "no or missing command or parameters\n" );
X return( 0 );
X }
X command = find_command( Parms[0].str );
X if( command == 0 ){
X (void)fprintf( stdout, "unknown command %s\n", Parms[0].str );
X return( 0 );
X }
X if(Debug>3)log(XLOG_DEBUG,"C_remote: command %s, %d, %s",
X dispatch[command].name,dispatch[command].flags,dispatch[command].summary);
X
X if( !IS_REMOTE(dispatch[command].flags) ){
X (void)fprintf( stdout, "command %s cannot be done remotely\n",
X Parms[0].str );
X }
X
X /*
X * check on the printer
X */
X if( strcmp("all", Parms[0].str) == 0){
X if(Debug>2)log(XLOG_DEBUG,"'all' parameter" );
X for( list = All_printers(); *list; ++list ){
X Printer = *list;
X if( remote_cando(dispatch[command].flags) ){
X Remote_control(dispatch[command].name);
X }
X }
X } else {
X for( i = 1; i < Parmcount; ++i ){
X Printer = Parms[i].str;
X if( remote_cando(dispatch[command].flags) ){
X Remote_control(dispatch[command].name);
X }
X }
X }
X return( 1 );
X}
X
X/***************************************************************************
X * remote_cando()
X * returns 0 if not able to do to remote site, 1 otherwise
X *
X ***************************************************************************/
remote_cando(flags)
X{
X int perms = 'C'; /* Permission Checking */
X
X if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){
X log(XLOG_INFO,"Printer %s does not have printcap entry", Printer);
X return( 0 );
X }
X if( RM == 0 || RP == 0 ){
X if(Debug>5)log(XLOG_DEBUG,"%s not remote", Printer );
X return( 0 );
X }
X /*
X * check on the privileges needed
X * You have to be local and root OR have C privs
X */
X if( IS_PRIV(flags) && !( Is_local && Is_root )
X && !( Permfile && *Permfile
X && Checkperm(Permfile,From,Person,First_name,&perms,(int *)0,0))){
X (void)fprintf(stdout,
X "You do not have printer control perms on '%s'\n", Printer);
X return( 0 );
X }
X return( 1 );
X}
X
X/***************************************************************************
X * C_lpd()
X * 1. Check to see if there is an active lpd server by checking the
X * lock file.
X * 2. Check to see if the /dev/printer is available as well.
X ***************************************************************************/
X
C_lpd()
X{
X int f;
X
X (void)Checklockfile(Masterlock, &f, (char *)0, 0, &LO_statb );
X if(f){
X (void)fprintf(stdout, "active LPD %d\n", f );
X } else {
X (void)fprintf( stdout, "LPD is not active\n" );
X }
X (void)fflush(stdout);
X}
END_OF_FILE
if test 28050 -ne `wc -c <'src/control_ops.c'`; then
echo shar: \"'src/control_ops.c'\" unpacked with wrong size!
fi
# end of 'src/control_ops.c'
fi
echo shar: End of archive 16 \(of 16\).
cp /dev/null ark16isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 16 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0