home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume16
/
plp
/
part06
< prev
next >
Wrap
Text File
|
1988-09-14
|
56KB
|
1,924 lines
Subject: v16i019: Public lineprinter spooler package, Part06/16
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: papowell@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@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,¤t);
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