Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Jul 2000 17:39:55 -0400 (EDT)
From:      Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
To:        current@freebsd.org
Subject:   Request for comments: new `lpd' suite feature
Message-ID:  <200007142139.RAA88779@khavrinen.lcs.mit.edu>

next in thread | raw e-mail | index | archive | help
Around here, we have a convention that each printer has a record in
the DNS for printername.lpd-spooler which points to the print server for
that printer.  It occurred to me that, if there are no local printers,
no additional information is needed for lpr and lpd to operate -- thus
obviating the need for that pesky `/etc/printcap' file which never
seems to be stay up-to-date.  Here is some code which I am planning to
commit soon (after I've actually tested it) which does precisely
that.  The patch also contains a few bug fixes and enhancements for
chkprintcap(8).  (I've already noticed some bugs in reading this
patch.)

Index: chkprintcap/chkprintcap.8
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/chkprintcap/chkprintcap.8,v
retrieving revision 1.3
diff -u -r1.3 chkprintcap.8
--- chkprintcap/chkprintcap.8	1999/08/28 01:16:46	1.3
+++ chkprintcap/chkprintcap.8	2000/07/14 19:35:10
@@ -26,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" $FreeBSD: src/usr.sbin/lpr/chkprintcap/chkprintcap.8,v 1.3 1999/08/28 01:16:46 peter Exp $
-.Dd November 30, 1997
+.Dd July 14, 2000
 .Dt CHKPRINTCAP 8
 .Os
 .Sh NAME
@@ -34,7 +34,7 @@
 .Nd check validity of entries in the print spooler database
 .Sh SYNOPSIS
 .Nm chkprintcap
-.Op Fl d
+.Op Fl ds
 .Op Fl f Ar printcap
 .Sh DESCRIPTION
 .Nm Chkprintcap
@@ -60,6 +60,13 @@
 .Sq Li sd=
 capability
 .Pc .
+.It
+Every spool directory is owned by the daemon user
+.Po
+.Sq Li du#
+capability
+.Pc ,
+and is only writable by that user.
 .El
 .Pp
 .Nm Chkprintcap
@@ -68,6 +75,15 @@
 entire file is scanned.)
 .Pp
 If the
+.Fl s
+flag is used,
+.Nm chkprintcap
+will
+.Dq synthesize
+a printer database, as described in
+.Xr lpd 8 .
+.Pp
+If the
 .Fl d
 flag is given,
 .Nm chkprintcap
@@ -79,6 +95,13 @@
 .Sq Li du=
 capability in the database (default 1, which corresponds to user
 .Sq Li daemon ) .
+.Sh FILES
+.Bl -tag -width "/var/spool/output"
+.It Pa /var/spool/output
+default directory scanned for spool directories by the
+.Fl s
+option.
+.El
 .Sh SEE ALSO
 .Xr lpr 1 ,
 .Xr printcap 5 ,
@@ -89,8 +112,6 @@
 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
+Other parameters whose value could cause
 .Xr lpd 8
 to fail should be diagnosed.
Index: chkprintcap/chkprintcap.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/chkprintcap/chkprintcap.c,v
retrieving revision 1.5
diff -u -r1.5 chkprintcap.c
--- chkprintcap/chkprintcap.c	2000/05/26 02:08:31	1.5
+++ chkprintcap/chkprintcap.c	2000/07/14 20:23:18
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997 Massachusetts Institute of Technology
+ * Copyright 1997, 2000 Massachusetts Institute of Technology
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -28,7 +28,7 @@
  */
 
 static const char copyright[] =
-	"Copyright (C) 1997, Massachusetts Institute of Technology\r\n";
+	"Copyright 1997, 2000 Massachusetts Institute of Technology\r\n";
 static const char rcsid[] =
   "$FreeBSD: src/usr.sbin/lpr/chkprintcap/chkprintcap.c,v 1.5 2000/05/26 02:08:31 jake Exp $";
 
@@ -38,7 +38,7 @@
 
 #include <err.h>
 #include <errno.h>
-#include <grp.h>
+#include <pwd.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -57,6 +57,15 @@
 
 static	int problems;		/* number of problems encountered */
 
+#ifndef SPOOL_DIR_MODE
+#define	SPOOL_DIR_MODE	(S_IRUSR | S_IWUSR | S_IXUSR \
+			 | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+#endif
+#define ALL_MODE_BITS	(S_IRUSR | S_IWUSR | S_IXUSR \
+			 | S_IRGRP | S_IWGRP | S_IXGRP \
+			 | S_IROTH | S_IWOTH | S_IXOTH \
+			 | S_ISUID | S_ISGID | S_ISVTX)
+
 /*
  * chkprintcap - check the printcap file for syntactic and semantic errors
  * Returns the number of problems found.
@@ -64,13 +73,14 @@
 int
 main(int argc, char **argv)
 {
-	int c, error, makedirs, more;
+	int c, error, makedirs, gotone;
 	struct printer myprinter, *pp;
 
+	do_synthesize_printcap = 0;
 	makedirs = 0;
 	pp = &myprinter;
 
-	while ((c = getopt(argc, argv, "df:")) != -1) {
+	while ((c = getopt(argc, argv, "df:s")) != -1) {
 		switch (c) {
 		case 'd':
 			makedirs = 1;
@@ -80,6 +90,10 @@
 			setprintcap(optarg);
 			break;
 
+		case 's':
+			do_synthesize_printcap = 1;
+			break;
+
 		default:
 			usage();
 		}
@@ -87,12 +101,13 @@
 
 	if (optind != argc)
 		usage();
+
+	gotone = firstprinter(pp, &error);
 
-	more = firstprinter(pp, &error);
-	if (interpret_error(pp, error) && more)
+	if (interpret_error(pp, error) && gotone)
 		goto next;
 
-	while (more) {
+	while (gotone) {
 		struct stat stab;
 
 		errno = 0;
@@ -107,12 +122,26 @@
 			note_spool_dir(pp, &stab);
 		}
 
-		/* Make other validity checks here... */
+		if ((stab.st_mode & ALL_MODE_BITS) != SPOOL_DIR_MODE) {
+			problems++;
+			warnx("%s: %s: mode is %#lo, should be %#lo",
+			      pp->printer, pp->spool_dir, 
+			      (u_long)(stab.st_mode & ALL_MODE_BITS),
+			      (u_long)SPOOL_DIR_MODE);
+		}
 
+		if (stab.st_uid != pp->daemon_user) {
+			problems++;
+			warnx("%s: %s: owner is %ld, should be %ld",
+			      pp->printer, pp->spool_dir, (long)stab.st_uid,
+			      (long)pp->daemon_user);
+		}
+
+		/* Make other validity checks here... */
 next:
-		more = nextprinter(pp, &error);
-		if (interpret_error(pp, error) && more)
-			goto next;
+		do {
+			gotone = nextprinter(pp, &error);
+		} while (interpret_error(pp, error) && gotone);
 	}
 	check_spool_dirs();
 	return problems;
@@ -136,6 +165,8 @@
 	case PCAPERR_TCOPEN:
 		warnx("%s: unresolved tc= expansion", pp->printer);
 		return 1;
+	case PCAPERR_NOTFOUND:
+		return 1;
 	case PCAPERR_SUCCESS:
 		break;
 	default:
@@ -226,20 +257,14 @@
 			}
 			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 passwd *pw;
 	struct stat stab;
 
 	if (mkdir(sd, S_IRUSR | S_IXUSR) < 0) {
@@ -247,20 +272,22 @@
 		warn("%s: mkdir %s", pp->printer, sd);
 		return;
 	}
-	gr = getgrnam("daemon");
-	if (gr == 0)
-		errx(++problems, "cannot locate daemon group");
+	
+	pw = getpwuid(pp->daemon_user);
+	if (pw == 0)
+		errx(++problems, "cannot locate daemon user");
 
-	if (chown(sd, pp->daemon_user, gr->gr_gid) < 0) {
+	if (chown(sd, pp->daemon_user, pw->pw_gid) < 0) {
 		++problems;
 		warn("%s: cannot change ownership to %ld:%ld", sd,
-		     (long)pp->daemon_user, (long)gr->gr_gid);
+		     (long)pp->daemon_user, (long)pw->pw_gid);
 		return;
 	}
 
 	if (chmod(sd, SPOOL_DIR_MODE) < 0) {
 		++problems;
-		warn("%s: cannot change mode to %lo", sd, (long)SPOOL_DIR_MODE);
+		warn("%s: cannot change mode to %#lo", sd, 
+		     (u_long)SPOOL_DIR_MODE);
 		return;
 	}
 	if (stat(sd, &stab) < 0)
@@ -272,6 +299,6 @@
 static void
 usage(void)
 {
-	fprintf(stderr, "usage:\n\tchkprintcap [-d] [-f printcapfile]\n");
+	fprintf(stderr, "usage:\n\tchkprintcap [-ds] [-f printcapfile]\n");
 	exit(1);
 }
Index: common_source/lp.h
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/common_source/lp.h,v
retrieving revision 1.11
diff -u -r1.11 lp.h
--- common_source/lp.h	2000/05/26 02:08:37	1.11
+++ common_source/lp.h	2000/07/14 18:51:22
@@ -137,6 +137,8 @@
 /*
  * Global definitions for the line printer system.
  */
+extern int	do_synthesize_printcap;
+
 extern char	line[BUFSIZ];
 extern char	*name;		/* program name */
 				/* host machine name */
@@ -230,5 +232,8 @@
 int      startdaemon __P((const struct printer *pp));
 char	*status_file_name __P((const struct printer *pp, char *buf,
 			       size_t len));
+int	 synfirstprinter __P((struct printer *pp, int *status));
+int	 synnextprinter __P((struct printer *pp, int *status));
+void	 synlastprinter __P((void));
 ssize_t	 writel __P((int s, ...));
 __END_DECLS
Index: common_source/lp.local.h
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/common_source/lp.local.h,v
retrieving revision 1.2
diff -u -r1.2 lp.local.h
--- common_source/lp.local.h	1997/10/14 16:00:34	1.2
+++ common_source/lp.local.h	2000/07/14 18:20:11
@@ -42,6 +42,7 @@
  */
 #define	DEFLP		"lp"
 #define DEFLOCK		"lock"
+#define	DEFLOG		"log"
 #define DEFSTAT		"status"
 #define	DEFMX		1000
 #define DEFMAXCOPIES	0
@@ -50,6 +51,7 @@
 #define DEFLENGTH	66
 #define DEFUID		1
 #define DEFTIMEOUT	120
+#define	DEFSPOOLERDOM	".lpd-spooler"
 
 /*
  * When files are created in the spooling area, they are normally
Index: common_source/pathnames.h
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/common_source/pathnames.h,v
retrieving revision 1.2
diff -u -r1.2 pathnames.h
--- common_source/pathnames.h	1997/12/02 20:45:24	1.2
+++ common_source/pathnames.h	2000/07/14 17:39:30
@@ -37,6 +37,7 @@
 
 #define	_PATH_DEFDEVLP		"/dev/lp"
 #define	_PATH_DEFSPOOL		"/var/spool/output/lpd"
+#define	_PATH_DEFSPOOLDIR	"/var/spool/output"
 #define	_PATH_HOSTSEQUIV	"/etc/hosts.equiv"
 #define	_PATH_HOSTSLPD		"/etc/hosts.lpd"
 #define	_PATH_MASTERLOCK	"/var/spool/output/lpd.lock"
Index: common_source/printcap.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/common_source/printcap.c,v
retrieving revision 1.6
diff -u -r1.6 printcap.c
--- common_source/printcap.c	1999/08/28 01:16:48	1.6
+++ common_source/printcap.c	2000/07/14 20:22:52
@@ -43,14 +43,16 @@
   "$FreeBSD: src/usr.sbin/lpr/common_source/printcap.c,v 1.6 1999/08/28 01:16:48 peter Exp $";
 #endif /* not lint */
 
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
 #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"
@@ -60,14 +62,28 @@
  */
 static 	char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; /* list for cget* */
 
+static	int dbfirstprinter(struct printer *pp, int *error);
+static	int dbnextprinter(struct printer *pp, int *error);
+static	void dblastprinter(struct printer *pp, int *error);
 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);
+static	int synthesize_printcap(const char *printer, struct printer *pp);
+static	int synfirstprinter(struct printer *pp, int *error);
+static	int synnextprinter(struct printer *pp, int *error);
+static	void synlastprinter(void);
+static	DIR *synth_dir;
 
 /*
+ * lpd(8) and chkprintcap(8) set this to +1 in order to force the synthetic
+ * printcap to be used all the time.
+ */
+int	do_synthesize_printcap = -1;
+
+/*
  * 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.
@@ -101,8 +117,18 @@
 	 * to hide the constness of its third argument.
 	 */
 	XXX = (char *)printer;
-	if ((status = cgetent(&bp, printcapdb, XXX)) < 0)
+	errno = 0;
+	if (do_synthesize_printcap > 0) {
+		status = synthesize_printcap(printer, pp);
 		return status;
+	}
+
+	if ((status = cgetent(&bp, printcapdb, XXX)) < 0) {
+		if (status == PCAPERR_OSERR
+		    && errno == ENOENT && do_synthesize_printcap)
+			status = synthesize_printcap(printer, pp);
+		return status;
+	}
 	status = getprintcap_int(bp, pp);
 	free(bp);
 	return status;
@@ -139,10 +165,10 @@
 
 /*
  * Scan through the database of printers using cgetfirst/cgetnext.
- * Return false of error or end-of-database; else true.
+ * Return false on error or end-of-database; else true.
  */
-int
-firstprinter(struct printer *pp, int *error)
+static int
+dbfirstprinter(struct printer *pp, int *error)
 {
 	int status;
 	char *bp;
@@ -163,8 +189,8 @@
 	return 1;
 }
 
-int
-nextprinter(struct printer *pp, int *error)
+static int
+dbnextprinter(struct printer *pp, int *error)
 {
 	int status;
 	char *bp;
@@ -185,8 +211,8 @@
 	return 1;
 }
 
-void
-lastprinter(void)
+static void
+dblastprinter(void)
 {
 	cgetclose();
 }
@@ -273,7 +299,7 @@
 	pp->rp_matches_local = 1;
 	CHK((error = capdb_getaltstr(bp, "rp", "remote.queue", 0, &rp_name)));
 	if (error != PCAPERR_NOTFOUND && rp_name != NULL) {
-		if (cgetmatch(bp,rp_name) != 0)
+		if (cgetmatch(bp, rp_name) != 0)
 			pp->rp_matches_local = 0;
 		free(rp_name);
 	}
@@ -352,6 +378,136 @@
 
 	init_printer(pp);
 }
+
+/*
+ * Invent a struct printer in PP for a printer named PRINTER.
+ * This is intended for large sites where distributing the printcap file
+ * is a pain; it will infer from the presence of spool directories
+ * in _PATH_DEFSPOOLDIR a printcap entry with rm=%s.lpd-spooler and
+ * rp=%s (following the convention used at MIT-LCS where the author
+ * currently works).
+ */
+int
+synthesize_printcap(const char *printer, struct printer *pp)
+{
+	char *spooldir;
+	struct stat stab;
+
+	asprintf(&spooldir, "%s/%s", _PATH_DEFSPOOLDIR, printer);
+	if (spooldir == 0)
+		return PCAPERR_OSERR;
+
+	errno = 0;
+	if (stat(spooldir, &stab) < 0) {
+		if (errno == ENOENT)
+			return PCAPERR_NOTFOUND;
+		else
+			return PCAPERR_OSERR;
+	}
+
+	/* Ignore non-directories. */
+	if (!S_ISDIR(stab.st_mode))
+		return PCAPERR_NOTFOUND;
+
+	/* OK, we think this one is a winner. */
+	init_printer(pp);
+	pp->printer = strdup(printer);
+	pp->conn_timeout = DEFTIMEOUT;
+	pp->daemon_user = DEFUID;
+	pp->form_feed = strdup(DEFFF);
+	pp->log_file = strdup(DEFLOG);
+	pp->lock_file = strdup(DEFLOCK);
+	pp->lp = strdup(_PATH_DEVNULL);
+	pp->max_copies = DEFMAXCOPIES;
+	pp->max_blocks = DEFMX;
+	pp->page_length = DEFLENGTH;
+	pp->page_width = DEFWIDTH;
+	asprintf(&pp->remote_host, "%s%s", printer, DEFSPOOLERDOM);
+	pp->remote_queue = strdup(printer);
+	pp->spool_dir = spooldir;
+	pp->status_file = strdup(DEFSTAT);
+	pp->rp_matches_local = 1;
+
+	return 0;
+}
+
+static int
+synfirstprinter(struct printer *pp, int *error)
+{
+	struct dirent *dp;
+	int status;
+
+	init_printer(pp);	/* inoculate */
+
+	errno = 0;
+	synth_dir = opendir(_PATH_DEFSPOOLDIR);
+	if (synth_dir == 0) {
+		if (error != 0)
+			*error = ((errno == ENOENT) 
+				  ? PCAPERR_NOTFOUND : PCAPERR_OSERR);
+		return 0;
+	}
+
+	return (synnextprinter(pp, error));
+}
+
+static int
+synnextprinter(struct printer *pp, int *error)
+{
+	int status;
+	struct dirent *dp;
+
+	free_printer(pp);
+	status = 0;
+
+	do {
+		dp = readdir(synth_dir);
+		if (dp == 0) {
+			if (error != 0)
+				*error = 0;
+			return 0;
+		}
+	} while (dp->d_name[0] == '.'
+		 || (status = synthesize_printcap(dp->d_name, pp)) != 0);
+	if (error)
+		*error = status;
+	return (status == 0);
+}
+
+static void
+synlastprinter(void)
+{
+	if (synth_dir != 0)
+		closedir(synth_dir);
+}
+
+int
+firstprinter(struct printer *pp, int *error)
+{
+	if (do_synthesize_printcap)
+		return synfirstprinter(pp, error);
+	else
+		return dbfirstprinter(pp, error);
+}
+
+int
+nextprinter(struct printer *pp, int *error)
+{
+	if (do_synthesize_printcap)
+		return synnextprinter(pp, error);
+	else
+		return dbnextprinter(pp, error);
+}
+
+void
+lastprinter(void)
+{
+	if (do_synthesize_printcap)
+		synlastprinter();
+	else
+		dblastprinter();
+}
+
 
 
 /* 
Index: lpd/lpd.8
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/lpd/lpd.8,v
retrieving revision 1.15
diff -u -r1.15 lpd.8
--- lpd/lpd.8	2000/03/29 11:15:54	1.15
+++ lpd/lpd.8	2000/07/14 21:01:38
@@ -40,7 +40,7 @@
 .Nd line printer spooler daemon
 .Sh SYNOPSIS
 .Nm lpd
-.Op Fl dlp
+.Op Fl dlps
 .Op Ar port#
 .Sh DESCRIPTION
 .Nm Lpd
@@ -88,6 +88,14 @@
 but can be changed with the
 .Ar port#
 argument.
+.It Fl s
+When this option is given,
+.Nm
+ignores the
+.Pa /etc/printcap
+file and
+.Dq synthesizes
+printer queue information as described below.
 .El
 .Pp
 Access control is provided by two means.
@@ -234,6 +242,54 @@
 .Xr lpq 1
 and
 .Xr lprm 1 .
+.Ss Synthesizing Printer Definitions
+The
+.Nm lpd
+program is capable of operating without a
+.Pa /etc/printcap
+file, in certain restricted configurations, when the
+.Fl s
+flag is given on the command line.  This functionality is intended for
+workstations at large sites where distributing
+.Pa /etc/printcap
+is inconvenient, and most client workstations do not need access to
+all of the available printers.  The following conditions must be met:
+.Bl -enum -offset indent
+.It
+No printers are attached locally to a client.
+.It
+The queue names on the print servers are the same as the queue names on
+every client.
+.It
+The mapping of printers to servers is stored in the Domain Name System
+(or equivalent), using aliases of the form
+.Dq Sy printername Ns Li .lpd-spooler
+(the target of which is the print server for that printer).
+.It
+Any necessary accounting or filtering must be performed on the print
+servers and not on the clients.
+.It
+Only one name is used to refer to each distinct printer or queue.
+.El
+.Pp
+The
+.Fl s
+option works by scanning the
+.Pa /var/spool/output
+directory.  Each subdirectory found is interpreted as a spool
+directory for the printer of the same name.  The defaults described in
+.Xr printcap 5
+apply for all capabilities, except:
+.Pp
+.Bl -tag -compact -offset indent -width indent
+.It Li lf
+.Pa log
+(in the spool directory)
+.It Li lp
+.Pa /dev/null
+.It Li rp
+name of the printer
+.El
 .Sh FILES
 .Bl -tag -width "/var/spool/*/minfree" -compact
 .It Pa /etc/printcap
Index: lpd/lpd.c
===================================================================
RCS file: /home/cvs/src/usr.sbin/lpr/lpd/lpd.c,v
retrieving revision 1.13
diff -u -r1.13 lpd.c
--- lpd/lpd.c	2000/03/29 11:15:54	1.13
+++ lpd/lpd.c	2000/07/14 21:22:36
@@ -134,6 +134,7 @@
 	sigset_t omask, nmask;
 	struct servent *sp, serv;
 
+	do_synthesize_printcap = 0;
 	euid = geteuid();	/* these shouldn't be different */
 	uid = getuid();
 	options = 0;
@@ -145,7 +146,7 @@
 		errx(EX_NOPERM,"must run as root");
 
 	errs = 0;
-	while ((i = getopt(argc, argv, "dlp")) != -1)
+	while ((i = getopt(argc, argv, "dlps")) != -1)
 		switch (i) {
 		case 'd':
 			options |= SO_DEBUG;
@@ -156,6 +157,9 @@
 		case 'p':
 			pflag++;
 			break;
+		case 's':
+			do_synthesize_printcap = 1;
+			break;
 		default:
 			errs++;
 		}
@@ -192,12 +196,25 @@
 	{
 		pid_t pid;
 		int status;
-		pid = fork();
+		char *argv[2];
+
+		argv[0] = _PATH_CHKPRINTCAP;
+		if (do_synthesize_printcap) {
+			argv[1] = "-s";
+			argv[2] = 0;
+		} else
+			argv[1] = 0;
+
+		pid = vfork();
 		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);
+			execv(_PATH_CHKPRINTCAP, argv);
+			write(STDERR_FILENO, "cannot execute ", 15);
+			write(STDERR_FILENO, _PATH_CHKPRINTCAP, 
+			      sizeof(_PATH_CHKPRINTCAP) - 1);
+			write(STDERR_FILENO, "\n", 1);
+			_exit(1);
 		}
 		if (waitpid(pid, &status, 0) < 0) {
 			err(EX_OSERR, "cannot wait");
@@ -205,6 +222,9 @@
 		if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
 			errx(EX_OSFILE, "%d errors in printcap file, exiting",
 			     WEXITSTATUS(status));
+		else if (WIFSIGNALED(status))
+			 errx(EX_OSFILE, "%s exited on signal %d",
+			      _PATH_CHKPRINTCAP, WTERMSIG(status));
 	}
 
 #ifndef DEBUG
@@ -227,7 +247,7 @@
 	lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK,
 		   LOCK_FILE_MODE);
 	if (lfd < 0) {
-		if (errno == EWOULDBLOCK)	/* active deamon present */
+		if (errno == EWOULDBLOCK)	/* active daemon present */
 			exit(0);
 		syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK);
 		exit(1);
@@ -638,6 +658,6 @@
 static void
 usage()
 {
-	fprintf(stderr, "usage: lpd [-dlp] [port#]\n");
+	fprintf(stderr, "usage: lpd [-dlps] [port#]\n");
 	exit(EX_USAGE);
 }


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200007142139.RAA88779>