mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Mega lpd/lpd upgrade, part I:
- Get rid of a lot of the static variables which were shared by many routines and programs in the suite. - Create an abstract interface to the printcap database, so that other retrieval and iteration mechanisms could be developed (e.g., YP, Hesiod, or automatic retrieval from a trusted server). - Give each capability a human-readable name in addition to the historic two-character one. - Otherwise generally clean up a lot of dark corners. Many still remain. - When submitting jobs, use the official login name record (from getlogin()) if there is one, rather than reverse-mapping the uid. More to come...
This commit is contained in:
parent
a846453c5e
commit
4a1a0dbedb
43 changed files with 2907 additions and 1932 deletions
|
|
@ -1,6 +1,7 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $Id$
|
||||
|
||||
SUBDIR= lp lpc lpd lpq lpr lprm lptest pac filters
|
||||
SUBDIR= common_source chkprintcap lp lpc lpd lpq lpr lprm lptest pac \
|
||||
filters SMM.doc
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
|
|
|
|||
3
usr.sbin/lpr/Makefile.inc
Normal file
3
usr.sbin/lpr/Makefile.inc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# $Id$
|
||||
|
||||
CWARNFLAGS= -Werror -Wall -Wnested-externs -Wmissing-prototypes
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/8/93
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/8/93
|
||||
# $Id: Makefile,v 1.3 1997/02/22 13:05:43 peter Exp $
|
||||
|
||||
DIR= smm/07.lpd
|
||||
VOLUME= smm/07.lpd
|
||||
SRCS= 0.t 1.t 2.t 3.t 4.t 5.t 6.t 7.t
|
||||
MACROS= -ms
|
||||
|
||||
paper.ps: ${SRCS}
|
||||
${TBL} ${SRCS} | ${ROFF} > ${.TARGET}
|
||||
USE_TBL= yes
|
||||
SRCDIR= ${.CURDIR}
|
||||
|
||||
.include <bsd.doc.mk>
|
||||
|
|
|
|||
10
usr.sbin/lpr/chkprintcap/Makefile
Normal file
10
usr.sbin/lpr/chkprintcap/Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# $Id$
|
||||
|
||||
PROG= chkprintcap
|
||||
MAN8= chkprintcap.8
|
||||
CFLAGS+=-I${.CURDIR}/../common_source -Wall -Werror
|
||||
.PATH: ${.CURDIR}/../common_source
|
||||
LDADD= -L${.OBJDIR}/../common_source -llpr
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
96
usr.sbin/lpr/chkprintcap/chkprintcap.8
Normal file
96
usr.sbin/lpr/chkprintcap/chkprintcap.8
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
.\" Copyright 1997 Massachusetts Institute of Technology
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software and
|
||||
.\" its documentation for any purpose and without fee is hereby
|
||||
.\" granted, provided that both the above copyright notice and this
|
||||
.\" permission notice appear in all copies, that both the above
|
||||
.\" copyright notice and this permission notice appear in all
|
||||
.\" supporting documentation, and that the name of M.I.T. not be used
|
||||
.\" in advertising or publicity pertaining to distribution of the
|
||||
.\" software without specific, written prior permission. M.I.T. makes
|
||||
.\" no representations about the suitability of this software for any
|
||||
.\" purpose. It is provided "as is" without express or implied
|
||||
.\" warranty.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||
.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||
.\" SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id$
|
||||
.Dd November 30, 1997
|
||||
.Dt CHKPRINTCAP 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm chkprintcap
|
||||
.Nd check validity of entries in the print spooler database
|
||||
.Sh SYNOPSIS
|
||||
.Nm chkprintcap
|
||||
.Op Fl d
|
||||
.Op Fl f Ar printcap
|
||||
.Sh DESCRIPTION
|
||||
.Nm Chkprintcap
|
||||
scans a
|
||||
.Xr printcap 5
|
||||
database
|
||||
(named by the
|
||||
.Ar printcap
|
||||
argument, or by default
|
||||
.Pa /etc/printcap ) ,
|
||||
looking for entries which are invalid in one way or another.
|
||||
The following checks are currently implemented:
|
||||
.Bl -enum -offset indent
|
||||
.It
|
||||
.Sq Li tc=
|
||||
references were properly expanded
|
||||
.It
|
||||
.Sq Li tc=
|
||||
references did not form a loop
|
||||
.It
|
||||
No two printers share the same spool directory
|
||||
.Po
|
||||
.Sq Li sd=
|
||||
capability
|
||||
.Pc .
|
||||
.El
|
||||
.Pp
|
||||
.Nm Chkprintcap
|
||||
exits with a status equal to the number of errors encountered before
|
||||
processing stopped. (In some cases, processing can stop before the
|
||||
entire file is scanned.)
|
||||
.Pp
|
||||
If the
|
||||
.Fl d
|
||||
flag is given,
|
||||
.Nm chkprintcap
|
||||
will attempt to create any missing spool directories, giving them
|
||||
.Sq Li u=rwx,go=rx
|
||||
(0755) mode, group
|
||||
.Sq Li daemon ,
|
||||
and the owner specified by the
|
||||
.Sq Li du=
|
||||
capability in the database (default 1, which corresponds to user
|
||||
.Sq Li daemon ) .
|
||||
.Sh SEE ALSO
|
||||
.Xr lpr 1 ,
|
||||
.Xr printcap 5 ,
|
||||
.Xr lpd 8
|
||||
.Sh AUTHOR
|
||||
The
|
||||
.Nm chkprintcap
|
||||
command was written by
|
||||
.An Garrett A. Wollman Aq wollman@lcs.mit.edu .
|
||||
.Sh BUGS
|
||||
Not enough sanity-checking is done. At a minimum, the ownership and
|
||||
mode of the spool directories should also be checked. Other
|
||||
parameters whose value could cause
|
||||
.Xr lpd 8
|
||||
to fail should be diagnosed.
|
||||
277
usr.sbin/lpr/chkprintcap/chkprintcap.c
Normal file
277
usr.sbin/lpr/chkprintcap/chkprintcap.c
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* Copyright 1997 Massachusetts Institute of Technology
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that both the above copyright notice and this
|
||||
* permission notice appear in all copies, that both the above
|
||||
* copyright notice and this permission notice appear in all
|
||||
* supporting documentation, and that the name of M.I.T. not be used
|
||||
* in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. M.I.T. makes
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
static const char copyright[] =
|
||||
"Copyright (C) 1997, Massachusetts Institute of Technology\r\n";
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/param.h> /* needed for lp.h but not used here */
|
||||
#include <dirent.h> /* ditto */
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
|
||||
static void check_spool_dirs(void);
|
||||
static int interpret_error(const struct printer *pp, int error);
|
||||
static void make_spool_dir(const struct printer *pp);
|
||||
static void note_spool_dir(const struct printer *pp, const struct stat *st);
|
||||
static void usage(void) __dead2;
|
||||
|
||||
static int problems; /* number of problems encountered */
|
||||
|
||||
/*
|
||||
* chkprintcap - check the printcap file for syntactic and semantic errors
|
||||
* Returns the number of problems found.
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c, error, makedirs, more;
|
||||
struct printer myprinter, *pp;
|
||||
|
||||
makedirs = 0;
|
||||
pp = &myprinter;
|
||||
|
||||
while ((c = getopt(argc, argv, "df:")) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
makedirs = 1;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
setprintcap(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc)
|
||||
usage();
|
||||
|
||||
more = firstprinter(pp, &error);
|
||||
if (interpret_error(pp, error) && more)
|
||||
goto next;
|
||||
|
||||
while (more) {
|
||||
struct stat stab;
|
||||
|
||||
errno = 0;
|
||||
if (stat(pp->spool_dir, &stab) < 0) {
|
||||
if (errno == ENOENT && makedirs) {
|
||||
make_spool_dir(pp);
|
||||
} else {
|
||||
problems++;
|
||||
warn("%s: %s", pp->printer, pp->spool_dir);
|
||||
}
|
||||
} else {
|
||||
note_spool_dir(pp, &stab);
|
||||
}
|
||||
|
||||
/* Make other validity checks here... */
|
||||
|
||||
next:
|
||||
more = nextprinter(pp, &error);
|
||||
if (interpret_error(pp, error) && more)
|
||||
goto next;
|
||||
}
|
||||
check_spool_dirs();
|
||||
return problems;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret the error code. Returns 1 if we should skip to the next
|
||||
* record (as this record is unlikely to make sense). If the problem
|
||||
* is very severe, exit. Otherwise, return zero.
|
||||
*/
|
||||
static int
|
||||
interpret_error(const struct printer *pp, int error)
|
||||
{
|
||||
switch(error) {
|
||||
case PCAPERR_OSERR:
|
||||
err(++problems, "reading printer database");
|
||||
case PCAPERR_TCLOOP:
|
||||
++problems;
|
||||
warnx("%s: loop detected in tc= expansion", pp->printer);
|
||||
return 1;
|
||||
case PCAPERR_TCOPEN:
|
||||
warnx("%s: unresolved tc= expansion", pp->printer);
|
||||
return 1;
|
||||
case PCAPERR_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
errx(++problems, "unknown printcap library error %d", error);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep the list of spool directories. Note that we don't whine
|
||||
* until all spool directories are noted, so that all of the more serious
|
||||
* problems are noted first. We keep the list sorted by st_dev and
|
||||
* st_ino, so that the problem spool directories can be noted in
|
||||
* a single loop.
|
||||
*/
|
||||
struct dirlist {
|
||||
LIST_ENTRY(dirlist) link;
|
||||
struct stat stab;
|
||||
char *path;
|
||||
char *printer;
|
||||
};
|
||||
|
||||
static LIST_HEAD(, dirlist) dirlist;
|
||||
|
||||
static int
|
||||
lessp(const struct dirlist *a, const struct dirlist *b)
|
||||
{
|
||||
if (a->stab.st_dev == b->stab.st_dev)
|
||||
return a->stab.st_ino < b->stab.st_ino;
|
||||
return a->stab.st_dev < b->stab.st_dev;
|
||||
}
|
||||
|
||||
static int
|
||||
equal(const struct dirlist *a, const struct dirlist *b)
|
||||
{
|
||||
return ((a->stab.st_dev == b->stab.st_dev)
|
||||
&& (a->stab.st_ino == b->stab.st_ino));
|
||||
}
|
||||
|
||||
static void
|
||||
note_spool_dir(const struct printer *pp, const struct stat *st)
|
||||
{
|
||||
struct dirlist *dp, *dp2, *last;
|
||||
|
||||
dp = malloc(sizeof *dp);
|
||||
if (dp == 0)
|
||||
err(++problems, "malloc(%lu)", (u_long)sizeof *dp);
|
||||
|
||||
dp->stab = *st;
|
||||
dp->printer = strdup(pp->printer);
|
||||
if (dp->printer == 0)
|
||||
err(++problems, "malloc(%lu)", strlen(pp->printer) + 1UL);
|
||||
dp->path = strdup(pp->spool_dir);
|
||||
if (dp->path == 0)
|
||||
err(++problems, "malloc(%lu)", strlen(pp->spool_dir) + 1UL);
|
||||
|
||||
last = 0;
|
||||
dp2 = dirlist.lh_first;
|
||||
while (dp2 && lessp(dp, dp2)) {
|
||||
last = dp2;
|
||||
dp2 = dp2->link.le_next;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
LIST_INSERT_AFTER(last, dp, link);
|
||||
} else {
|
||||
LIST_INSERT_HEAD(&dirlist, dp, link);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_spool_dirs(void)
|
||||
{
|
||||
struct dirlist *dp, *dp2;
|
||||
|
||||
for (dp = dirlist.lh_first; dp; dp = dp2) {
|
||||
dp2 = dp->link.le_next;
|
||||
|
||||
if (dp2 != 0 && equal(dp, dp2)) {
|
||||
++problems;
|
||||
if (strcmp(dp->path, dp2->path) == 0) {
|
||||
warnx("%s and %s share the same spool, %s",
|
||||
dp->printer, dp2->printer, dp->path);
|
||||
} else {
|
||||
warnx("%s (%s) and %s (%s) are the same "
|
||||
"directory", dp->path, dp->printer,
|
||||
dp2->path, dp2->printer);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* Should probably check owners and modes here. */
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SPOOL_DIR_MODE
|
||||
#define SPOOL_DIR_MODE (S_IRUSR | S_IWUSR | S_IXUSR \
|
||||
| S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
|
||||
#endif
|
||||
|
||||
static void
|
||||
make_spool_dir(const struct printer *pp)
|
||||
{
|
||||
char *sd = pp->spool_dir;
|
||||
struct group *gr;
|
||||
struct stat stab;
|
||||
|
||||
if (mkdir(sd, S_IRUSR | S_IXUSR) < 0) {
|
||||
problems++;
|
||||
warn("%s: mkdir %s", pp->printer, sd);
|
||||
return;
|
||||
}
|
||||
gr = getgrnam("daemon");
|
||||
if (gr == 0)
|
||||
errx(++problems, "cannot locate daemon group");
|
||||
|
||||
if (chown(sd, pp->daemon_user, gr->gr_gid) < 0) {
|
||||
++problems;
|
||||
warn("%s: cannot change ownership to %ld:%ld", sd,
|
||||
(long)pp->daemon_user, (long)gr->gr_gid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (chmod(sd, SPOOL_DIR_MODE) < 0) {
|
||||
++problems;
|
||||
warn("%s: cannot change mode to %lo", (long)SPOOL_DIR_MODE);
|
||||
return;
|
||||
}
|
||||
if (stat(sd, &stab) < 0)
|
||||
err(++problems, "stat: %s", sd);
|
||||
|
||||
note_spool_dir(pp, &stab);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage:\n\tchkprintcap [-d] [-f printcapfile]\n");
|
||||
exit(1);
|
||||
}
|
||||
19
usr.sbin/lpr/common_source/Makefile
Normal file
19
usr.sbin/lpr/common_source/Makefile
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# $Id$
|
||||
|
||||
#
|
||||
# Library of internal routines for the print spooler suite.
|
||||
# Originally these were compiled separately into each program,
|
||||
# but the library makes it much easier to modularize them.
|
||||
#
|
||||
LIB= lpr
|
||||
SRCS= common.c displayq.c net.c printcap.c request.c rmjob.c \
|
||||
startdaemon.c
|
||||
NOMAN= noman
|
||||
NOPROFILE= noprofile
|
||||
NOPIC= nopic
|
||||
CFLAGS+= -Werror -Wall -Wnested-externs -Wmissing-prototypes \
|
||||
-Wstrict-prototypes -Wredundant-decls
|
||||
|
||||
install:
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
|
@ -37,150 +37,37 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
* Routines and data common to all the line printer functions.
|
||||
*/
|
||||
|
||||
char *AF; /* accounting file */
|
||||
long BR; /* baud rate if lp is a tty */
|
||||
char *CF; /* name of cifplot filter (per job) */
|
||||
long CT; /* TCP connection timeout */
|
||||
char *DF; /* name of tex filter (per job) */
|
||||
long DU; /* daeomon user-id */
|
||||
char *FF; /* form feed string */
|
||||
char *GF; /* name of graph(1G) filter (per job) */
|
||||
long HL; /* print header last */
|
||||
char *IF; /* name of input filter (created per job) */
|
||||
char *LF; /* log file for error messages */
|
||||
char *LO; /* lock file name */
|
||||
char *LP; /* line printer device name */
|
||||
long MC; /* maximum number of copies allowed */
|
||||
long MX; /* maximum number of blocks to copy */
|
||||
char *NF; /* name of ditroff filter (per job) */
|
||||
char *OF; /* name of output filter (created once) */
|
||||
char *PF; /* name of vrast filter (per job) */
|
||||
long PL; /* page length */
|
||||
long PW; /* page width */
|
||||
long PX; /* page width in pixels */
|
||||
long PY; /* page length in pixels */
|
||||
char *RF; /* name of fortran text filter (per job) */
|
||||
char *RG; /* resricted group */
|
||||
char *RM; /* remote machine name */
|
||||
char *RP; /* remote printer name */
|
||||
long RS; /* restricted to those with local accounts */
|
||||
long RW; /* open LP for reading and writing */
|
||||
long SB; /* short banner instead of normal header */
|
||||
long SC; /* suppress multiple copies */
|
||||
char *SD; /* spool directory */
|
||||
long SF; /* suppress FF on each print job */
|
||||
long SH; /* suppress header page */
|
||||
char *ST; /* status file name */
|
||||
char *TF; /* name of troff filter (per job) */
|
||||
char *TR; /* trailer string to be output when Q empties */
|
||||
char *MS; /* mode set, a la stty */
|
||||
char *VF; /* name of vplot filter (per job) */
|
||||
|
||||
char line[BUFSIZ];
|
||||
char *bp; /* pointer into printcap buffer. */
|
||||
char *name; /* program name */
|
||||
char *printer; /* printer name */
|
||||
/* host machine name */
|
||||
char host[MAXHOSTNAMELEN];
|
||||
char *from = host; /* client's machine name */
|
||||
int remote; /* true if sending files to a remote host */
|
||||
char *printcapdb[2] = { _PATH_PRINTCAP, 0 };
|
||||
|
||||
extern uid_t uid, euid;
|
||||
|
||||
static int compar __P((const void *, const void *));
|
||||
|
||||
/*
|
||||
* Create a TCP connection to host "rhost" at port "rport".
|
||||
* If rport == 0, then use the printer service port.
|
||||
* Most of this code comes from rcmd.c.
|
||||
*/
|
||||
int
|
||||
getport(rhost, rport)
|
||||
char *rhost;
|
||||
int rport;
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct servent *sp;
|
||||
struct sockaddr_in sin;
|
||||
int s, timo = 1, lport = IPPORT_RESERVED - 1;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Get the host address and port number to connect to.
|
||||
*/
|
||||
if (rhost == NULL)
|
||||
fatal("no remote host to connect to");
|
||||
bzero((char *)&sin, sizeof(sin));
|
||||
sin.sin_addr.s_addr = inet_addr(rhost);
|
||||
if (sin.sin_addr.s_addr != INADDR_NONE)
|
||||
sin.sin_family = AF_INET;
|
||||
else {
|
||||
hp = gethostbyname(rhost);
|
||||
if (hp == NULL)
|
||||
fatal("unknown host %s", rhost);
|
||||
bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
|
||||
sin.sin_family = hp->h_addrtype;
|
||||
}
|
||||
if (rport == 0) {
|
||||
sp = getservbyname("printer", "tcp");
|
||||
if (sp == NULL)
|
||||
fatal("printer/tcp: unknown service");
|
||||
sin.sin_port = sp->s_port;
|
||||
} else
|
||||
sin.sin_port = htons(rport);
|
||||
|
||||
/*
|
||||
* Try connecting to the server.
|
||||
*/
|
||||
retry:
|
||||
seteuid(euid);
|
||||
s = rresvport(&lport);
|
||||
seteuid(uid);
|
||||
if (s < 0)
|
||||
return(-1);
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
err = errno;
|
||||
(void) close(s);
|
||||
errno = err;
|
||||
if (errno == EADDRINUSE) {
|
||||
lport--;
|
||||
goto retry;
|
||||
}
|
||||
if (errno == ECONNREFUSED && timo <= 16) {
|
||||
sleep(timo);
|
||||
timo *= 2;
|
||||
goto retry;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
return(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Getline reads a line from the control file cfp, removes tabs, converts
|
||||
* new-line to null and leaves it in line.
|
||||
|
|
@ -217,7 +104,8 @@ getline(cfp)
|
|||
* Return the number of entries and a pointer to the list.
|
||||
*/
|
||||
int
|
||||
getq(namelist)
|
||||
getq(pp, namelist)
|
||||
const struct printer *pp;
|
||||
struct queue *(*namelist[]);
|
||||
{
|
||||
register struct dirent *d;
|
||||
|
|
@ -228,7 +116,7 @@ getq(namelist)
|
|||
int arraysz;
|
||||
|
||||
seteuid(euid);
|
||||
if ((dirp = opendir(SD)) == NULL)
|
||||
if ((dirp = opendir(pp->spool_dir)) == NULL)
|
||||
return(-1);
|
||||
if (fstat(dirp->dd_fd, &stbuf) < 0)
|
||||
goto errdone;
|
||||
|
|
@ -294,65 +182,65 @@ compar(p1, p2)
|
|||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out whether the local machine is the same
|
||||
* as the remote machine (RM) entry (if it exists).
|
||||
*/
|
||||
char *
|
||||
checkremote()
|
||||
{
|
||||
char name[MAXHOSTNAMELEN];
|
||||
register struct hostent *hp;
|
||||
static char errbuf[128];
|
||||
|
||||
remote = 0; /* assume printer is local */
|
||||
if (RM != NULL) {
|
||||
/* get the official name of the local host */
|
||||
gethostname(name, sizeof(name));
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
hp = gethostbyname(name);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
(void) snprintf(errbuf, sizeof(errbuf),
|
||||
"unable to get official name for local machine %s",
|
||||
name);
|
||||
return errbuf;
|
||||
} else {
|
||||
(void) strncpy(name, hp->h_name, sizeof(name));
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
}
|
||||
|
||||
/* get the official name of RM */
|
||||
hp = gethostbyname(RM);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
(void) snprintf(errbuf, sizeof(errbuf),
|
||||
"unable to get official name for remote machine %s",
|
||||
RM);
|
||||
return errbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the two hosts are not the same,
|
||||
* then the printer must be remote.
|
||||
*/
|
||||
if (strcasecmp(name, hp->h_name) != 0)
|
||||
remote = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sleep n milliseconds */
|
||||
void
|
||||
delay(n)
|
||||
int n;
|
||||
{
|
||||
struct timeval tdelay;
|
||||
|
||||
if (n <= 0 || n > 10000)
|
||||
fatal("unreasonable delay period (%d)", n);
|
||||
fatal((struct printer *)0, /* fatal() knows how to deal */
|
||||
"unreasonable delay period (%d)", n);
|
||||
tdelay.tv_sec = n / 1000;
|
||||
tdelay.tv_usec = n * 1000 % 1000000;
|
||||
(void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay);
|
||||
}
|
||||
|
||||
char *
|
||||
lock_file_name(pp, buf, len)
|
||||
const struct printer *pp;
|
||||
char *buf;
|
||||
size_t len;
|
||||
{
|
||||
static char staticbuf[MAXPATHLEN];
|
||||
|
||||
if (buf == 0)
|
||||
buf = staticbuf;
|
||||
if (len == 0)
|
||||
len = MAXPATHLEN;
|
||||
|
||||
if (pp->lock_file[0] == '/') {
|
||||
buf[0] = '\0';
|
||||
strncpy(buf, pp->lock_file, len);
|
||||
} else {
|
||||
snprintf(buf, len, "%s/%s", pp->spool_dir, pp->lock_file);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
status_file_name(pp, buf, len)
|
||||
const struct printer *pp;
|
||||
char *buf;
|
||||
size_t len;
|
||||
{
|
||||
static char staticbuf[MAXPATHLEN];
|
||||
|
||||
if (buf == 0)
|
||||
buf = staticbuf;
|
||||
if (len == 0)
|
||||
len = MAXPATHLEN;
|
||||
|
||||
if (pp->status_file[0] == '/') {
|
||||
buf[0] = '\0';
|
||||
strncpy(buf, pp->status_file, len);
|
||||
} else {
|
||||
snprintf(buf, len, "%s/%s", pp->spool_dir, pp->status_file);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
|
|
@ -361,9 +249,10 @@ delay(n)
|
|||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
fatal(const char *msg, ...)
|
||||
fatal(const struct printer *pp, const char *msg, ...)
|
||||
#else
|
||||
fatal(msg, va_alist)
|
||||
fatal(pp, msg, va_alist)
|
||||
const struct printer *pp;
|
||||
char *msg;
|
||||
va_dcl
|
||||
#endif
|
||||
|
|
@ -377,10 +266,27 @@ fatal(msg, va_alist)
|
|||
if (from != host)
|
||||
(void)printf("%s: ", host);
|
||||
(void)printf("%s: ", name);
|
||||
if (printer)
|
||||
(void)printf("%s: ", printer);
|
||||
if (pp && pp->printer)
|
||||
(void)printf("%s: ", pp->printer);
|
||||
(void)vprintf(msg, ap);
|
||||
va_end(ap);
|
||||
(void)putchar('\n');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close all file descriptors from START on up.
|
||||
* This is a horrific kluge, since getdtablesize() might return
|
||||
* ``infinity'', in which case we will be spending a long time
|
||||
* closing ``files'' which were never open. Perhaps it would
|
||||
* be better to close the first N fds, for some small value of N.
|
||||
*/
|
||||
void
|
||||
closeallfds(start)
|
||||
int start;
|
||||
{
|
||||
int stop = getdtablesize();
|
||||
for (; start < stop; start++)
|
||||
close(start);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,21 +32,30 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#define psignal foil_gcc_psignal
|
||||
#define sys_siglist foil_gcc_siglist
|
||||
#include <unistd.h>
|
||||
#undef psignal
|
||||
#undef sys_siglist
|
||||
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
#include "pathnames.h"
|
||||
|
|
@ -76,13 +85,14 @@ static char *head0 = "Rank Owner Job Files";
|
|||
static char *head1 = "Total Size\n";
|
||||
|
||||
static void alarmhandler __P((int));
|
||||
static void warn __P((void));
|
||||
static void warn __P((const struct printer *pp));
|
||||
|
||||
/*
|
||||
* Display the current state of the queue. Format = 1 if long format.
|
||||
*/
|
||||
void
|
||||
displayq(format)
|
||||
displayq(pp, format)
|
||||
struct printer *pp;
|
||||
int format;
|
||||
{
|
||||
register struct queue *q;
|
||||
|
|
@ -96,71 +106,55 @@ displayq(format)
|
|||
lflag = format;
|
||||
totsize = 0;
|
||||
rank = -1;
|
||||
if ((i = cgetent(&bp, printcapdb, printer)) == -2)
|
||||
fatal("can't open printer description file");
|
||||
else if (i == -1)
|
||||
fatal("unknown printer");
|
||||
else if (i == -3)
|
||||
fatal("potential reference loop detected in printcap file");
|
||||
if (cgetstr(bp, "lp", &LP) < 0)
|
||||
LP = _PATH_DEFDEVLP;
|
||||
if (cgetstr(bp, "rp", &RP) < 0)
|
||||
RP = DEFLP;
|
||||
if (cgetstr(bp, "sd", &SD) < 0)
|
||||
SD = _PATH_DEFSPOOL;
|
||||
if (cgetstr(bp,"lo", &LO) < 0)
|
||||
LO = DEFLOCK;
|
||||
if (cgetstr(bp, "st", &ST) < 0)
|
||||
ST = DEFSTAT;
|
||||
if (cgetnum(bp, "ct", &CT) < 0)
|
||||
CT = DEFTIMEOUT;
|
||||
if (cgetstr(bp, "rm", &RM) < 0)
|
||||
RM = NULL;
|
||||
if ((cp = checkremote()))
|
||||
|
||||
if ((cp = checkremote(pp))) {
|
||||
printf("Warning: %s\n", cp);
|
||||
free(cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out local queue
|
||||
* Find all the control files in the spooling directory
|
||||
*/
|
||||
seteuid(euid);
|
||||
if (chdir(SD) < 0)
|
||||
fatal("cannot chdir to spooling directory");
|
||||
if (chdir(pp->spool_dir) < 0)
|
||||
fatal(pp, "cannot chdir to spooling directory: %s",
|
||||
strerror(errno));
|
||||
seteuid(uid);
|
||||
if ((nitems = getq(&queue)) < 0)
|
||||
fatal("cannot examine spooling area\n");
|
||||
if ((nitems = getq(pp, &queue)) < 0)
|
||||
fatal(pp, "cannot examine spooling area\n");
|
||||
seteuid(euid);
|
||||
ret = stat(LO, &statb);
|
||||
ret = stat(pp->lock_file, &statb);
|
||||
seteuid(uid);
|
||||
if (ret >= 0) {
|
||||
if (statb.st_mode & 0100) {
|
||||
if (remote)
|
||||
if (statb.st_mode & LFM_PRINT_DIS) {
|
||||
if (pp->remote)
|
||||
printf("%s: ", host);
|
||||
printf("Warning: %s is down: ", printer);
|
||||
printf("Warning: %s is down: ", pp->printer);
|
||||
seteuid(euid);
|
||||
fd = open(ST, O_RDONLY);
|
||||
fd = open(pp->status_file, O_RDONLY|O_SHLOCK);
|
||||
seteuid(uid);
|
||||
if (fd >= 0) {
|
||||
(void) flock(fd, LOCK_SH);
|
||||
while ((i = read(fd, line, sizeof(line))) > 0)
|
||||
(void) fwrite(line, 1, i, stdout);
|
||||
(void) close(fd); /* unlocks as well */
|
||||
} else
|
||||
putchar('\n');
|
||||
}
|
||||
if (statb.st_mode & 010) {
|
||||
if (remote)
|
||||
if (statb.st_mode & LFM_QUEUE_DIS) {
|
||||
if (pp->remote)
|
||||
printf("%s: ", host);
|
||||
printf("Warning: %s queue is turned off\n", printer);
|
||||
printf("Warning: %s queue is turned off\n",
|
||||
pp->printer);
|
||||
}
|
||||
}
|
||||
|
||||
if (nitems) {
|
||||
seteuid(euid);
|
||||
fp = fopen(LO, "r");
|
||||
fp = fopen(pp->lock_file, "r");
|
||||
seteuid(uid);
|
||||
if (fp == NULL)
|
||||
warn();
|
||||
warn(pp);
|
||||
else {
|
||||
/* get daemon pid */
|
||||
cp = current;
|
||||
|
|
@ -176,7 +170,7 @@ displayq(format)
|
|||
seteuid(uid);
|
||||
}
|
||||
if (ret < 0) {
|
||||
warn();
|
||||
warn(pp);
|
||||
} else {
|
||||
/* read current file name */
|
||||
cp = current;
|
||||
|
|
@ -186,16 +180,16 @@ displayq(format)
|
|||
/*
|
||||
* Print the status file.
|
||||
*/
|
||||
if (remote)
|
||||
if (pp->remote)
|
||||
printf("%s: ", host);
|
||||
seteuid(euid);
|
||||
fd = open(ST, O_RDONLY);
|
||||
fd = open(pp->status_file, O_RDONLY|O_SHLOCK);
|
||||
seteuid(uid);
|
||||
if (fd >= 0) {
|
||||
(void) flock(fd, LOCK_SH);
|
||||
while ((i = read(fd, line, sizeof(line))) > 0)
|
||||
(void) fwrite(line, 1, i, stdout);
|
||||
(void) close(fd); /* unlocks as well */
|
||||
while ((i = read(fd, line,
|
||||
sizeof(line))) > 0)
|
||||
fwrite(line, 1, i, stdout);
|
||||
close(fd); /* unlocks as well */
|
||||
} else
|
||||
putchar('\n');
|
||||
}
|
||||
|
|
@ -209,12 +203,12 @@ displayq(format)
|
|||
header();
|
||||
for (i = 0; i < nitems; i++) {
|
||||
q = queue[i];
|
||||
inform(q->q_name);
|
||||
inform(pp, q->q_name);
|
||||
free(q);
|
||||
}
|
||||
free(queue);
|
||||
}
|
||||
if (!remote) {
|
||||
if (!pp->remote) {
|
||||
if (nitems == 0)
|
||||
puts("no entries");
|
||||
return;
|
||||
|
|
@ -226,7 +220,8 @@ displayq(format)
|
|||
*/
|
||||
if (nitems)
|
||||
putchar('\n');
|
||||
(void) snprintf(line, sizeof(line), "%c%s", format + '\3', RP);
|
||||
(void) snprintf(line, sizeof(line), "%c%s", format ? '\4' : '\3',
|
||||
pp->remote_queue);
|
||||
cp = line;
|
||||
for (i = 0; i < requests && cp-line+10 < sizeof(line) - 1; i++) {
|
||||
cp += strlen(cp);
|
||||
|
|
@ -240,19 +235,19 @@ displayq(format)
|
|||
}
|
||||
strcat(line, "\n");
|
||||
savealrm = signal(SIGALRM, alarmhandler);
|
||||
alarm(CT);
|
||||
fd = getport(RM, 0);
|
||||
alarm(pp->conn_timeout);
|
||||
fd = getport(pp, pp->remote_host, 0);
|
||||
alarm(0);
|
||||
(void)signal(SIGALRM, savealrm);
|
||||
if (fd < 0) {
|
||||
if (from != host)
|
||||
printf("%s: ", host);
|
||||
printf("connection to %s is down\n", RM);
|
||||
printf("connection to %s is down\n", pp->remote_host);
|
||||
}
|
||||
else {
|
||||
i = strlen(line);
|
||||
if (write(fd, line, i) != i)
|
||||
fatal("Lost connection");
|
||||
fatal(pp, "Lost connection");
|
||||
while ((i = read(fd, line, sizeof(line))) > 0)
|
||||
(void) fwrite(line, 1, i, stdout);
|
||||
(void) close(fd);
|
||||
|
|
@ -263,9 +258,10 @@ displayq(format)
|
|||
* Print a warning message if there is no daemon present.
|
||||
*/
|
||||
static void
|
||||
warn()
|
||||
warn(pp)
|
||||
const struct printer *pp;
|
||||
{
|
||||
if (remote)
|
||||
if (pp->remote)
|
||||
printf("%s: ", host);
|
||||
puts("Warning: no daemon present");
|
||||
current[0] = '\0';
|
||||
|
|
@ -284,7 +280,8 @@ header()
|
|||
}
|
||||
|
||||
void
|
||||
inform(cf)
|
||||
inform(pp, cf)
|
||||
const struct printer *pp;
|
||||
char *cf;
|
||||
{
|
||||
register int j;
|
||||
|
|
@ -301,7 +298,7 @@ inform(cf)
|
|||
|
||||
if (rank < 0)
|
||||
rank = 0;
|
||||
if (remote || garbage || strcmp(cf, current))
|
||||
if (pp->remote || garbage || strcmp(cf, current))
|
||||
rank++;
|
||||
j = 0;
|
||||
while (getline(cfp)) {
|
||||
|
|
|
|||
|
|
@ -30,69 +30,123 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)lp.h 8.2 (Berkeley) 4/28/95
|
||||
* From: @(#)lp.h 8.2 (Berkeley) 4/28/95
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
/*
|
||||
* All this information used to be in global static variables shared
|
||||
* mysteriously by various parts of the lpr/lpd suite.
|
||||
* This structure attempts to centralize all these declarations in the
|
||||
* hope that they can later be made more dynamic.
|
||||
*/
|
||||
enum lpd_filters { LPF_CIFPLOT, LPF_DVI, LPF_GRAPH, LPF_INPUT,
|
||||
LPF_DITROFF, LPF_OUTPUT, LPF_FORTRAN, LPF_TROFF,
|
||||
LPF_RASTER, LPF_COUNT };
|
||||
/* NB: there is a table in common.c giving the mapping from capability names */
|
||||
|
||||
struct printer {
|
||||
char *printer; /* printer name */
|
||||
int remote; /* true if RM points to a remote host */
|
||||
int tof; /* true if we are at top-of-form */
|
||||
/* ------------------------------------------------------ */
|
||||
char *acct_file; /* AF: accounting file */
|
||||
long baud_rate; /* BR: baud rate if lp is a tty */
|
||||
char *filters[LPF_COUNT]; /* CF, DF, GF, IF, NF, OF, RF, TF, VF */
|
||||
long conn_timeout; /* CT: TCP connection timeout */
|
||||
long daemon_user; /* DU: daemon user id -- XXX belongs ???? */
|
||||
char *form_feed; /* FF: form feed */
|
||||
long header_last; /* HL: print header last */
|
||||
char *log_file; /* LF: log file */
|
||||
char *lock_file; /* LO: lock file */
|
||||
char *lp; /* LP: device name or network address */
|
||||
long max_copies; /* MC: maximum number of copies allowed */
|
||||
long max_blocks; /* MX: maximum number of blocks to copy */
|
||||
long price100; /* PC: price per 100 units of output */
|
||||
long page_length; /* PL: page length */
|
||||
long page_width; /* PW: page width */
|
||||
long page_pwidth; /* PX: page width in pixels */
|
||||
long page_plength; /* PY: page length in pixels */
|
||||
char *restrict_grp; /* RG: restricted group */
|
||||
char *remote_host; /* RM: remote machine name */
|
||||
char *remote_queue; /* RP: remote printer name */
|
||||
long restricted; /* RS: restricted to those with local accts */
|
||||
long rw; /* RW: open LP for reading and writing */
|
||||
long short_banner; /* SB: short banner */
|
||||
long no_copies; /* SC: suppress multiple copies */
|
||||
char *spool_dir; /* SD: spool directory */
|
||||
long no_formfeed; /* SF: suppress FF on each print job */
|
||||
long no_header; /* SH: suppress header page */
|
||||
char *status_file; /* ST: status file name */
|
||||
char *trailer; /* TR: trailer string send when Q empties */
|
||||
char *mode_set; /* MS: mode set, a la stty */
|
||||
};
|
||||
|
||||
/*
|
||||
* Lists of user names and job numbers, for the benefit of the structs
|
||||
* defined below. We use TAILQs so that requests don't get mysteriously
|
||||
* reversed in process.
|
||||
*/
|
||||
struct req_user {
|
||||
TAILQ_ENTRY(req_user) ru_link; /* macro glue */
|
||||
char ru_uname[1]; /* name of user */
|
||||
};
|
||||
TAILQ_HEAD(req_user_head, req_user);
|
||||
|
||||
struct req_file {
|
||||
TAILQ_ENTRY(req_file) rf_link; /* macro glue */
|
||||
char rf_type; /* type (lowercase cf file letter) of file */
|
||||
char *rf_prettyname; /* user-visible name of file */
|
||||
char rf_fname[1]; /* name of file */
|
||||
};
|
||||
TAILQ_HEAD(req_file_head, req_file);
|
||||
|
||||
struct req_jobid {
|
||||
TAILQ_ENTRY(req_jobid) rj_link; /* macro glue */
|
||||
int rj_job; /* job number */
|
||||
};
|
||||
TAILQ_HEAD(req_jobid_head, req_jobid);
|
||||
|
||||
/*
|
||||
* Encapsulate all the information relevant to a request in the
|
||||
* lpr/lpd protocol.
|
||||
*/
|
||||
enum req_type { REQ_START, REQ_RECVJOB, REQ_LIST, REQ_DELETE };
|
||||
|
||||
struct request {
|
||||
enum req_type type; /* what sort of request is this? */
|
||||
struct printer prtr; /* which printer is it for? */
|
||||
int remote; /* did request arrive over network? */
|
||||
char *logname; /* login name of requesting user */
|
||||
char *authname; /* authenticated identity of requesting user */
|
||||
char *prettyname; /* ``pretty'' name of requesting user */
|
||||
int privileged; /* was the request from a privileged user? */
|
||||
void *authinfo; /* authentication information */
|
||||
int authentic; /* was the request securely authenticated? */
|
||||
|
||||
/* Information for queries and deletes... */
|
||||
int nusers; /* length of following list... */
|
||||
struct req_user_head users; /* list of users to query/delete */
|
||||
int njobids; /* length of following list... */
|
||||
struct req_jobid_head jobids; /* list of jobids to query/delete */
|
||||
};
|
||||
|
||||
/*
|
||||
* Global definitions for the line printer system.
|
||||
*/
|
||||
|
||||
extern char *AF; /* accounting file */
|
||||
extern long BR; /* baud rate if lp is a tty */
|
||||
extern char *CF; /* name of cifplot filter (per job) */
|
||||
extern long CT; /* TCP connection timeout */
|
||||
extern char *DF; /* name of tex filter (per job) */
|
||||
extern long DU; /* daeomon user-id */
|
||||
extern char *FF; /* form feed string */
|
||||
extern char *GF; /* name of graph(1G) filter (per job) */
|
||||
extern long HL; /* print header last */
|
||||
extern char *IF; /* name of input filter (created per job) */
|
||||
extern char *LF; /* log file for error messages */
|
||||
extern char *LO; /* lock file name */
|
||||
extern char *LP; /* line printer device name */
|
||||
extern long MC; /* maximum number of copies allowed */
|
||||
extern long MX; /* maximum number of blocks to copy */
|
||||
extern char *NF; /* name of ditroff(1) filter (per job) */
|
||||
extern char *OF; /* name of output filter (created once) */
|
||||
extern long PL; /* page length */
|
||||
extern long PW; /* page width */
|
||||
extern long PX; /* page width in pixels */
|
||||
extern long PY; /* page length in pixels */
|
||||
extern char *RF; /* name of fortran text filter (per job) */
|
||||
extern char *RG; /* restricted group */
|
||||
extern char *RM; /* remote machine name */
|
||||
extern char *RP; /* remote printer name */
|
||||
extern long RS; /* restricted to those with local accounts */
|
||||
extern long RW; /* open LP for reading and writing */
|
||||
extern long SB; /* short banner instead of normal header */
|
||||
extern long SC; /* suppress multiple copies */
|
||||
extern char *SD; /* spool directory */
|
||||
extern long SF; /* suppress FF on each print job */
|
||||
extern long SH; /* suppress header page */
|
||||
extern char *ST; /* status file name */
|
||||
extern char *TF; /* name of troff(1) filter (per job) */
|
||||
extern char *TR; /* trailer string to be output when Q empties */
|
||||
extern char *MS; /* mode set, a la stty */
|
||||
extern char *VF; /* name of raster filter (per job) */
|
||||
|
||||
extern char line[BUFSIZ];
|
||||
extern char *bp; /* pointer into printcap buffer */
|
||||
extern char *name; /* program name */
|
||||
extern char *printer; /* printer name */
|
||||
/* host machine name */
|
||||
extern char host[MAXHOSTNAMELEN];
|
||||
extern char *from; /* client's machine name */
|
||||
extern int remote; /* true if sending files to a remote host */
|
||||
extern char *printcapdb[]; /* printcap database array */
|
||||
|
||||
extern int requ[]; /* job number of spool entries */
|
||||
extern int requests; /* # of spool requests */
|
||||
extern char *user[]; /* users to process */
|
||||
extern int users; /* # of users in user array */
|
||||
extern char *person; /* name of person doing lprm */
|
||||
extern char *name;
|
||||
|
||||
|
||||
/*
|
||||
* Structure used for building a sorted list of control files.
|
||||
|
|
@ -102,32 +156,78 @@ struct queue {
|
|||
char q_name[MAXNAMLEN+1]; /* control file name */
|
||||
};
|
||||
|
||||
/*
|
||||
* Error codes for our mini printcap library.
|
||||
*/
|
||||
#define PCAPERR_TCLOOP (-3)
|
||||
#define PCAPERR_OSERR (-2)
|
||||
#define PCAPERR_NOTFOUND (-1)
|
||||
#define PCAPERR_SUCCESS 0
|
||||
#define PCAPERR_TCOPEN 1
|
||||
|
||||
/*
|
||||
* File modes for the various status files maintained by lpd.
|
||||
*/
|
||||
#define LOCK_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
|
||||
#define LFM_PRINT_DIS (S_IXUSR)
|
||||
#define LFM_QUEUE_DIS (S_IXGRP)
|
||||
#define LFM_RESET_QUE (S_IXOTH)
|
||||
|
||||
#define STAT_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
|
||||
#define LOG_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
|
||||
#define TEMP_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
|
||||
|
||||
/*
|
||||
* Command codes used in the protocol.
|
||||
*/
|
||||
#define CMD_CHECK_QUE '\1'
|
||||
#define CMD_TAKE_THIS '\2'
|
||||
#define CMD_SHOWQ_SHORT '\3'
|
||||
#define CMD_SHOWQ_LONG '\4'
|
||||
#define CMD_RMJOB '\5'
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
struct dirent;
|
||||
struct dirent;
|
||||
|
||||
void blankfill __P((int));
|
||||
char *checkremote __P((void));
|
||||
char *checkremote __P((struct printer *pp));
|
||||
int chk __P((char *));
|
||||
void displayq __P((int));
|
||||
void closeallfds __P((int start));
|
||||
void delay __P((int));
|
||||
void displayq __P((struct printer *pp, int format));
|
||||
void dump __P((char *, char *, int));
|
||||
void fatal __P((const char *, ...));
|
||||
void fatal __P((const struct printer *pp, const char *fmp, ...));
|
||||
int firstprinter __P((struct printer *pp, int *status));
|
||||
void free_printer __P((struct printer *pp));
|
||||
void free_request __P((struct request *rp));
|
||||
int getline __P((FILE *));
|
||||
int getport __P((char *, int));
|
||||
int getq __P((struct queue *(*[])));
|
||||
int getport __P((const struct printer *pp, const char *, int));
|
||||
int getprintcap __P((const char *printer, struct printer *pp));
|
||||
int getq __P((const struct printer *, struct queue *(*[])));
|
||||
void header __P((void));
|
||||
void inform __P((char *));
|
||||
void inform __P((const struct printer *pp, char *cf));
|
||||
void init_printer __P((struct printer *pp));
|
||||
void init_request __P((struct request *rp));
|
||||
int inlist __P((char *, char *));
|
||||
int iscf __P((struct dirent *));
|
||||
int isowner __P((char *, char *));
|
||||
void ldump __P((char *, char *, int));
|
||||
int lockchk __P((char *));
|
||||
void lastprinter __P((void));
|
||||
int lockchk __P((struct printer *pp, char *));
|
||||
char *lock_file_name __P((const struct printer *pp, char *buf, size_t len));
|
||||
int nextprinter __P((struct printer *pp, int *status));
|
||||
const
|
||||
char *pcaperr __P((int error));
|
||||
void prank __P((int));
|
||||
void process __P((char *));
|
||||
void rmjob __P((void));
|
||||
void rmremote __P((void));
|
||||
void process __P((const struct printer *pp, char *));
|
||||
void rmjob __P((const char *printer));
|
||||
void rmremote __P((const struct printer *pp));
|
||||
void setprintcap __P((char *newprintcap));
|
||||
void show __P((char *, char *, int));
|
||||
int startdaemon __P((char *));
|
||||
void delay __P((int));
|
||||
int startdaemon __P((const struct printer *pp));
|
||||
char *status_file_name __P((const struct printer *pp, char *buf,
|
||||
size_t len));
|
||||
ssize_t writel __P((int s, ...));
|
||||
__END_DECLS
|
||||
|
|
|
|||
260
usr.sbin/lpr/common_source/net.c
Normal file
260
usr.sbin/lpr/common_source/net.c
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* From: @(#)common.c 8.5 (Berkeley) 4/28/95
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <dirent.h> /* required for lp.h, not used here */
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/* host machine name */
|
||||
char host[MAXHOSTNAMELEN];
|
||||
char *from = host; /* client's machine name */
|
||||
|
||||
extern uid_t uid, euid;
|
||||
|
||||
/*
|
||||
* Create a TCP connection to host "rhost" at port "rport".
|
||||
* If rport == 0, then use the printer service port.
|
||||
* Most of this code comes from rcmd.c.
|
||||
*/
|
||||
int
|
||||
getport(const struct printer *pp, const char *rhost, int rport)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct servent *sp;
|
||||
struct sockaddr_in sin;
|
||||
int s, timo = 1, lport = IPPORT_RESERVED - 1;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Get the host address and port number to connect to.
|
||||
*/
|
||||
if (rhost == NULL)
|
||||
fatal(pp, "no remote host to connect to");
|
||||
bzero((char *)&sin, sizeof(sin));
|
||||
sin.sin_len = sizeof sin;
|
||||
sin.sin_family = AF_INET;
|
||||
if (inet_aton(rhost, &sin.sin_addr) == 0) {
|
||||
hp = gethostbyname2(rhost, AF_INET);
|
||||
if (hp == NULL)
|
||||
fatal(pp, "cannot resolve %s: %s", rhost,
|
||||
hstrerror(h_errno));
|
||||
/* XXX - should deal with more addresses */
|
||||
sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0];
|
||||
}
|
||||
if (rport == 0) {
|
||||
sp = getservbyname("printer", "tcp");
|
||||
if (sp == NULL)
|
||||
fatal(pp, "printer/tcp: unknown service");
|
||||
sin.sin_port = sp->s_port;
|
||||
} else
|
||||
sin.sin_port = htons(rport);
|
||||
|
||||
/*
|
||||
* Try connecting to the server.
|
||||
*/
|
||||
retry:
|
||||
seteuid(euid);
|
||||
s = rresvport(&lport);
|
||||
seteuid(uid);
|
||||
if (s < 0)
|
||||
return(-1);
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
err = errno;
|
||||
(void) close(s);
|
||||
errno = err;
|
||||
/*
|
||||
* This used to decrement lport, but the current semantics
|
||||
* of rresvport do not provide such a function (in fact,
|
||||
* rresvport should guarantee that the chosen port will
|
||||
* never result in an EADDRINUSE).
|
||||
*/
|
||||
if (errno == EADDRINUSE)
|
||||
goto retry;
|
||||
|
||||
if (errno == ECONNREFUSED && timo <= 16) {
|
||||
sleep(timo);
|
||||
timo *= 2;
|
||||
goto retry;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
return(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out whether the local machine is the same
|
||||
* as the remote machine (RM) entry (if it exists).
|
||||
* We do this by counting the intersection of our
|
||||
* address list and theirs. This is better than the
|
||||
* old method (comparing the canonical names), as it
|
||||
* allows load-sharing between multiple print servers.
|
||||
* The return value is an error message which must be
|
||||
* free()d.
|
||||
*/
|
||||
char *
|
||||
checkremote(struct printer *pp)
|
||||
{
|
||||
char name[MAXHOSTNAMELEN];
|
||||
register struct hostent *hp;
|
||||
char *err;
|
||||
struct in_addr *localaddrs;
|
||||
int i, j, nlocaladdrs, ncommonaddrs;
|
||||
|
||||
pp->remote = 0; /* assume printer is local */
|
||||
if (pp->remote_host != NULL) {
|
||||
/* get the addresses of the local host */
|
||||
gethostname(name, sizeof(name));
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
hp = gethostbyname2(name, AF_INET);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
asprintf(&err, "unable to get official name "
|
||||
"for local machine %s: %s",
|
||||
name, hstrerror(h_errno));
|
||||
return err;
|
||||
}
|
||||
for (i = 0; hp->h_addr_list[i]; i++)
|
||||
;
|
||||
nlocaladdrs = i;
|
||||
localaddrs = malloc(i * sizeof(struct in_addr));
|
||||
if (localaddrs == 0) {
|
||||
asprintf(&err, "malloc %lu bytes failed",
|
||||
(u_long)i * sizeof(struct in_addr));
|
||||
return err;
|
||||
}
|
||||
for (i = 0; hp->h_addr_list[i]; i++)
|
||||
localaddrs[i] = *(struct in_addr *)hp->h_addr_list[i];
|
||||
|
||||
/* get the official name of RM */
|
||||
hp = gethostbyname2(pp->remote_host, AF_INET);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
asprintf(&err, "unable to get address list for "
|
||||
"remote machine %s: %s",
|
||||
pp->remote_host, hstrerror(h_errno));
|
||||
free(localaddrs);
|
||||
return err;
|
||||
}
|
||||
|
||||
ncommonaddrs = 0;
|
||||
for (i = 0; i < nlocaladdrs; i++) {
|
||||
for (j = 0; hp->h_addr_list[j]; j++) {
|
||||
char *them = hp->h_addr_list[j];
|
||||
if (localaddrs[i].s_addr ==
|
||||
(*(struct in_addr *)them).s_addr)
|
||||
ncommonaddrs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if the two hosts do not share at least one IP address
|
||||
* then the printer must be remote.
|
||||
*/
|
||||
if (ncommonaddrs == 0)
|
||||
pp->remote = 1;
|
||||
free(localaddrs);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This isn't really network-related, but it's used here to write
|
||||
* multi-part strings onto sockets without using stdio. Return
|
||||
* values are as for writev(2).
|
||||
*/
|
||||
ssize_t
|
||||
writel(int s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, n;
|
||||
const char *cp;
|
||||
#define NIOV 12
|
||||
struct iovec iov[NIOV], *iovp = iov;
|
||||
ssize_t retval;
|
||||
|
||||
/* first count them */
|
||||
va_start(ap, s);
|
||||
n = 0;
|
||||
do {
|
||||
cp = va_arg(ap, char *);
|
||||
n++;
|
||||
} while (cp);
|
||||
va_end(ap);
|
||||
n--; /* correct for count of trailing null */
|
||||
|
||||
if (n > NIOV) {
|
||||
iovp = malloc(n * sizeof *iovp);
|
||||
if (iovp == 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now make up iovec and send */
|
||||
va_start(ap, s);
|
||||
for (i = 0; i < n; i++) {
|
||||
iovp[i].iov_base = va_arg(ap, char *);
|
||||
iovp[i].iov_len = strlen(iovp[i].iov_base);
|
||||
}
|
||||
va_end(ap);
|
||||
retval = writev(s, iovp, n);
|
||||
if (iovp != iov)
|
||||
free(iovp);
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -48,3 +48,4 @@
|
|||
#define _PATH_VFONTI "/usr/libdata/vfont/I"
|
||||
#define _PATH_VFONTR "/usr/libdata/vfont/R"
|
||||
#define _PATH_VFONTS "/usr/libdata/vfont/S"
|
||||
#define _PATH_CHKPRINTCAP "/usr/sbin/chkprintcap"
|
||||
|
|
|
|||
428
usr.sbin/lpr/common_source/printcap.c
Normal file
428
usr.sbin/lpr/common_source/printcap.c
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* From: @(#)common.c 8.5 (Berkeley) 4/28/95
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/param.h> /* required for lp.h, but not used here */
|
||||
#include <sys/dirent.h> /* ditto */
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
* Routines and data used in processing the printcap file.
|
||||
*/
|
||||
static char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; /* list for cget* */
|
||||
|
||||
static char *capdb_canonical_name(const char *);
|
||||
static int capdb_getaltlog(char *, const char *, const char *);
|
||||
static int capdb_getaltnum(char *, const char *, const char *, long, long *);
|
||||
static int capdb_getaltstr(char *, const char *, const char *, const char *,
|
||||
char **);
|
||||
static int getprintcap_int(char *bp, struct printer *pp);
|
||||
|
||||
/*
|
||||
* Change the name of the printcap file. Used by chkprintcap(8),
|
||||
* but could be used by other members of the suite with appropriate
|
||||
* security measures.
|
||||
*/
|
||||
void
|
||||
setprintcap(char *newfile)
|
||||
{
|
||||
printcapdb[0] = newfile;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the printcap database for printer `printer' into the
|
||||
* struct printer pointed by `pp'. Return values are as for
|
||||
* cgetent(3): -1 means we could not find what we wanted, -2
|
||||
* means a system error occurred (and errno is set), -3 if a
|
||||
* reference (`tc=') loop was detected, and 0 means success.
|
||||
*
|
||||
* Copied from lpr; should add additional capabilities as they
|
||||
* are required by the other programs in the suite so that
|
||||
* printcap-reading is consistent across the entire family.
|
||||
*/
|
||||
int
|
||||
getprintcap(const char *printer, struct printer *pp)
|
||||
{
|
||||
int status;
|
||||
char *XXX;
|
||||
char *bp;
|
||||
|
||||
/*
|
||||
* A bug in the declaration of cgetent(3) means that we have
|
||||
* to hide the constness of its third argument.
|
||||
*/
|
||||
XXX = (char *)printer;
|
||||
if ((status = cgetent(&bp, printcapdb, XXX)) < 0)
|
||||
return status;
|
||||
status = getprintcap_int(bp, pp);
|
||||
free(bp);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the status values returned by cgetfirst/cgetnext into those
|
||||
* used by cgetent, returning truth if there are more records to
|
||||
* examine. This points out what is arguably a bug in the cget*
|
||||
* interface (or at least a nasty wart).
|
||||
*/
|
||||
static int
|
||||
firstnextmap(int *status)
|
||||
{
|
||||
switch (*status) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
*status = 0;
|
||||
return 1;
|
||||
case 2:
|
||||
*status = 1;
|
||||
return 1;
|
||||
case -1:
|
||||
*status = -2;
|
||||
return 0;
|
||||
case -2:
|
||||
*status = -3;
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan through the database of printers using cgetfirst/cgetnext.
|
||||
* Return false of error or end-of-database; else true.
|
||||
*/
|
||||
int
|
||||
firstprinter(struct printer *pp, int *error)
|
||||
{
|
||||
int status;
|
||||
char *bp;
|
||||
|
||||
init_printer(pp);
|
||||
status = cgetfirst(&bp, printcapdb);
|
||||
if (firstnextmap(&status) == 0) {
|
||||
if (error)
|
||||
*error = status;
|
||||
return 0;
|
||||
}
|
||||
if (error)
|
||||
*error = status;
|
||||
status = getprintcap_int(bp, pp);
|
||||
free(bp);
|
||||
if (error && status)
|
||||
*error = status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
nextprinter(struct printer *pp, int *error)
|
||||
{
|
||||
int status;
|
||||
char *bp;
|
||||
|
||||
free_printer(pp);
|
||||
status = cgetnext(&bp, printcapdb);
|
||||
if (firstnextmap(&status) == 0) {
|
||||
if (error)
|
||||
*error = status;
|
||||
return 0;
|
||||
}
|
||||
if (error)
|
||||
*error = status;
|
||||
status = getprintcap_int(bp, pp);
|
||||
free(bp);
|
||||
if (error && status)
|
||||
*error = status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
lastprinter(void)
|
||||
{
|
||||
cgetclose();
|
||||
}
|
||||
|
||||
/*
|
||||
* This must match the order of declaration of enum filter in lp.h.
|
||||
*/
|
||||
static const char *filters[] = {
|
||||
"cf", "df", "gf", "if", "nf", "of", "rf", "tf", "vf"
|
||||
};
|
||||
|
||||
static const char *longfilters[] = {
|
||||
"filt.cifplot", "filt.dvi", "filt.plot", "filt.input", "filt.ditroff",
|
||||
"filt.output", "filt.fortran", "filt.troff", "filt.raster"
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal routine for both getprintcap() and nextprinter().
|
||||
* Actually parse the printcap entry using cget* functions.
|
||||
* Also attempt to figure out the canonical name of the printer
|
||||
* and store a malloced copy of it in pp->printer.
|
||||
*/
|
||||
static int
|
||||
getprintcap_int(bp, pp)
|
||||
char *bp;
|
||||
struct printer *pp;
|
||||
{
|
||||
enum lpd_filters filt;
|
||||
|
||||
if ((pp->printer = capdb_canonical_name(bp)) == 0)
|
||||
return PCAPERR_OSERR;
|
||||
|
||||
#define CHK(x) do {if ((x) == PCAPERR_OSERR) return PCAPERR_OSERR;}while(0)
|
||||
CHK(capdb_getaltstr(bp, "af", "acct.file", 0, &pp->acct_file));
|
||||
CHK(capdb_getaltnum(bp, "br", "tty.rate", 0, &pp->baud_rate));
|
||||
CHK(capdb_getaltnum(bp, "ct", "remote.timeout", DEFTIMEOUT,
|
||||
&pp->conn_timeout));
|
||||
CHK(capdb_getaltnum(bp, "du", "daemon.user", DEFUID,
|
||||
&pp->daemon_user));
|
||||
CHK(capdb_getaltstr(bp, "ff", "job.formfeed", DEFFF, &pp->form_feed));
|
||||
CHK(capdb_getaltstr(bp, "lf", "spool.log", _PATH_CONSOLE,
|
||||
&pp->log_file));
|
||||
CHK(capdb_getaltstr(bp, "lo", "spool.lock", DEFLOCK, &pp->lock_file));
|
||||
CHK(capdb_getaltstr(bp, "lp", "tty.device", _PATH_DEFDEVLP, &pp->lp));
|
||||
CHK(capdb_getaltnum(bp, "mc", "max.copies", DEFMAXCOPIES,
|
||||
&pp->max_copies));
|
||||
CHK(capdb_getaltstr(bp, "ms", "tty.mode", 0, &pp->mode_set));
|
||||
CHK(capdb_getaltnum(bp, "mx", "max.blocks", DEFMX, &pp->max_blocks));
|
||||
CHK(capdb_getaltnum(bp, "pc", "acct.price", 0, &pp->price100));
|
||||
CHK(capdb_getaltnum(bp, "pl", "page.length", DEFLENGTH,
|
||||
&pp->page_length));
|
||||
CHK(capdb_getaltnum(bp, "pw", "page.width", DEFWIDTH,
|
||||
&pp->page_width));
|
||||
CHK(capdb_getaltnum(bp, "px", "page.pwidth", 0, &pp->page_pwidth));
|
||||
CHK(capdb_getaltnum(bp, "py", "page.plength", 0, &pp->page_plength));
|
||||
CHK(capdb_getaltstr(bp, "rg", "daemon.restrictgrp", 0,
|
||||
&pp->restrict_grp));
|
||||
CHK(capdb_getaltstr(bp, "rm", "remote.host", 0, &pp->remote_host));
|
||||
CHK(capdb_getaltstr(bp, "rp", "remote.queue", DEFLP,
|
||||
&pp->remote_queue));
|
||||
CHK(capdb_getaltstr(bp, "sd", "spool.dir", _PATH_DEFSPOOL,
|
||||
&pp->spool_dir));
|
||||
CHK(capdb_getaltstr(bp, "st", "spool.status", DEFSTAT,
|
||||
&pp->status_file));
|
||||
CHK(capdb_getaltstr(bp, "tr", "job.trailer", 0, &pp->trailer));
|
||||
|
||||
pp->restricted = capdb_getaltlog(bp, "rs", "daemon.restricted");
|
||||
pp->short_banner = capdb_getaltlog(bp, "sb", "banner.short");
|
||||
pp->no_copies = capdb_getaltlog(bp, "sc", "job.no_copies");
|
||||
pp->no_formfeed = capdb_getaltlog(bp, "sf", "job.no_formfeed");
|
||||
pp->no_header = capdb_getaltlog(bp, "sh", "banner.disable");
|
||||
pp->header_last = capdb_getaltlog(bp, "hl", "banner.last");
|
||||
pp->rw = capdb_getaltlog(bp, "rw", "tty.rw");
|
||||
pp->tof = capdb_getaltlog(bp, "fo", "job.topofform");
|
||||
|
||||
/*
|
||||
* Filters:
|
||||
*/
|
||||
for (filt = 0; filt < LPF_COUNT; filt++) {
|
||||
CHK(capdb_getaltstr(bp, filters[filt], longfilters[filt], 0,
|
||||
&pp->filters[filt]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the error codes returned by cgetent() using the names we
|
||||
* made up for them from "lp.h".
|
||||
* This would have been much better done with Common Error, >sigh<.
|
||||
* Perhaps this can be fixed in the next incarnation of cget*.
|
||||
*/
|
||||
const char *
|
||||
pcaperr(int error)
|
||||
{
|
||||
switch(error) {
|
||||
case PCAPERR_TCOPEN:
|
||||
return "unresolved tc= expansion";
|
||||
case PCAPERR_SUCCESS:
|
||||
return "no error";
|
||||
case PCAPERR_NOTFOUND:
|
||||
return "printer not found";
|
||||
case PCAPERR_OSERR:
|
||||
return strerror(errno);
|
||||
case PCAPERR_TCLOOP:
|
||||
return "loop detected in tc= expansion";
|
||||
default:
|
||||
return "unknown printcap error";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a `struct printer' to contain values harmless to
|
||||
* the other routines in liblpr.
|
||||
*/
|
||||
void
|
||||
init_printer(struct printer *pp)
|
||||
{
|
||||
static struct printer zero;
|
||||
*pp = zero;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the dynamically-allocated strings in a `struct printer'.
|
||||
* Idempotent.
|
||||
*/
|
||||
void
|
||||
free_printer(struct printer *pp)
|
||||
{
|
||||
enum lpd_filters filt;
|
||||
#define cfree(x) do { if (x) free(x); } while(0)
|
||||
cfree(pp->printer);
|
||||
cfree(pp->acct_file);
|
||||
for (filt = 0; filt < LPF_COUNT; filt++)
|
||||
cfree(pp->filters[filt]);
|
||||
cfree(pp->form_feed);
|
||||
cfree(pp->log_file);
|
||||
cfree(pp->lock_file);
|
||||
cfree(pp->lp);
|
||||
cfree(pp->restrict_grp);
|
||||
cfree(pp->remote_host);
|
||||
cfree(pp->remote_queue);
|
||||
cfree(pp->spool_dir);
|
||||
cfree(pp->status_file);
|
||||
cfree(pp->trailer);
|
||||
cfree(pp->mode_set);
|
||||
|
||||
init_printer(pp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The following routines are part of what would be a sensible library
|
||||
* interface to capability databases. Maybe someday this will become
|
||||
* the default.
|
||||
*/
|
||||
|
||||
/*
|
||||
* It provides similar functionality to cgetstr(),
|
||||
* except that it provides for both a long and a short
|
||||
* capability name and allows for a default to be specified.
|
||||
*/
|
||||
static int
|
||||
capdb_getaltstr(char *bp, const char *shrt, const char *lng,
|
||||
const char *dflt, char **result)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = cgetstr(bp, (char *)/*XXX*/lng, result);
|
||||
if (status >= 0 || status == PCAPERR_OSERR)
|
||||
return status;
|
||||
status = cgetstr(bp, (char *)/*XXX*/shrt, result);
|
||||
if (status >= 0 || status == PCAPERR_OSERR)
|
||||
return status;
|
||||
if (dflt) {
|
||||
*result = strdup(dflt);
|
||||
if (*result == 0)
|
||||
return PCAPERR_OSERR;
|
||||
return strlen(*result);
|
||||
}
|
||||
return PCAPERR_NOTFOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* The same, only for integers.
|
||||
*/
|
||||
static int
|
||||
capdb_getaltnum(char *bp, const char *shrt, const char *lng, long dflt,
|
||||
long *result)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = cgetnum(bp, (char *)/*XXX*/lng, result);
|
||||
if (status >= 0)
|
||||
return status;
|
||||
status = cgetnum(bp, (char *)/*XXX*/shrt, result);
|
||||
if (status >= 0)
|
||||
return status;
|
||||
*result = dflt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise for logical values. There's no need for a default parameter
|
||||
* because the default is always false.
|
||||
*/
|
||||
static int
|
||||
capdb_getaltlog(char *bp, const char *shrt, const char *lng)
|
||||
{
|
||||
if (cgetcap(bp, (char *)/*XXX*/lng, ':'))
|
||||
return 1;
|
||||
if (cgetcap(bp, (char *)/*XXX*/shrt, ':'))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Also should be a part of a better cget* library.
|
||||
* Given a capdb entry, attempt to figure out what its canonical name
|
||||
* is, and return a malloced copy of it. The canonical name is
|
||||
* considered to be the first one listed.
|
||||
*/
|
||||
static char *
|
||||
capdb_canonical_name(const char *bp)
|
||||
{
|
||||
char *retval;
|
||||
const char *nameend;
|
||||
|
||||
nameend = strpbrk(bp, "|:");
|
||||
if (nameend == 0)
|
||||
nameend = bp + 1;
|
||||
if ((retval = malloc(nameend - bp + 1)) != 0) {
|
||||
retval[0] = '\0';
|
||||
strncat(retval, bp, nameend - bp);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ static const char copyright[] =
|
|||
static char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id: recvjob.c,v 1.10 1997/09/24 06:47:55 charnier Exp $";
|
||||
"$Id: recvjob.c,v 1.11 1997/10/06 03:58:48 imp Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
@ -80,54 +80,56 @@ static int noresponse __P((void));
|
|||
static void rcleanup __P((int));
|
||||
static int read_number __P((char *));
|
||||
static int readfile __P((char *, int));
|
||||
static int readjob __P((void));
|
||||
static int readjob __P((struct printer *pp));
|
||||
|
||||
|
||||
void
|
||||
recvjob()
|
||||
recvjob(printer)
|
||||
const char *printer;
|
||||
{
|
||||
struct stat stb;
|
||||
int status;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
/*
|
||||
* Perform lookup for printer name or abbreviation
|
||||
*/
|
||||
if ((status = cgetent(&bp, printcapdb, printer)) == -2)
|
||||
status = getprintcap(printer, pp);
|
||||
switch (status) {
|
||||
case PCAPERR_OSERR:
|
||||
frecverr("cannot open printer description file");
|
||||
else if (status == -1)
|
||||
break;
|
||||
case PCAPERR_NOTFOUND:
|
||||
frecverr("unknown printer %s", printer);
|
||||
else if (status == -3)
|
||||
fatal("potential reference loop detected in printcap file");
|
||||
break;
|
||||
case PCAPERR_TCLOOP:
|
||||
fatal(pp, "potential reference loop detected in printcap file");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cgetstr(bp, "lf", &LF) == -1)
|
||||
LF = _PATH_CONSOLE;
|
||||
if (cgetstr(bp, "sd", &SD) == -1)
|
||||
SD = _PATH_DEFSPOOL;
|
||||
if (cgetstr(bp, "lo", &LO) == -1)
|
||||
LO = DEFLOCK;
|
||||
|
||||
(void) close(2); /* set up log file */
|
||||
if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
|
||||
syslog(LOG_ERR, "%s: %m", LF);
|
||||
if (open(pp->log_file, O_WRONLY|O_APPEND, 0664) < 0) {
|
||||
syslog(LOG_ERR, "%s: %m", pp->log_file);
|
||||
(void) open(_PATH_DEVNULL, O_WRONLY);
|
||||
}
|
||||
|
||||
if (chdir(SD) < 0)
|
||||
frecverr("%s: %s: %m", printer, SD);
|
||||
if (stat(LO, &stb) == 0) {
|
||||
if (chdir(pp->spool_dir) < 0)
|
||||
frecverr("%s: %s: %m", pp->printer, pp->spool_dir);
|
||||
if (stat(pp->lock_file, &stb) == 0) {
|
||||
if (stb.st_mode & 010) {
|
||||
/* queue is disabled */
|
||||
putchar('\1'); /* return error code */
|
||||
exit(1);
|
||||
}
|
||||
} else if (stat(SD, &stb) < 0)
|
||||
frecverr("%s: %s: %m", printer, SD);
|
||||
} else if (stat(pp->spool_dir, &stb) < 0)
|
||||
frecverr("%s: %s: %m", pp->printer, pp->spool_dir);
|
||||
minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
|
||||
signal(SIGTERM, rcleanup);
|
||||
signal(SIGPIPE, rcleanup);
|
||||
|
||||
if (readjob())
|
||||
printjob();
|
||||
if (readjob(pp))
|
||||
printjob(pp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -135,7 +137,8 @@ recvjob()
|
|||
* Return the number of jobs successfully transfered.
|
||||
*/
|
||||
static int
|
||||
readjob()
|
||||
readjob(pp)
|
||||
struct printer *pp;
|
||||
{
|
||||
register int size, nfiles;
|
||||
register char *cp;
|
||||
|
|
@ -151,7 +154,7 @@ readjob()
|
|||
if ((size = read(1, cp, 1)) != 1) {
|
||||
if (size < 0)
|
||||
frecverr("%s: lost connection",
|
||||
printer);
|
||||
pp->printer);
|
||||
return(nfiles);
|
||||
}
|
||||
} while (*cp++ != '\n' && (cp - line + 1) < sizeof(line));
|
||||
|
|
|
|||
80
usr.sbin/lpr/common_source/request.c
Normal file
80
usr.sbin/lpr/common_source/request.c
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 1997 Massachusetts Institute of Technology
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that both the above copyright notice and this
|
||||
* permission notice appear in all copies, that both the above
|
||||
* copyright notice and this permission notice appear in all
|
||||
* supporting documentation, and that the name of M.I.T. not be used
|
||||
* in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. M.I.T. makes
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied
|
||||
* warranty.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
static const char copyright[] =
|
||||
"Copyright (C) 1997, Massachusetts Institute of Technology\r\n";
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/param.h> /* needed for lp.h but not used here */
|
||||
#include <dirent.h> /* ditto */
|
||||
#include <stdio.h> /* ditto */
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
|
||||
void
|
||||
init_request(struct request *rp)
|
||||
{
|
||||
static struct request zero;
|
||||
|
||||
*rp = zero;
|
||||
TAILQ_INIT(&rp->users);
|
||||
TAILQ_INIT(&rp->jobids);
|
||||
}
|
||||
|
||||
void
|
||||
free_request(struct request *rp)
|
||||
{
|
||||
struct req_user *ru;
|
||||
struct req_jobid *rj;
|
||||
|
||||
if (rp->logname)
|
||||
free(rp->logname);
|
||||
if (rp->authname)
|
||||
free(rp->authname);
|
||||
if (rp->prettyname)
|
||||
free(rp->prettyname);
|
||||
if (rp->authinfo)
|
||||
free(rp->authinfo);
|
||||
while ((ru = rp->users.tqh_first) != 0) {
|
||||
TAILQ_REMOVE(&rp->users, ru, ru_link);
|
||||
free(ru);
|
||||
}
|
||||
while ((rj = rp->jobids.tqh_first) != 0) {
|
||||
TAILQ_REMOVE(&rp->jobids, rj, rj_link);
|
||||
free(rj);
|
||||
}
|
||||
init_request(rp);
|
||||
}
|
||||
|
|
@ -36,19 +36,25 @@
|
|||
static char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id: rmjob.c,v 1.9 1997/09/24 06:47:31 charnier Exp $";
|
||||
"$Id: rmjob.c,v 1.10 1997/10/14 16:00:37 joerg Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define psignal foil_gcc_psignal
|
||||
#define sys_siglist foil_gcc_siglist
|
||||
#include <unistd.h>
|
||||
#undef psignal
|
||||
#undef sys_siglist
|
||||
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
#include "pathnames.h"
|
||||
|
|
@ -71,32 +77,22 @@ static void alarmhandler __P((int));
|
|||
static void do_unlink __P((char *));
|
||||
|
||||
void
|
||||
rmjob()
|
||||
rmjob(printer)
|
||||
const char *printer;
|
||||
{
|
||||
register int i, nitems;
|
||||
int assasinated = 0;
|
||||
struct dirent **files;
|
||||
char *cp;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
if ((i = cgetent(&bp, printcapdb, printer)) == -2)
|
||||
fatal("can't open printer description file");
|
||||
else if (i == -1)
|
||||
fatal("unknown printer");
|
||||
else if (i == -3)
|
||||
fatal("potential reference loop detected in printcap file");
|
||||
if (cgetstr(bp, "lp", &LP) < 0)
|
||||
LP = _PATH_DEFDEVLP;
|
||||
if (cgetstr(bp, "rp", &RP) < 0)
|
||||
RP = DEFLP;
|
||||
if (cgetstr(bp, "sd", &SD) < 0)
|
||||
SD = _PATH_DEFSPOOL;
|
||||
if (cgetstr(bp,"lo", &LO) < 0)
|
||||
LO = DEFLOCK;
|
||||
if (cgetnum(bp, "ct", &CT) < 0)
|
||||
CT = DEFTIMEOUT;
|
||||
cgetstr(bp, "rm", &RM);
|
||||
if ((cp = checkremote()))
|
||||
init_printer(pp);
|
||||
if ((i = getprintcap(printer, pp)) < 0)
|
||||
fatal(pp, "getprintcap: %s", pcaperr(i));
|
||||
if ((cp = checkremote(pp))) {
|
||||
printf("Warning: %s\n", cp);
|
||||
free(cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the format was `lprm -' and the user isn't the super-user,
|
||||
|
|
@ -112,16 +108,16 @@ rmjob()
|
|||
}
|
||||
if (!strcmp(person, "-all")) {
|
||||
if (from == host)
|
||||
fatal("The login name \"-all\" is reserved");
|
||||
fatal(pp, "The login name \"-all\" is reserved");
|
||||
all = 1; /* all those from 'from' */
|
||||
person = root;
|
||||
}
|
||||
|
||||
seteuid(euid);
|
||||
if (chdir(SD) < 0)
|
||||
fatal("cannot chdir to spool directory");
|
||||
if (chdir(pp->spool_dir) < 0)
|
||||
fatal(pp, "cannot chdir to spool directory");
|
||||
if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
|
||||
fatal("cannot access spool directory");
|
||||
fatal(pp, "cannot access spool directory");
|
||||
seteuid(uid);
|
||||
|
||||
if (nitems) {
|
||||
|
|
@ -130,25 +126,25 @@ rmjob()
|
|||
* kill it if it is reading our file) then remove stuff
|
||||
* (after which we have to restart the daemon).
|
||||
*/
|
||||
if (lockchk(LO) && chk(current)) {
|
||||
if (lockchk(pp, pp->lock_file) && chk(current)) {
|
||||
seteuid(euid);
|
||||
assasinated = kill(cur_daemon, SIGINT) == 0;
|
||||
seteuid(uid);
|
||||
if (!assasinated)
|
||||
fatal("cannot kill printer daemon");
|
||||
fatal(pp, "cannot kill printer daemon");
|
||||
}
|
||||
/*
|
||||
* process the files
|
||||
*/
|
||||
for (i = 0; i < nitems; i++)
|
||||
process(files[i]->d_name);
|
||||
process(pp, files[i]->d_name);
|
||||
}
|
||||
rmremote();
|
||||
rmremote(pp);
|
||||
/*
|
||||
* Restart the printer daemon if it was killed
|
||||
*/
|
||||
if (assasinated && !startdaemon(printer))
|
||||
fatal("cannot restart printer daemon\n");
|
||||
if (assasinated && !startdaemon(pp))
|
||||
fatal(pp, "cannot restart printer daemon\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +154,8 @@ rmjob()
|
|||
* Return boolean indicating existence of a lock file.
|
||||
*/
|
||||
int
|
||||
lockchk(s)
|
||||
lockchk(pp, s)
|
||||
struct printer *pp;
|
||||
char *s;
|
||||
{
|
||||
register FILE *fp;
|
||||
|
|
@ -167,7 +164,7 @@ lockchk(s)
|
|||
seteuid(euid);
|
||||
if ((fp = fopen(s, "r")) == NULL) {
|
||||
if (errno == EACCES)
|
||||
fatal("can't access lock file");
|
||||
fatal(pp, "%s: %s", s, strerror(errno));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -197,7 +194,8 @@ lockchk(s)
|
|||
* Process a control file.
|
||||
*/
|
||||
void
|
||||
process(file)
|
||||
process(pp, file)
|
||||
const struct printer *pp;
|
||||
char *file;
|
||||
{
|
||||
FILE *cfp;
|
||||
|
|
@ -206,7 +204,7 @@ process(file)
|
|||
return;
|
||||
seteuid(euid);
|
||||
if ((cfp = fopen(file, "r")) == NULL)
|
||||
fatal("cannot open %s", file);
|
||||
fatal(pp, "cannot open %s", file);
|
||||
seteuid(uid);
|
||||
while (getline(cfp)) {
|
||||
switch (line[0]) {
|
||||
|
|
@ -315,14 +313,15 @@ isowner(owner, file)
|
|||
* then try removing files on the remote machine.
|
||||
*/
|
||||
void
|
||||
rmremote()
|
||||
rmremote(pp)
|
||||
const struct printer *pp;
|
||||
{
|
||||
register char *cp;
|
||||
register int i, rem;
|
||||
int i, rem, niov, totlen;
|
||||
char buf[BUFSIZ];
|
||||
void (*savealrm)(int);
|
||||
struct iovec *iov;
|
||||
|
||||
if (!remote)
|
||||
if (!pp->remote)
|
||||
return; /* not sending to a remote machine */
|
||||
|
||||
/*
|
||||
|
|
@ -331,34 +330,55 @@ rmremote()
|
|||
*/
|
||||
fflush(stdout);
|
||||
|
||||
(void)snprintf(buf, sizeof(buf), "\5%s %s", RP, all ? "-all" : person);
|
||||
cp = buf;
|
||||
for (i = 0; i < users && cp-buf+1+strlen(user[i]) < sizeof(buf); i++) {
|
||||
cp += strlen(cp);
|
||||
*cp++ = ' ';
|
||||
strcpy(cp, user[i]);
|
||||
/*
|
||||
* Counting:
|
||||
* 4 == "\5" + remote_queue + " " + person
|
||||
* 2 * users == " " + user[i] for each user
|
||||
* requests == asprintf results for each request
|
||||
* 1 == "\n"
|
||||
* Although laborious, doing it this way makes it possible for
|
||||
* us to process requests of indeterminate length without
|
||||
* applying an arbitrary limit. Arbitrary Limits Are Bad (tm).
|
||||
*/
|
||||
niov = 4 + 2 * users + requests + 1;
|
||||
iov = malloc(niov * sizeof *iov);
|
||||
if (iov == 0)
|
||||
fatal(pp, "out of memory");
|
||||
iov[0].iov_base = "\5";
|
||||
iov[1].iov_base = pp->remote_queue;
|
||||
iov[2].iov_base = " ";
|
||||
iov[3].iov_base = all ? "-all" : person;
|
||||
for (i = 0; i < users; i++) {
|
||||
iov[4 + 2 * i].iov_base = " ";
|
||||
iov[4 + 2 * i + 1].iov_base = user[i];
|
||||
}
|
||||
for (i = 0; i < requests && cp-buf+10 < sizeof(buf) - 1; i++) {
|
||||
cp += strlen(cp);
|
||||
(void) sprintf(cp, " %d", requ[i]);
|
||||
for (i = 0; i < requests; i++) {
|
||||
asprintf(&iov[4 + 2 * users + i].iov_base, " %d", requ[i]);
|
||||
if (iov[4 + 2 * users + i].iov_base == 0)
|
||||
fatal(pp, "out of memory");
|
||||
}
|
||||
strcat(cp, "\n");
|
||||
iov[4 + 2 * users + requests].iov_base = "\n";
|
||||
for (totlen = i = 0; i < niov; i++)
|
||||
totlen += (iov[i].iov_len = strlen(iov[i].iov_base));
|
||||
|
||||
savealrm = signal(SIGALRM, alarmhandler);
|
||||
alarm(CT);
|
||||
rem = getport(RM, 0);
|
||||
alarm(pp->conn_timeout);
|
||||
rem = getport(pp, pp->remote_host, 0);
|
||||
(void)signal(SIGALRM, savealrm);
|
||||
if (rem < 0) {
|
||||
if (from != host)
|
||||
printf("%s: ", host);
|
||||
printf("connection to %s is down\n", RM);
|
||||
printf("connection to %s is down\n", pp->remote_host);
|
||||
} else {
|
||||
i = strlen(buf);
|
||||
if (write(rem, buf, i) != i)
|
||||
fatal("Lost connection");
|
||||
if (writev(rem, iov, niov) != totlen)
|
||||
fatal(pp, "Lost connection");
|
||||
while ((i = read(rem, buf, sizeof(buf))) > 0)
|
||||
(void) fwrite(buf, 1, i, stdout);
|
||||
(void) close(rem);
|
||||
}
|
||||
for (i = 0; i < requests; i++)
|
||||
free(iov[4 + 2 * users + i].iov_base);
|
||||
free(iov);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -373,6 +393,7 @@ iscf(d)
|
|||
|
||||
void
|
||||
alarmhandler(signo)
|
||||
int signo;
|
||||
{
|
||||
/* ignored */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,12 +36,13 @@
|
|||
static char sccsid[] = "@(#)startdaemon.c 8.2 (Berkeley) 4/17/94";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: startdaemon.c,v 1.6 1997/09/24 06:47:32 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <dirent.h>
|
||||
|
|
@ -59,20 +60,20 @@ extern uid_t uid, euid;
|
|||
*/
|
||||
|
||||
int
|
||||
startdaemon(printer)
|
||||
char *printer;
|
||||
startdaemon(pp)
|
||||
const struct printer *pp;
|
||||
{
|
||||
struct sockaddr_un un;
|
||||
register int s, n;
|
||||
char buf[BUFSIZ];
|
||||
char c;
|
||||
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
s = socket(PF_LOCAL, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
warn("socket");
|
||||
return(0);
|
||||
}
|
||||
memset(&un, 0, sizeof(un));
|
||||
un.sun_family = AF_UNIX;
|
||||
un.sun_family = AF_LOCAL;
|
||||
strcpy(un.sun_path, _PATH_SOCKETNAME);
|
||||
#ifndef SUN_LEN
|
||||
#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
|
||||
|
|
@ -85,25 +86,25 @@ startdaemon(printer)
|
|||
return(0);
|
||||
}
|
||||
seteuid(uid);
|
||||
if (snprintf(buf, sizeof(buf), "\1%s\n", printer) > sizeof(buf) - 1) {
|
||||
close(s);
|
||||
return (0);
|
||||
}
|
||||
n = strlen(buf);
|
||||
if (write(s, buf, n) != n) {
|
||||
|
||||
/*
|
||||
* Avoid overruns without putting artificial limitations on
|
||||
* the length.
|
||||
*/
|
||||
if (writel(s, "\1", pp->printer, "\n", (char *)0) <= 0) {
|
||||
warn("write");
|
||||
(void) close(s);
|
||||
return(0);
|
||||
}
|
||||
if (read(s, buf, 1) == 1) {
|
||||
if (buf[0] == '\0') { /* everything is OK */
|
||||
if (read(s, &c, 1) == 1) {
|
||||
if (c == '\0') { /* everything is OK */
|
||||
(void) close(s);
|
||||
return(1);
|
||||
}
|
||||
putchar(buf[0]);
|
||||
putchar(c);
|
||||
}
|
||||
while ((n = read(s, buf, sizeof(buf))) > 0)
|
||||
fwrite(buf, 1, n, stdout);
|
||||
while ((n = read(s, &c, 1)) > 0)
|
||||
putchar(c);
|
||||
(void) close(s);
|
||||
return(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# @(#)Makefile 5.6 (Berkeley) 6/23/90
|
||||
# $Id$
|
||||
|
||||
BINDIR = /usr/bin
|
||||
MAN1 = lp.1
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $Id$
|
||||
|
||||
PROG= lpc
|
||||
CFLAGS+=-I${.CURDIR}/../common_source
|
||||
CFLAGS+=-I${.CURDIR}/../common_source ${CWARNFLAGS}
|
||||
MAN8= lpc.8
|
||||
SRCS= lpc.c cmds.c cmdtab.c startdaemon.c common.c
|
||||
SRCS= lpc.c cmds.c cmdtab.c
|
||||
BINGRP= daemon
|
||||
BINMODE=2555
|
||||
.PATH: ${.CURDIR}/../common_source
|
||||
LDADD= -L${.OBJDIR}/../common_source -llpr
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -32,7 +32,11 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
|
@ -58,20 +62,20 @@ char topqhelp[] = "put job at top of printer queue";
|
|||
char uphelp[] = "enable everything and restart spooling daemon";
|
||||
|
||||
struct cmd cmdtab[] = {
|
||||
{ "abort", aborthelp, doabort, 1 },
|
||||
{ "clean", cleanhelp, clean, 1 },
|
||||
{ "enable", enablehelp, enable, 1 },
|
||||
{ "abort", aborthelp, 0, 1, doabort },
|
||||
{ "clean", cleanhelp, 0, 1, clean },
|
||||
{ "enable", enablehelp, 0, 1, enable },
|
||||
{ "exit", quithelp, quit, 0 },
|
||||
{ "disable", disablehelp, disable, 1 },
|
||||
{ "disable", disablehelp, 0, 1, disable },
|
||||
{ "down", downhelp, down, 1 },
|
||||
{ "help", helphelp, help, 0 },
|
||||
{ "quit", quithelp, quit, 0 },
|
||||
{ "restart", restarthelp, restart, 0 },
|
||||
{ "start", starthelp, startcmd, 1 },
|
||||
{ "status", statushelp, status, 0 },
|
||||
{ "stop", stophelp, stop, 1 },
|
||||
{ "restart", restarthelp, 0, 0, restart },
|
||||
{ "start", starthelp, 0, 1, startcmd },
|
||||
{ "status", statushelp, 0, 0, status },
|
||||
{ "stop", stophelp, 0, 1, stop },
|
||||
{ "topq", topqhelp, topq, 1 },
|
||||
{ "up", uphelp, up, 1 },
|
||||
{ "up", uphelp, 0, 1, up },
|
||||
{ "?", helphelp, help, 0 },
|
||||
{ 0 },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,19 +39,20 @@
|
|||
|
||||
|
||||
__BEGIN_DECLS
|
||||
void clean __P((int, char **));
|
||||
void disable __P((int, char **));
|
||||
void doabort __P((int, char **));
|
||||
void clean __P((struct printer *));
|
||||
void disable __P((struct printer *));
|
||||
void doabort __P((struct printer *));
|
||||
void down __P((int, char **));
|
||||
void enable __P((int, char **));
|
||||
void enable __P((struct printer *));
|
||||
void generic __P((void (*) __P((struct printer *)), int, char **));
|
||||
void help __P((int, char **));
|
||||
void quit __P((int, char **));
|
||||
void restart __P((int, char **));
|
||||
void startcmd __P((int, char **));
|
||||
void status __P((int, char **));
|
||||
void stop __P((int, char **));
|
||||
void restart __P((struct printer *));
|
||||
void startcmd __P((struct printer *));
|
||||
void status __P((struct printer *));
|
||||
void stop __P((struct printer *));
|
||||
void topq __P((int, char **));
|
||||
void up __P((int, char **));
|
||||
void up __P((struct printer *));
|
||||
__END_DECLS
|
||||
|
||||
extern int NCMDS;
|
||||
|
|
|
|||
|
|
@ -43,13 +43,14 @@ static const char copyright[] =
|
|||
static char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: lpc.c,v 1.5 1997/09/24 06:47:46 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <grp.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -58,7 +59,7 @@ static const char rcsid[] =
|
|||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "lp.h"
|
||||
#include "lpc.h"
|
||||
#include "extern.h"
|
||||
|
|
@ -116,7 +117,10 @@ main(argc, argv)
|
|||
printf("?Privileged command\n");
|
||||
exit(1);
|
||||
}
|
||||
(*c->c_handler)(argc, argv);
|
||||
if (c->c_generic != 0)
|
||||
generic(c->c_generic, argc, argv);
|
||||
else
|
||||
(*c->c_handler)(argc, argv);
|
||||
exit(0);
|
||||
}
|
||||
fromatty = isatty(fileno(stdin));
|
||||
|
|
@ -172,7 +176,10 @@ cmdscanner(top)
|
|||
printf("?Privileged command\n");
|
||||
continue;
|
||||
}
|
||||
(*c->c_handler)(margc, margv);
|
||||
if (c->c_generic != 0)
|
||||
generic(c->c_generic, margc, margv);
|
||||
else
|
||||
(*c->c_handler)(margc, margv);
|
||||
}
|
||||
longjmp(toplevel, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,13 @@
|
|||
/*
|
||||
* Line printer control program.
|
||||
*/
|
||||
struct printer;
|
||||
|
||||
struct cmd {
|
||||
char *c_name; /* command name */
|
||||
char *c_help; /* help message */
|
||||
/* routine to do the work */
|
||||
void (*c_handler) __P((int, char *[]));
|
||||
int c_priv; /* privileged command */
|
||||
void (*c_generic) __P((struct printer *)); /* generic command */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $Id$
|
||||
|
||||
PROG= lpd
|
||||
CFLAGS+=-I${.CURDIR}/../common_source
|
||||
CFLAGS+=-I${.CURDIR}/../common_source -Wall -Werror
|
||||
MAN8= lpd.8
|
||||
SRCS= lpd.c printjob.c recvjob.c displayq.c rmjob.c startdaemon.c \
|
||||
lpdchar.c common.c modes.c
|
||||
.PATH: ${.CURDIR}/../common_source
|
||||
SRCS= lpd.c printjob.c recvjob.c lpdchar.c modes.c
|
||||
LDADD= -L${.OBJDIR}/../common_source -llpr
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
* From: @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
|
@ -38,5 +39,10 @@
|
|||
extern char scnkey[][HEIGHT]; /* in lpdchar.c */
|
||||
extern char fromb[];
|
||||
|
||||
void printjob __P((void));
|
||||
void recvjob __P((void));
|
||||
struct printer;
|
||||
|
||||
__BEGIN_DECLS
|
||||
void printjob __P((struct printer *pp));
|
||||
void startprinting __P((const char *printer));
|
||||
void recvjob __P((const char *printer));
|
||||
__END_DECLS
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static const char copyright[] =
|
|||
static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: lpd.c,v 1.8 1997/09/24 06:47:54 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
@ -111,8 +111,11 @@ static void mcleanup __P((int));
|
|||
static void doit __P((void));
|
||||
static void startup __P((void));
|
||||
static void chkhost __P((struct sockaddr_in *));
|
||||
static int ckqueue __P((char *));
|
||||
static int ckqueue __P((struct printer *));
|
||||
static void usage __P((void));
|
||||
/* From rcmd.c: */
|
||||
int __ivaliduser __P((FILE *, u_long, const char *,
|
||||
const char *));
|
||||
|
||||
uid_t uid, euid;
|
||||
|
||||
|
|
@ -125,7 +128,8 @@ main(argc, argv)
|
|||
fd_set defreadfds;
|
||||
struct sockaddr_un un, fromunix;
|
||||
struct sockaddr_in sin, frominet;
|
||||
int omask, lfd;
|
||||
int lfd;
|
||||
sigset_t omask, nmask;
|
||||
struct servent *sp, serv;
|
||||
|
||||
euid = geteuid(); /* these shouldn't be different */
|
||||
|
|
@ -173,6 +177,31 @@ main(argc, argv)
|
|||
if (argc != 0)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* We run chkprintcap right away to catch any errors and blat them
|
||||
* to stderr while we still have it open, rather than sending them
|
||||
* to syslog and leaving the user wondering why lpd started and
|
||||
* then stopped. There should probably be a command-line flag to
|
||||
* ignore errors from chkprintcap.
|
||||
*/
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
err(EX_OSERR, "cannot fork");
|
||||
} else if (pid == 0) { /* child */
|
||||
execl(_PATH_CHKPRINTCAP, _PATH_CHKPRINTCAP, (char *)0);
|
||||
err(EX_OSERR, "cannot execute %s", _PATH_CHKPRINTCAP);
|
||||
}
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
err(EX_OSERR, "cannot wait");
|
||||
}
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
|
||||
errx(EX_OSFILE, "%d errors in printcap file, exiting",
|
||||
WEXITSTATUS(status));
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
/*
|
||||
* Set up standard environment by detaching from the parent.
|
||||
|
|
@ -183,17 +212,22 @@ main(argc, argv)
|
|||
openlog("lpd", LOG_PID, LOG_LPR);
|
||||
syslog(LOG_INFO, "restarted");
|
||||
(void) umask(0);
|
||||
lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644);
|
||||
/*
|
||||
* NB: This depends on O_NONBLOCK semantics doing the right thing;
|
||||
* i.e., applying only to the O_EXLOCK and not to the rest of the
|
||||
* open/creation. As of 1997-12-02, this is the case for commonly-
|
||||
* used filesystems. There are other places in this code which
|
||||
* make the same assumption.
|
||||
*/
|
||||
lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK,
|
||||
LOCK_FILE_MODE);
|
||||
if (lfd < 0) {
|
||||
syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
|
||||
exit(1);
|
||||
}
|
||||
if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
|
||||
if (errno == EWOULDBLOCK) /* active deamon present */
|
||||
exit(0);
|
||||
syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
|
||||
exit(1);
|
||||
}
|
||||
fcntl(lfd, F_SETFL, 0); /* turn off non-blocking mode */
|
||||
ftruncate(lfd, 0);
|
||||
/*
|
||||
* write process id for others to know
|
||||
|
|
@ -215,8 +249,14 @@ main(argc, argv)
|
|||
syslog(LOG_ERR, "socket: %m");
|
||||
exit(1);
|
||||
}
|
||||
#define mask(s) (1 << ((s) - 1))
|
||||
omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
|
||||
|
||||
sigemptyset(&nmask);
|
||||
sigaddset(&nmask, SIGHUP);
|
||||
sigaddset(&nmask, SIGINT);
|
||||
sigaddset(&nmask, SIGQUIT);
|
||||
sigaddset(&nmask, SIGTERM);
|
||||
sigprocmask(SIG_BLOCK, &nmask, &omask);
|
||||
|
||||
(void) umask(07);
|
||||
signal(SIGHUP, mcleanup);
|
||||
signal(SIGINT, mcleanup);
|
||||
|
|
@ -233,7 +273,7 @@ main(argc, argv)
|
|||
exit(1);
|
||||
}
|
||||
(void) umask(0);
|
||||
sigsetmask(omask);
|
||||
sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
|
||||
FD_ZERO(&defreadfds);
|
||||
FD_SET(funix, &defreadfds);
|
||||
listen(funix, 5);
|
||||
|
|
@ -259,6 +299,9 @@ main(argc, argv)
|
|||
*/
|
||||
memset(&frominet, 0, sizeof(frominet));
|
||||
memset(&fromunix, 0, sizeof(fromunix));
|
||||
/*
|
||||
* XXX - should be redone for multi-protocol
|
||||
*/
|
||||
for (;;) {
|
||||
int domain, nfds, s;
|
||||
fd_set readfds;
|
||||
|
|
@ -353,17 +396,21 @@ char *cmdnames[] = {
|
|||
static void
|
||||
doit()
|
||||
{
|
||||
register char *cp;
|
||||
register int n;
|
||||
char *cp, *printer;
|
||||
int n;
|
||||
int status;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
init_printer(&myprinter);
|
||||
|
||||
for (;;) {
|
||||
cp = cbuf;
|
||||
do {
|
||||
if (cp >= &cbuf[sizeof(cbuf) - 1])
|
||||
fatal("Command line too long");
|
||||
fatal(0, "Command line too long");
|
||||
if ((n = read(1, cp, 1)) != 1) {
|
||||
if (n < 0)
|
||||
fatal("Lost connection");
|
||||
fatal(0, "Lost connection");
|
||||
return;
|
||||
}
|
||||
} while (*cp++ != '\n');
|
||||
|
|
@ -372,26 +419,25 @@ doit()
|
|||
if (lflag) {
|
||||
if (*cp >= '\1' && *cp <= '\5')
|
||||
syslog(LOG_INFO, "%s requests %s %s",
|
||||
from, cmdnames[*cp], cp+1);
|
||||
from, cmdnames[(u_char)*cp], cp+1);
|
||||
else
|
||||
syslog(LOG_INFO, "bad request (%d) from %s",
|
||||
*cp, from);
|
||||
}
|
||||
switch (*cp++) {
|
||||
case '\1': /* check the queue and print any jobs there */
|
||||
printer = cp;
|
||||
printjob();
|
||||
case CMD_CHECK_QUE: /* check the queue, print any jobs there */
|
||||
startprinting(cp);
|
||||
break;
|
||||
case '\2': /* receive files to be queued */
|
||||
case CMD_TAKE_THIS: /* receive files to be queued */
|
||||
if (!from_remote) {
|
||||
syslog(LOG_INFO, "illegal request (%d)", *cp);
|
||||
exit(1);
|
||||
}
|
||||
printer = cp;
|
||||
recvjob();
|
||||
recvjob(cp);
|
||||
break;
|
||||
case '\3': /* display the queue (short form) */
|
||||
case '\4': /* display the queue (long form) */
|
||||
case CMD_SHOWQ_SHORT: /* display the queue (short form) */
|
||||
case CMD_SHOWQ_LONG: /* display the queue (long form) */
|
||||
/* XXX - this all needs to be redone. */
|
||||
printer = cp;
|
||||
while (*cp) {
|
||||
if (*cp != ' ') {
|
||||
|
|
@ -405,17 +451,20 @@ doit()
|
|||
break;
|
||||
if (isdigit(*cp)) {
|
||||
if (requests >= MAXREQUESTS)
|
||||
fatal("Too many requests");
|
||||
fatal(0, "Too many requests");
|
||||
requ[requests++] = atoi(cp);
|
||||
} else {
|
||||
if (users >= MAXUSERS)
|
||||
fatal("Too many users");
|
||||
fatal(0, "Too many users");
|
||||
user[users++] = cp;
|
||||
}
|
||||
}
|
||||
displayq(cbuf[0] - '\3');
|
||||
status = getprintcap(printer, pp);
|
||||
if (status < 0)
|
||||
fatal(pp, pcaperr(status));
|
||||
displayq(pp, cbuf[0] == CMD_SHOWQ_LONG);
|
||||
exit(0);
|
||||
case '\5': /* remove a job from the queue */
|
||||
case CMD_RMJOB: /* remove a job from the queue */
|
||||
if (!from_remote) {
|
||||
syslog(LOG_INFO, "illegal request (%d)", *cp);
|
||||
exit(1);
|
||||
|
|
@ -439,18 +488,18 @@ doit()
|
|||
break;
|
||||
if (isdigit(*cp)) {
|
||||
if (requests >= MAXREQUESTS)
|
||||
fatal("Too many requests");
|
||||
fatal(0, "Too many requests");
|
||||
requ[requests++] = atoi(cp);
|
||||
} else {
|
||||
if (users >= MAXUSERS)
|
||||
fatal("Too many users");
|
||||
fatal(0, "Too many users");
|
||||
user[users++] = cp;
|
||||
}
|
||||
}
|
||||
rmjob();
|
||||
rmjob(printer);
|
||||
break;
|
||||
}
|
||||
fatal("Illegal service request");
|
||||
fatal(0, "Illegal service request");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -461,66 +510,36 @@ doit()
|
|||
static void
|
||||
startup()
|
||||
{
|
||||
char *buf;
|
||||
register char *cp;
|
||||
int pid;
|
||||
char *spooldirs[16]; /* Which spooldirs are active? */
|
||||
int i; /* Printer index presently processed */
|
||||
int j; /* Printer index of potential conflict */
|
||||
char *spooldir; /* Spooldir of present printer */
|
||||
int canfreespool; /* Is the spooldir malloc()ed? */
|
||||
int pid, status, more;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
/*
|
||||
* Restart the daemons and test for spooldir conflict.
|
||||
*/
|
||||
i = 0;
|
||||
while (cgetnext(&buf, printcapdb) > 0) {
|
||||
|
||||
/* Check for duplicate spooldirs */
|
||||
canfreespool = 1;
|
||||
if (cgetstr(buf, "sd", &spooldir) <= 0) {
|
||||
spooldir = _PATH_DEFSPOOL;
|
||||
canfreespool = 0;
|
||||
more = firstprinter(pp, &status);
|
||||
if (status)
|
||||
goto errloop;
|
||||
while (more) {
|
||||
if (ckqueue(pp) <= 0) {
|
||||
goto next;
|
||||
}
|
||||
if (i < sizeof(spooldirs)/sizeof(spooldirs[0]))
|
||||
spooldirs[i] = spooldir;
|
||||
for (j = 0;
|
||||
j < MIN(i,sizeof(spooldirs)/sizeof(spooldirs[0]));
|
||||
j++) {
|
||||
if (strcmp(spooldir, spooldirs[j]) == 0) {
|
||||
syslog(LOG_ERR,
|
||||
"startup: duplicate spool directories: %s",
|
||||
spooldir);
|
||||
mcleanup(0);
|
||||
}
|
||||
}
|
||||
if (canfreespool && i >= sizeof(spooldirs)/sizeof(spooldirs[0]))
|
||||
free(spooldir);
|
||||
i++;
|
||||
/* Spooldir test done */
|
||||
|
||||
if (ckqueue(buf) <= 0) {
|
||||
free(buf);
|
||||
continue; /* no work to do for this printer */
|
||||
}
|
||||
for (cp = buf; *cp; cp++)
|
||||
if (*cp == '|' || *cp == ':') {
|
||||
*cp = '\0';
|
||||
break;
|
||||
}
|
||||
if (lflag)
|
||||
syslog(LOG_INFO, "work for %s", buf);
|
||||
syslog(LOG_INFO, "work for %s", pp->printer);
|
||||
if ((pid = fork()) < 0) {
|
||||
syslog(LOG_WARNING, "startup: cannot fork");
|
||||
mcleanup(0);
|
||||
}
|
||||
if (!pid) {
|
||||
printer = buf;
|
||||
cgetclose();
|
||||
printjob();
|
||||
if (pid == 0) {
|
||||
lastprinter();
|
||||
printjob(pp);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
else free(buf);
|
||||
do {
|
||||
next:
|
||||
more = nextprinter(pp, &status);
|
||||
errloop:
|
||||
if (status)
|
||||
syslog(LOG_WARNING,
|
||||
"printcap for %s has errors, skipping",
|
||||
pp->printer ? pp->printer : "<???>");
|
||||
} while (more && status);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -528,15 +547,14 @@ startup()
|
|||
* Make sure there's some work to do before forking off a child
|
||||
*/
|
||||
static int
|
||||
ckqueue(cap)
|
||||
char *cap;
|
||||
ckqueue(pp)
|
||||
struct printer *pp;
|
||||
{
|
||||
register struct dirent *d;
|
||||
DIR *dirp;
|
||||
char *spooldir;
|
||||
|
||||
if (cgetstr(cap, "sd", &spooldir) == -1)
|
||||
spooldir = _PATH_DEFSPOOL;
|
||||
spooldir = pp->spool_dir;
|
||||
if ((dirp = opendir(spooldir)) == NULL)
|
||||
return (-1);
|
||||
while ((d = readdir(dirp)) != NULL) {
|
||||
|
|
@ -567,7 +585,7 @@ chkhost(f)
|
|||
hp = gethostbyaddr((char *)&f->sin_addr,
|
||||
sizeof(struct in_addr), f->sin_family);
|
||||
if (hp == NULL)
|
||||
fatal("Host name for your address (%s) unknown",
|
||||
fatal(0, "Host name for your address (%s) unknown",
|
||||
inet_ntoa(f->sin_addr));
|
||||
|
||||
(void) strncpy(fromb, hp->h_name, sizeof(fromb) - 1);
|
||||
|
|
@ -577,7 +595,7 @@ chkhost(f)
|
|||
/* Check for spoof, ala rlogind */
|
||||
hp = gethostbyname(fromb);
|
||||
if (!hp)
|
||||
fatal("hostname for your address (%s) unknown",
|
||||
fatal(0, "hostname for your address (%s) unknown",
|
||||
inet_ntoa(f->sin_addr));
|
||||
for (; good == 0 && hp->h_addr_list[0] != NULL; hp->h_addr_list++) {
|
||||
if (!bcmp(hp->h_addr_list[0], (caddr_t)&f->sin_addr,
|
||||
|
|
@ -585,7 +603,7 @@ chkhost(f)
|
|||
good = 1;
|
||||
}
|
||||
if (good == 0)
|
||||
fatal("address for your hostname (%s) not matched",
|
||||
fatal(0, "address for your hostname (%s) not matched",
|
||||
inet_ntoa(f->sin_addr));
|
||||
|
||||
hostf = fopen(_PATH_HOSTSEQUIV, "r");
|
||||
|
|
@ -603,7 +621,7 @@ again:
|
|||
hostf = fopen(_PATH_HOSTSLPD, "r");
|
||||
goto again;
|
||||
}
|
||||
fatal("Your host does not have line printer access");
|
||||
fatal(0, "Your host does not have line printer access");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,11 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)lpdchar.c 8.1 (Berkeley) 6/6/93";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -29,12 +29,14 @@
|
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)modes.c 8.3 (Berkeley) 4/2/94";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stddef.h>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -43,7 +43,7 @@ static const char copyright[] =
|
|||
static char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id: recvjob.c,v 1.10 1997/09/24 06:47:55 charnier Exp $";
|
||||
"$Id: recvjob.c,v 1.11 1997/10/06 03:58:48 imp Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
@ -80,54 +80,56 @@ static int noresponse __P((void));
|
|||
static void rcleanup __P((int));
|
||||
static int read_number __P((char *));
|
||||
static int readfile __P((char *, int));
|
||||
static int readjob __P((void));
|
||||
static int readjob __P((struct printer *pp));
|
||||
|
||||
|
||||
void
|
||||
recvjob()
|
||||
recvjob(printer)
|
||||
const char *printer;
|
||||
{
|
||||
struct stat stb;
|
||||
int status;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
/*
|
||||
* Perform lookup for printer name or abbreviation
|
||||
*/
|
||||
if ((status = cgetent(&bp, printcapdb, printer)) == -2)
|
||||
status = getprintcap(printer, pp);
|
||||
switch (status) {
|
||||
case PCAPERR_OSERR:
|
||||
frecverr("cannot open printer description file");
|
||||
else if (status == -1)
|
||||
break;
|
||||
case PCAPERR_NOTFOUND:
|
||||
frecverr("unknown printer %s", printer);
|
||||
else if (status == -3)
|
||||
fatal("potential reference loop detected in printcap file");
|
||||
break;
|
||||
case PCAPERR_TCLOOP:
|
||||
fatal(pp, "potential reference loop detected in printcap file");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cgetstr(bp, "lf", &LF) == -1)
|
||||
LF = _PATH_CONSOLE;
|
||||
if (cgetstr(bp, "sd", &SD) == -1)
|
||||
SD = _PATH_DEFSPOOL;
|
||||
if (cgetstr(bp, "lo", &LO) == -1)
|
||||
LO = DEFLOCK;
|
||||
|
||||
(void) close(2); /* set up log file */
|
||||
if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
|
||||
syslog(LOG_ERR, "%s: %m", LF);
|
||||
if (open(pp->log_file, O_WRONLY|O_APPEND, 0664) < 0) {
|
||||
syslog(LOG_ERR, "%s: %m", pp->log_file);
|
||||
(void) open(_PATH_DEVNULL, O_WRONLY);
|
||||
}
|
||||
|
||||
if (chdir(SD) < 0)
|
||||
frecverr("%s: %s: %m", printer, SD);
|
||||
if (stat(LO, &stb) == 0) {
|
||||
if (chdir(pp->spool_dir) < 0)
|
||||
frecverr("%s: %s: %m", pp->printer, pp->spool_dir);
|
||||
if (stat(pp->lock_file, &stb) == 0) {
|
||||
if (stb.st_mode & 010) {
|
||||
/* queue is disabled */
|
||||
putchar('\1'); /* return error code */
|
||||
exit(1);
|
||||
}
|
||||
} else if (stat(SD, &stb) < 0)
|
||||
frecverr("%s: %s: %m", printer, SD);
|
||||
} else if (stat(pp->spool_dir, &stb) < 0)
|
||||
frecverr("%s: %s: %m", pp->printer, pp->spool_dir);
|
||||
minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
|
||||
signal(SIGTERM, rcleanup);
|
||||
signal(SIGPIPE, rcleanup);
|
||||
|
||||
if (readjob())
|
||||
printjob();
|
||||
if (readjob(pp))
|
||||
printjob(pp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -135,7 +137,8 @@ recvjob()
|
|||
* Return the number of jobs successfully transfered.
|
||||
*/
|
||||
static int
|
||||
readjob()
|
||||
readjob(pp)
|
||||
struct printer *pp;
|
||||
{
|
||||
register int size, nfiles;
|
||||
register char *cp;
|
||||
|
|
@ -151,7 +154,7 @@ readjob()
|
|||
if ((size = read(1, cp, 1)) != 1) {
|
||||
if (size < 0)
|
||||
frecverr("%s: lost connection",
|
||||
printer);
|
||||
pp->printer);
|
||||
return(nfiles);
|
||||
}
|
||||
} while (*cp++ != '\n' && (cp - line + 1) < sizeof(line));
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $Id$
|
||||
|
||||
PROG= lpq
|
||||
CFLAGS+=-I${.CURDIR}/../common_source
|
||||
SRCS= lpq.c displayq.c common.c
|
||||
CFLAGS+=-I${.CURDIR}/../common_source ${CWARNFLAGS}
|
||||
SRCS= lpq.c
|
||||
BINOWN= root
|
||||
BINGRP= daemon
|
||||
BINMODE=6555
|
||||
BINDIR= /usr/bin
|
||||
MAN1= lpq.1
|
||||
.PATH: ${.CURDIR}/../common_source
|
||||
LDADD= -L${.OBJDIR}/../common_source -llpr
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
|
|
@ -33,13 +33,17 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)lpq.c 8.3 (Berkeley) 5/10/95";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
@ -54,12 +58,14 @@ static char sccsid[] = "@(#)lpq.c 8.3 (Berkeley) 5/10/95";
|
|||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <syslog.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lp.h"
|
||||
#include "lp.local.h"
|
||||
#include "pathnames.h"
|
||||
|
|
@ -71,19 +77,19 @@ int users; /* # of users in user array */
|
|||
|
||||
uid_t uid, euid;
|
||||
|
||||
static int ckqueue __P((char *));
|
||||
static int ckqueue __P((const struct printer *));
|
||||
static void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
register int argc;
|
||||
register char **argv;
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int ch, aflag, lflag;
|
||||
char *buf, *cp;
|
||||
int ch, aflag, lflag;
|
||||
char *printer;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
printer = NULL;
|
||||
euid = geteuid();
|
||||
uid = getuid();
|
||||
seteuid(uid);
|
||||
|
|
@ -115,47 +121,64 @@ main(argc, argv)
|
|||
for (argc -= optind, argv += optind; argc; --argc, ++argv)
|
||||
if (isdigit(argv[0][0])) {
|
||||
if (requests >= MAXREQUESTS)
|
||||
fatal("too many requests");
|
||||
fatal(0, "too many requests");
|
||||
requ[requests++] = atoi(*argv);
|
||||
}
|
||||
else {
|
||||
if (users >= MAXUSERS)
|
||||
fatal("too many users");
|
||||
fatal(0, "too many users");
|
||||
user[users++] = *argv;
|
||||
}
|
||||
|
||||
if (aflag) {
|
||||
while (cgetnext(&buf, printcapdb) > 0) {
|
||||
if (ckqueue(buf) <= 0) {
|
||||
free(buf);
|
||||
continue; /* no jobs */
|
||||
int more, status;
|
||||
|
||||
more = firstprinter(pp, &status);
|
||||
if (status)
|
||||
goto looperr;
|
||||
while (more) {
|
||||
if (ckqueue(pp) > 0) {
|
||||
printf("%s:\n", pp->printer);
|
||||
displayq(pp, lflag);
|
||||
printf("\n");
|
||||
}
|
||||
for (cp = buf; *cp; cp++)
|
||||
if (*cp == '|' || *cp == ':') {
|
||||
*cp = '\0';
|
||||
do {
|
||||
more = nextprinter(pp, &status);
|
||||
looperr:
|
||||
switch (status) {
|
||||
case PCAPERR_TCOPEN:
|
||||
printf("warning: %s: unresolved "
|
||||
"tc= reference(s) ",
|
||||
pp->printer);
|
||||
case PCAPERR_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
fatal(pp, pcaperr(status));
|
||||
}
|
||||
printer = buf;
|
||||
printf("%s:\n", printer);
|
||||
displayq(lflag);
|
||||
free(buf);
|
||||
printf("\n");
|
||||
} while (more && status);
|
||||
}
|
||||
} else
|
||||
displayq(lflag);
|
||||
} else {
|
||||
int status;
|
||||
|
||||
init_printer(pp);
|
||||
status = getprintcap(printer, pp);
|
||||
if (status < 0)
|
||||
fatal(pp, pcaperr(status));
|
||||
|
||||
displayq(pp, lflag);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int
|
||||
ckqueue(cap)
|
||||
char *cap;
|
||||
ckqueue(pp)
|
||||
const struct printer *pp;
|
||||
{
|
||||
register struct dirent *d;
|
||||
DIR *dirp;
|
||||
char *spooldir;
|
||||
|
||||
if (cgetstr(cap, "sd", &spooldir) == -1)
|
||||
spooldir = _PATH_DEFSPOOL;
|
||||
spooldir = pp->spool_dir;
|
||||
if ((dirp = opendir(spooldir)) == NULL)
|
||||
return (-1);
|
||||
while ((d = readdir(dirp)) != NULL) {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $Id$
|
||||
|
||||
PROG= lpr
|
||||
CFLAGS+=-I${.CURDIR}/../common_source
|
||||
SRCS= lpr.c startdaemon.c common.c
|
||||
CFLAGS+=-I${.CURDIR}/../common_source ${CWARNFLAGS}
|
||||
SRCS= lpr.c
|
||||
BINOWN= root
|
||||
BINGRP= daemon
|
||||
BINMODE=6555
|
||||
BINDIR= /usr/bin
|
||||
MAN1= lpr.1
|
||||
.PATH: ${.CURDIR}/../common_source
|
||||
LDADD= -L${.OBJDIR}/../common_source -llpr
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ static const char copyright[] =
|
|||
static char sccsid[] = "@(#)from: lpr.c 8.4 (Berkeley) 4/28/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: lpr.c,v 1.21 1997/09/24 06:48:07 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
@ -64,6 +64,7 @@ static const char rcsid[] =
|
|||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <a.out.h>
|
||||
#include <err.h>
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <pwd.h>
|
||||
|
|
@ -104,14 +105,14 @@ static struct stat statb;
|
|||
|
||||
static void card __P((int, char *));
|
||||
static int checkwriteperm __P((char*, char *));
|
||||
static void chkprinter __P((char *));
|
||||
static void chkprinter __P((char *printer, struct printer *pp));
|
||||
static void cleanup __P((int));
|
||||
static void copy __P((int, char []));
|
||||
static void fatal2 __P((const char *, ...));
|
||||
static void copy __P((const struct printer *, int, char []));
|
||||
static char *itoa __P((int));
|
||||
static char *linked __P((char *));
|
||||
static char *lmktemp __P((char *, int, int));
|
||||
static void mktemps __P((void));
|
||||
int main __P((int, char **));
|
||||
static char *lmktemp __P((const struct printer *pp, char *, int, int));
|
||||
static void mktemps __P((const struct printer *pp));
|
||||
static int nfile __P((char *));
|
||||
static int test __P((char *));
|
||||
static void usage __P((void));
|
||||
|
|
@ -125,11 +126,13 @@ main(argc, argv)
|
|||
{
|
||||
struct passwd *pw;
|
||||
struct group *gptr;
|
||||
register char *arg, *cp;
|
||||
char *arg, *cp, *printer;
|
||||
char buf[BUFSIZ];
|
||||
int c, i, f, errs;
|
||||
struct stat stb;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
printer = NULL;
|
||||
euid = geteuid();
|
||||
uid = getuid();
|
||||
seteuid(uid);
|
||||
|
|
@ -247,27 +250,32 @@ main(argc, argv)
|
|||
usage();
|
||||
if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
|
||||
printer = DEFLP;
|
||||
chkprinter(printer);
|
||||
if (SC && ncopies > 1)
|
||||
fatal2("multiple copies are not allowed");
|
||||
if (MC > 0 && ncopies > MC)
|
||||
fatal2("only %d copies are allowed", MC);
|
||||
chkprinter(printer, pp);
|
||||
if (pp->no_copies && ncopies > 1)
|
||||
errx(1, "multiple copies are not allowed");
|
||||
if (pp->max_copies > 0 && ncopies > pp->max_copies)
|
||||
errx(1, "only %d copies are allowed", pp->max_copies);
|
||||
/*
|
||||
* Get the identity of the person doing the lpr using the same
|
||||
* algorithm as lprm.
|
||||
* algorithm as lprm. Actually, not quite -- lprm will override
|
||||
* the login name with "root" if the user is running as root;
|
||||
* the daemon actually checks for the string "root" in its
|
||||
* permission checking. Sigh.
|
||||
*/
|
||||
userid = getuid();
|
||||
if (userid != DU || person == 0) {
|
||||
if ((pw = getpwuid(userid)) == NULL)
|
||||
fatal2("Who are you?");
|
||||
person = pw->pw_name;
|
||||
if ((person = getlogin()) == NULL) {
|
||||
userid = getuid();
|
||||
if (userid != pp->daemon_user || person == 0) {
|
||||
if ((pw = getpwuid(userid)) == NULL)
|
||||
errx(1, "Who are you?");
|
||||
person = pw->pw_name;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Check for restricted group access.
|
||||
*/
|
||||
if (RG != NULL && userid != DU) {
|
||||
if ((gptr = getgrnam(RG)) == NULL)
|
||||
fatal2("Restricted group specified incorrectly");
|
||||
if (pp->restrict_grp != NULL && userid != pp->daemon_user) {
|
||||
if ((gptr = getgrnam(pp->restrict_grp)) == NULL)
|
||||
errx(1, "Restricted group specified incorrectly");
|
||||
if (gptr->gr_gid != getgid()) {
|
||||
while (*gptr->gr_mem != NULL) {
|
||||
if ((strcmp(person, *gptr->gr_mem)) == 0)
|
||||
|
|
@ -275,22 +283,23 @@ main(argc, argv)
|
|||
gptr->gr_mem++;
|
||||
}
|
||||
if (*gptr->gr_mem == NULL)
|
||||
fatal2("Not a member of the restricted group");
|
||||
errx(1, "Not a member of the restricted group");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Check to make sure queuing is enabled if userid is not root.
|
||||
*/
|
||||
(void) snprintf(buf, sizeof(buf), "%s/%s", SD, LO);
|
||||
if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
|
||||
fatal2("Printer queue is disabled");
|
||||
lock_file_name(pp, buf, sizeof buf);
|
||||
if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS))
|
||||
errx(1, "Printer queue is disabled");
|
||||
/*
|
||||
* Initialize the control file.
|
||||
*/
|
||||
mktemps();
|
||||
mktemps(pp);
|
||||
tfd = nfile(tfname);
|
||||
seteuid(euid);
|
||||
(void) fchown(tfd, DU, -1); /* owned by daemon for protection */
|
||||
(void) fchown(tfd, pp->daemon_user, -1);
|
||||
/* owned by daemon for protection */
|
||||
seteuid(uid);
|
||||
card('H', host);
|
||||
card('P', person);
|
||||
|
|
@ -299,7 +308,8 @@ main(argc, argv)
|
|||
if (argc == 0)
|
||||
jobname = "stdin";
|
||||
else
|
||||
jobname = (arg = strrchr(argv[0], '/')) ? arg+1 : argv[0];
|
||||
jobname = ((arg = strrchr(argv[0], '/'))
|
||||
? arg + 1 : argv[0]);
|
||||
}
|
||||
card('J', jobname);
|
||||
card('C', class);
|
||||
|
|
@ -320,11 +330,11 @@ main(argc, argv)
|
|||
* Read the files and spool them.
|
||||
*/
|
||||
if (argc == 0)
|
||||
copy(0, " ");
|
||||
copy(pp, 0, " ");
|
||||
else while (argc--) {
|
||||
if (argv[0][0] == '-' && argv[0][1] == '\0') {
|
||||
/* use stdin */
|
||||
copy(0, " ");
|
||||
copy(pp, 0, " ");
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -352,7 +362,7 @@ main(argc, argv)
|
|||
if ((i = open(arg, O_RDONLY)) < 0) {
|
||||
printf("%s: cannot open %s\n", name, arg);
|
||||
} else {
|
||||
copy(i, arg);
|
||||
copy(pp, i, arg);
|
||||
(void) close(i);
|
||||
if (f && unlink(arg) < 0)
|
||||
printf("%s: %s: not removed\n", name, arg);
|
||||
|
|
@ -387,7 +397,7 @@ main(argc, argv)
|
|||
seteuid(uid);
|
||||
if (qflag) /* just q things up */
|
||||
exit(0);
|
||||
if (!startdaemon(printer))
|
||||
if (!startdaemon(pp))
|
||||
printf("jobs queued, but cannot start daemon.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
|
@ -400,7 +410,8 @@ main(argc, argv)
|
|||
* Create the file n and copy from file descriptor f.
|
||||
*/
|
||||
static void
|
||||
copy(f, n)
|
||||
copy(pp, f, n)
|
||||
const struct printer *pp;
|
||||
int f;
|
||||
char n[];
|
||||
{
|
||||
|
|
@ -424,8 +435,9 @@ copy(f, n)
|
|||
if (nc >= BUFSIZ) {
|
||||
nc -= BUFSIZ;
|
||||
nr++;
|
||||
if (MX > 0 && nr > MX) {
|
||||
printf("%s: %s: copy file is too large\n", name, n);
|
||||
if (pp->max_blocks > 0 && nr > pp->max_blocks) {
|
||||
printf("%s: %s: copy file is too large\n",
|
||||
name, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -669,27 +681,23 @@ itoa(i)
|
|||
* Perform lookup for printer name or abbreviation --
|
||||
*/
|
||||
static void
|
||||
chkprinter(s)
|
||||
chkprinter(s, pp)
|
||||
char *s;
|
||||
struct printer *pp;
|
||||
{
|
||||
int status;
|
||||
|
||||
if ((status = cgetent(&bp, printcapdb, s)) == -2)
|
||||
fatal2("cannot open printer description file");
|
||||
else if (status == -1)
|
||||
fatal2("%s: unknown printer", s);
|
||||
if (cgetstr(bp, "sd", &SD) == -1)
|
||||
SD = _PATH_DEFSPOOL;
|
||||
if (cgetstr(bp, "lo", &LO) == -1)
|
||||
LO = DEFLOCK;
|
||||
cgetstr(bp, "rg", &RG);
|
||||
if (cgetnum(bp, "mx", &MX) < 0)
|
||||
MX = DEFMX;
|
||||
if (cgetnum(bp,"mc", &MC) < 0)
|
||||
MC = DEFMAXCOPIES;
|
||||
if (cgetnum(bp, "du", &DU) < 0)
|
||||
DU = DEFUID;
|
||||
SC = (cgetcap(bp, "sc", ':') != NULL);
|
||||
init_printer(pp);
|
||||
status = getprintcap(s, pp);
|
||||
switch(status) {
|
||||
case PCAPERR_OSERR:
|
||||
case PCAPERR_TCLOOP:
|
||||
errx(1, "%s: %s", s, pcaperr(status));
|
||||
case PCAPERR_NOTFOUND:
|
||||
errx(1, "%s: unknown printer", s);
|
||||
case PCAPERR_TCOPEN:
|
||||
warnx("%s: unresolved tc= reference(s)", s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -709,14 +717,14 @@ usage()
|
|||
* Make the temp files.
|
||||
*/
|
||||
static void
|
||||
mktemps()
|
||||
mktemps(pp)
|
||||
const struct printer *pp;
|
||||
{
|
||||
register int len, fd, n;
|
||||
register char *cp;
|
||||
char buf[BUFSIZ];
|
||||
char *lmktemp();
|
||||
|
||||
(void) snprintf(buf, sizeof(buf), "%s/.seq", SD);
|
||||
(void) snprintf(buf, sizeof(buf), "%s/.seq", pp->spool_dir);
|
||||
seteuid(euid);
|
||||
if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) {
|
||||
printf("%s: cannot create %s\n", name, buf);
|
||||
|
|
@ -735,11 +743,11 @@ mktemps()
|
|||
n = n * 10 + (*cp++ - '0');
|
||||
}
|
||||
}
|
||||
len = strlen(SD) + strlen(host) + 8;
|
||||
tfname = lmktemp("tf", n, len);
|
||||
cfname = lmktemp("cf", n, len);
|
||||
dfname = lmktemp("df", n, len);
|
||||
inchar = strlen(SD) + 3;
|
||||
len = strlen(pp->spool_dir) + strlen(host) + 8;
|
||||
tfname = lmktemp(pp, "tf", n, len);
|
||||
cfname = lmktemp(pp, "cf", n, len);
|
||||
dfname = lmktemp(pp, "df", n, len);
|
||||
inchar = strlen(pp->spool_dir) + 3;
|
||||
n = (n + 1) % 1000;
|
||||
(void) lseek(fd, (off_t)0, 0);
|
||||
snprintf(buf, sizeof(buf), "%03d\n", n);
|
||||
|
|
@ -751,42 +759,15 @@ mktemps()
|
|||
* Make a temp file name.
|
||||
*/
|
||||
static char *
|
||||
lmktemp(id, num, len)
|
||||
lmktemp(pp, id, num, len)
|
||||
const struct printer *pp;
|
||||
char *id;
|
||||
int num, len;
|
||||
{
|
||||
register char *s;
|
||||
|
||||
if ((s = malloc(len)) == NULL)
|
||||
fatal2("out of memory");
|
||||
(void) snprintf(s, len, "%s/%sA%03d%s", SD, id, num, host);
|
||||
errx(1, "out of memory");
|
||||
(void) snprintf(s, len, "%s/%sA%03d%s", pp->spool_dir, id, num, host);
|
||||
return(s);
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
#ifdef __STDC__
|
||||
fatal2(const char *msg, ...)
|
||||
#else
|
||||
fatal2(msg, va_alist)
|
||||
char *msg;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#ifdef __STDC__
|
||||
va_start(ap, msg);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
printf("%s: ", name);
|
||||
vprintf(msg, ap);
|
||||
putchar('\n');
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $Id$
|
||||
|
||||
PROG= lprm
|
||||
CFLAGS+=-I${.CURDIR}/../common_source
|
||||
SRCS= lprm.c rmjob.c startdaemon.c common.c
|
||||
CFLAGS+=-I${.CURDIR}/../common_source -Wall -Werror
|
||||
SRCS= lprm.c
|
||||
BINOWN= root
|
||||
BINGRP= daemon
|
||||
BINMODE=6555
|
||||
BINDIR= /usr/bin
|
||||
MAN1= lprm.1
|
||||
.PATH: ${.CURDIR}/../common_source
|
||||
LDADD= -L${.OBJDIR}/../common_source -llpr
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static const char copyright[] =
|
|||
static char sccsid[] = "@(#)lprm.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: lprm.c,v 1.3 1997/09/24 06:48:17 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
@ -89,21 +89,33 @@ main(argc, argv)
|
|||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register char *arg;
|
||||
char *arg, *printer;
|
||||
struct passwd *p;
|
||||
static char root[] = "root";
|
||||
|
||||
printer = NULL;
|
||||
uid = getuid();
|
||||
euid = geteuid();
|
||||
seteuid(uid); /* be safe */
|
||||
name = argv[0];
|
||||
gethostname(host, sizeof(host));
|
||||
openlog("lpd", 0, LOG_LPR);
|
||||
if ((p = getpwuid(getuid())) == NULL)
|
||||
fatal("Who are you?");
|
||||
if (strlen(p->pw_name) >= sizeof(luser))
|
||||
fatal("Your name is too long");
|
||||
strcpy(luser, p->pw_name);
|
||||
person = luser;
|
||||
|
||||
/*
|
||||
* Bogus code later checks for string equality between
|
||||
* `person' and "root", so if we are root, better make sure
|
||||
* that code will succeed.
|
||||
*/
|
||||
if (getuid() == 0) {
|
||||
person = root;
|
||||
} else if ((person = getlogin()) == NULL) {
|
||||
if ((p = getpwuid(getuid())) == NULL)
|
||||
fatal(0, "Who are you?");
|
||||
if (strlen(p->pw_name) >= sizeof(luser))
|
||||
fatal(0, "Your name is too long");
|
||||
strcpy(luser, p->pw_name);
|
||||
person = luser;
|
||||
}
|
||||
while (--argc) {
|
||||
if ((arg = *++argv)[0] == '-')
|
||||
switch (arg[1]) {
|
||||
|
|
@ -128,11 +140,11 @@ main(argc, argv)
|
|||
usage();
|
||||
if (isdigit(arg[0])) {
|
||||
if (requests >= MAXREQUESTS)
|
||||
fatal("Too many requests");
|
||||
fatal(0, "Too many requests");
|
||||
requ[requests++] = atoi(arg);
|
||||
} else {
|
||||
if (users >= MAXUSERS)
|
||||
fatal("Too many users");
|
||||
fatal(0, "Too many users");
|
||||
user[users++] = arg;
|
||||
}
|
||||
}
|
||||
|
|
@ -140,7 +152,7 @@ main(argc, argv)
|
|||
if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
|
||||
printer = DEFLP;
|
||||
|
||||
rmjob();
|
||||
rmjob(printer);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $Id$
|
||||
|
||||
PROG= pac
|
||||
CFLAGS+=-I${.CURDIR}/../common_source
|
||||
MAN8= pac.8
|
||||
SRCS= pac.c common.c
|
||||
SRCS= pac.c
|
||||
.PATH: ${.CURDIR}/../common_source
|
||||
LDADD= -L${.OBJDIR}/../common_source -llpr
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static const char copyright[] =
|
|||
static char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
"$Id: pac.c,v 1.7 1997/09/24 06:48:24 charnier Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
@ -110,9 +110,10 @@ main(argc, argv)
|
|||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register FILE *acct;
|
||||
register char *cp;
|
||||
FILE *acct;
|
||||
char *cp, *printer;
|
||||
|
||||
printer = NULL;
|
||||
euid = geteuid(); /* these aren't used in pac(1) */
|
||||
uid = getuid();
|
||||
while (--argc) {
|
||||
|
|
@ -433,21 +434,22 @@ chkprinter(s)
|
|||
register char *s;
|
||||
{
|
||||
int stat;
|
||||
struct printer myprinter, *pp = &myprinter;
|
||||
|
||||
if ((stat = cgetent(&bp, printcapdb, s)) == -2) {
|
||||
printf("pac: can't open printer description file\n");
|
||||
init_printer(&myprinter);
|
||||
stat = getprintcap(s, pp);
|
||||
switch(stat) {
|
||||
case PCAPERR_OSERR:
|
||||
printf("pac: getprintcap: %s\n", pcaperr(stat));
|
||||
exit(3);
|
||||
} else if (stat == -1)
|
||||
return(0);
|
||||
else if (stat == -3)
|
||||
fatal("potential reference loop detected in printcap file");
|
||||
|
||||
if (cgetstr(bp, "af", &acctfile) == -1) {
|
||||
printf("accounting not enabled for printer %s\n", printer);
|
||||
exit(2);
|
||||
case PCAPERR_NOTFOUND:
|
||||
return 0;
|
||||
case PCAPERR_TCLOOP:
|
||||
fatal(pp, "%s", pcaperr(stat));
|
||||
}
|
||||
if (!pflag && (cgetnum(bp, "pc", &price100) == 0))
|
||||
price = price100/10000.0;
|
||||
acctfile = pp->acct_file;
|
||||
if (!pflag && pp->price100)
|
||||
price = pp->price100/10000.0;
|
||||
sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5);
|
||||
if (sumfile == NULL)
|
||||
errx(1, "calloc failed");
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
* From: @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
|
@ -38,5 +39,10 @@
|
|||
extern char scnkey[][HEIGHT]; /* in lpdchar.c */
|
||||
extern char fromb[];
|
||||
|
||||
void printjob __P((void));
|
||||
void recvjob __P((void));
|
||||
struct printer;
|
||||
|
||||
__BEGIN_DECLS
|
||||
void printjob __P((struct printer *pp));
|
||||
void startprinting __P((const char *printer));
|
||||
void recvjob __P((const char *printer));
|
||||
__END_DECLS
|
||||
|
|
|
|||
|
|
@ -32,7 +32,11 @@
|
|||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)lpdchar.c 8.1 (Berkeley) 6/6/93";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -29,12 +29,14 @@
|
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
/*
|
||||
static char sccsid[] = "@(#)modes.c 8.3 (Berkeley) 4/2/94";
|
||||
*/
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stddef.h>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue