home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume16
/
plp
/
part08
< prev
next >
Wrap
Text File
|
1988-09-14
|
50KB
|
1,622 lines
Subject: v16i021: Public lineprinter spooler package, Part08/16
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: papowell@julius.cs.umn.edu
Posting-number: Volume 16, Issue 21
Archive-name: plp/part08
#! /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 8 (of 16)."
# Contents: filters/main.c src/link_support.c src/lpr.c
# src/lpr_filters.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'filters/main.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'filters/main.c'\"
else
echo shar: Extracting \"'filters/main.c'\" \(11034 characters\)
sed "s/^X//" >'filters/main.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: main.c for filters
X ***************************************************************************
X * Revision History: Created Fri Mar 4 19:45:03 CST 1988
X * $Log: main.c,v $
X * Revision 2.2 88/05/19 07:36:17 papowell
X * Added a -D (debug) flag
X *
X * Revision 2.1 88/05/09 10:12:10 papowell
X * *** empty log message ***
X *
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X "$Header: main.c,v 2.2 88/05/19 07:36:17 papowell Locked $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X/***************************************************************************
X * UMN-LPR filter template and frontend.
X *
X * A filter 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 [affile]
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. Suspension when used as the "of" filter.
X * 3. Termination and accounting
X * The front end will extract parameters, then call the filter()
X * routine, which is responsible for carrying out the required filter
X * actions. filter() is invoked with the printer device on fd 1,
X * and error log on fd 2. The npages variable is used to record the
X * number of pages that were used.
X * The "halt string", which is a sequence of characters that
X * should cause the filter to suspend itself, is passed to filter.
X * When these characters are detected, the "suspend()" routine should be
X * called.
X *
X * On successful termination, the accounting file will be updated.
X *
X * The filter() 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 [affile]
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 * npages - number of pages for accounting
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 <sys/types.h>
X#include <sys/file.h>
X#include <signal.h>
X
X/*
X * default exit status, causes abort
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, *accntfile, *format;
char *printer;
int npages; /* number of pages */
char filter_stop[] = "\031\001"; /* sent to cause filter to suspend */
X
main( argc, argv )
X int argc;
X char **argv;
X{
X int i;
X
X getargs( argc, argv );
X /*
X * Turn off SIGPIPE
X */
X (void)signal( SIGPIPE, SIG_IGN );
X if( format && *format == 'o' ){
X filter( filter_stop );
X } else {
X filter( (char *)0 );
X }
X doaccnt();
X return(0);
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
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
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
X/*
X * doaccnt()
X * writes the accounting information to the accounting file
X * This has the format: user host printer pages format date
X */
doaccnt()
X{
X time_t t, time();
X char *ctime();
X FILE *f;
X
X t = time((time_t *)0);
X if(accntfile && access(accntfile, W_OK) >= 0 &&
X (f = fopen(accntfile, "a" )) != NULL) {
X fprintf(f,"%s\t%s\t%s\t%7d\t%s\t%s",
X login? login: "NULL",
X host? host: "NULL",
X printer? printer: "NULL",
X npages,
X format? format: "NULL",
X ctime(&t));
X (void)fclose(f);
X }
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 /* must be accounting file */
X accntfile = arg;
X }
X }
X if( debug ){
X for( i = 0; i < argc; ++i ){
X fprintf(stderr, "%s ", argv[i] );
X }
X fprintf( stderr, "\n" );
X fprintf(stderr,"login '%s'\n", login? login : "null" );
X fprintf(stderr,"host '%s'\n", host? host : "null" );
X fprintf(stderr,"class '%s'\n", class? class : "null" );
X fprintf(stderr,"format '%s'\n", format? format : "null" );
X fprintf(stderr,"job '%s'\n", job? job : "null" );
X fprintf(stderr,"printer '%s'\n", printer? printer : "null" );
X fprintf(stderr,"accntname '%s'\n", accntname? accntname : "null" );
X fprintf(stderr,"zopts '%s'\n", zopts? zopts : "null" );
X fprintf(stderr,"literal, %d\n", literal);
X fprintf(stderr,"indent, %d\n", indent);
X fprintf(stderr,"length, %d\n", length);
X fprintf(stderr,"width, %d\n", width);
X fprintf(stderr,"xwidth, %d\n", xwidth);
X fprintf(stderr,"ylength, %d\n", ylength);
X fprintf(stderr,"accntfile '%s'\n", accntfile? accntfile : "null" );
X for( i = 0; i < argc; ++i ){
X fprintf(stderr, "%s ", argv[i] );
X }
X fprintf( stderr, "\n" );
X fflush(stderr);
X fflush(stderr);
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 /* fprintf(stderr, "down parm %c, %d\n", flag, i ); */
X u = i - 1 ;
X } else {
X /* fprintf(stderr, "up parm %c, %d\n", flag, i ); */
X l = i + 1 ;
X }
X }
X /* fprintf(stderr, "did not find parm %c, %d\n", flag, i ); */
X return;
X}
X
X/*
X * suspend(): suspends the output filter, waits for a signal
X */
suspend()
X{
X if(debug)fprintf(stderr,"suspending\n");
X fflush(stderr);
X kill(getpid(), SIGSTOP);
X if(debug)fprintf(stderr,"awake\n");
X fflush(stderr);
X}
X#ifdef DEBUG
X/******************************************
X * prototype filter() and cleanup() functions;
X * filter will scan the input looking for the suspend string
X * if any.
X ******************************************/
cleanup() {}
X
filter(stop)
X char *stop;
X{
X int c;
X int state, i;
X int lines = 0;
X
X /*
X * do whatever initializations are needed
X */
X /* fprintf(stderr, "filter ('%s')\n", stop ? stop : "NULL" ); */
X /*
X * now scan the input string, looking for the stop string
X */
X state = 0;
X npages = 1;
X
X while( (c = getchar()) != EOF ){
X if( c == '\n' ){
X ++lines;
X if( lines > length ){
X lines -= length;
X ++npages;
X }
X }
X if( stop || state ){
X if( c == stop[state] ){
X ++state;
X if( stop[state] == 0 ){
X state = 0;
X if( fflush(stdout) ){
X logerr_die( "fflush returned error" );
X }
X suspend();
X }
X } else if( state ){
X for( i = 0; i < state; ++i ){
X dochar( stop[i] );
X }
X state = 0;
X dochar( c );
X } else {
X dochar( c );
X }
X } else {
X dochar( c );
X }
X }
X if( ferror( stdin ) ){
X logerr_die( "read error on stdin");
X }
X for( i = 0; i < state; ++i ){
X dochar( stop[i] );
X }
X if( lines > 0 ){
X ++npages;
X }
X if( fflush(stdout) ){
X logerr_die( "fflush returned error" );
X }
X}
X
dochar(c)
X int c;
X{
X putchar( c );
X}
X#endif DEBUG
END_OF_FILE
if test 11034 -ne `wc -c <'filters/main.c'`; then
echo shar: \"'filters/main.c'\" unpacked with wrong size!
fi
# end of 'filters/main.c'
fi
if test -f 'src/link_support.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/link_support.c'\"
else
echo shar: Extracting \"'src/link_support.c'\" \(12422 characters\)
sed "s/^X//" >'src/link_support.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: Link_support.c
X ***************************************************************************
X * Revision History: Created Fri Jan 15 20:13:48 CST 1988
X * $Log: link_support.c,v $
X * Revision 3.1 88/06/18 09:34:21 papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X *
X * Revision 2.1 88/05/09 10:08:20 papowell
X * PLP: Released Version
X *
X * Revision 1.5 88/04/06 12:12:12 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.4 88/03/25 14:59:39 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.3 88/03/12 10:03:50 papowell
X * *** empty log message ***
X *
X * Revision 1.2 88/03/11 19:28:26 papowell
X * Minor Changes, Updates
X *
X * Revision 1.1 88/03/01 11:08:29 papowell
X * Initial revision
X *
X * Support for the inter-machine communications
X * Link_open(int retry)
X * opens a link to the remote host
X * Link_close()
X * closes the link to the remote Printer
X * Link_send( char *l)
X * sends a line to the remote host
X * Link_line( int retry, char *l)
X * opens the link (with or without retry)
X * sends a line to the remote host
X * Link_confirm()
X * gets a single character back, confirming the action
X * Link_ack( c )
X * sends a single character back, confirming the action
X * Link_copy( FILE *fp, count)
X * copies a file to the remote host;
X * if count bytes not transfered, an error is generated
X * Link_get()
X * gets and prints all information on stdout
X * Link_port_num()
X * gets remote port number for connection
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X "$Header: link_support.c,v 3.1 88/06/18 09:34:21 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X
X#include "lp.h"
X
static int Link_fd; /* fd for the socket */
X
X/***************************************************************************
X * Link_open(retry)
X * 1. Set up an inet socket; a socket has a local host/local port and
X * remote host/remote port address part. The LPR software runs SUID
X * root, and will attempt to open a privileged port (number less than
X * PRIV); at the remote end this is checked to make sure that the
X * remote machine is running SUID root. Primitive, but it is adequate
X * in a trusting environment.
X *
X * (See Advanced 4.3 BSD IPC Tutorial for more information) The server on
X * the remote machine will be listening on the port given by the entry in
X * the /etc/service for the particular service desired. If we are using
X * the "real" version of lpd this will be the "Printer" service, the test
X * version will use a "test" service. The LPD daemon will open a socket
X * and bind to the appropriate "port" number. The
X * getservbyname("printer","tcp"), is used to get the port information
X * (sp->s_port), which is used in a bind call.
X *
X * When we want to communicate with the lpd daemon on the remote machine,
X * listening on that particular port, we call getseverbyname(...) to get
X * the port number and protocol. The remote host expects the local port
X * to be in a range that is available only to a root UID process, i.e.-
X * less than IPPORT_RESERVED. When we open the local port, we get a local
X * port in this range. At the remote end, the port number is checked to
X * ensure that it is in a valid range. Since the reserved ports can only
X * be accessed by UID 0 (root) processes, this would appear to prevent
X * ordinary users from directly contacting the remote daemon.
X *
X ***************************************************************************/
X/*
X * getport()
X * gets a port, in the correct range, to the remote machine
X * This code comes from a description of the RLOGIN and LPD
X * materials
X */
static int
getport()
X{
X struct hostent *host; /* host entry pointer */
X int port_num; /* port number to connect to */
X struct sockaddr_in sin; /* inet socket address */
X int sock; /* socket */
X
X /*
X * !!! Warning: zero out the sockaddr_in struct
X */
X bzero( (char *)&sin, sizeof( sin ));
X /*
X * Get the host address and port number to connect to.
X */
X if(Debug>4)log( XLOG_DEBUG, "getport: host %s", RM );
X host = gethostbyname(RM);
X if (host == NULL){
X logerr_die( XLOG_INFO,"getport: unknown host %s", RM);
X }
X /*
X * get the server name and protocol information from /etc/services
X */
X port_num = Link_port_num();
X /*
X * set up the address information
X */
X bzero((char *)&sin, sizeof(sin));
X bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length);
X sin.sin_family = host->h_addrtype;
X sin.sin_port = port_num;
X
X /*
X * Try connecting to the server.
X */
X if(Debug>3)log( XLOG_DEBUG, "trying connection to %s", RM );
X sock = reserveport(Maxportno,Minportno);
X if(sock < 0){
X return(-1);
X }
X if(connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0){
X if(Debug>2)logerr( XLOG_DEBUG, "connect failed to %s", RM );
X (void) close(sock);
X return(-1);
X }
X return(sock);
X}
X
X/*
X * reserveport(int port_no, min_port_no)
X * Reserve a port, starting at port_no, down to min_port_no.
X * while port_no > min_port_no
X * try to grab the port;
X * if you can, then return socket
X * else return -1
X * Returns: socket if successful, -1 if not
X */
static int
reserveport(port_no, min_port_no)
X int port_no, min_port_no;
X{
X struct sockaddr_in sin;
X int sock;
X
X sock = socket(AF_INET, SOCK_STREAM, 0);
X if(sock < 0){
X logerr_die( XLOG_INFO, "reserveport socket call failed" );
X } else if( sock == 0 ){
X logerr_die( XLOG_INFO, "reserveport: socket returns 0" );
X }
X while( port_no >= min_port_no ){
X bzero( (char *)&sin, sizeof( sin ));
X sin.sin_family = AF_INET;
X sin.sin_addr.s_addr = 0;
X sin.sin_port = htons((u_short) port_no);
X if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0){
X if(Debug>4)log( XLOG_DEBUG, "reserveport got socket %d", port_no );
X return(sock);
X }
X if(Debug>4)logerr( XLOG_DEBUG,"reserveport bind failed on %d",port_no );
X if (errno != EADDRINUSE && errno != EADDRNOTAVAIL){
X logerr_die( XLOG_INFO, "reserveport: bind failed" );
X }
X --port_no;
X }
X (void)close(sock);
X return(-1);
X}
X
Link_open(retry)
X int retry;
X{
X unsigned int i = 1;
X int l;
X
X if( Link_fd ){
X return( JSUCC );
X }
X while( Link_fd == 0 ){
X if(Debug>3)log( XLOG_DEBUG,"Link_open: retry %d, attempt %d",retry,i );
X l = getport();
X if( l < 0 ){
X if( retry == 0 ){
X if(Debug>3)log( XLOG_DEBUG,"Link_open: failed" );
X return( JFAIL );
X } else if( retry > 0 ){
X --retry;
X }
X sleep((unsigned)i);
X if( i < 512 ){
X i = i << 1;
X }
X } else if( l == 0 ){
X fatal( XLOG_INFO, "Link_open: cannot happen- fd 0" );
X } else {
X Link_fd = l;
X }
X }
X if(Debug>3)log( XLOG_DEBUG, "made connection to %s", RM );
X return( JSUCC );
X}
X
X/***************************************************************************
X * Link_close()
X * 1. close the link
X ***************************************************************************/
void
Link_close()
X{
X if(Debug>4)log(XLOG_DEBUG,"Link_close: closing link (%d)", Link_fd);
X if( Link_fd ){
X (void)close( Link_fd );
X }
X Link_fd = 0;
X}
X
X
X/***************************************************************************
X * Link_line( int retry; char *line )
X * send a line to the remote end
X * if retry != 0, blocks until connection made
X ***************************************************************************/
X
int
Link_line( retry, str )
X char *str;
X{
X if( Link_open(retry) != JSUCC ){
X return( JFAIL );
X }
X return( Link_send( str ));
X}
X
int
Link_send( str )
X char *str;
X{
X int i, l; /* ACME Integers, Inc. */
X
X l = strlen( str );
X if( Link_fd == 0 ){
X log(XLOG_INFO, "Link_send: link to %s not open", RM);
X return( JFAIL );
X }
X if( l != 0 && (i = write( Link_fd, str, l )) != l){
X if( i < 0 ){
X logerr( XLOG_INFO, "write error to remote site %s", RM);
X }
X Link_close();
X return( JFAIL );
X }
X if(Debug>4)log(XLOG_DEBUG,"Link_send: sent to %s- '%d'%s",RM,*str,str+1);
X return( JSUCC );
X}
X
X/***************************************************************************
X * Link_confirm()
X * gets a single character back, confirming the action
X ***************************************************************************/
Link_confirm()
X{
X char buf[1]; /* buffer */
X int n;
X
X if( Link_fd == 0 ){
X log( XLOG_INFO, "link to %s not open", RM);
X return( JFAIL );
X }
X if( (n = read( Link_fd, buf, 1 )) != 1 ){
X if( n == 0 ){
X log( XLOG_INFO, "Link_confirm: nothing from remote site %s", RM);
X } else {
X logerr( XLOG_INFO, "Link_confirm: error from remote site %s", RM);
X }
X Link_close();
X return( JFAIL );
X }
X if( buf[0] != 0 ){
X if(Debug>4)log(XLOG_DEBUG,"Link_confim: failed (%d) from %s",*buf,RM);
X Link_close();
X return( JFAIL );
X }
X if(Debug>4)log( XLOG_DEBUG, "successful confirm from %s", RM);
X return( JSUCC );
X}
X
X/***************************************************************************
X * Link_copy( FILE *fp; long count; char *name)
X * copies a file to the remote nost;
X * if count bytes not transfered, an error is generated
X ***************************************************************************/
Link_copy( fp, count, name )
X FILE *fp;
X long count;
X char *name;
X{
X char buf[BUFSIZ]; /* buffer */
X int i, l; /* ACME Integer, Inc. */
X long total; /* total number of bytes */
X
X if(Debug>4)log( XLOG_DEBUG, "Link_copy: %s- %d bytes to %s",name,count,RM);
X if( Link_fd == 0 ){
X log( XLOG_INFO, "Link_copy: Link_fd is not open");
X goto error;
X }
X
X total = 0;
X while( (i = fread( buf, 1, sizeof(buf), fp )) > 0 ){
X total = total + i;
X if( total > count ){
X log(XLOG_DEBUG,
X "Link_copy: file '%s', length %d instead of %d bytes",
X name, total, count );
X goto error;
X }
X if( (l = write( Link_fd, buf, i )) != i ){
X if( l < 0 ){
X logerr(XLOG_INFO,"Link_copy: write error while sending '%s' to %s",
X name, RM);
X } else {
X logerr(XLOG_INFO,"Link_copy: partial write sending '%s' to %s",
X name, RM);
X }
X goto error;
X }
X }
X if( i < 0 ){
X logerr(XLOG_INFO,"Link_copy: file '%s' read error", name);
X goto error;
X } else if( total != count ){
X log(XLOG_DEBUG,
X "Link_copy: file '%s', copied %d instead of %d bytes to %s",
X name, total, count, RM);
X goto error;
X }
X if(Debug>4)log(XLOG_DEBUG,"Link_copy: file '%s' %d bytes to %s",
X name,count,RM);
X return( JSUCC );
error:
X Link_close();
X return( JFAIL );
X}
X
Link_ack( c )
X int c;
X{
X char buf[1];
X int succ;
X
X buf[0] = c;
X succ = JFAIL;
X
X if( write( Link_fd, buf, 1 ) != 1 ){
X if(Debug>4)logerr(XLOG_DEBUG,"ack '%d' write error to %s",c,RM);
X } else {
X succ = JSUCC;
X if(Debug>4)log(XLOG_DEBUG,"ack '%d' sent to site %s",c,RM);
X }
X if( succ != JSUCC ){
X Link_close();
X }
X return( succ );
X}
X
X/***************************************************************************
X * Link_get()
X * reads all information from the link, and prints on stdout
X ***************************************************************************/
Link_get()
X{
X int i; /* ACME Integers, Inc. */
X char buf[BUFSIZ]; /* buffer */
X
X if( Link_fd == 0 ){
X fatal( XLOG_INFO, "Link_copy: Link_fd is not open");
X }
X
X while( (i = read( Link_fd, buf, sizeof(buf)) ) > 0 ){
X (void)fwrite( buf, 1, i, stdout );
X }
X}
X
X/***************************************************************************
X * Link_port_num()
X * - look up the service in the service directory using getservent
X * - if the port number has been set, don't do it a second time.
X * - Note that Setup_test will set the port number if necessary.
X ***************************************************************************/
X
Link_port_num()
X{
X static char *name = SERVERNAME;
X static char *prot = SERVERPROT;
X struct servent *sp;
X if( Lpr_port_num == 0 ){
X if( ( sp = getservbyname( name, prot )) == 0 ){
X logerr_die( XLOG_CRIT, "Get_port_nun: getservbyname(%s,%s) failed",
X name, prot );
X }
X Lpr_port_num = sp->s_port;
X }
X return( Lpr_port_num );
X}
END_OF_FILE
if test 12422 -ne `wc -c <'src/link_support.c'`; then
echo shar: \"'src/link_support.c'\" unpacked with wrong size!
fi
# end of 'src/link_support.c'
fi
if test -f 'src/lpr.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/lpr.c'\"
else
echo shar: Extracting \"'src/lpr.c'\" \(10711 characters\)
sed "s/^X//" >'src/lpr.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: lpr.c
X * lpr - off line print
X ***************************************************************************
X * Revision History: Created Mon Jan 25 14:04:26 CST 1988
X * $Log: lpr.c,v $
X * Revision 3.2 88/06/24 17:56:01 papowell
X * MODS for VAX 4.3BSD UNIX
X *
X * Revision 3.1 88/06/18 09:34:46 papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X *
X * Revision 2.1 88/05/09 10:09:00 papowell
X * PLP: Released Version
X *
X * Revision 1.6 88/04/27 18:02:45 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:09 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/06 12:13:28 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:16 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:47 papowell
X * Minor Changes, Updates
X *
X * Revision 1.1 88/03/01 11:08:41 papowell
X * Initial revision
X *
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X "$Header: lpr.c,v 3.2 88/06/24 17:56:01 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X#include "lpr.h"
X
X/***************************************************************************
X * SYNOPSIS
X * lpr [ -PPrinter ] [ -#num ] [ -C class ] [ -J job ] [
X * -RremoteAccount ] [ -m[mailTo] ] [ -T title ] [-i[numcols]]
X * [ -1234 font ] [ -wnum ] [ -Zzoptions ] [ -Uuser ] [ -HHost
X * ] [ -Ffilter ] [ -bhrs ] [ -Dn ] [ -X ] [ filename ... ]
X * DESCRIPTION
X * Lpr uses a spooling server to print the named files when
X * facilities become available. If no Names appear, the stan-
X * dard input is assumed.
X * -PPrinter Output to the specified Printer
X * -F? Filter or format specification
X * -p text to be printed using pr(1) to format the files.
X * -l (literal) text with control characters to be printed
X * -t output from troff(1)
X * -n output from DITROFF
X * -d output from tex(l) (DVI format from Stanford).
X * -g standard plot data as produced by the plot(3X) routines
X * -v a raster image for devices like the Benson Varian.
X * -c data produced by cifplot(l).
X * -f same as -Fr, FORTAN carriage control
X * -m[mailTo] Send mail upon completion
X * -s Use symbolic links.
X * -J jobname Specify the job name to print on the burst page
X * -T title specify the title used by pr(1);
X * -wwidth specify the page width for pr.
X * -C class or priority (A - Z)
X * -R remoteAccount
X * -#num number of copies of each file to be printed.
X * -i[numcols] Cause the output to be indented
X * -b The files are assumed to contain binary data
X * -Z extra options
X * -D[n] debug level
X * -X Use an Xperimental version of LPD
X * -Uuser Used by root process to specify a user
X * -HHost Used by root process to specify a Host
X ****************************************************************************
X * Implementation:
X * Each time lpr is invoked it creates a "job" entry in the appropriate
X * spool directory. Each job consists of a control file and zero or more
X * data files. The control file contains lines that specify the job
X * parameters, such as job Name, etc., and the Names of the data files.
X * Control file format
X * First character in the line flags kind of entry, remainder of line is
X * the arguemnt.
X *
X * C -- "class Name" on banner page
X * H -- "Host Name" of machine where lpr was done
X * I -- "indent" amount to indent output
X * J -- "job Name" on banner page
X * L -- "literal" user's Name to print on banner
X * M -- "mail" to user when done printing
X * N -- "Name" of file (used by lpq)
X * P -- "Person" user's login Name
X * R -- account id for charging
X * U -- "unlink" Name of file to remove after we print it
X * W -- "width" page width for PR
X * X -- "header" header title for PR
X * Z -- xtra options to filters
X *
X * Lower case letters are formats, and are together with the Name
X * of the file to print
X * f -- "file Name" Name of text file to print
X * l -- "file Name" text file with control chars
X * p -- "file Name" text file to print with pr(1)
X * t -- "file Name" troff(1) file to print
X * n -- "file Name" ditroff(1) file to print
X * d -- "file Name" dvi file to print
X * g -- "file Name" plot(1G) file to print
X * v -- "file Name" plain raster file to print
X * c -- "file Name" cifplot file to print
X ***************************************************************************/
X
X/***************************************************************************
X * main(int argc, char **argv)
X * 1. get the Host computer Name and user Name
X * 2. get the parameters and other information
X * 3. set up signals to handle abrupt termination.
X * 4. set up the control file for the job
X * 5. if we are spooling from stdin, copy stdin to a file.
X * 6. if we have -p option (use pr), run the input files through pr
X * and save to a single file.
X * 7. create a job entry
X * 8. start the server
X ****************************************************************************/
X
extern int cleanup();
X
main(argc, argv)
X int argc;
X char **argv;
X{
X int i; /* ACME Integers, Inc. */
X struct passwd *pw_ent; /* user entry in /etc/passwd */
X int fd, job_size; /* size of file and job */
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 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 if( getuid() == 0 ){
X /* we are being invoked by root */
X Is_root = 1;
X }
X /*
X * Get the home directory for the use
X */
X (void)Get_home();
X /*
X * setup parameters
X */
X Setup_parms(argc, argv);
X /*
X * set up chatty information for user
X */
X if( BNRNAME[0] == 0 ){
X if( strcmp( LOGNAME, pw_ent->pw_name ) == 0 ){
X (void)strncpy( BNRNAME, pw_ent->pw_gecos, MAXPARMLEN );
X } else {
X (void)strcpy( BNRNAME, LOGNAME );
X }
X }
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 /**************************************************************************
X * The following possibilities exist:
X * Files No Files
X * p format,no 'f' PF PR ->spool input->PR -> spool
X * p format, 'f' PF PR->PF->spool input->PR->PF->spool
X * ? format, no PF files->spool files input->spool
X * ? format, PF PF(files) -> file input->spool
X *
X * If we have a prefilter for a file format, we have to run the files
X * through the prefilter, and spool the output of the prefilter.
X * The prefilter will create a single output file which is printed
X *
X * If we have 'p' format, we will create a printer process, and run
X * its output into a temporary file in the spool directory.
X * If there are no names specified, we copy the input to a temporary
X * file in the spool directory. The Read_stdin file is the name of the
X * output file. This is also used to hold the name of the output of
X * the PR program.
X *
X * If we have a prefilter, we place its output in the Read_filter
X * file.
X *************************************************************************/
X if( Format == 'p' ){
X /*
X * run PR and put the output in a spool file
X */
X if(Debug>3)log(XLOG_DEBUG,"using PR" );
X if( Run_pr() == 0 ){
X Diemsg( "nothing to print" );
X }
X Format = 'f';
X } else if( Parmcount == 0 ){
X if(Debug>3)log(XLOG_DEBUG,"Copying stdin" );
X if( Copy_stdin() == 0 ){
X Diemsg( "nothing to print" );
X }
X } else {
X /*
X * check to see that the input files are printable
X */
X job_size = 0;
X for(i = 0; i < Parmcount; ++i ){
X fd = Is_printable( Parms[i].str, &LO_statb );
X if( fd < 0 ){
X Parms[i].str = 0;
X } else {
X job_size = 1;
X }
X (void)close(fd);
X }
X if( job_size == 0 ){
X Diemsg( "nothing to print" );
X }
X }
X /*
X * now we check for prefilter;
X * if we have one, then we have to run all the files through it;
X * we invoke the prefilter with the appropriate parameters.
X * The output of the prefilter (on stdout) is spooled
X */
X if( Prefilter_name[Format - 'a'] ){
X /* yes, we have prefilter */
X if(Debug>3)log(XLOG_DEBUG,"Prefilter %c '%s'",Format,
X Prefilter_name[Format - 'a'] );
X if( Do_prefilter(Prefilter_name[Format - 'a'], Read_stdin) <= 0 ){
X Diemsg( "nothing to print" );
X }
X }
X /*
X * we now either have to spool a single file, produced by the
X * PR and/or Prefilters, or we have to spool all the input files
X */
X Make_job();
X /*
X * start up the server
X */
X (void)Startserver();
X exit( 0 );
X}
X/***************************************************************************
X * cleanup()
X * remove the temp files
X ***************************************************************************/
X
cleanup()
X{
X (void)sigblock(sigmask(SIGCHLD)|sigmask(SIGHUP)
X |sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
X if( geteuid() && geteuid() != getuid() ){
X /*
X * whoops, we must have been caught as user
X * try and force to EUID root
X */
X if( setreuid( geteuid(), 0 ) < 0 ){
X logerr( XLOG_INFO, "cleanup: setreuid( %d, %d) failed",
X geteuid(), 0 );
X exit(1);
X }
X }
X if( geteuid() == 0 && setreuid( -1, Daemon_uid ) < 0 ){
X logerr( XLOG_INFO, "cleanup: setreuid( %d, %d) failed",
X -1, Daemon_uid );
X exit(1);
X }
X Remove_temp();
X exit( 1 );
X}
END_OF_FILE
if test 10711 -ne `wc -c <'src/lpr.c'`; then
echo shar: \"'src/lpr.c'\" unpacked with wrong size!
fi
# end of 'src/lpr.c'
fi
if test -f 'src/lpr_filters.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/lpr_filters.c'\"
else
echo shar: Extracting \"'src/lpr_filters.c'\" \(11355 characters\)
sed "s/^X//" >'src/lpr_filters.c' <<'END_OF_FILE'
X/***************************************************************************
X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
X ***************************************************************************
X * MODULE: lpr_filters.c
X * filter programs for LPR
X * Supports the reading and enqueuing of input
X ***************************************************************************
X * Revision History: Created Sat Jan 30 08:06:50 CST 1988
X * $Log: lpr_filters.c,v $
X * Revision 3.1 88/06/18 09:34:53 papowell
X * Version 3.0- Distributed Sat Jun 18 1988
X *
X * Revision 2.1 88/05/09 10:09:11 papowell
X * PLP: Released Version
X *
X * Revision 1.3 88/03/25 15:00:27 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:36 papowell
X * Minor Changes, Updates
X *
X * Revision 1.1 88/03/01 11:08:45 papowell
X * Initial revision
X *
X ***************************************************************************/
X#ifndef lint
static char id_str1[] =
X "$Header: lpr_filters.c,v 3.1 88/06/18 09:34:53 papowell Exp $ PLP Copyright 1988 Patrick Powell";
X#endif lint
X#include "lpr.h"
X
X/***************************************************************************
X * Run_pr()
X * Copies input the PR program; temp file name left in Read_stdin
X * Returns: 0 if nothing, 1 otherwise
X * Copy_stdin()
X * Copies input to a temporary file; temp file name left in Read_stdin
X * Returns: 0 if nothing, 1 otherwise
X * char *Copy_file( int infile, char *name )
X * copies file to temp file, returns name of temp file
X * int Open_SD(char *s) Open the file in the spool directory
X ***************************************************************************/
X
X/***************************************************************************
X * Run_pr()
X * 1. Gets the name of a temporary file for the output
X * 2. Sets up the PR command
X * 3. Forks a process
X * 4. Arranges the process output goes to the output file
X * 5. Waits for PR to complete
X ***************************************************************************/
char * estr3(); /* copies 3 strings to end */
X
Run_pr()
X{
X int fd; /* Data file */
X char cmdbuf[BUFSIZ]; /* build up the command here */
X char buf[BUFSIZ]; /* local buf up the command here */
X char *bp; /* bp points to cmdbuf */
X char *ep; /* ep is limit */
X int pid; /* pid of pr process */
X union wait status; /* the status.w_status is the integer value */
X int i; /* ACME Integer, Inc. */
X struct stat statb; /* for stating the output file */
X
X /*
X * get name of the data file
X */
X Read_stdin = Get_tmp_data();
X fd = Open_SD( Read_stdin );
X /*
X * set up the printer name
X */
X if( PR == 0 || *PR == 0 ){
X Diemsg( "there is no pr program specified for -p format");
X }
X /* set up the command */
X ep = cmdbuf + sizeof(cmdbuf);
X bp = estr3( cmdbuf, PR,(char *)0,(char *)0, ep );
X /*
X * set the width, length, and title flags
X */
X
X if( PWIDTH[0] ){
X bp = estr3( bp, " -w", PWIDTH, " ", ep );
X } else if( PW ){
X (void)sprintf( buf, " -w%d ", PW );
X bp = estrcp( bp, buf, ep );
X }
X if( PL ){
X (void)sprintf( buf, "-l%d ", PL );
X bp = estrcp( bp, buf, ep );
X }
X if( PRTITLE[0] ){
X bp = estr3( bp, "-h '", PRTITLE, "' ", ep );
X } else if( JOBNAME[0] ){
X bp = estr3( bp, "-h '", JOBNAME, "' ", ep );
X } else if( Parmcount == 0 ){
X bp = estr3( bp, "-h '", "(stdin)", "' ", ep );
X }
X /*
X * Put the file names in the list
X */
X for( i = 0; i < Parmcount; ++i ){
X bp = estr3( bp, Parms[i].str, " ", (char *)0, ep );
X }
X if( bp == 0 ){
X Diemsg( "pr command is too long: %s", cmdbuf);
X }
X if(Debug>2)log(XLOG_DEBUG, "pr command is '%s'", cmdbuf);
X /*
X * start up the pr process
X */
X if( (pid = fork()) < 0 ){
X logerr_die(XLOG_INFO,"Run_pr: fork failed");
X } else if( pid == 0 ){
X if( dup2(fd,1) < 0 ){
X logerr_die(XLOG_INFO,"Run_pr: dup2 failed" );
X }
X if( setreuid( getuid(), getuid() )< 0 ){
X logerr_die(XLOG_INFO,"setreuid failed" );
X }
X mexecv( cmdbuf );
X exit(1);
X }
X /* wait for printer */
X while ((i = wait(&status)) > 0 && i != pid);
X if( i < 0 || status.w_status ){
X logerr_die(XLOG_INFO,"pr failed (%s)", Decode_status(&status) );
X }
X if(Debug>3)log(XLOG_DEBUG,"pr done successfully");
X if( fstat( fd, &statb ) <0 ){
X logerr_die(XLOG_INFO, "Run_pr: cannot stat output file %s", Read_stdin);
X }
X if(Debug>3)log(XLOG_DEBUG,"Run_pr: %s is %d",Read_stdin,statb.st_size);
X (void)close(fd);
X return( statb.st_size != 0 );
X}
X
static char *
estr3( s, s1, s2, s3, e )
X char *s, *s1, *s2, *s3, *e;
X{
X if( s1 ) s = estrcp( s, s1, e );
X if( s2 ) s = estrcp( s, s2, e );
X if( s3 ) s = estrcp( s, s3, e );
X return( s );
X}
X
X/***************************************************************************
X * int Open_SD(char *s)
X * Open the name of the file in the spool directory
X * 1. Prepend the SD name
X * 2. Create the file with the desired perms
X * Returns: fd if successful; dies otherwise
X ***************************************************************************/
X
Open_SD( s )
X char *s;
X{
X char buf[BUFSIZ];
X int fd;
X
X (void)sprintf(buf, "%s/%s", SD, s);
X fd = Exlockcf( buf );
X if( fd < 0 ){
X logerr_die( XLOG_INFO, "Open_SD: could not open and lock %s", buf );
X }
X if(Debug>3)log(XLOG_DEBUG,"Open_SD: file %s, fd %d", buf, fd );
X return( fd );
X}
X
X/***************************************************************************
X * Copy_stdin()
X * 1. Gets the name of a temporary file for the output
X * 2. Copies stdin to the file
X * 3. Returns 0 if empty file, 1 otherwise
X ***************************************************************************/
X
Copy_stdin()
X{
X int fd; /* Data file */
X char buf[BUFSIZ]; /* local buf up the command here */
X int n, i; /* bytes read */
X int count; /* number of bytes */
X long blocks; /* number of blocks */
X
X /*
X * get name of the data file
X */
X Read_stdin = Get_tmp_data();
X fd = Open_SD( Read_stdin );
X
X count = 0;
X blocks = 0;
X while( (n = fread( buf, 1, sizeof(buf), stdin )) > 0 ){
X count += n; /* update count */
X while( count >= 1024 ){
X count -= 1024;
X ++blocks;
X }
X if( MX && blocks > MX ){
X Diemsg( "input from stdin exceeds maximum file size limits" );
X }
X i = write( fd, buf, n );
X if( i != n ){
X logerr_die(XLOG_INFO,"Copy_stdin: cannot write %s",Read_stdin);
X }
X }
X if( ferror( stdin ) ){
X Diemsg( "error reading from stdin" );
X }
X (void)close(fd);
X if( count ){
X ++blocks;
X }
X if(Debug>3)log(XLOG_DEBUG,"Copy_stdin: %s is %d blocks", Read_stdin,blocks);
X return( blocks != 0 );
X}
X/***************************************************************************
X * char *Copy_file( int *in_fp, char *in_file )
X * 1. Gets the name of a temporary file for the output
X * 2. Copies file to the temporary file
X * Returns: temporary file name
X ***************************************************************************/
X
char *
Copy_file( in_fd, in_file, statb )
X int in_fd;
X char *in_file;
X struct stat *statb;
X{
X int out_fd; /* Data file */
X char buf[BUFSIZ]; /* local buf for IO */
X int n, i; /* bytes read */
X int count; /* number of bytes */
X long blocks; /* number of blocks */
X char *fname; /* file name */
X
X /*
X * get name of the data file
X */
X fname = Get_tmp_data();
X out_fd = Open_SD( fname );
X
X count = 0;
X blocks = 0;
X while( (n = read( in_fd, buf, sizeof(buf))) > 0 ){
X count += n; /* update count */
X while( count >= 1024 ){
X count -= 1024;
X ++blocks;
X }
X if( MX && blocks > MX ){
X Diemsg( "file %s too large",in_file);
X }
X i = write( out_fd, buf, n );
X if( i != n ){
X logerr_die(XLOG_INFO,"Copy_file: cannot write to file %s",in_file);
X }
X }
X if( n < 0 ){
X logerr_die( XLOG_INFO,"Copy_file: error reading from %s", in_file );
X }
X if( fstat( out_fd, statb ) < 0 ){
X logerr_die( XLOG_INFO,"Copy_file: cannot stat %s", fname);
X }
X (void)close( out_fd );
X return( fname );
X}
X/***************************************************************************
X * Do_prefilter( char *cmd, char *file )
X *
X * Prefilter handler
X * 1. Sets up a prefilter command.
X * filtername arguments \ <- from filtername
X * -PPrinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \
X * [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost
X * -Fformat [file]
X * Note: the filter parameter is of the form "filter,X", where
X * output format is specified. If there is no specified format,
X * 'f' will be used.
X * 2. Gets a temporary file for output
X * 3. If file is explicitly named, uses that for input instead of
X * parameter files.
X * 4. Forks and runs the command.
X * 5. Filter must return 0 for successful status, otherwise we abort
X ***************************************************************************/
X
Do_prefilter( cmd, file )
X char *cmd;
X char *file;
X{
X char cmdbuf[BUFSIZ]; /* build up the command here */
X union wait status; /* the status.w_status is the integer value */
X char *cp, *ep; /* ACME Pointers, Inc. */
X int i, l, pid; /* ACME Integers, Inc. */
X int new_format = 'f'; /* new format */
X int fd; /* the output file */
X struct stat statb; /* for stating the output file */
X
X /*
X * get the output format
X */
X (void)strcpy(cmdbuf, cmd);
X l = strlen( cmdbuf );
X if( l > 2 ){
X if( cmdbuf[l-2] == ',' ){
X new_format = cmdbuf[l-1];
X cmdbuf[l-2] = 0;
X }
X }
X if( !isascii(new_format) || !islower(new_format)){
X fatal(XLOG_INFO, "bad prefilter new format, %s", cmd);
X }
X /*
X * set up the basic filter command
X */
X AF = 0;
X cp = Setup_filter( Format, cmdbuf );
X Format = new_format;
X ep = cmdbuf+sizeof(cmdbuf);
X /*
X * copy command to buffer
X */
X cp = estrcp( cmdbuf, cp, ep );
X
X /*
X * add the file names
X */
X if( file ){
X /*
X * we have an explicitly named file
X */
X cp = estrcp( cp, " ", ep );
X cp = estrcp( cp, file, ep );
X } else {
X for( l = 0; l < Parmcount; ++l ){
X cp = estrcp( cp, " ", ep );
X cp = estrcp( cp, Parms[l].str, ep );
X }
X }
X if( cp == 0 ){
X fatal( XLOG_INFO, "Do_prefilter: command too long: %s", cmd);
X }
X if(Debug>3)log(XLOG_DEBUG, "Do_prefilter: command '%s'", cmdbuf);
X /*
X * get the output file name
X */
X Filter_out = Get_tmp_data();
X fd = Open_SD( Filter_out );
X
X /*
X * start the prefilter up and wait for output
X */
X if( (pid = fork()) < 0 ){
X logerr_die(XLOG_INFO,"Do_prefilter: fork failed");
X } else if( pid == 0 ){
X if( dup2(fd,1) < 0 ){
X logerr_die(XLOG_INFO,"Do_prefilter: dup2 failed" );
X }
X if( setreuid( getuid(), Daemon_uid ) < 0 ){
X logerr_die(XLOG_INFO,"Do_prefilter: setreuid failed" );
X }
X mexecv( cmdbuf );
X logerr_die(XLOG_INFO,"Do_prefilter: execv failed");
X }
X /*
X * wait for prefilter
X */
X while ((i = wait(&status)) > 0 && i != pid) ;
X if( i < 0 || status.w_status ){
X logerr_die(XLOG_INFO,"Do_prefilter: prefilter %d failed (%s)", i,
X Decode_status( &status ) );
X }
X if(Debug>3)log(XLOG_DEBUG,"Do_prefilter: prefilter successful");
X if( fstat( fd, &statb ) <0 ){
X logerr_die(XLOG_INFO, "Do_prefilter: cannot stat output file %s",
X Filter_out);
X }
X if(Debug>3)log(XLOG_DEBUG,"Do_prefilter: %s is %ld",
X Filter_out,statb.st_size);
X (void)close(fd);
X return( statb.st_size != 0 );
X}
END_OF_FILE
if test 11355 -ne `wc -c <'src/lpr_filters.c'`; then
echo shar: \"'src/lpr_filters.c'\" unpacked with wrong size!
fi
# end of 'src/lpr_filters.c'
fi
echo shar: End of archive 8 \(of 16\).
cp /dev/null ark8isdone
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