v16i029: Public lineprinter spooler package, Part16/16

Rich Salz rsalz at uunet.uu.net
Sat Sep 17 04:30:16 AEST 1988


Submitted-by: papowell at 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

-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.



More information about the Comp.sources.unix mailing list