rsalz@uunet.uu.net (Rich Salz) (09/15/88)
Submitted-by: papowell@julius.cs.umn.edu Posting-number: Volume 16, Issue 18 Archive-name: plp/part05 #! /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 5 (of 16)." # Contents: doc/PLP/05.t doc/PLP/09.t filters/lpf.c man/lpd.8 # man/lpr.1 src/mexecv.c src/rmjob.c # Wrapped by papowell@attila on Wed Aug 10 10:44:53 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'doc/PLP/05.t' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'doc/PLP/05.t'\" else echo shar: Extracting \"'doc/PLP/05.t'\" \(7584 characters\) sed "s/^X//" >'doc/PLP/05.t' <<'END_OF_FILE' X.ig X$Header: 05.t,v 1.1 88/05/21 18:39:40 papowell Locked $ X$log$ X.. X.bp X.NH 1 Remote Spool Queue X.PP XEntries in a remote spool queue are transfered to the remote host by a server process forked by the X.I lpd daemon. The server process checks the spool queue for entries and then initiates communication with the remote host and the line printer daemon on the remote end. The following section discusses the protocol used to transfer files to the remote hosts. X.NH 2 XEstablishing Communication X.PP Interhost job transfer is done by using the Internet (Inet) interprocess communication facilities. XFor an excellent tutorial on this, see the 4.3BSD Advanced Tutorial On Interprocess Communications. The client or process that wishes to send files to a remote host establishes communication using the following procedure. X.IP 1). 3 The client opens an AF_INET socket, using the SOCK_STREAM protocol. The socket will use a reliable message delivery method for communication. Note that the socket is written to send a message, read to receive a message. X.IP 2). 3 The client socket is bound to a reserved port on the local host, that is, a port on the local host whose port number is less than 1024. These are reserved ports and can only be bound to by root processes or a process which is SUID root. The server on the remote machine will check to ensure that the client originated his request from a reserved port. X.IP 3). 3 The client determines the remote host addressing information using the X.IR gethostbynam (3) facility. This returns the network address of the remote host. X.IP 4). 3 The client determines the port number that the remote X.I lpd server is listening on by using the X.IR getservent (3) facility; for example, X.L getservent("printer","tcp") will return the port number and other needed information. X.IP 5). 3 Using the above information, the client process will use X.IR connect (2) to establish a connection to the remote host. If the connect call fails, then the client may retry a couple of times until successful, or terminate with an error condition. X.NH 2 Sending Requests X.PP After establishing connection with the remote host, the X.I lpd daemon will fork a server process to deal with the request. The format of the requests is specified in Table 1.1. Requests consist of a simple message consisting of a flag X(unsigned character value) followed by a string terminated with a new line character. XFor example, the request to transfer files to the remote host consists of a line of the form: X.ti +5n X\&^Bprinter X.PP The remote server process uses network supplied information to determine the name of the client host machine, and the port that originated the message. It will check the local printer permissions file to determine if the host is allowed to access the specified printer spool queue. After checking this basic permission, the remote host will then perform any requested actions. X.NH 2 XFile Transfers X.PP A job is transferred between the local and remote hosts by using one of two methods. The first method is to send the data files of a job first, followed by the control file (Berkeley Protocol); the second method is to send the control file, followed by the data files (PLP Protocol). The X.B fj flag is used to select the PLP (control file first) protocol to be used in sending jobs. The default protocol is the Berkeley (data files first) protocol. X.PP The file transfer protocol consists of sending a line identifying the type of protocol being used, the size of the file (in bytes), and the name of the file. The remote host will return a single X0 (zero) confirmation byte if it agrees to accept the file; any other value is a fatal error. After confirmation, the file is transferred to the other end, followed by a single X0 (zero) byte. If the remote end receives the file and the terminating 0 byte, it will return a confirming X0 (zero) byte. The next file may then be transferred. After all files have been transferred, a single X0 (zero) byte will terminate the file transfer. X.PP The file transferred to the remote site will be placed in the remote site spool queue directory, with the same path name it had at the local site. Both the local and remote sites will lock any files being transfered in order to prevent other PLP processes from manipulating them. Table 5.1 specifies the values of the flags used in the protocol. X.KF X.TS tab(:) box center; l | l | l. Protocol:Flag:Meaning X_ Berkeley:2 (^B):control file Both:3 (^C):data file PLP:4 (^D):control file PLP:5 (^E):last file X.TE X.ce Table 5.1. File Transfer Protocol Flags X.KE X.PP To use the Berkeley Protocol, the data files would be transferred first using the 3 (^B) flag, followed by the control file using the 2 (^C) flag. To use the PLP Protocol, the control file would be transferred first using the 4 (^D) flag, followed by the data files. When all of the data files had been transferred, a confirming message would be sent using the 5 (^E) flag, indicating that the job had been transferred. X.PP XFor example, assume that we have a job with a control file X.L cfA123attila.cs.umn.edu , and a data file X.L dfA123attila.cs.umn.edu . Using the Berkeley Protocol, the client would first send the message X.ti +5n X.L "^C1293 dfA123attila.cs.umn.edu" , X.br requesting transfer of a 1293 byte data file, whose name is X.L dfA123attila . After confirmation, the data file followed by a single 0 byte would be sent, and a confirmation should be received. Next, the message X.L "^B343 cfA123attila.cs.umn.edu" , would be sent, and then the control file followed by a single 0 byte would be sent. Having received the control file, the remote end would acknowledge the reception of the job, allowing the client to delete the job and send another one. When control file is transferred, the remote host will check the job to make sure that all data files have been transferred, and enable it for printing or further processing. If anything happens to disturb this communication, the connection is terminated and any partially transferred jobs are removed. X.PP To prevent interaction between an unspooler server and a file transfer server, the job control file is locked by the file transfer server until it has been completely transferred. X.NH 2 XError Recovery and Retry X.PP When either end of the file transfer protocol detects an error, they will shut down the link. It is the responsibility of the client process to retry sending jobs. X.NH 2 Security Checks and Authorizations X.PP The PLP file transfer protocol restricts the names of control and data files to a fixed format. In addition, the X.B U X(unlink) flag has no effect on a remote host. The enforcement of the fixed format of data and control file names makes it simple to remove all files associated with a job on completion. X.PP Before placing a job in the spool queue, the user name and hostname are checked to see if permissions are acceptible. The security of this check is based on the assumption that the client host is a trusted originator of PLP jobs. In a networked environment with many different users, this may not be the case, as it is possible to forge information in a control file. The X.B fd X(no forward) flag in a printcap entry prevents the acceptance of jobs from other than the current client. This is intended to prevent clients from attempting to transfer control files that would appear to have originated from another host. While this will provide verification at the host level, assuming that network level software will uniquely identify a host, it still does not provide a secure user identification. END_OF_FILE if test 7584 -ne `wc -c <'doc/PLP/05.t'`; then echo shar: \"'doc/PLP/05.t'\" unpacked with wrong size! fi # end of 'doc/PLP/05.t' fi if test -f 'doc/PLP/09.t' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'doc/PLP/09.t'\" else echo shar: Extracting \"'doc/PLP/09.t'\" \(6569 characters\) sed "s/^X//" >'doc/PLP/09.t' <<'END_OF_FILE' X.ig X$Header: 09.t,v 1.1 88/05/21 18:39:48 papowell Locked $ X$log$ X.. X.NH 1 Line Printer Spooler Administration X.PP Most of the administration of PLP commands consists of printcap entries, permissions entries, and spooler queue management. In addition, killing and restarting the X.I lpd daemon is sometimes needed. X.NH 2 Printcap File Management X.PP XEach spool queue or printer must have an entry in a printcap file. In a single, non-networked environment, this is usually a simple and easily managed system, but in a highly networked environment it may be a difficult procedure. In order to simply the generation of printcap files, the PLP distribution has a set of programs that allow a simple printcap data base to be set up, and a set of programs to generate printcaps for different hosts. X.NH 3 Printer Names X.PP Printer names and aliases are a major problem faced by administrators. The convention adopted by many sites is to make the primary (first) name of the printer correspond to the physical printer type and its location. XFor exmple, X.L lw_lind23 is the name of the Apple LaserWriter in Lind Hall 23. Additional aliases or names can then be added. X.PP In performing permissions checking, the name supplied by the user is checked against the information in the printer permissions file, and also checked in the printcap database. XFor this reason, the name used in the printer permissions file and the name of the printer should be identical. When sending files to a remote site, the printer name found in the printcap entry and not the alias provided by a user is used to determine permissions. X.NH 3 Printcap File Generation X.PP XEach printer usually has three forms of printcap entries: remote, forward, and actual device. The remote entry is used by a system that will treat the spool queue as a remote site and forward all jobs to a remote site. The forwarding entry is usually used for sites that accept jobs from other sites, and then forward them to a remote site. The forwarding is usually done by a specialized file transfer program. XFinally, a local or actual device entry is used for the host which has the actual printer attached. XFiles with the appropriate form printcap entry can be prepared. As part of the PLP software, a set of programs to generate printcap files tailored to a particular host has been developed, and is available in the X.L printcap directory. X.NH 3 Printer Permissions File X.PP The main printer permissions file is intended to act as a filter for general user permissions. As described elsewhere, each line is checked for a matching set of user permissions, and the first matching line determines the available permissions. It is strongly suggested that the set of entries in the printcap file be used to filter out unauthorized users, and the remaining set of entries used to determine the appropriate permissions. X.PP If restrictions on the number of pages are desired, the printer permissions file can be used on a global or local basis. The current page count field is compared against the maximum field at the time a job is spooled or printed. In order to keep this file concurrent, some form of simple permissions file updating must be done. This can be done by using the X.I pac X(printer accounting) program and a suitable shell script. Due to the wide divergence of different sites, an accounting package to do this automatically has not been provided. X.NH 2 Using LPC X.PP The X.I lpc program provides control over line printer activity. The major commands and their intended use are described in this section. See X.IR lpc (8) for details. X.LP X.B status and lpq X.R X.IP Status is used to display the current status of various line printers. The lpq function invokes lpq with various parameters. This is useful to monitor various printer activities. X.LP X.B start, abort, kill X.R X.IP X.I Start enables printing and requests X.I lpd to start printing jobs. X.sp X.I Abort disables unspooling and terminates an active server and its filters. This is normally used to kill a catatonic filter or spooler process X(i.e., X.I lpq reports that there is a daemon present but nothing is happening). It does not remove any jobs from the queue. X.sp X.I Kill does an abort followed by a start. This is handy to kill a server and start another. Note that there is an upper limit on the numbers of times a server will attempt to print a job. X.B enable and disable X.R X.IP X.I Enable and X.I disable control spooling to a queue. This is used to prevent X.I lpr from putting new jobs in the spool queue. The main use is to prevent users from putting jobs in the queue when the printer is expected to be unavailable for a long time. X.LP X.B restart X.IP X.I Restart allows mere mortals users to restart printer daemons when X.I lpq reports that there is no daemon present. X.LP X.B stop X.IP X.I Stop disables unspooling, but does not kill off the server. This is a clean way to shutdown a printer in order to perform maintenence, etc. Note that users can still enter jobs in a spool queue while a printer is X.IR stopped . X.LP X.B topq X.IP X.I Topq places jobs at the top of a printer queue. This can be used to reorder high priority jobs. X.LP X.B remote (command) X.R X.IP X.I remote is used to send a command to the remote site for processing. This is useful to control remote line printer queues. X.LP X.B clean X.IP X.I clean totally purges a queue. This functionality is needed very infrequently, and perhaps should be removed. X.NH 2 Starting the LPD Daemon X.PP Under various circumstances it may be necessary to kill and/or restart the X.I lpd daemon. The currently executing daemon writes its process ID and the time it was started in the X.L /usr/spool/lock.lpd file. The program in Figure 9.1, usually stored in X.L /usr/etc/lpd.kill , can be used to kill and restart the LPD daemon. X.KF X.in +1i X.SM X.L X.nf X.ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n 8i X#!/bin/csh -f set p=`head -1 /usr/spool/lpd.lock` set h=`hostname` if ( "$p" == "" ) then X echo $h - no lpd daemon else X echo $h - daemon $p X kill $p X sleep 1 X /usr/lib/lpd endif X.fi X.LG X.R X.in -1i X.ce XFigure 9.1 lpd.kill Program X.KE X.PP In a heavily networked system, it may be desirable to kill and restart daemons on a set of machines. The program in Figure 9.2, usually stored in X.L /usr/etc/lpd.all , can be used to kill and restart remote daemons. X.KF X.in +1i X.SM X.L X.nf X.ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n 8i X#!/bin/csh -f set l=(`cat /etc/remote.lpd`) foreach i ($l) X rsh $i /usr/etc/lpd.kill X echo done $i endfor X.LG X.R X.in -1i X.ce XFigure 9.2 lpd.all Program X.KE END_OF_FILE if test 6569 -ne `wc -c <'doc/PLP/09.t'`; then echo shar: \"'doc/PLP/09.t'\" unpacked with wrong size! fi # end of 'doc/PLP/09.t' fi if test -f 'filters/lpf.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'filters/lpf.c'\" else echo shar: Extracting \"'filters/lpf.c'\" \(6527 characters\) sed "s/^X//" >'filters/lpf.c' <<'END_OF_FILE' X/*************************************************************************** X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell X *************************************************************************** X * MODULE: lpf.c X *************************************************************************** X * Revision History: Created Fri Mar 4 19:05:43 CST 1988 X * $Log: lpf.c,v $ X * Revision 2.2 88/05/19 07:35:38 papowell X * fixed minor bug with overstrikes X * X * Revision 2.1 88/05/09 10:12:08 papowell X * *** empty log message *** X * X ***************************************************************************/ X#ifndef lint static char id_str1[] = X "$Header: lpf.c,v 2.2 88/05/19 07:35:38 papowell Locked $ PLP Copyright 1988 Patrick Powell"; X#endif lint X/*************************************************************************** X * LPF and VPF filters. X * Filter which converts lines with ^H's to overwritten lines. X * Thus this works like 'ul' but is much better; it can handle X * more than 2 overwrites and it is written with some style. X * X * Also used as the versatec driver, with the VERSATEC defined X * Original source for this was the 4.2BSD release, but there have X * been substantial modifications since. This version has been derived X * from a total rewrite done in 1985. X ***************************************************************************/ X X#include <stdio.h> X#include <ctype.h> X#include <signal.h> X#include <sys/types.h> X#include <sys/time.h> X extern int errorcode; X/* set from flags */ extern int debug, width, length, xwidth, ylength, literal, indent; extern char *zopts, *class, *job, *login, *accntname, *host, *accntfile; extern char *printer, *format, *name; extern int npages; /* number of pages */ extern char *calloc(); /* memory allocation */ X X#ifdef VERSATEC X#include <sys/vcmd.h> X X int pltmode[] = {VPLOT}; int prtmode[] = {VPRINT}; X#define MAXREP 10 X X#else VERSATEC X/* line printer */ X X#define MAXREP 10 X#endif VERSATEC X X#define TIMEOUT (5*60) /* 5 minute time out */ X char *buf; int *maxcol; int lineno; X X int timeout(); X filter(stop) X char *stop; X{ X register FILE *p = stdin, *o = stdout; X register int i, j, col; X register char *cp; X int done, linedone, maxrep; X unsigned int bufsize; X char ch, *limit; X int state, partial; X X partial = 0; X state = 0; X if( xwidth <= 0 ){ X xwidth = width; X /* fatal( "bad xwidth value %d", xwidth ); */ X } X if( width > xwidth || width <= 0 ){ X fatal( "width (%d) out of range, max %d", width, xwidth ); X } X /* X * check on width X */ X bufsize = (unsigned)( MAXREP * xwidth ); X if( (buf = calloc( bufsize, sizeof(char) )) == 0 X || (maxcol = (int *)calloc( (unsigned)( MAXREP ), sizeof(int) )) == 0 ){ X fatal( "malloc failed"); X } X maxcol[0] = -1; X state = 0; X /* X * set up timeout X */ X X# ifdef VERSATEC X (void) signal( SIGALRM, timeout ); X errorcode = 1; /* set retry on failure */ X if( ioctl(1, VSETSTATE, prtmode) < 0 ){ X logerr_die( "ioctl failed" ); X } X# endif VERSATEC X X X for( i = 0; i < MAXREP; ++i ){ X maxcol[i] = -1; X } X for( i = 0; i < bufsize; ++i ){ X buf[i] = ' '; X } X done = 0; X X while (!done) { X col = indent; X maxrep = -1; X linedone = 0; X while (!linedone) { X if( state ){ X /* we read a partial stop and want to process it normally */ X ch = stop[partial]; X ++partial; X if( partial == state ){ X state = 0; X } X } else { X ch = getc(p); X if( stop && ch == *stop){ X /* we have hit the first character in the stop sequence */ X for(state = 1; X stop[state] && (ch = getc(p)) == stop[state]; X ++state ); X /* we either have last, or we have a bad character */ X if( stop[state] == 0 ){ X state = 0; /* suspend yourself!! */ X /* X * if this filter is running as the OF X * filter, it is used only for banners. X * lpd needs to use a different filter to X * print data so stop what we are doing and X * wait for lpd to restart us. X */ X (void)alarm( TIMEOUT ); X if( fflush(stdout) < 0 ){ X logerr_die( "fflush failed" ); X } X (void)alarm( 0 ); X suspend(); X# ifdef VERSATEC X if( ioctl(1, VSETSTATE, prtmode) < 0 ){ X logerr_die( "ioctl failed" ); X } X# endif VERSATEC X } else { X /* we don't have all of the characters */ X partial = 0; X if( ch != EOF ){ X (void)ungetc(ch, stdin); X } X } X /* we want to iterate, using new characters */ X continue; X } X } X switch (ch) { X case EOF: X linedone = done = 1; X ch = '\n'; X break; X X case '\f': X lineno = length; X case '\n': X if (maxrep < 0) X maxrep = 0; X linedone = 1; X break; X X case '\b': X --col; X if( col < indent) X col = indent; X break; X X case '\r': X col = indent; X break; X X case '\t': X col = ((col - indent) | 07) + indent + 1; X break; X X default: X if (col >= width || !literal && !isprint(ch)) { X col++; X break; X } X if(debug)fprintf(stderr,"ch '%c', col %d\n", ch, col ); X cp = buf+col; X for (i = 0; i < MAXREP; i++) { X if (i > maxrep) X maxrep = i; X if (*cp == ' ') { X *cp = ch; X if (col > maxcol[i]) X maxcol[i] = col; X break; X } X cp += xwidth; X } X col++; X } X } X X /* print out lines */ X (void)alarm( TIMEOUT ); X /* print out the lines in order of last to first */ X if(debug){ X fprintf(stderr,"maxrep %d\n"); X } X for (i = maxrep; i >= 0; --i) { X cp = buf+i*xwidth; X if(debug){ X fprintf(stderr,"line %d, col %d, '%s'\n",i, X maxcol[i], cp); X } X if( (col = maxcol[i]+1) > 0 ){ X if(col != fwrite(cp,1,col,o)){ X logerr_die( "write failed" ); X } X } X for( j = 0; j < xwidth; ++j ){ X cp[j] = ' '; X } X maxcol[i] = -1; X# ifdef PRINTRONIX X if( putc('\r', o) < 0 ){ X logerr_die( "putc failed" ); X } X# else PRINTRONIX X if( i > 0 ){ X if( putc('\r', o) < 0 ){ X logerr_die( "putc failed" ); X } X } X# endif PRINTRONIX X } X if( putc(ch, o) < 0 ){ X logerr_die( "write failed" ); X } X (void)alarm( 0 ); X X /* X * update page count X */ X if(++lineno >= length){ X npages++; X lineno = 0; X } X } X X (void)alarm( TIMEOUT ); /* set up timeout */ X if (lineno) { /* be sure to end on a page boundary */ X if( putc('\f', o) < 0 ){ X logerr_die( "putc failed" ); X } X npages++; X } X (void)fflush( o ); X if( ferror(o) ){ X logerr_die( "write failed" ); X } X (void)alarm( 0 ); X } X X timeout() X { X fatal( "timeout" ); X } X X/* X * do nothing on cleanup X */ X cleanup() X {} END_OF_FILE if test 6527 -ne `wc -c <'filters/lpf.c'`; then echo shar: \"'filters/lpf.c'\" unpacked with wrong size! fi # end of 'filters/lpf.c' fi if test -f 'man/lpd.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'man/lpd.8'\" else echo shar: Extracting \"'man/lpd.8'\" \(6781 characters\) sed "s/^X//" >'man/lpd.8' <<'END_OF_FILE' X.TH LPD 8 "19 Mar 1988" "U-MN PLP" X.ig X$Header: lpd.8,v 2.1 88/05/09 10:08:31 papowell Exp $ X$Log: lpd.8,v $ Revision 2.1 88/05/09 10:08:31 papowell PLP: Released Version X Revision 1.1 88/04/28 10:58:50 papowell Initial revision X X.. X.SH NAME lpd \- line printer daemon X.SH SYNOPSIS X.B /usr/lib/lpd X[\-Llogfile] [\-D[n]] [\-X] X.SH DESCRIPTION X.I Lpd is the line printer daemon (spool queue handler) and is normally invoked at boot time from the X.IR rc (8) file. It makes a single pass through the X.IR printcap (5) file to find out about the existing printers and starts spool queue servers. It then uses the system calls X.IR listen (2) and X.IR accept (2) to receive requests to print files in the queue, transfer files to the spooling area, display the queue, remove jobs from the queue, or perform a spool queue control function. In each case it creates a server process to handle the request and the lpd process will listen for more requests. The X.B \-L option specifies an alternate file to be used for logging error messages. The X.IR syslog (8) facility is used to log critical messages as well. The X.B \-D flag enables generation of debugging messages, and the X.B \-X flag forces use of an Xperimental version of the software if it is avilable. X.PP Access control is provided by two means: a general set of printer permissions determined by the X.I /etc/printer_perm file, and an optional additional set of restrictions set by the X.B XU X(check user) permissions file specified in the printcap entry. XEach entry in the /etc/printer_perm file specifies a machine, user, printer, and maximum priority allowed; the ``*'' is a wildcard entry and matches anything. XFor example, the following entry allows root on any machine, to have to access to all queues and any priority, all users to have access to the lp queue but only a max of C priority, and admin on central to have access to the pr queue. The max and current fields are used to determine the maximum and current number of pages used by a particular user; this information is checked by the particular device to determine if a user or group of users have exceeded their limits, and is usually present only in the device specific permissions file. X.RS X.nf X.ta 1.i +1.i +1.i +.5i +.5i +.5i +.5i +.5i +.5i +.5i +.5i X#host user queue priority max current X* root * A 0 0 X* * lp C 0 0 central admin lp C 0 0 X.fi X.RE X.PP The spool queue X.I lock file in each spool directory is used to control spooling activities, prevent multiple servers from becoming active simultaneously, and to store information about the server process. The X.IR lpr (1), X.IR lpq (1), X.IR lpc (1) and X.IR lprm (1) programs use this file to report on queue status. To gain control of a spool queue, a server process locks the control file, and then unspools the jobs. XEach job has a control file and a set of data files. Lines in the control file file specify files to be printed or non-printing actions to be performed. XEach line consists of a flag character and a parameter. Lower case letters are reserved for the format indication, specified by the X\-F option of LPR. the following is a partial list of the flag characters and their uses. X.in +3 X.IP J Job Name. String to be used for the job name on the burst page. X.IP C Classification. String to be used for the classification line on the burst page and to determine job priority. The first letter of the string sets the level; A is highest, Z is lowest. The maximum level that can be used is determined by the printer_perm database and/or the X.B XU printcap entry. X.IP L Literal. The line contains identification info from the password file and appears on the banner page. X.IP T Title. String to be used as the title for X.IR pr (1). X.IP H Host Name. Name of the machine where X.I lpr was invoked. X.IP P Person. Login name of the person who invoked X.IR lpr . This is used to verify ownership by X.IR lprm . X.IP M Send mail to the specified user when the current print job completes. X.IP Z zoptions. Options passed by X.IR lpr X.IR -Zzoptions. These are passed to output filters. X.IP f XFormatted File. Name of a file to print which is already formatted. X.IP l Like ``f'' but passes control characters and does not make page breaks. X.IP p Name of a file to print using X.IR pr (1) as a filter. X.IP t Troff File. The file contains X.IR troff (1) output (cat phototypesetter commands). X.IP d DVI File. The file contains X.IR Tex (l) output (DVI format from Stanford). X.IP g Graph File. The file contains data produced by X.IR plot (3X). X.IP c Cifplot File. The file contains data produced by X.IR cifplot . X.IP v The file contains a raster image. X.IP r The file contains text data with FORTRAN carriage control characters. X.IP 1 Troff Font R. Name of the font file to use instead of the default. X(Obsolete, not used) X.IP 2 Troff Font I. Name of the font file to use instead of the default. X(Obsolete, not used) X.IP 3 Troff Font B. Name of the font file to use instead of the default. X(Obsolete, not used) X.IP 4 Troff Font S. Name of the font file to use instead of the default. X(Obsolete, not used) X.IP W Width. Changes the page width (in characters) used by X.IR pr (1) and the text filters. X.IP I Indent. The number of characters to indent the output by (in ascii). X.IP U Unlink. Name of file to remove upon completion of printing. X.IP N XFile name. The name of the file which is being printed, or a blank for the standard input (when X.I lpr is invoked in a pipeline). X.in -5 X.PP The spool server will attempt to print a job a limited number of times before abandoning it. X.PP X.I Lpd uses X.IR flock (2) to provide exclusive access to the lock file and to prevent multiple deamons from becoming active simultaneously. If the daemon should be killed or die unexpectedly, the lock file need not be removed. The lock file is kept in a readable ASCII form and contains two lines. The first is the process id of the daemon and the second is the control file name of the current job being printed. The second line is updated to reflect the current status of X.I lpd for the programs X.IR lpq (1) and X.IR lprm (1). X.SH FILES X.nf X.ta \w'/etc/printcap 'u X/etc/printcap printer description file X/usr/spool/* spool directories X/dev/lp* line printer devices X/dev/printer socket for local requests X/etc/hosts.equiv lists machine names allowed printer access X/etc/printer_perms permissions X.fi X.SH "SEE ALSO" lpc(8), pac(1), lpr(1), lpq(1), lprm(1), printcap(5) X.br X.I "PLP - The Public Line Printer Spooler", by Patrick Powell, University of Minnesota. X.fi X.SH "HISTORY" X.PP The PLP is a reverse engineered version of the Berkeley 4.3BSD Line Printer Spooler. It has many advanced features which are described in X.I "PLP - The Public Line Printer Spooler" by Patrick Powell, University of Minnesota. END_OF_FILE if test 6781 -ne `wc -c <'man/lpd.8'`; then echo shar: \"'man/lpd.8'\" unpacked with wrong size! fi # end of 'man/lpd.8' fi if test -f 'man/lpr.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'man/lpr.1'\" else echo shar: Extracting \"'man/lpr.1'\" \(7221 characters\) sed "s/^X//" >'man/lpr.1' <<'END_OF_FILE' X.TH LPR 1 "19 Mar 1988" "U-MN PLP" X.ig X$Header: lpr.1,v 2.2 88/05/19 07:43:00 papowell Locked $ X$Log: lpr.1,v $ Revision 2.2 88/05/19 07:43:00 papowell XFixed up the -H, -h descriptions X Revision 2.1 88/05/09 10:08:40 papowell PLP: Released Version X Revision 1.2 88/05/09 10:01:51 papowell added -h option X Revision 1.1 88/04/28 10:58:53 papowell Initial revision X X.. X.SH NAME lpr \- off line print X.SH SYNOPSIS X.B lpr X[ X.BI \-P printer X] [ X.BI \-# num X] [ X.B \-C X.I class X] [ X.B \-J X.I job X] [ X.BI \-R remoteAccount X] [ X.BI \-m \fR[\fImailTo\fR]\fI X] [ X.B \-T X.I title X] X[\fB\-i\fP[\fInumcols\fP]] X[ X.BI \-w num X] [ X.BI \-Z zoptions X] [ X.BI \-U user X] [ X.BI \-F filter X] [ X.B \-bhrs X] [ X.BI \-D n X] [ X.B \-X X] [ filename ... X] X.SH DESCRIPTION X.B Lpr uses a spooling daemon to print the named files when facilities become available. If no names appear, the standard input is assumed. X.IP "\fB\-P\fIprinter\fR" 5 Output to the specific printer; the default is to use the value of the environment variable PRINTER and and then the default (site dependent) printer. X.IP "\fB\-F\fIf\fR" 5 XFilter or format specification. By default, input is assumed to a standard text file and the X.I f format is used; the output device is assmed to be a simple line printer. Therer are other formats available, listed below. Not all formats may be available on all printers; see X.IR printcap (5) for details. XFormats are single lower case letters; the following are the valid arguments for X.B \-F together with the assumed type of data. XFor compatibility with previous versions of X.BR lpr , the format types can be used as options themselves X(i.e. by omitting the X.BR F ) except where noted below, a warning may be issued in such cases. X.IP \fBp\fP 5 text to be printed using X.IR pr (1) to format the files. The output is then formatted using the X.I f format. X.IP \fBl\fP 5 text with control characters to be printed, and page breaks suppressed. X.IP \fBt\fP 5 output from X.IR troff (1) X(originally cat phototypesetter commands, but now we assume the same as the X.B n format). X.IP \fBn\fP 5 output from (device independent) X.IR troff . X.IP \fBd\fP 5 output from X.IR tex (l) X(DVI format from Stanford). X.IP \fBg\fP 5 standard plot data as produced by the X.IR plot (3X) routines (see also X.IR plot (1G) for the filters used by the printer spooler). X.IP \fBv\fP 5 a raster image for devices like the Benson Varian. X.IP \fBc\fP 5 data produced by X.IR cifplot (l). X.IP \fBr\fP 5 text in which the first character of each line is interpreted as a standard FORTRAN carriage control character. The effect of this format used to be obtained with the X.B \-f option. X.PP The remaining single letter options have the following meaning. X.IP \fB\-m\fP[\fImailTo\fP] 5 Send mail upon completion to user X.I mailTo X(default is to the submitter). If the \-m flag is followed by another flag or a single \-, the default submitter name will be used. X.IP \fB\-h\fP 5 Request no banner or header for this job. X.IP \fB\-s\fP 5 Use symbolic links. Usually files are copied to the spool directory. This flag will cause a symbolic link to be made to the file, and the file should not be modified or removed until it has been printed. Primarily useful for printing very large files, and its use is restricted due to security loopholes. X.IP \fB\-r\fP 5 Remove the file after printing it. This option is also restricted due to security loopholes. X.IP \fB\-J\fP\ \fIjobname\fP 5 Specify the job name to print on the burst page; defaults to the name of the first file. X.IP \fB\-T\fP\ \fItitle\fP 5 Specify the title used by X.IR pr (1); defaults to the file name. X.IP \fB\-w\fP\fIwidth\fP 5 Specify the page width for X.IR pr . X.IP \fB\-C\fP\ \fIclass\fP 5 Specify the job classification for use on the burst page and to set the priority. Priorities range from A (highest) to Z (lowest); the default priority is Z. XFor example, X.br X.ti +0.5i lpr \-C A foo.c X.br sets the priority to A and the file foo.c to be printed. X.IP \fB\-R\fP\ \fIremoteAccount\fP 5 Specify accounting information to be used by a remote system that prints your output. X.sp XFor some printers, such as the Imagen, it can be used to specify a real money billing code to be charged for the printing. This is only needed if the user has more than one real money billing code. X.IP \fB\-#\fP\fInum\fP 5 Specify the number of copies of each file to be printed. Note that this option is NOT SUPPORTED on all printers, and its use is strongly discouraged. X.IP \fB\-i\fP[\fInumcols\fP] 5 Cause the output to be indented; X\fInumcols\fP defaults to 8 blanks. Note that this option is NOT SUPPORTED on all printers, and thus its use is discouraged. X.IP \fB\-b\fP 5 The files are assumed to contain binary data. This option allows the X.I lpr-spooler to be used for file transfers. X.IP "\fB\-Z\fP\ \fIextra\ options\fP" 5 This option is used to pass extra options to the input filter for the printer in question and is mainly used when spooling to non-Unix printers or when using the spooler to to do file transfers to non-Unix machines. X.IP "\fB\-D\fR[\fIn\fR]" XEnables display of debugging information. The X.B \-D selects level 1; X.B \-D\fIn\fR X\fRselects level X.I n X(n is a single digit). X.IP "\fB\-X" Use an Xperimental version of LPD if the software has been compiled with the appropriate support; ignored otherwise. X.PP The X.B \-U option is used to specify a user name for the purpose of accounting and banners. X.PP The old LPR options X.B \-1234 are obsolete; they were used to specify a font to be mounted on font position \fIi\fR. The X.B \-r X(delete files on job completion) and X.B \-s options are restricted to users who are in a group specified by the X.B ln X(allowed to use links) printcap entry for the printer. X.SH FILES X.nf X.ta \w'/usr/spool/*/cf* 'u X/etc/passwd personal identification X/etc/printcap printer capabilities data base X/etc/printer_perms printer permissions X/usr/lib/lpd* line printer daemons X/usr/spool/* directories used for spooling X/usr/spool/*/cf* daemon control files X/usr/spool/*/df* data files specified in "cf" files X/usr/spool/*/tf* temporary copies of "cf" files X.fi X.SH DIAGNOSTICS The diagnostics from X.I lpr are extremely verbose. If you try to spool too large a file or too many files, the job will be rejected. If this is the case, use X.I cat to append the files and then pipe them to LPR. X.I Lpr will object to printing binary files, as determined by a crude sanity and a.out header check. If a connection to the X.I lpd daemon socket /dev/printer cannot be made, X.I lpr will say that the server cannot be started. X.PP XEntries in the printcap will determine the exact actions taken by X.I lpr in spooling files; see the X.IR printcap (5) man pages for details. X.IR lpd . X.SH "SEE ALSO" lpq(1), lprm(1), pr(1), printcap(5), lpc(8), lpd(8), X.br X.I "PLP - The Public Line Printer Spooler", by Patrick Powell, University of Minnesota. X.fi X.SH "HISTORY" X.PP The PLP is a reverse engineered version of the Berkeley 4.3BSD Line Printer Spooler, done in 1988 at the University of Minnesota. It has many advanced features which are described in X.I "PLP - The Public Line Printer Spooler" by Patrick Powell, Department of Computer Science, University of Minnesota. END_OF_FILE if test 7221 -ne `wc -c <'man/lpr.1'`; then echo shar: \"'man/lpr.1'\" unpacked with wrong size! fi # end of 'man/lpr.1' fi if test -f 'src/mexecv.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/mexecv.c'\" else echo shar: Extracting \"'src/mexecv.c'\" \(6769 characters\) sed "s/^X//" >'src/mexecv.c' <<'END_OF_FILE' X/*************************************************************************** X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell X *************************************************************************** X * MODULE: mexecv.c X * ExecrV a la 4 BSD for brain damaged System V X *************************************************************************** X * Revision History: Created Sat Jan 9 15:23:23 CST 1988 X * $Log: mexecv.c,v $ X * Revision 3.1 88/06/18 09:35:11 papowell X * Version 3.0- Distributed Sat Jun 18 1988 X * X * Revision 2.1 88/05/09 10:09:36 papowell X * PLP: Released Version X * X * Revision 1.6 88/04/28 11:02:48 papowell X * removed unused variables, shuts up lint X * X * Revision 1.5 88/04/27 20:24:08 papowell X * Modified the SYSV Braindamaged mode to invoke shells better. X * The invocation is rather odd, but appears to work. X * X * Revision 1.4 88/03/25 15:00:52 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/11 19:29:44 papowell X * Minor Changes, Updates X * X * Revision 1.2 88/03/05 15:00:56 papowell X * Minor Corrections, Lint Problems X * X * Revision 1.1 88/03/01 11:08:56 papowell X * Initial revision X * X ***************************************************************************/ X#ifndef lint static char id_str1[] = X "$Header: mexecv.c,v 3.1 88/06/18 09:35:11 papowell Exp $ PLP Copyright 1988 Patrick Powell"; X#endif lint X X/*************************************************************************** X * ExecrV a la 4 BSD for brain damaged System V X * Sun Dec 6 20:04:57 CST 1987 Patrick Powell X * This is a massive hack, based on all sorts of checks and balances. X * X * 1. First, we try blinding using exev() X * 2. Next, we check the perms; if not executable, tough. X * 3. Next we try to read the file; if not readable, tough. X * 4. We read the first character of the file. X * 5. If it is not #, use Bourne shell; X * 6. We check for the #!; if not, we use CSH X * 7. We get the pathname of the file, and args, and use that. X */ X#include "lp.h" X mexecv( command) X char *command; X{ X int i; /* ACME Integer, Inc. */ X struct stat statb; X FILE *fp; X char buf[BUFSIZ]; X char cmd[BUFSIZ]; X char *cp; X char *args[100]; X char **argv = args+2; X char *option = 0; X char *fname; X char *path; X X /* X * close all the file descriptors X */ X for( i = 3; i < NOFILE; ++i){ X (void)close(i); X } X /* X * split command line up X */ X (void)strcpy(cmd,command); X if( getwords(cmd, argv, 98) == 0 ){ X log(XLOG_INFO,"mexecv: invalid argv passed, command %s",command); X return; X } X if(Debug>4){ X char **s, b[BUFSIZ]; X (void)sprintf(b,"mexecv: "); X for( s = argv; *s; ++s){ X (void)sprintf(b+strlen(b),"'%s' ",*s); X } X log(XLOG_DEBUG,"%s",b); X } X execv( argv[0],argv ); X X if(Debug>4)logerr(XLOG_DEBUG,"mexecv: execv failed" ); X X /* X * well, that didn't work, lets try the shell options X */ X fname = argv[0]; X if( stat(fname, &statb) < 0 ){ X logerr( XLOG_INFO,"mexecv: cannot stat %s", fname ); X return; X } X if(Debug>4)log(XLOG_DEBUG, X "mexecv: %s, perms %o, st_uid %d, st_gid %d, uid %d, gid %d", X fname,statb.st_mode &0777, statb.st_uid, statb.st_gid, X getegid(), geteuid()); X if(! (statb.st_mode & 0001) X && !((statb.st_mode & 0010) && statb.st_gid == getegid()) X && !((statb.st_mode & 0100) && statb.st_uid == geteuid())){ X log( XLOG_INFO,"mexecv: %s has no valid execute perms",fname); X return; X } X fp = fopen( fname, "r" ); X if( fp == NULL ){ X logerr(XLOG_INFO,"mexecv: cannot open %s for reading and failed execv", X fname); X return; X } X if( fgets( buf, sizeof(buf), fp ) == NULL X || (cp = index(buf, '\n')) == NULL ){ X /* empty file , bad format */ X log( XLOG_INFO,"mexecv: bad format %s", fname ); X return; X } X (void)fclose(fp); X *cp = 0; X if( buf[0] != '#' ){ X path = "/bin/sh"; X } else { X /* check for the #! magic number */ X if( buf[1] != '!' ){ X /* use csh, be paranoid, and sure */ X path = "/bin/csh"; X } else { X /* we have an explicit path Name formed */ X for( path = &buf[2]; *path && isspace(*path); ++path); X /* path points to the start of the command */ X if( *path == 0 ){ X log( XLOG_INFO,"mexecv: bad format %s", path ); X return; X } X /* look for the end of the command */ X for( cp = path; *cp && !isspace(*cp); ++cp ); X if( *cp ){ X /* we have options */ X *cp = 0; X for( ++cp; *cp && isspace(*cp); ++cp); X option = cp; X ++cp; X for( ++cp; *cp && !isspace(*cp); ++cp); X *cp = 0; X } X } X } X if( strcmp( path, "/bin/csh" ) == 0 ){ X /* we are using csh */ X if( option == 0 ){ X option = "-f"; X } else { X (void)strcat(option, "f"); X } X } else if (strcmp( path, "/bin/sh") == 0 ){ X /* X * nothing X */ X ; X } else { X fatal( XLOG_INFO,"mexecv: shell (%s) not /bin/csh or /bin/sh", path ); X } X if( option ){ X --argv; X argv[0] = option; X } X --argv; X argv[0] = fname; X if(Debug>4){ X char **s, b[BUFSIZ]; X (void)sprintf(b,"mexecv: path '%s'", path); X for( s = argv; *s; ++s){ X (void)sprintf(b+strlen(b),"'%s' ",*s); X } X log(XLOG_DEBUG,"%s",b); X } X execv( path,argv ); X logerr_die(XLOG_INFO,"mexecv: execv failed '%s'", path); X} X X X/* X * getwords splits a string up into words, and returns a non-null X * pointer if there are any. X * Note that splitting is done on a crude basis of matched quotes only X */ int getwords(s, argv, maxargc) X char *s; /* string containing isspace separated words */ X char *argv[]; X int maxargc; X{ X char **w; X char *tp = s; X int num_words = 0; X X if (s==NULL || *s == 0 ) X return(0); X while (*tp) { X while(*tp && isspace(*tp)) X ++tp; X if (*tp == 0) continue; X num_words++; X if( *tp == '\'' ){ X if( (tp = index( tp+1, '\'')) == 0 ){ X log(XLOG_INFO,"getwords: unmatched ' in string: %s", s ); X return(0); X } X ++tp; X } else if( *tp == '\"' ){ X if( (tp = index( tp+1, '\"')) == 0 ){ X log(XLOG_INFO,"getwords: unmatched ' in string: %s", s ); X return(0); X } X ++tp; X } else { X while ((*tp) && !isspace(*tp)) X ++tp; X } X } X if (num_words==0) X return(0); X if( num_words > maxargc ){ X log(XLOG_INFO,"getwords: more than %d arguments" ); X return(0); X } X w = argv; X while(*s) { X while(*s && isspace(*s)) X ++s; X if (*s == 0) { X *w = NULL; X return(1); X } X if( *s == '\'' ){ X *w++ = s+1; X s = index( s+1, '\''); X *s++ = 0; X } else if( *s == '\"' ){ X *w++ = s+1; X s = index( s+1, '\"'); X *s++ = 0; X } else { X *w++ = s; X while ((*s) && !isspace(*s)) X ++s; X if( *s ) *s++ = '\0'; X } X } X *w = NULL; X return(1); X} END_OF_FILE if test 6769 -ne `wc -c <'src/mexecv.c'`; then echo shar: \"'src/mexecv.c'\" unpacked with wrong size! fi # end of 'src/mexecv.c' fi if test -f 'src/rmjob.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/rmjob.c'\" else echo shar: Extracting \"'src/rmjob.c'\" \(7416 characters\) sed "s/^X//" >'src/rmjob.c' <<'END_OF_FILE' X/*************************************************************************** X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell X *************************************************************************** X * MODULE: rmjob.c X * Remove jobs from a printer queue X *************************************************************************** X * Revision History: Created Sat Jan 9 20:08:26 CST 1988 X * $Log: rmjob.c,v $ X * Revision 3.1 88/06/18 09:35:34 papowell X * Version 3.0- Distributed Sat Jun 18 1988 X * X * Revision 2.2 88/05/14 10:21:11 papowell X * Modified -X flag handling X * X * Revision 2.1 88/05/09 10:10:09 papowell X * PLP: Released Version X * X * Revision 1.4 88/03/25 15:01:32 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/11 19:29:16 papowell X * Minor Changes, Updates X * X * Revision 1.2 88/03/05 15:01:42 papowell X * Minor Corrections, Lint Problems X * X * Revision 1.1 88/03/01 11:09:11 papowell X * Initial revision X * X ***************************************************************************/ X#ifndef lint static char id_str1[] = X "$Header: rmjob.c,v 3.1 88/06/18 09:35:34 papowell Exp $ PLP Copyright 1988 Patrick Powell"; X#endif lint X X#include "lp.h" X X/*************************************************************************** X * rmjob() X * 1. get the printcap entries X * 2. get the queue entries X * 3. get the active server files and see if they are in queue X * 4. scan the queue, checking each job for removal X * X * user local job from remove_all perms inlist remove? X * =============================================================== X * root yes * * yes * * yes X * root yes * * no * yes yes X * root no * mach yes * * yes X * root no * mach no * yes yes X * user - user mach - R yes yes X * user - * * - C yes yes X * X * 5. remove the job; this may necessitate stopping or killing a deamon X ***************************************************************************/ static int remove_all; /* remove all jobs */ static int control_perms; /* has C perms */ X rmjob() X{ X int i; /* ACME Integers, Inc. */ X struct queue *q; /* job entry */ X int perms; /* hold perms values */ X X /* X * get the printcap entry X */ X if(Get_pc_entry(Printer, Status_pc_vars, Status_pc_len) == 0){ X (void)fprintf(stdout, "Printer %s does not exist\n", Printer ); X (void)fflush(stdout); X return; X } X if( SD == 0 || *SD == 0 ){ X if(Debug>2)log(XLOG_DEBUG,"not a Printer"); X return; X } X /* chdir to spool directory */ X if (chdir(SD) < 0) { X logerr_die( XLOG_NOTICE,"cannot chdir to %s", SD); X } X /* X * set the flags needed X */ X Is_local = strcmp( From, Host ) == 0; X Is_root = strcmp( Person, "root" ); X remove_all = (Parmcount > 0 && (strcmp( Parms[0].str, "-all" ) == 0)); X /* X * check to see that the user has RMJOB privs on this machine X */ X perms = 'R'; /* must be able to at least use the Printer */ X if( !Is_root && ( X (Permfile && *Permfile X && !Checkperm( Permfile,From,Person,First_name,&perms,(int *)0,0 )) X || (XU && *XU X && !Checkperm( XU,From,Person,First_name,&perms,(int *)0,0 )))) { X (void)fprintf(stdout, "No remove permission on %s", First_name); X return; X } X perms = 'C'; /* check for control perms */ X control_perms = 0; X if( !Is_root && ( X (Permfile && *Permfile X && Checkperm( Permfile,From,Person,First_name,&perms,(int *)0,0 )) X || (XU && *XU X && Checkperm( XU,From,Person,First_name,&perms,(int *)0,0 )))) { X control_perms = 1; X } X if(Debug>4)log(XLOG_DEBUG, X "rmjob: Is_root %d, Is_local %d, remove_all %d, control_perms %d", X Is_root, Is_local, remove_all, control_perms ); X /* X * check for remote machine and networked file system X */ X if( RM && NW ){ X Remote_remove(); X return; X } X /* X * get the job queue X */ X Jobcount = Getq(); X (void)Checkactive(); X /* X * run down list X */ X (void)fprintf(stdout,"Printer '%s' (%s):\n", Printer, Host ); X (void)fflush(stdout); X for( i = 0; i < Jobcount; ++i ){ X q = &Queue[i]; X if( shouldremove( q ) ){ X (void)fprintf(stdout,"removing %s, job %d owner %s\n", X q->q_name, q->q_num, q->q_user); X (void)fflush(stdout); X doremove(q); X } X } X /* X * check for remote machine X */ X if( RM ){ X Remote_remove(); X } X /* X * give the server a kick X */ X (void)Startserver(); X} X X/*********************************************************************** X * shouldremove( q ) X * a simple application of the removal decision table X * X * user local job from remove_all perms inlist remove? X * =============================================================== X * root yes * * yes * * yes X * root yes * * no * yes yes X * root no * mach yes * * yes X * root no * mach no * yes yes X * user - user mach - R yes yes X * user - * * - C yes yes X * X * Returns: 1 if removal is indicated, 0 otherwise X ***********************************************************************/ int shouldremove( q ) X struct queue *q; X{ X int i, same_host; X X same_host = (strcmp( From, &q->q_from ) == 0); X i = Match_entry(q); X if( Is_root && Is_local && remove_all ) return(1); X if( Is_root && Is_local && !remove_all && i ) return(1); X if( Is_root && !Is_local && same_host && remove_all ) return(1); X if( Is_root && !Is_local && same_host && !remove_all && i ) return(1); X if( strcmp( Person, q->q_user) == 0 && same_host && i ) return(1); X if( i && control_perms ) return(1); X return( 0 ); X} X X/*************************************************************************** X * doremove(struct queue *q) X * remove the job X * 1. Lock the control file. X * 2. If unsuccessful, find the server PID and kill it off. X * 3. Use brute force and remove the files. X ***************************************************************************/ X doremove( q ) X struct queue *q; X{ X FILE *cfp; X X if( (cfp = Lockcf( q->q_name )) == NULL ){ X /* hmmm... looks like an active server */ X if( (cfp = fopen_daemon( q->q_name, "r" )) == NULL ){ X /* nope, the file has really gone */ X logerr(XLOG_INFO,"control file %s not readable", q->q_name ); X return; X } X /* well, we will just have to kill of the server */ X if( q->q_daemon == 0){ X /* X * Hmmm... we have this fellow running the file, and it is X * locked. That means that it just started running this X * guy. Better check again. X */ X (void)Checkactive(); X } X if( q->q_daemon ){ X (void)fprintf( stdout, "killing off %s server %d", X q->q_server,q->q_daemon ); X if( killpg( q->q_daemon, SIGINT) < 0 ){ X if(Debug>2)log(XLOG_DEBUG, X "server %s (%d) was not alive", X q->q_server,q->q_daemon ); X } X } X } X /* use brute force; we simply remove files */ X if(Debug>3)log(XLOG_DEBUG,"removing files for job %s",q->q_name); X Remove_job( cfp, q ); X (void)fclose( cfp ); X} END_OF_FILE if test 7416 -ne `wc -c <'src/rmjob.c'`; then echo shar: \"'src/rmjob.c'\" unpacked with wrong size! fi # end of 'src/rmjob.c' fi echo shar: End of archive 5 \(of 16\). cp /dev/null ark5isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 16 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.