v16i019: Public lineprinter spooler package, Part06/16

Rich Salz rsalz at uunet.uu.net
Thu Sep 15 06:17:40 AEST 1988


Submitted-by: papowell at julius.cs.umn.edu
Posting-number: Volume 16, Issue 19
Archive-name: plp/part06

#! /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 6 (of 16)."
# Contents:  filters/pf_main.c src/checkperm.c src/displayq.c src/lpc.c
#   src/lpq.c src/lpr_job.c
# Wrapped by papowell at attila on Wed Aug 10 10:44:55 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'filters/pf_main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'filters/pf_main.c'\"
else
echo shar: Extracting \"'filters/pf_main.c'\" \(8221 characters\)
sed "s/^X//" >'filters/pf_main.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: pf_main.c for prefilters
X ***************************************************************************
X * Revision History: Created Fri Mar  4 19:45:03 CST 1988
X * $Log:	pf_main.c,v $
X * Revision 2.1  88/05/09  10:12:12  papowell
X * *** empty log message ***
X * 
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X	"$Header: pf_main.c,v 2.1 88/05/09 10:12:12 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X/***************************************************************************
X *  UMN-LPR prefilter template and frontend.
X *
X *	A prefilter is invoked with the following parameters,
X *  which can be in any order, and perhaps some missing.
X *
X *  filtername arguments \   <- from PRINTCAP entry
X *      -PPrinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \
X *		[-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost  \
X *      -Fformat -Ddebug files
X * 
X *  1. Parameters can be in different order than the above.
X *  2. Optional parameters can be missing
X *  3. Values specified for the width, length, etc., are from PRINTCAP
X *     or from the overridding user specified options.
X *
X *  This program provides a common front end for most of the necessary
X *  grunt work.  This falls into the following classes:
X * 1. Parameter extraction.
X * 2. Picking off files.
X *  The front end will extract parameters,  then call the prefilter(file)
X *  routine,  which is responsible for carrying out the required prefilter
X *  actions.
X *
X *  The prefilter() routine should return 0 (success), 1 (retry) or 2 (abort).
X *
X * Parameter Extraction
X *	The main() routine will extract parameters
X *  whose values are placed in the appropriate variables.  This is done
X *  by using the ParmTable[], which has entries for each valid letter
X *  parmeter, such as the letter flag, the type of variable,
X *  and the address of the variable.
X *  The following variables are provided as a default set.
X *      -PPrinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \
X *		[-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost  \
X *      -Fformat files
X * VARIABLE  FLAG          TYPE    PURPOSE / PRINTCAP ENTRTY
X * name     name of filter char*    argv[0], program identification
X * width    -wwidth	       int      PW, width in chars
X * length   -llength	   int      PL, length in lines
X * xwidth   -xwidth        int      PX, width in pixels
X * xlength  -xlength       int      PY, length in pixels
X * literal  -c	           int      if set, ignore control chars
X * indent   -iindent       int      indent amount (depends on device)
X * zopts    -Zoptions      char*    extra options for printer
X * class    -Cclass        char*    classname
X * job      -Jjob          char*    jobname
X * accntname -Raccntname   char*    account for billing purposes
X * login    -nlogin        char*    login name
X * host     -hhost         char*    host name
X * format   -Fformat       char*    format
X * accntfile file          char*    AF, accounting file
X *
X * debug     - sets debug level
X *
X *	The functions fatal(), logerr(), and logerr_die() can be used to report
X *	status. The variable errorcode can be set by the user before calling
X *	these functions, and will be the exit value of the program. Its default
X *	value will be 2 (abort status).
X *	fatal() reports a fatal message, and terminates.
X *	logerr() reports a message, appends information indicated by errno
X *	(see perror(2) for details), and then returns.
X *	logerr_die() will call logerr(), and then will exit with errorcode
X *	status.
X *	Both fatal() and logerr_die() call the cleanup() function before exit.
X *
X * DEBUGGING:  a simple minded debugging version can be enabled by
X * compiling with the -DDEBUG option.
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <sys/file.h>
X
int errorcode = 2;
X
char *name;		/* name of filter */
X/* set from flags */
int debug, width, length, xwidth, ylength, literal, indent;
char *zopts, *class, *job, *login, *accntname, *host, *format;
char *printer;
int optind;
X
main( argc, argv )
X	int argc;
X	char **argv;
X{
X	int i;
X
X	getargs( argc, argv );
X
X	/*
X	 * Turn off SIGPIPE
X	 */
X	(void)signal( SIGPIPE, SIG_IGN );
X	errorcode = 0;
X	for( i = optind; i < argc; ++ i ){
X		errorcode = prefilter( argv[i] );
X	}
X	return(errorcode);
X}
X
X/*VARARGS1*/
log(msg, a1, a2, a3)
X	char *msg;
X{
X	(void)fprintf(stderr, "%s: ", name);
X	(void)fprintf(stderr, msg, a1, a2, a3);
X	(void)putc('\n', stderr);
X	(void)fflush(stderr);
X}
X
X/*VARARGS1*/
fatal(msg, a1, a2, a3)
X	char *msg;
X{
X	log(msg, a1, a2, a3);
X	cleanup();
X	exit(errorcode);
X}
X
X/*VARARGS1*/
logerr(msg, a1, a2, a3)
X	char *msg;
X{
X	extern int errno, sys_nerr;
X	extern char *sys_errlist[];
X	int err = errno;
X
X	(void)fprintf(stderr, "%s: ", name);
X	if (msg){
X		(void)fprintf(stderr, msg, a1, a2, a3);
X		(void)fputs( "- ", stderr);
X	}
X	if( err < sys_nerr ){
X		(void)fputs(sys_errlist[err]);
X	} else {
X		(void)fprintf(stderr, "Unknown error %d", err);
X	}
X	(void)putc('\n', stderr);
X	(void)fflush(stderr);
X}
X
X/*VARARGS1*/
logerr_die(msg, a1, a2, a3)
X	char *msg;
X{
X	logerr(msg, a1, a2, a3);
X	cleanup();
X	exit(errorcode);
X}
X
getargs(argc, argv)
X	int argc;
X	char **argv;
X{
X	int i;		/* argument index */
X	char *arg;	/* argument */
X	int flag;	/* flag */
X
X	name = argv[0];
X	for( i = 1; i < argc; ++i ){
X		arg = argv[i];
X		if( *arg == '-' ){ /* arg will be string */
X				setvar( arg[1], &arg[2] );
X		} else {
X			optind = i;
X			break;
X		}
X	}
X	if( debug ){
X		for( i = 0; i < argc; ++i ){
X			fprintf(stdout, "%s ", argv[i] );
X		}
X		fprintf( stdout, "\n" );
X		printf("login '%s'\n", login? login : "null" );
X		printf("host '%s'\n", host? host : "null" );
X		printf("class '%s'\n", class? class : "null" );
X		printf("format '%s'\n", format? format : "null" );
X		printf("job '%s'\n", job? job : "null" );
X		printf("printer '%s'\n", printer? printer : "null" );
X		printf("accntname '%s'\n", accntname? accntname : "null" );
X		printf("zopts '%s'\n", zopts? zopts : "null" );
X		printf("literal, %d\n", literal);
X		printf("indent, %d\n", indent);
X		printf("length, %d\n", length);
X		printf("width, %d\n", width);
X		printf("xwidth, %d\n", xwidth);
X		printf("ylength, %d\n", ylength);
X		for( i = 0; i < argc; ++i ){
X			fprintf(stderr, "%s ", argv[i] );
X		}
X		fprintf( stderr, "\n" );
X		fflush(stderr);
X		fflush(stdout);
X	}
X}
X			
X#define INTV 0
X#define STRV 1
X#define FLGV 2
struct parm {
X	int flag;
X	char **var;
X	int kind;
X} Parmlist[] = {
X{'C', &class, STRV },
X{'D', (char **)&debug, INTV },
X{'F', &format, STRV },
X{'J', &job, STRV },
X{'P', &printer, STRV },
X{'R', &accntname, STRV },
X{'Z', &zopts, STRV },
X{'c', (char **)&literal, FLGV },
X{'h', &host, STRV },
X{'i', (char **)&indent, INTV },
X{'l', (char **)&length, INTV },
X{'n', &login, STRV },
X{'w', (char **)&width, INTV },
X{'x', (char **)&xwidth, INTV },
X{'y', (char **)&ylength, INTV } };
X
int Parmlen = sizeof(Parmlist)/sizeof(struct parm);
X
X/*
X * setvar( int flag, char *arg )
X * 1. look in table and find entry
X * 2. if STRV, then set 
X * 3. if INTV, then convert and set
X * 4. if FLGV, then set to 1
X */
setvar( flag, arg )
X	int flag;
X	char *arg;
X{
X	int u, l, i, c;	/* upper, lower, i */
X
X	l = 0; u = Parmlen;
X	while( l <= u ){
X		i = (u+l)/2;
X		c = flag - Parmlist[i].flag;
X		if( 0 == c ){
X			/* printf( "found parm %c, %d\n", flag, i ); */
X			switch( Parmlist[i].kind ){
X			case STRV: *Parmlist[i].var = arg; break;
X			case INTV: *(int *)Parmlist[i].var = atoi(arg); break;
X			case FLGV: *(int *)Parmlist[i].var = 1; break;
X			}
X			return;
X		} else if( c < 0 ){
X			/* printf( "down parm %c, %d\n", flag, i ); */
X			u = i - 1 ;
X		} else {
X			/* printf( "up parm %c, %d\n", flag, i ); */
X			l = i + 1 ;
X		}
X	}
X	/* printf( "did not find parm %c, %d\n", flag, i ); */
X	return;
X}
X
X#ifdef DEBUG
cleanup() {}
X
prefilter( file )
X	char *file;
X{
X	FILE *fp;
X	int c;
X
X	log( "file %s", file );
X	if( (fp = fopen( file, "r" )) == NULL ){
X		fatal( "cannot open file %s", file );
X	}
X	while( (c = getc(fp)) != EOF ){
X		putchar(c);
X    }
X}
X#endif DEBUG
END_OF_FILE
if test 8221 -ne `wc -c <'filters/pf_main.c'`; then
    echo shar: \"'filters/pf_main.c'\" unpacked with wrong size!
fi
# end of 'filters/pf_main.c'
fi
if test -f 'src/checkperm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/checkperm.c'\"
else
echo shar: Extracting \"'src/checkperm.c'\" \(8361 characters\)
sed "s/^X//" >'src/checkperm.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: Checkperm.c
X * printer permission checking
X ***************************************************************************
X * Revision History: Created Sun Jan  3 19:08:26 CST 1988
X * $Log:	checkperm.c,v $
X * Revision 3.1  88/06/18  09:33:59  papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X * 
X * Revision 2.4  88/05/27  08:27:23  papowell
X * Fixed the '~' permissions line
X * 
X * Revision 2.3  88/05/21  10:26:22  papowell
X * Added check for '~' or always
X * 
X * Revision 2.2  88/05/16  09:44:32  papowell
X * Modified match() to handle null strings better
X * 
X * Revision 2.1  88/05/09  10:07:46  papowell
X * PLP: Released Version
X * 
X * Revision 1.3  88/04/07  09:11:14  papowell
X * Modified 'while' loop; removed break
X * 
X * Revision 1.2  88/03/25  14:59:09  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.1  88/03/01  11:08:18  papowell
X * Initial revision
X * 
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X	"$Header: checkperm.c,v 3.1 88/06/18 09:33:59 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X/******************************************************************************
X * Checkperm - determine if a user has permissions to act on a printer queue
X *
X * Input:
X *  permfile - name of the permissions file,
X *    each line of which has the form:
X *		hostname userid printer_name op pr max current
X * 		hostname - the host name of the invoker
X * 		userid - the user name of the invoker
X * 		printer_name - the printer queue to be checked
X *		op -the maximum operation level, A is 'Highest', Z is 'lowest'
X *			Note: R is for LPR, C is for LPC, * allows all
X *		pr - the maximum priority level, A is 'Highest', Z is 'lowest'
X *		max - max number of pages allowed
X *		current - current number of pages
X *
X *	# -- comment
X *	#hostname username printername op pr maxpages currentpages
X *	attila    papowell imagen      C  A  1000     100
X *  !*        cs9*     lpr         *  *
X *	*         jsmith   imagen      *  *  0        0
X *	*         root     *           *  *
X *	
X *	Note: * is the wildcard indicator and matches all characters
X *	Note: if maxpages == 0, then page count is unlimited.
X *  Note: if a ! is in the first column  and there is a match
X *    (i.e.- we should grant permission), then permission is refused.
X *    In the example above, this prevents users whose names start with
X *    cs9 will be forbidden access to the lpr queue.
X *
X * Output:
X * 0 - if userid does not have permissions to act on printer queue
X * nonzero - permission granted
X *
X * If any of arguments is not specified (i.e.- 0 or NULL value),
X * then checking is not done for the field.
X *****************************************************************************/
X
X#include "lp.h"
X
int
Checkperm(permfile, host, user, printerq, op, pr_level, pages)
X	char	*permfile;	/* file to read for permissions */
X	char	*host;		/* hostname to check for */
X	char	*user;		/* username to check for */
X	char	*printerq;	/* printername to check for */
X	int		*op;		/* operation level to check for */
X	int		*pr_level;	/* priority level to check for */
X	int		pages;		/* check page limits flag */
X{
X	FILE	*fp;
X	int		i;
X	char	buf[BUFSIZ];
X	char	username[MAXPARMLEN+1];
X	char	hostname[MAXPARMLEN+1];
X	char	printerqname[MAXPARMLEN+1];
X	char	priority[MAXPARMLEN+1];
X	char	operation[MAXPARMLEN+1];
X	char	*str;
X	int		max, current;
X	int		permission = 0;
X	int		invert, must, found;
X
X	must = 0;
X	invert = 0;
X	if( permfile == 0 ){
X		logerr( XLOG_INFO, "Checkperm: no perm file" );
X		return(permission);
X	}
X	if(Debug>5)log(XLOG_DEBUG,
X	"Checkperm file %s,host=%s,user=%s,printerq=%s,op=%c,pr_level=%c,pages=%d",
X		permfile, host?host:"NONE", user?user:"NONE", printerq?printerq:"NONE",
X		 op?*op:'?', pr_level?*pr_level:'?', pages);
X	/*
X	 * open permfile for reading
X	 */
X	if((fp = fopen_daemon(permfile,"r")) == NULL){
X		logerr( XLOG_CRIT, "Checkperm: cannot open perms file %s",permfile);
X		return(permission);
X	}
X
X	/*
X	 * scan through the file looking for a match
X	 */
X	found = 0;
X	while( found == 0 && fgets( buf, sizeof(buf), fp ) != NULL ){
X		/* read in the host name */
X		/* sscanf returns number of fields converted */
X		if( buf[0] == '\n' || buf[0] == '#' ){
X			continue;
X		}
X		must = 0;
X		invert = 0;
X		max = current = 0;
X		priority[0] = 0;
X		operation[0] = 0;
X		str = buf;
X		switch( buf[0] ){
X			case '!': invert = 1; ++str; break;
X			case '~': must = 1; ++str; break;
X		}
X		i = sscanf(str, "%s%s%s%s%s%d%d", hostname, username,
X				printerqname,operation,priority,&max,&current);
X		if( i == 0 ){
X			continue;
X		} else if( i < 4 ){
X			log(XLOG_CRIT,
X			"Error in %s, '%s'\n  Please inform system guru.", permfile, buf);
X			(void)fclose(fp);
X			return(permission);
X		}
X		if(Debug>6)log(XLOG_DEBUG,
X			"host=%s,user=%s,printer=%s,oper=%s,priority=%s,max%d,current%d",
X			hostname, username, printerqname,operation,priority,max,current );
X
X		/*
X		 * if the hostname field is '*', this means any host can do it
X		 * otherwise we should check to see if a valid host name
X		 */
X		if( !match(host,hostname) ){
X			if( must ){
X				found = 1;
X			}
X			continue;
X		}
X		if(Debug>6)log(XLOG_DEBUG, "Checkperm: host ok, %s, %s",
X			host?host:"<NONE>",hostname);
X
X		/* compare the user names */
X		if( !match(user,username) ){
X			if( must ){
X				found = 1;
X			}
X			continue;
X		}
X		if(Debug>6)log(XLOG_DEBUG, "Checkperm: user ok, %s, %s",
X			user?user:"<NONE>",username);
X
X		/* compare the printer queue names */
X		if( !match(printerq,printerqname) ){
X			if( must ){
X				found = 1;
X			}
X			continue;
X		}
X		if(Debug>6)log(XLOG_DEBUG, "Checkperm: printerq ok, %s, %s",
X			printerq?printerq:"<NONE>",printerqname);
X
X		/* compare the operations */
X		if( op && operation[0] != '*' && *op < operation[0]){
X			if( must ){
X				found = 1;
X			}
X			continue;
X		}
X		if(Debug>6)log(XLOG_DEBUG,
X			"Checkperm: OK, must %d, wanted %c(%d), have %c(%d), invert %d",
X			must, op?*op:'?', op?*op:'?', operation[0], operation[0], invert);
X		/*
X		 * Well, you had to have a match, and you did.  So this means that
X		 * you passed, but you do not use this entry.
X		 */
X		if( must ){
X			continue;
X		}
X		if(Debug>6)log(XLOG_DEBUG,
X			"Checkperm: pages- %d, max %d, current %d", pages,max,current);
X		found = 1;
X		permission = 1;
X		if( pages && max && current > max ){
X			/* page limit exceeded in first matching entry: bad news */
X			permission = 0;
X		}
X		if( pr_level && priority[0] && priority[0] != '*'){
X			/* we want to check priory and there are limits */
X			if( priority[0] > *pr_level ){
X				/* sorry, this is too high */
X				*pr_level = priority[0];
X			}
X		}
X	}
X	if( permission && invert ){
X		permission = 0;
X	}
X	if(Debug>4)log(XLOG_DEBUG,"Checkperm %d in %s, printerq %s for %s@%s",
X		permission, permfile,
X		printerq?printerq:"NONE",user?user:"NONE",host?host:"NONE");
X	(void)fclose(fp);
X	return(permission);
X}
X
X/*
X * match( str, pattern )
X *  -- str is null (match returns 1 )
X *	-- pattern is <fixed>*, str is <fixed><anything> (match returns 1)
X *  -- pattern is !<fixed>*, str is <fixed><anything> (match returns 0)
X *	-- if not above, match returns 0
X */
X
static int
match( str, pattern)
X	char *str, *pattern;
X{
X	int c;
X
X	if(Debug>8)log(XLOG_DEBUG,"match str '%s', pattern '%s'\n", str, pattern );
X	if( str == 0 || pattern == 0) return(1);
X	while( c = *pattern ){
X		if(Debug>8)log(XLOG_DEBUG,"match partial str '%s', pattern '%s'\n",
X			str, pattern );
X		switch( c ){
X			/*
X			 * match 0 or more characters in the string
X			 */
X			case '*':
X				if( match( str, pattern+1 ) ){
X					return( 1 );
X				}
X				if( *str && match( str+1, pattern ) ){
X					return( 1 );
X				}
X				return( 0 );
X			case '?':
X				if( *str == 0 ){
X					return( 0 );
X				}
X				break;
X			default:
X				if( c != *str ){
X					return( 0 );
X				}
X				break;
X		}
X		++pattern; ++str;
X	}
X	return( *pattern == *str );
X}
END_OF_FILE
if test 8361 -ne `wc -c <'src/checkperm.c'`; then
    echo shar: \"'src/checkperm.c'\" unpacked with wrong size!
fi
# end of 'src/checkperm.c'
fi
if test -f 'src/displayq.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/displayq.c'\"
else
echo shar: Extracting \"'src/displayq.c'\" \(7973 characters\)
sed "s/^X//" >'src/displayq.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: displayq.c
X * Display the status of a Printer queue
X ***************************************************************************
X * Revision History: Created Sat Jan  9 20:08:26 CST 1988
X * $Log:	displayq.c,v $
X * Revision 3.1  88/06/18  09:34:07  papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X * 
X * Revision 2.3  88/05/16  12:09:08  papowell
X * Added a queue printing, spooling message
X * 
X * Revision 2.2  88/05/14  10:17:57  papowell
X * Use long format for job file names;
X * Added 'fd', no forward flag;
X * Control file has to have hostname and origination agree.
X * 
X * Revision 2.1  88/05/09  10:07:58  papowell
X * PLP: Released Version
X * 
X * Revision 1.6  88/04/06  12:13:18  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:21  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:25  papowell
X * *** empty log message ***
X * 
X * Revision 1.3  88/03/11  19:28:04  papowell
X * Minor Changes, Updates
X * 
X * Revision 1.2  88/03/05  15:01:25  papowell
X * Minor Corrections,  Lint Problems
X * 
X * Revision 1.1  88/03/01  11:08:21  papowell
X * Initial revision
X * 
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X	"$Header: displayq.c,v 3.1 88/06/18 09:34:07 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X
X#include "lp.h"
static int header;
static int server;
X
X/***************************************************************************
X * Displayq()
X *  1. get the printcap entries
X *  2. get the queue entries
X *  3. get the active server files and see if they are in queue
X *  4. print the queue status
X ***************************************************************************/
X
Displayq()
X{
X	int i;				/* ACME Integers, Inc. */
X	struct queue *q;	/* job entry */
X	char buf[BUFSIZ];	/* status message buffer */
X
X	header = 0;
X	/*
X	 * get the printcap entry
X	 */
X	if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){
X		(void)fprintf(stdout, "Printer %s does not exist\n", Printer );
X		(void)fflush(stdout);
X		return;
X	}
X	if( SD == 0 || *SD == 0 ){
X		if(Debug>0)log(XLOG_DEBUG,"Printer %s does not have a spool queue\n",
X			Printer);
X		return;
X	}
X	
X	if(Debug>5)log(XLOG_DEBUG,"Displayq: doing %s", Printer );
X	/*
X	 * If you are running NFS, use the remote lpr
X	 */
X	if( RM && *RM && NW ){
X		Remote_status();
X		return;
X	}
X	/* chdir to spool directory */
X	if (chdir(SD) < 0) {
X		logerr_die( XLOG_NOTICE,"cannot chdir to %s", SD);
X	}
X	/*
X	 * get the numbers of jobs here
X	 */
X	Jobcount = Getq();
X	/*
X	 * Checkactive checks for the active jobs
X	 */
X	server = Checkactive();
X	buf[0] = 0;
X	if( LO_statb.st_mode & DISABLE_QUEUE ){
X		(void)strcat(buf, "no spooling" );
X	}
X	if( LO_statb.st_mode & DISABLE_PRINT ){
X		if( buf[0] ){
X			(void)strcat( buf, ", ");
X		}
X		(void)strcat(buf, "no printing" );
X	}
X
X	if( Short_format ){
X		if( From == Host ){
X			(void)fprintf(stdout,"%s: %d jobs", Printer, Jobcount );
X		} else {
X			(void)fprintf(stdout,"%s@%s: %d jobs", Printer, Host, Jobcount );
X		}
X		if( buf[0] ){
X			(void)fprintf(stdout," (%s)", buf );
X		}
X		(void)fprintf(stdout,"\n");
X	} else {
X		if( From == Host ){
X			if( SV == 0 || *SV == 0 ){
X				(void)fprintf(stdout, "Printer '%s' (%s):", Printer, Host );
X			} else {
X				(void)fprintf(stdout, "Queue '%s' (%s):", Printer, Host );
X			}
X			if( buf[0] ){
X				(void)fprintf(stdout," (%s)", buf );
X			}
X			(void)fprintf(stdout,"\n");
X		} else {
X			if( SV == 0 || *SV == 0 ){
X			(void)fprintf(stdout, "Remote printer '%s' (%s):",Printer,Host);
X			} else {
X			(void)fprintf(stdout, "Remote queue '%s' (%s):", Printer, Host );
X			}
X			if( buf[0] ){
X				(void)fprintf(stdout," (%s)", buf );
X			}
X			(void)fprintf(stdout,"\n");
X		}
X		/*
X		 * show status files
X		 */
X		showstatus();
X	}
X	(void)fflush(stdout);
X	/*
X	 * run down list
X	 */
X	for( i = 0; i < Jobcount; ++i ){
X		q = &Queue[i];
X		if( Parmcount <= 0 || Match_entry( q ) ){
X			showentry(i+1, q);
X		}
X	}
X	if( RM && *RM ){
X		Remote_status();
X	}
X	if( From == Host ){
X		putchar('\n');
X	}
X}
X
X/*****************************************************************************
X * showentry( int seq, struct queue *q )
X *  show status for entry
X * Rank   Owner      Pr Job  Host         Files                Size
X * active sutantha   Z  260  umn-cs       (stdin)              177744 bytes
X * 2      powell     Z    1  attila       junk, morejunk,...   32767 bytes
X *
X * if you have multiple servers, the first column will contain the name
X * of the server.
X * Rank   Owner      Pr Job  Host         Files                Size
X * sv1    sutantha   Z  260  umn-cs       (stdin)              177744 bytes
X * sv2    powell     Z    1  attila       junk, morejunk,...   32767 bytes
X *****************************************************************************/
X
static char hdr_format[] = "%6s %-11s %-2s %-3s %-11s %-20s %-6s %-s\n";
static char info_format[] = "%6s %-11s %-c  %-3d %-11s %-20s %-6d %s\n";
X
static char *
short_time( tvec )
X	time_t tvec;		/* time */
X{
X	char *ctime();
X	static char s[40];
X
X	/*
X	 *	012345678901234567890123456789
X	 *	Mon May 30 20:53:27 CDT 1988
X	 */
X	(void)strcpy(s,ctime(&tvec));
X	s[16] = 0;
X	return( &s[4] );
X}
showentry( seq, q )
X	int seq;
X	struct queue *q;
X{
X	char buf[10];
X	char *suffix;
X	char name[BUFSIZ];
X	char date[BUFSIZ];
X
X	if( Short_format ){
X		(void)fprintf(stdout,"%d %s: %s\n", seq, q->q_name, q->q_user );
X		(void)fflush(stdout);
X		return;
X	}
X	if( header == 0 ){
X		(void)fprintf(stdout, hdr_format,"Rank","Owner","Pr","Job",
X			"Host","Files","Size","Date");
X		header = 1;
X	}
X	if( q->q_daemon ){
X		if( SV == 0 || *SV == 0 ){
X			(void)strcpy( buf, "active" );
X		} else {
X			(void)strcpy( buf, q->q_server );
X		}
X	} else {
X		switch( seq ){
X		case 1: suffix = "st"; break;
X		case 2: suffix = "nd"; break;
X		case 3: suffix = "rd"; break;
X		default: suffix = "th"; break;
X		}
X		(void)sprintf(buf, "%d%s", seq, suffix );
X	}
X	/*
X	 * print short name
X	 */
X	(void)strcpy(name, &q->q_from );
X	suffix = index( name, '.' );
X	if( suffix ){
X		*suffix = 0;
X	}
X	(void)fprintf(stdout, info_format, buf, q->q_user, q->q_priority, q->q_num,
X		name,q->q_data, q->q_size, short_time(q->q_sp) );
X	(void)fflush(stdout);
X}
X
X/*
X * show status:
X * show the status files for the server devices
X */
showstatus()
X{
X	static char server_name[BUFSIZ];	/* Name of server file */
X	int active, pid;
X	char buf[BUFSIZ];
X	char *sp, *ep;			/* ACME Pointer */
X
X	if( SV == 0 || *SV == 0 ){
X		if( Jobcount > 0 && server == 0 ){
X			(void)fprintf(stdout, "Warning: no server present\n" );
X		}
X		printstatus();
X		return;
X	}
X	/*
X	 * check for each of the servers
X	 */
X	(void)strcpy( server_name, SV );
X	for( sp = server_name; sp; sp = ep ){
X		if( ep = index( sp, ',' ) ){
X			*ep = 0;
X			++ep;
X		}
X		/*
X		 * get the lock file and the status from the server
X		 */
X		if( Set_pc_entry( sp, Server_pc_vars, Server_pc_len ) == 0 ){
X			fatal( XLOG_INFO, "no server entry for %s", sp );
X		}
X		buf[0] = 0;
X		active = Checklockfile( sp, &pid,buf,sizeof(buf),&LO_statb );
X		(void)fprintf(stdout, " server- %s", sp );
X		if( LO_statb.st_mode & DISABLE_PRINT ){
X			(void)fprintf(stdout, " disabled");
X		} else {
X			(void)fprintf(stdout, " enabled");
X		}
X		if( active ){
X			(void)fprintf(stdout, ", server %d, processing %s",pid, buf );
X		}
X		putchar( '\n' );
X		(void)fflush( stdout );
X		printstatus();
X	}
X}
X
END_OF_FILE
if test 7973 -ne `wc -c <'src/displayq.c'`; then
    echo shar: \"'src/displayq.c'\" unpacked with wrong size!
fi
# end of 'src/displayq.c'
fi
if test -f 'src/lpc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/lpc.c'\"
else
echo shar: Extracting \"'src/lpc.c'\" \(8375 characters\)
sed "s/^X//" >'src/lpc.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: lpc.c
X * lpc - control LPR queues
X ***************************************************************************
X * Revision History: Created Mon Jan 25 14:04:26 CST 1988
X * $Log:	lpc.c,v $
X * Revision 3.1  88/06/18  09:34:36  papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X * 
X * Revision 2.2  88/05/14  10:21:01  papowell
X * Modified -X flag handling
X * 
X * Revision 2.1  88/05/09  10:08:40  papowell
X * PLP: Released Version
X * 
X * Revision 1.7  88/04/27  18:02:54  papowell
X * The SIGCHLD signal has an odd behaviour on some systems.  Modified so that
X * it will not get set UNLESS processes are started;  also,  it is reset
X * to SIG_DFL, not SIG_IGN.
X * 
X * Revision 1.6  88/04/15  13:06:23  papowell
X * Std_environ() call added, to ensure that fd 0 (stdin), 1 (stdout), 2(stderr)
X * have valid file descriptors;  if not open, then /dev/null is used.
X * 
X * Revision 1.5  88/04/07  12:32:26  papowell
X * Modified to use Getopt
X * 
X * Revision 1.4  88/04/06  12:12:17  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.3  88/03/25  15:00:00  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.2  88/03/11  19:28:21  papowell
X * Minor Changes, Updates
X * 
X * Revision 1.1  88/03/01  11:08:35  papowell
X * Initial revision
X * 
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X	"$Header: lpc.c,v 3.1 88/06/18 09:34:36 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X#include "lp.h"
X
X
X/***************************************************************************
X * SYNOPSIS
X *      lpc [ -Dn ] [ -X [ command [ argument ... ] ]
X * DESCRIPTION
X *      Lpc  is  used  by  the  system  administrator to control the
X *      operation  of the line printer system. For each line printer
X *      configured in /etc/printcap, lpc may be used to:
X *      + disable or enable a printer,
X *      + disable or enable a printer's spooling queue,
X *      + rearrange the order of jobs in a spooling queue,
X *      + find the status of printers, and their associated spooling
X *        queues and printer dameons.
X *      Without any arguments, lpc will prompt for commands from the
X *      standard  input.   If arguments are supplied, lpc interprets
X *      the  first argument as a command and the remaining arguments
X *      as  parameters  to  the  command.  The standard input may be
X *      redirected causing lpc to read commands from file.  Commands
X *      may  be  abreviated; the following is the list of recognized
X *      commands.
X *      ? [ command ... ]
X *      help [ command ... ]
X *      abort { all | printer ... }
X *      clean { all | printer ... }
X *      enable { all | printer ... }
X *      exit
X *      quit
X *      disable { all | printer ... }
X *      restart { all | printer ... }
X *      start { all | printer ... }
X *      kill { all | printer ... }
X *      status [ terse ] [ all ] [ printer ... ]
X *      stop { all | printer ... }
X *      remote { abort | clean | enable | disable | restart  } printer
X *      topq printer [ jobnum ... ] [ user ... ]
X *      lpq [options]
X *      lprm [options]
X *      lpd
X *
X *      -Dn  Enables  display  of  debugging  information.   The  -D
X *           selects  level  1;  -Dn  selects level n (n is a single
X *           digit).
X *      -X   Use  an  Xperimental version of LPD if the software has
X *           been  compiled  with  the  appropriate support; ignored
X *           otherwise.
X ***************************************************************************/
X/***************************************************************************
X * main(int argc, char **argv)
X * 1. get the host computer name and user name
X * 2. set up the Host and Person information
X * 3. get the parameters or set up a read from STDIN
X * 4. convert parameters and call the server routine
X ****************************************************************************/
X
extern int cleanup();
X
main(argc, argv)
X	int argc;
X	char **argv;
X{
X	struct passwd *pw_ent;		/* user entry in /etc/passwd */
X
X	/*
X	 * set umask to avoid problems with user umask
X	 */
X	(void)umask(0);
X	/*
X	 * Set fd 0, 1, 2 to /dev/null if not open
X	 */
X	Std_environ();
X#	ifdef XPERIMENT
X		Setup_test();
X#	endif XPERIMENT
X
X	/*
X     * set up the pathnames for information files
X	 */
X	Tailor_names();
X	/*
X	 * set the from flag
X	 */
X	From = Host;
X	/*
X	 * get the user name
X	 */
X	if( (pw_ent = getpwuid( getuid() )) == 0 ){
X		logerr_die( XLOG_INFO, "lpc: getpwuid failed on uid %d", getuid());
X	}
X	(void)strcpy( LOGNAME, pw_ent->pw_name );
X	Person = LOGNAME;
X	if( getuid() == 0 ){
X		/* we are being invoked by root */
X		Is_root = 1;
X	}
X	/*
X	 * setup parameters
X	 */
X	Lpc_parms(argc, argv);
X	/*
X	 * set signals
X	 */
X	(void)signal(SIGPIPE, SIG_IGN);
X	(void)signal(SIGHUP, cleanup);
X	(void)signal(SIGINT, cleanup);
X	(void)signal(SIGQUIT, cleanup);
X	(void)signal(SIGTERM, cleanup);
X	if( Parmcount != 0 ){
X		(void)Control_ops();
X	} else {
X		Get_line();
X	}
X	exit( 0 );
X}
X
X/***************************************************************************
X * cleanup()
X * remove the temp files
X ***************************************************************************/
X
cleanup()
X{
X	exit( 1 );
X}
X
X/***************************************************************************
X * Lpc_parms( int arc, char **argv )
X * 1. pick off the options
X * 2. set up the parameters
X ***************************************************************************/
X
static char *optstr = "D:X";
static int Xpert;
Lpc_parms( argc, argv )
X	int argc;
X	char **argv;
X{
X	int option;
X	int i;
X
X	while( (option = Getopt(argc,argv,optstr)) != EOF ){
X		switch( option ){
X		case 'D':
X			if(Debug){
X				Diemsg("Duplicate -D option");
X			}
X			if( sscanf( Optarg, "%d", &Debug ) != 1 || Debug <= 0){
X				Diemsg("-D parameter is not positive integer" );
X			}
X			break;
X		case 'X':
X			if( Xpert ){
X				Diemsg("Duplicate -X option");
X			}
X#	ifdef DEBUG
X			Setup_test();
X			Tailor_names();
X#	else
X			Diemsg("-X is not allowed" );
X#	endif DEBUG
X			break;
X		default:
X			break;
X		}
X	}
X
X	/*
X	 * set up the Parms[] array
X	 */
X	for( ; Optind < argc; ++Optind ){
X		if( Parmcount < MAXPARMS ){
X			Parms[Parmcount].str = argv[Optind];
X			i = atoi( Parms[Parmcount].str );
X			if( i > 0 ){
X				Parms[Parmcount].num = i;
X			} else {
X				Parms[Parmcount].num = -1;
X			}
X			++Parmcount;
X		} else {
X			Diemsg( "too many parameters" );
X		}
X	}
X}
X
X
X/***************************************************************************
X * Get_line()
X * Repeat:
X * 1. Get a line.
X * 2. if EOF return
X * 3. Split it up and put into Parms[]
X * 4. Call Control_ops()
X ***************************************************************************/
X
Get_line()
X{
X	char buf[BUFSIZ];	/* get a line */
X	int i;				/* ACME Integers, Inc. */
X	char *cp;			/* ACME Pointers, Inc. */
X
X	while( 1 ){
X		(void)fprintf(stdout, "lpc>");
X		(void)fflush(stdout);
X		if( fgets( buf, sizeof(buf), stdin ) == 0 ) return;
X		buf[ strlen(buf) -1 ] = 0;	/* clobber the last char */
X		/*
X		 * now set up the parameters
X		 */
X		Parmcount = 0;
X		for( cp = buf; *cp; ){
X			/* skip leading blanks */
X			Parms[Parmcount].str = 0;
X			Parms[Parmcount].num = -1;
X			while( *cp && isspace( *cp ) ) ++cp;
X			if( *cp ){
X				Parms[Parmcount].str = cp;
X			}
X			while( *cp && !isspace( *cp ) ) ++cp;
X			if( *cp ){
X				*cp = 0;
X				++cp;
X			}
X			if( Parms[Parmcount].str != 0 ){
X				Parms[Parmcount].num = -1;
X				i = atoi( Parms[Parmcount].str );
X				if( i > 0 ){
X					Parms[Parmcount].num = i;
X				}
X				++Parmcount;
X			}
X		}
X		if( Parmcount ){
X			if(Debug>3){
X				for( i = 0; i < Parmcount; ++i ){
X					(void)fprintf(stderr,"Parms[%d]: '%s', %d\n",i,
X						Parms[i].str,Parms[i].num );
X				}
X			}
X			(void)Control_ops();
X		}
X	}
X	/*NOTREACHED*/
X}
END_OF_FILE
if test 8375 -ne `wc -c <'src/lpc.c'`; then
    echo shar: \"'src/lpc.c'\" unpacked with wrong size!
fi
# end of 'src/lpc.c'
fi
if test -f 'src/lpq.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/lpq.c'\"
else
echo shar: Extracting \"'src/lpq.c'\" \(8037 characters\)
sed "s/^X//" >'src/lpq.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: lpq.c
X ***************************************************************************
X * Revision History: Created Mon Feb  1 11:34:11 CST 1988
X * $Log:	lpq.c,v $
X * Revision 3.2  88/07/01  15:44:39  papowell
X * Added multiple -P parameters
X * 
X * Revision 3.1  88/06/18  09:34:43  papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X * 
X * Revision 2.2  88/05/14  10:20:56  papowell
X * Modified -X flag handling
X * 
X * Revision 2.1  88/05/09  10:08:54  papowell
X * PLP: Released Version
X * 
X * Revision 1.7  88/04/28  11:03:01  papowell
X * removed unused variables,  shuts up lint
X * 
X * Revision 1.6  88/04/27  18:02:50  papowell
X * The SIGCHLD signal has an odd behaviour on some systems.  Modified so that
X * it will not get set UNLESS processes are started;  also,  it is reset
X * to SIG_DFL, not SIG_IGN.
X * 
X * Revision 1.5  88/04/15  13:06:14  papowell
X * Std_environ() call added, to ensure that fd 0 (stdin), 1 (stdout), 2(stderr)
X * have valid file descriptors;  if not open, then /dev/null is used.
X * 
X * Revision 1.4  88/04/07  12:26:49  papowell
X * modified to use Getopt
X * 
X * Revision 1.3  88/03/25  15:00:11  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.2  88/03/11  19:28:16  papowell
X * Minor Changes, Updates
X * 
X * Revision 1.1  88/03/01  11:08:39  papowell
X * Initial revision
X * 
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X	"$Header: lpq.c,v 3.2 88/07/01 15:44:39 papowell Locked $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X#include "lp.h"
X
X/***************************************************************************
X *   lpq - spool queue examination program
X *   lpq [-Pprinter ][-a][-l][+[n]][-D[n]][-X][ job # ... ][ user ... ]
X * DESCRIPTION
X *   lpq examines the spooling area used by lpd(8) for printing
X *   files on the line printer, and reports the status of the
X *   specified jobs or all jobs associated with a user. lpq
X *   invoked without any arguments reports on the printer given
X *   by the default printer (see -P option).  For each job sub-
X *   mitted (i.e. invocation of lpr(1)) lpq reports the user's
X *   name, current rank in the queue, the names of files compris-
X *   ing the job, the job identifier (a number which may be sup-
X *   plied to lprm(1) for removing a specific job), and the total
X *   size in bytes.  Job ordering is dependent on the algorithm
X *   used to scan the spooling directory and is FIFO (First in
X *   First Out), in order of priority level.  File names compris-
X *   ing a job may be unavailable (when lpr(1) is used as a sink
X *   in a pipeline) in which case the file is indicated as
X *   ``(stdin)''.  The following options are available.
X *   -P printer  spool queue name
X *   -a   All printers listed in /etc/printcap(5) file are reported.
X *   -l   aLternate display format
X *   [+[n]] redisplay the spool queue
X *   -D[n]  debug level n
X *   -X   Use an Xperimental version of LPD
X *   [ job # ... ][ user ... ]
X ***************************************************************************/
X
static int Delay;	/* time to wait */
static int Do_all_pr;		/* do all printers */
static int Xpert;			/* X flag */
static char **Printer_name;
static int Printer_count;
static int Max_printer_count;
int cleanup();
X
main( argc, argv )
X	int argc;
X	char **argv;
X{
X	struct passwd *pw_ent;		/* user entry in /etc/passwd */
X	int i;
X
X	/*
X	 * set umask to avoid problems with user umask
X	 */
X	(void)umask(0);
X	/*
X	 * Set fd 0, 1, 2 to /dev/null if not open
X	 */
X	Std_environ();
X#	ifdef XPERIMENT
X		Setup_test();
X#	endif XPERIMENT
X
X	/*
X     * set up the pathnames for information files
X	 */
X	Tailor_names();
X	/*
X	 * set up the from information
X	 */
X	From = Host;
X	/*
X	 * get the user name
X	 */
X	if( (pw_ent = getpwuid( getuid() )) == 0 ){
X		logerr_die( XLOG_INFO, "getpwuid failed on uid %d", getuid());
X	}
X	(void)strcpy( LOGNAME, pw_ent->pw_name );
X	Person = LOGNAME;
X	/*
X	 * get the parameters
X	 */
X	Get_parms(argc, argv);
X	(void)signal(SIGPIPE, SIG_IGN);
X	(void)signal(SIGHUP, cleanup);
X	(void)signal(SIGINT, cleanup);
X	(void)signal(SIGQUIT, cleanup);
X	(void)signal(SIGTERM, cleanup);
X	do{
X		/*
X		 * if we are to clear the terminal, do so
X		 */
X		if( Delay ){
X			Term_clear();
X		}
X		/*
X		 * if we have all printers to display, do so
X		 */
X		if( Do_all_pr ){
X			Display_all();
X		} else if( Printer_count == 0 ){
X				Displayq();
X		} else {
X			for( i = 0; i < Printer_count; ++i ){
X				Printer = Printer_name[i];
X				Displayq();
X			}
X		}
X		if( Delay ){
X			sleep( (unsigned)Delay );
X		}
X	} while( Delay );
X	exit( 0 );
X}
X
X
X/***************************************************************************
X * Get_parms( argc, argv )
X * 1. set up the name routine
X * 2. extract parameters
X *  -Pprinter sets Printer to printer
X *  -Dn set Debug to n
X *  -a   sets Do_all_pr
X *  -l   set Short_format
X *  -X   sets Xpert
X *  +nn
X ***************************************************************************/
static char *optstr= "P:D:alX+?";
Get_parms( argc, argv )
X	int argc;
X	char **argv;
X{
X	int c;		/* ACME Integers, Inc. */
X	char *arg;	/* argument from list */
X
X	Opt_flag = "+";
X	while( (c = Getopt(argc,argv,optstr)) != EOF ){
X		switch( c ){
X		case 'P':
X			if( Printer_count == Max_printer_count ){
X				if( Max_printer_count == 0 ){
X					Max_printer_count = 3;
X					Printer_name =
X						(char **)malloc( Max_printer_count * sizeof(char *));
X				} else {
X					Max_printer_count += 3;
X					Printer_name =
X						(char **)realloc( Printer_name,
X							Max_printer_count * sizeof(char *));
X				}
X			}
X			Printer_name[Printer_count] =  Optarg;
X			++Printer_count;
X			break;
X		case 'D':
X			Check_already( c, &Debug );
X			if( Optarg ){
X				Debug = atoi( Optarg );
X			} else {
X				Debug = 1;
X			}
X			break;
X		case 'a':
X			Check_already( c, &Do_all_pr );
X			break;
X		case 'l':
X			Check_already( c, &Short_format );
X			break;
X		case 'X':
X			Check_already( c, &Xpert );
X#	ifdef DEBUG
X			Setup_test();
X			Tailor_names();
X#	else
X			Diemsg( "-X not allowed" );
X#	endif DEBUG
X			break;
X		case '+':
X			/**************************************
X			 [+[n]] set Delay to n
X			 **************************************/
X			Check_already( c, &Delay );
X			if( Optarg ){
X				Delay = atoi( Optarg );
X			}
X			if( Delay == 0 ){
X				Delay = 30;
X			}
X			break;
X		default:
X			Usemsg();
X			exit(1);
X		}
X	}
X	for(; Optind < argc; ++Optind ){
X		arg = argv[Optind];
X		Parms[Parmcount].str = arg;
X		if( isdigit( *arg ) ){
X			Parms[Parmcount].num = atoi( arg );
X		} else {
X			Parms[Parmcount].num = -1;
X		}
X		++Parmcount;
X		if( Parmcount >= MAXPARMS ){
X			Diemsg( "Too many arguments" );
X		}
X	}
X	/*
X	 * pick up the default printer name
X	 */
X	Get_Printer(0);
X}
X
static
Check_already( c, v )
X	int c;
X	int *v;
X{
X	if( *v ){
X		Usemsg();
X		Diemsg( "-%c has already been specified", c);
X	}
X	*v = 1;
X}
X
Usemsg()
X{
X	(void)fprintf(stderr,
X	"use: lpq [-Pprinter] [-alX] [+[n]] [-Dn] (job# | user)*\n");
X}
X
X/***************************************************************************
X * Display_all()
X * 1. get the printer list
X * 2. for each printer in the list call Displayq
X ***************************************************************************/
X
Display_all()
X{
X	char **list;
X
X	for( list = All_printers(); *list; ++list ){
X		Printer = *list;
X		Displayq();
X	}
X}
X/***************************************************************************
X * cleanup()
X * remove the temp files
X ***************************************************************************/
X
cleanup()
X{
X	Term_finish();
X	exit( 1 );
X}
END_OF_FILE
if test 8037 -ne `wc -c <'src/lpq.c'`; then
    echo shar: \"'src/lpq.c'\" unpacked with wrong size!
fi
# end of 'src/lpq.c'
fi
if test -f 'src/lpr_job.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/lpr_job.c'\"
else
echo shar: Extracting \"'src/lpr_job.c'\" \(9221 characters\)
sed "s/^X//" >'src/lpr_job.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: lpr_job.c
X * Submit job in the spool directory
X ***************************************************************************
X * Revision History: Created Sat Jan 30 18:11:41 CST 1988
X * $Log:	lpr_job.c,v $
X * Revision 3.2  88/06/24  17:55:45  papowell
X * MODS for VAX 4.3BSD UNIX
X * 
X * Revision 3.1  88/06/18  09:34:57  papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X * 
X * Revision 2.1  88/05/09  10:09:19  papowell
X * PLP: Released Version
X * 
X * Revision 1.6  88/05/06  07:08:11  papowell
X * Modified getwd() call so that a setreuid() is done first.  This way there
X * are no problems with root perms on different systems.
X * 
X * Revision 1.5  88/05/05  20:07:24  papowell
X * Minor changes to shut up lint.
X * 
X * Revision 1.4  88/04/06  12:08:06  papowell
X * Minor change, the 'A'printer control line not put in control file.
X * This allows the existing version to send control files to older versions.
X * 
X * Revision 1.3  88/03/25  15:00:35  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.2  88/03/11  19:28:08  papowell
X * Minor Changes, Updates
X * 
X * Revision 1.1  88/03/01  11:08:49  papowell
X * Initial revision
X * 
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X	"$Header: lpr_job.c,v 3.2 88/06/24 17:55:45 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X
X#include "lpr.h"
X
char *Make_link();
char *Full_path();
extern char *getwd();
X
X
X/***************************************************************************
X * Make_job()
X * 1. Get a control file (actually a temp file)
X * 2. Write the header information into the file
X * 3. If you have a filter output, queue that
X * 4. otherwise if you have a simple file, queue that
X * 5. otherwise copy all of the files 
X ***************************************************************************/
X
Make_job()
X{
X	char *cf;			/* control file name */
X	FILE *cfp;			/* control file fp */
X	int fd;				/* data file fd */
X	int i, c;			/* ACME Integers, Inc. */
X	long j, jobsize;	/* jobsize is a long */
X	char *s;			/* ACME Pointers, Inc. */
X	struct stat f_stat, c_stat;	/* source and copy files status */
X
X	/*
X	 * get the control file
X	 */
X	jobsize = 0;
X	cf = Get_cf();
X	i = Open_SD( cf );
X	if( (cfp = fdopen( i, "w")) == NULL ){
X		logerr_die( XLOG_INFO, "Make_job: IMPOSSIBLE- fdopen failed %s",cf);
X	}
X	/*
X	 * place in the time
X	 */
X	(void)sprintf( WHENSP, "%lu", (unsigned long)time( (time_t *)0 ));
X	/*
X	 * Put entries in for each character in the Parms list
X	 */
X	for( i = 'A'; i <= 'Z'; ++i ){
X		s = CFparm[i-'A'];
X		if( s[0] ){
X			Entry( i, s, cfp );
X		}
X	}
X	/* set the job name to the first file if not specified */
X	if( Parmcount == 0 ){
X		Entry( 'N', "(stdin)", cfp );
X		if( JOBNAME[0] == 0 ){
X			Entry( 'J', "(stdin)", cfp );
X		}
X	} else {
X		for( i = 0; i < Parmcount; ++i ){
X			if( Parms[i].str ){
X				Entry( 'N', Parms[i].str, cfp );
X				if( JOBNAME[0] == 0 ){
X					Entry( 'J', Parms[i].str, cfp );
X					JOBNAME[0] = 'X';
X				}
X			}
X		}
X	}
X	/* set the class name to the priority if not specified */
X	if( CLASSNAME[0] == 0 ){
X		CLASSNAME[0] = Priority;
X		CLASSNAME[1] = 0;
X		Entry( 'C', CLASSNAME, cfp );
X	}
X	/*
X	 * put out the created files or copy the ones passed
X	 * First find if there are any.
X	 */
X	s = Filter_out? Filter_out : Read_stdin;
X	if( s ){
X		Get_stat( SD, s, &f_stat );
X		j = (f_stat.st_size + 1023) / 1024;
X		for( c = 0; c == 0 || c < Copies; ++c ){
X			Entry( Format, s, cfp );
X			jobsize += j;
X			if( MX && jobsize > MX ){
X				Diemsg( "job too large. split up" );
X			}
X			Entry( 'U', s, cfp );
X		}
X	} else {
X		/*
X		 * we create an entry for each file in the list
X		 */
X		for( i = 0; i < Parmcount; ++i ){
X			if( Parms[i].str ){
X				/*
X				 * repeat the check for printability
X				 */
X				if( (fd = Is_printable( Parms[i].str, &f_stat )) < 0 ){
X					fatal(XLOG_CRIT, "Make_job: file %s become bad, %s@%s",
X						Parms[i].str, Person, Host );
X				}
X				if( Use_links ){
X					/*
X				 	 * try to make a symbolic link to the file
X					 */
X					s = Make_link(Parms[i].str, &c_stat );
X				} else {
X					/*
X				 	 * make a copy in the spool directory
X					 */
X					s = Copy_file( fd, Parms[i].str, &c_stat);
X				}
X				(void)strcpy(Parms[i].filename, s);
X				(void)close(fd);
X				if( f_stat.st_size != c_stat.st_size ){
X					fatal(XLOG_CRIT,"Make_job: file %s changed, %s@%s",
X						Parms[i].str, Person, Host );
X				}
X				Parms[i].size = (f_stat.st_size + 1023)/1024;
X				if(Debug>4)log(XLOG_DEBUG,"Make_job: %s -> %s, %d",
X					Parms[i].str, Parms[i].filename, Parms[i].size );
X			}
X		}
X		for( c = 0; c == 0 || c < Copies; ++c ){
X			for( i = 0; i < Parmcount; ++i ){
X				if( Parms[i].str ){
X					Entry( Format, Parms[i].filename, cfp );
X					jobsize += Parms[i].size;
X					if( MX && jobsize > MX ){
X						Diemsg( "job too large (over %ldK). split up", jobsize);
X					}
X				}
X			}
X		}
X		/*
X		 * Remove the file after we have used it
X		 */
X		for( i = 0; i < Parmcount; ++i ){
X			if( Parms[i].str ){
X				Entry( 'U', Parms[i].filename, cfp );
X				if( Remove && Use_links == 0 ){
X					/* set the EUID to user */
X					Set_uid( getuid() );
X					if( unlink( Parms[i].str ) < 0 ){
X						Warnmsg( "could not remove %s- %s",Parms[i].str,
X							Errormsg(errno) );
X					}
X					Clear_uid();
X				}
X			}
X		}
X	}
X	/*
X	 * flush the control file and rename it
X	 */
X	if( fflush( cfp ) == EOF ){
X		logerr_die(XLOG_INFO, "cannot flush %s", cf );
X	}
X	if( fclose( cfp ) == EOF ){
X		logerr_die(XLOG_INFO, "cannot close %s", cf );
X	}
X	Rename_cf(cf);
X}
X
X/***************************************************************************
X * Entry( char c; char *cp; FILE *fp )
X * Prints a line out in the control file
X ***************************************************************************/
XEntry( c, cp, fp )
X	int c;
X	char *cp;
X	FILE *fp;
X{
X	int d;
X
X	d = 0;
X	if(Debug>4)log(XLOG_DEBUG,"Entry: %c '%s'", c, cp );
X	if( strlen( cp ) > MAXPARMLEN ){
X		d = cp[MAXPARMLEN];
X		cp[MAXPARMLEN] = 0;
X	}
X	if( fprintf( fp, "%c%s\n", c, cp ) == EOF ){
X		logerr_die( XLOG_INFO, "error while writing control file" );
X	}
X	if( d ){
X		cp[MAXPARMLEN] = d;
X	}
X}
X
X
X/***************************************************************************
X * Make_link( char *target, struct stat *statb )
X * makes a link to the target, and puts out entry
X ***************************************************************************/
static char *
Make_link( target, statb )
X	char *target;
X	struct stat *statb;
X{
X#ifdef NOSYMLINK
X	fatal( XLOG_INFO, "no symbolic links allowed" );
X#else  NOSYMLINK
X	char *lf;	/* link file */
X	char buf[MAXPATHLEN];
X	uid_t ruid, euid;
X
X	euid = geteuid();
X	/*
X	 * get temp file name
X	 */
X	lf = Get_tmp_data();
X	(void)sprintf(buf,"%s/%s", SD, lf );
X	/*
X	 * generate absolute path name
X	 */
X	target = Full_path( target );
X	if(Debug>3)log(XLOG_DEBUG,"Make_link: from %s to %s", buf, target );
X	Set_daemon();
X	if( symlink( target, buf ) < 0 ){
X		logerr_die( XLOG_INFO, "Make_link: symbolic link from %s to %s failed",
X			buf, target );
X	}
X	if( stat( target, statb ) < 0 ){
X		logerr_die( XLOG_INFO, "Make_link: stat failed '%s'", target );
X	}
X	Clear_uid();
X	return( lf );
X#endif NOSYMLINK
X}
X
X
X/***************************************************************************
X * Get_stat( char * dir, char *file , struct stat *statb)
X * stat the file in the specified directory
X ***************************************************************************/
X
Get_stat(dir, file, statb )
X	char *dir;
X	char *file;
X	struct stat *statb;		/* status buffer */
X{
X	static char buf[BUFSIZ];	/* for holding the pathname */
X
X	if( dir && *dir ){
X		(void)sprintf( buf, "%s/%s", dir, file );
X	} else {
X		(void)strcpy( buf, file );
X	}
X	if( stat( buf, statb ) < 0 ){
X		logerr_die( XLOG_INFO, "Get_stat: cannot stat %s", buf );
X	}
X	if(Debug>5)log(XLOG_DEBUG,"Get_stat: %s is %ld", buf, statb->st_size );
X}
X
X/***************************************************************************
X * Get_home()
X * get the current directory
X ***************************************************************************/
static char dir[MAXPATHLEN];
X
char *
Get_home()
X{
X	/*
X	 * get current working directory
X	 */
X	if( dir[0] == 0 ){
X		Set_uid( getuid() );
X		if( getwd(dir) == 0 ){
X			logerr_die(XLOG_INFO, "Get_home: getwd() failed" );
X		}
X		Clear_uid();
X	}
X	return( dir );
X}
X/***************************************************************************
X * Full_path( char *file )
X * return the full path name
X ***************************************************************************/
X
static char full[MAXPATHLEN];
char *
XFull_path( file )
X	char *file;
X{
X	if( file[0] == '/' ){
X		(void)strcpy( full, file );
X	} else {
X		(void)sprintf( full, "%s/%s", Get_home(), file );
X	}
X	return( full );
X}
END_OF_FILE
if test 9221 -ne `wc -c <'src/lpr_job.c'`; then
    echo shar: \"'src/lpr_job.c'\" unpacked with wrong size!
fi
# end of 'src/lpr_job.c'
fi
echo shar: End of archive 6 \(of 16\).
cp /dev/null ark6isdone
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