rsalz@uunet.uu.net (Rich Salz) (09/17/88)
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 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.