home *** CD-ROM | disk | FTP | other *** search
- 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
-
-