Pull a bunch of fixes from the 4.4BSD-Lite2 branch. It's really

surprising how many trivial errors there have been... :-)

Some more cleanup is needed, but i'd like to separate the Lite2 changes
from other work, that's why this goes into a different commit.

People with serial printers should see whether i have broken the stty-
style printcap options (i hope not).

Inspired by: Sergey Shkonda <serg@bcs1.bcs.zaporizhzhe.ua>
This commit is contained in:
Joerg Wunsch 1996-05-05 22:40:51 +00:00
parent 7458568265
commit 5458e2f421
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=15648
12 changed files with 421 additions and 206 deletions

View File

@ -37,11 +37,12 @@
*/
#ifndef lint
static char sccsid[] = "@(#)common.c 8.2 (Berkeley) 1/21/94";
static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
@ -105,18 +106,20 @@ char *printer; /* printer name */
/* host machine name */
char host[MAXHOSTNAMELEN];
char *from = host; /* client's machine name */
int sendtorem; /* are we sending to a remote? */
int remote; /* true if sending files to a remote host */
char *printcapdb[2] = { _PATH_PRINTCAP, 0 };
static int compar __P((const void *, const void *));
/*
* Create a connection to the remote printer server.
* 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)
getport(rhost, rport)
char *rhost;
int rport;
{
struct hostent *hp;
struct servent *sp;
@ -129,16 +132,24 @@ getport(rhost)
*/
if (rhost == NULL)
fatal("no remote host to connect to");
hp = gethostbyname(rhost);
if (hp == NULL)
fatal("unknown host %s", rhost);
sp = getservbyname("printer", "tcp");
if (sp == NULL)
fatal("printer/tcp: unknown service");
bzero((char *)&sin, sizeof(sin));
bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
sin.sin_family = hp->h_addrtype;
sin.sin_port = sp->s_port;
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.
@ -241,8 +252,9 @@ getq(namelist)
* realloc the maximum size.
*/
if (++nitems > arraysz) {
arraysz *= 2;
queue = (struct queue **)realloc((char *)queue,
(stbuf.st_size/12) * sizeof(struct queue *));
arraysz * sizeof(struct queue *));
if (queue == NULL)
goto errdone;
}
@ -284,8 +296,8 @@ checkremote()
register struct hostent *hp;
static char errbuf[128];
sendtorem = 0; /* assume printer is local */
if (RM != (char *)NULL) {
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';
@ -310,10 +322,23 @@ checkremote()
* if the two hosts are not the same,
* then the printer must be remote.
*/
if (strcmp(name, hp->h_name) != 0)
sendtorem = 1;
if (strcasecmp(name, hp->h_name) != 0)
remote = 1;
}
return (char *)0;
return NULL;
}
/* sleep n milliseconds */
void
delay(n)
{
struct timeval tdelay;
if (n <= 0 || n > 10000)
fatal("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);
}
#if __STDC__

View File

@ -32,11 +32,12 @@
*/
#ifndef lint
static char sccsid[] = "@(#)displayq.c 8.1 (Berkeley) 6/6/93";
static char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <signal.h>
#include <fcntl.h>
@ -124,7 +125,7 @@ displayq(format)
fatal("cannot examine spooling area\n");
if (stat(LO, &statb) >= 0) {
if (statb.st_mode & 0100) {
if (sendtorem)
if (remote)
printf("%s: ", host);
printf("Warning: %s is down: ", printer);
fd = open(ST, O_RDONLY);
@ -137,7 +138,7 @@ displayq(format)
putchar('\n');
}
if (statb.st_mode & 010) {
if (sendtorem)
if (remote)
printf("%s: ", host);
printf("Warning: %s queue is turned off\n", printer);
}
@ -150,8 +151,8 @@ displayq(format)
else {
/* get daemon pid */
cp = current;
while ((*cp = getc(fp)) != EOF && *cp != '\n')
cp++;
while ((i = getc(fp)) != EOF && i != '\n')
*cp++ = i;
*cp = '\0';
i = atoi(current);
if (i <= 0 || kill(i, 0) < 0)
@ -159,13 +160,13 @@ displayq(format)
else {
/* read current file name */
cp = current;
while ((*cp = getc(fp)) != EOF && *cp != '\n')
cp++;
while ((i = getc(fp)) != EOF && i != '\n')
*cp++ = i;
*cp = '\0';
/*
* Print the status file.
*/
if (sendtorem)
if (remote)
printf("%s: ", host);
fd = open(ST, O_RDONLY);
if (fd >= 0) {
@ -191,7 +192,7 @@ displayq(format)
}
free(queue);
}
if (!sendtorem) {
if (!remote) {
if (nitems == 0)
puts("no entries");
return;
@ -215,7 +216,7 @@ displayq(format)
(void) strcpy(cp, user[i]);
}
strcat(line, "\n");
fd = getport(RM);
fd = getport(RM, 0);
if (fd < 0) {
if (from != host)
printf("%s: ", host);
@ -237,7 +238,7 @@ displayq(format)
void
warn()
{
if (sendtorem)
if (remote)
printf("\n%s: ", host);
puts("Warning: no daemon present");
current[0] = '\0';
@ -271,7 +272,7 @@ inform(cf)
if (rank < 0)
rank = 0;
if (sendtorem || garbage || strcmp(cf, current))
if (remote || garbage || strcmp(cf, current))
rank++;
j = 0;
while (getline(cfp)) {

View File

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)lp.h 8.1 (Berkeley) 6/6/93
* @(#)lp.h 8.2 (Berkeley) 4/28/95
*/
@ -82,7 +82,7 @@ extern char *printer; /* printer name */
/* host machine name */
extern char host[MAXHOSTNAMELEN];
extern char *from; /* client's machine name */
extern int sendtorem; /* are we sending to a remote? */
extern int remote; /* true if sending files to a remote host */
extern char *printcapdb[]; /* printcap database array */
/*
* Structure used for building a sorted list of control files.
@ -104,7 +104,7 @@ void displayq __P((int));
void dump __P((char *, char *, int));
void fatal __P((const char *, ...));
int getline __P((FILE *));
int getport __P((char *));
int getport __P((char *, int));
int getq __P((struct queue *(*[])));
void header __P((void));
void inform __P((char *));
@ -120,4 +120,5 @@ void rmremote __P((void));
void show __P((char *, char *, int));
int startdaemon __P((char *));
void warn __P((void));
void delay __P((int));
__END_DECLS

View File

@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)recvjob.c 8.1 (Berkeley) 6/6/93";
static char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95";
#endif /* not lint */
/*
@ -342,7 +342,7 @@ frecverr(msg, va_alist)
va_dcl
#endif
{
extern char *fromb;
extern char fromb[];
va_list ap;
#if __STDC__
va_start(ap, msg);

View File

@ -32,7 +32,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)rmjob.c 8.1 (Berkeley) 6/6/93";
static char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95";
#endif /* not lint */
#include <sys/param.h>
@ -292,7 +292,7 @@ rmremote()
register int i, rem;
char buf[BUFSIZ];
if (!sendtorem)
if (!remote)
return; /* not sending to a remote machine */
/*
@ -313,7 +313,7 @@ rmremote()
(void) sprintf(cp, " %d", requ[i]);
}
strcat(cp, "\n");
rem = getport(RM);
rem = getport(RM, 0);
if (rem < 0) {
if (from != host)
printf("%s: ", host);

View File

@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95";
#endif /* not lint */
/*
@ -49,6 +49,7 @@ static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
#include <sys/param.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <signal.h>
#include <fcntl.h>

View File

@ -29,9 +29,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)lpc.8 8.3 (Berkeley) 4/19/94
.\" @(#)lpc.8 8.5 (Berkeley) 4/28/95
.\"
.Dd April 19, 1994
.Dd April 28, 1995
.Dt LPC 8
.Os BSD 4.2
.Sh NAME
@ -117,6 +117,7 @@ to put new jobs in the spool queue.
.It Ic exit
.It Ic quit
Exit from lpc.
.\" ne 1i
.Pp
.It Ic restart No {\ all\ |\ printer\ }
Attempt to start a new printer daemon.
@ -165,7 +166,7 @@ abbreviation matches more than one command
.It Sy "?Invalid command"
no match was found
.It Sy "?Privileged command"
command can be executed by root only
you must be a member of group "operator" or root to execute this command
.El
.Sh HISTORY
The

View File

@ -247,13 +247,3 @@ but not under same administrative control.
An
.Nm
daemon appeared in Version 6 AT&T UNIX.
.Sh BUGS
.Nm Lpd
tends to dump core if a request specifies a file format where no filter
is assigned. This may be particular annoying if somebody is not aware
of the file format specification, such as for a DOS client that always
specifies the
.Em v
format. The workaround is to assign a dummy filter for these file
formats, e. g. a
.Xr cat 1 .

View File

@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)printjob.c 8.2 (Berkeley) 4/16/94";
static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95";
#endif /* not lint */
@ -96,7 +96,6 @@ static int ofilter; /* id of output filter, if any */
static int pfd; /* prstatic inter file descriptor */
static int pid; /* pid of lpd process */
static int prchild; /* id of pr process */
static int remote; /* true if sending files to remote */
static char title[80]; /* ``pr'' title */
static int tof; /* true if at top of form */
@ -118,6 +117,9 @@ static int dofork __P((int));
static int dropit __P((int));
static void init __P((void));
static void openpr __P((void));
static void opennet __P((char *));
static void opentty __P((void));
static void openrem __P((void));
static int print __P((int, char *));
static int printit __P((char *));
static void pstatus __P((const char *, ...));
@ -136,8 +138,8 @@ printjob()
register struct queue *q, **qp;
struct queue **queue;
register int i, nitems;
long pidoff;
int count = 0;
off_t pidoff;
int errcnt, count = 0;
init(); /* set up capabilities */
(void) write(1, "", 1); /* ack that daemon is started */
@ -210,8 +212,9 @@ printjob()
q = *qp++;
if (stat(q->q_name, &stb) < 0)
continue;
errcnt = 0;
restart:
(void) lseek(lfd, (off_t)pidoff, 0);
(void) lseek(lfd, pidoff, 0);
(void) sprintf(line, "%s\n", q->q_name);
i = strlen(line);
if (write(lfd, line, i) != i)
@ -240,12 +243,13 @@ printjob()
}
if (i == OK) /* file ok and printed */
count++;
else if (i == REPRINT) { /* try reprinting the job */
else if (i == REPRINT && ++errcnt < 5) {
/* try reprinting the job */
syslog(LOG_INFO, "restarting %s", printer);
if (ofilter > 0) {
kill(ofilter, SIGCONT); /* to be sure */
(void) close(ofd);
while ((i = wait(0)) > 0 && i != ofilter)
while ((i = wait(NULL)) > 0 && i != ofilter)
;
ofilter = 0;
}
@ -254,6 +258,17 @@ printjob()
syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
openpr(); /* try to reopen printer */
goto restart;
} else {
syslog(LOG_WARNING, "%s: job could not be %s (%s)", printer,
remote ? "sent to remote host" : "printed", q->q_name);
if (i == REPRINT) {
/* insure we don't attempt this job again */
(void) unlink(q->q_name);
q->q_name[0] = 'd';
(void) unlink(q->q_name);
if (logname[0])
sendmail(logname, FATALERR);
}
}
}
free((char *) queue);
@ -329,6 +344,7 @@ printit(file)
* H -- "host name" of machine where lpr was done
* P -- "person" user's login name
* I -- "indent" amount to indent output
* R -- laser dpi "resolution"
* f -- "file name" name of text file to print
* l -- "file name" text file with control chars
* p -- "file name" text file to print with pr(1)
@ -443,6 +459,7 @@ printit(file)
case 'N':
case 'U':
case 'M':
case 'R':
continue;
}
@ -544,7 +561,6 @@ print(format, file)
(void) close(n);
execl(_PATH_PR, "pr", width, length,
"-h", *title ? title : " ", "-F", 0);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "cannot execl %s", _PATH_PR);
exit(2);
}
@ -623,6 +639,13 @@ print(format, file)
printer, format);
return(ERROR);
}
if (prog == NULL) {
(void) close(fi);
syslog(LOG_ERR,
"%s: no filter found in printcap for format character '%c'",
printer, format);
return(ERROR);
}
if ((av[0] = rindex(prog, '/')) != NULL)
av[0]++;
else
@ -641,8 +664,9 @@ print(format, file)
;
if (status.w_stopval != WSTOPPED) {
(void) close(fi);
syslog(LOG_WARNING, "%s: output filter died (%d)",
printer, status.w_retcode);
syslog(LOG_WARNING,
"%s: output filter died (retcode=%d termsig=%d)",
printer, status.w_retcode, status.w_termsig);
return(REPRINT);
}
stopped++;
@ -658,7 +682,6 @@ print(format, file)
for (n = 3; n < NOFILE; n++)
(void) close(n);
execv(prog, av);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "cannot execv %s", prog);
exit(2);
}
@ -686,7 +709,7 @@ print(format, file)
}
if (!WIFEXITED(status)) {
syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",
syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)",
printer, format, status.w_termsig);
return(ERROR);
}
@ -696,11 +719,12 @@ print(format, file)
return(OK);
case 1:
return(REPRINT);
default:
syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)",
printer, format, status.w_retcode);
case 2:
return(ERROR);
default:
syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)",
printer, format, status.w_retcode);
return(FILTERERR);
}
}
@ -1022,47 +1046,54 @@ sendmail(user, bombed)
cp = _PATH_SENDMAIL;
sprintf(buf, "%s@%s", user, fromhost);
execl(_PATH_SENDMAIL, cp, buf, 0);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "cannot execl %s", _PATH_SENDMAIL);
exit(0);
} else if (s > 0) { /* parent */
dup2(p[1], 1);
printf("To: %s@%s\n", user, fromhost);
printf("Subject: printer job\n\n");
printf("Subject: %s printer job \"%s\"\n", printer,
*jobname ? jobname : "<unknown>");
printf("Reply-To: root@%s\n\n", host);
printf("Your printer job ");
if (*jobname)
printf("(%s) ", jobname);
switch (bombed) {
case OK:
printf("\ncompleted successfully\n");
cp = "OK";
break;
default:
case FATALERR:
printf("\ncould not be printed\n");
cp = "FATALERR";
break;
case NOACCT:
printf("\ncould not be printed without an account on %s\n", host);
cp = "NOACCT";
break;
case FILTERERR:
if (stat(tempfile, &stb) < 0 || stb.st_size == 0 ||
(fp = fopen(tempfile, "r")) == NULL) {
printf("\nwas printed but had some errors\n");
printf("\nhad some errors and may not have printed\n");
break;
}
printf("\nwas printed but had the following errors:\n");
printf("\nhad the following errors and may not have printed:\n");
while ((i = getc(fp)) != EOF)
putchar(i);
(void) fclose(fp);
cp = "FILTERERR";
break;
case ACCESS:
printf("\nwas not printed because it was not linked to the original file\n");
cp = "ACCESS";
}
fflush(stdout);
(void) close(1);
}
(void) close(p[0]);
(void) close(p[1]);
wait(&s);
wait(NULL);
syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)",
user, *jobname ? jobname : "<unknown>", printer, cp);
}
/*
@ -1073,7 +1104,6 @@ dofork(action)
int action;
{
register int i, pid;
struct passwd *pwd;
for (i = 0; i < 20; i++) {
if ((pid = fork()) < 0) {
@ -1083,15 +1113,8 @@ dofork(action)
/*
* Child should run as daemon instead of root
*/
if (pid == 0) {
if ((pwd = getpwuid(DU)) == NULL) {
syslog(LOG_ERR, "Can't lookup default uid in password file");
break;
}
initgroups(pwd->pw_name, pwd->pw_gid);
setgid(pwd->pw_gid);
if (pid == 0)
setuid(DU);
}
return(pid);
}
syslog(LOG_ERR, "can't fork");
@ -1202,60 +1225,27 @@ init()
static void
openpr()
{
register int i, n;
int resp;
register int i;
char *cp;
if (!sendtorem && *LP) {
for (i = 1; ; i = i < 32 ? i << 1 : i) {
pfd = open(LP, RW ? O_RDWR : O_WRONLY);
if (pfd >= 0)
break;
if (errno == ENOENT) {
syslog(LOG_ERR, "%s: %m", LP);
exit(1);
}
if (i == 1)
pstatus("waiting for %s to become ready (offline ?)", printer);
sleep(i);
}
if (isatty(pfd))
setty();
pstatus("%s is ready and printing", printer);
} else if (RM != NULL) {
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
pfd = getport(RM);
if (pfd >= 0) {
(void) sprintf(line, "\2%s\n", RP);
n = strlen(line);
if (write(pfd, line, n) == n &&
(resp = response()) == '\0')
break;
(void) close(pfd);
}
if (i == 1) {
if (resp < 0)
pstatus("waiting for %s to come up", RM);
else {
pstatus("waiting for queue to be enabled on %s", RM);
i = 256;
}
}
sleep(i);
}
pstatus("sending to %s", RM);
remote = 1;
if (!remote && *LP) {
if (cp = index(LP, '@'))
opennet(cp);
else
opentty();
} else if (remote) {
openrem();
} else {
syslog(LOG_ERR, "%s: no line printer device or host name",
printer);
exit(1);
}
/*
* Start up an output filter, if needed.
*/
if (!remote && OF) {
int p[2];
char *cp;
pipe(p);
if ((ofilter = dofork(DOABORT)) == 0) { /* child */
@ -1269,7 +1259,6 @@ openpr()
else
cp++;
execl(OF, cp, width, length, 0);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "%s: %s: %m", printer, OF);
exit(1);
}
@ -1281,6 +1270,115 @@ openpr()
}
}
/*
* Printer connected directly to the network
* or to a terminal server on the net
*/
static void
opennet(cp)
char *cp;
{
register int i;
int resp, port;
char save_ch;
save_ch = *cp;
*cp = '\0';
port = atoi(LP);
if (port <= 0) {
syslog(LOG_ERR, "%s: bad port number: %s", printer, LP);
exit(1);
}
*cp++ = save_ch;
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
pfd = getport(cp, port);
if (pfd < 0 && errno == ECONNREFUSED)
resp = 1;
else if (pfd >= 0) {
/*
* need to delay a bit for rs232 lines
* to stabilize in case printer is
* connected via a terminal server
*/
delay(500);
break;
}
if (i == 1) {
if (resp < 0)
pstatus("waiting for %s to come up", LP);
else
pstatus("waiting for access to printer on %s", LP);
}
sleep(i);
}
pstatus("sending to %s port %d", cp, port);
}
/*
* Printer is connected to an RS232 port on this host
*/
static void
opentty()
{
register int i;
int resp, port;
for (i = 1; ; i = i < 32 ? i << 1 : i) {
pfd = open(LP, RW ? O_RDWR : O_WRONLY);
if (pfd >= 0) {
delay(500);
break;
}
if (errno == ENOENT) {
syslog(LOG_ERR, "%s: %m", LP);
exit(1);
}
if (i == 1)
pstatus("waiting for %s to become ready (offline ?)",
printer);
sleep(i);
}
if (isatty(pfd))
setty();
pstatus("%s is ready and printing", printer);
}
/*
* Printer is on a remote host
*/
static void
openrem()
{
register int i, n;
int resp, port;
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
pfd = getport(RM, 0);
if (pfd >= 0) {
(void) sprintf(line, "\2%s\n", RP);
n = strlen(line);
if (write(pfd, line, n) == n &&
(resp = response()) == '\0')
break;
(void) close(pfd);
}
if (i == 1) {
if (resp < 0)
pstatus("waiting for %s to come up", RM);
else {
pstatus("waiting for queue to be enabled on %s",
RM);
i = 256;
}
}
sleep(i);
}
pstatus("sending to %s", RM);
}
struct bauds {
int baud;
int speed;
@ -1352,7 +1450,7 @@ setty()
#include <varargs.h>
#endif
void
static void
#if __STDC__
pstatus(const char *msg, ...)
#else

View File

@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)recvjob.c 8.1 (Berkeley) 6/6/93";
static char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95";
#endif /* not lint */
/*
@ -342,7 +342,7 @@ frecverr(msg, va_alist)
va_dcl
#endif
{
extern char *fromb;
extern char fromb[];
va_list ap;
#if __STDC__
va_start(ap, msg);

View File

@ -44,7 +44,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)lpr.c 8.3 (Berkeley) 3/30/94";
static char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95";
#endif /* not lint */
/*

View File

@ -39,7 +39,7 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)printjob.c 8.2 (Berkeley) 4/16/94";
static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95";
#endif /* not lint */
@ -96,7 +96,6 @@ static int ofilter; /* id of output filter, if any */
static int pfd; /* prstatic inter file descriptor */
static int pid; /* pid of lpd process */
static int prchild; /* id of pr process */
static int remote; /* true if sending files to remote */
static char title[80]; /* ``pr'' title */
static int tof; /* true if at top of form */
@ -118,6 +117,9 @@ static int dofork __P((int));
static int dropit __P((int));
static void init __P((void));
static void openpr __P((void));
static void opennet __P((char *));
static void opentty __P((void));
static void openrem __P((void));
static int print __P((int, char *));
static int printit __P((char *));
static void pstatus __P((const char *, ...));
@ -136,8 +138,8 @@ printjob()
register struct queue *q, **qp;
struct queue **queue;
register int i, nitems;
long pidoff;
int count = 0;
off_t pidoff;
int errcnt, count = 0;
init(); /* set up capabilities */
(void) write(1, "", 1); /* ack that daemon is started */
@ -210,8 +212,9 @@ printjob()
q = *qp++;
if (stat(q->q_name, &stb) < 0)
continue;
errcnt = 0;
restart:
(void) lseek(lfd, (off_t)pidoff, 0);
(void) lseek(lfd, pidoff, 0);
(void) sprintf(line, "%s\n", q->q_name);
i = strlen(line);
if (write(lfd, line, i) != i)
@ -240,12 +243,13 @@ printjob()
}
if (i == OK) /* file ok and printed */
count++;
else if (i == REPRINT) { /* try reprinting the job */
else if (i == REPRINT && ++errcnt < 5) {
/* try reprinting the job */
syslog(LOG_INFO, "restarting %s", printer);
if (ofilter > 0) {
kill(ofilter, SIGCONT); /* to be sure */
(void) close(ofd);
while ((i = wait(0)) > 0 && i != ofilter)
while ((i = wait(NULL)) > 0 && i != ofilter)
;
ofilter = 0;
}
@ -254,6 +258,17 @@ printjob()
syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
openpr(); /* try to reopen printer */
goto restart;
} else {
syslog(LOG_WARNING, "%s: job could not be %s (%s)", printer,
remote ? "sent to remote host" : "printed", q->q_name);
if (i == REPRINT) {
/* insure we don't attempt this job again */
(void) unlink(q->q_name);
q->q_name[0] = 'd';
(void) unlink(q->q_name);
if (logname[0])
sendmail(logname, FATALERR);
}
}
}
free((char *) queue);
@ -329,6 +344,7 @@ printit(file)
* H -- "host name" of machine where lpr was done
* P -- "person" user's login name
* I -- "indent" amount to indent output
* R -- laser dpi "resolution"
* f -- "file name" name of text file to print
* l -- "file name" text file with control chars
* p -- "file name" text file to print with pr(1)
@ -443,6 +459,7 @@ printit(file)
case 'N':
case 'U':
case 'M':
case 'R':
continue;
}
@ -544,7 +561,6 @@ print(format, file)
(void) close(n);
execl(_PATH_PR, "pr", width, length,
"-h", *title ? title : " ", "-F", 0);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "cannot execl %s", _PATH_PR);
exit(2);
}
@ -623,6 +639,13 @@ print(format, file)
printer, format);
return(ERROR);
}
if (prog == NULL) {
(void) close(fi);
syslog(LOG_ERR,
"%s: no filter found in printcap for format character '%c'",
printer, format);
return(ERROR);
}
if ((av[0] = rindex(prog, '/')) != NULL)
av[0]++;
else
@ -641,8 +664,9 @@ print(format, file)
;
if (status.w_stopval != WSTOPPED) {
(void) close(fi);
syslog(LOG_WARNING, "%s: output filter died (%d)",
printer, status.w_retcode);
syslog(LOG_WARNING,
"%s: output filter died (retcode=%d termsig=%d)",
printer, status.w_retcode, status.w_termsig);
return(REPRINT);
}
stopped++;
@ -658,7 +682,6 @@ print(format, file)
for (n = 3; n < NOFILE; n++)
(void) close(n);
execv(prog, av);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "cannot execv %s", prog);
exit(2);
}
@ -686,7 +709,7 @@ print(format, file)
}
if (!WIFEXITED(status)) {
syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",
syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)",
printer, format, status.w_termsig);
return(ERROR);
}
@ -696,11 +719,12 @@ print(format, file)
return(OK);
case 1:
return(REPRINT);
default:
syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)",
printer, format, status.w_retcode);
case 2:
return(ERROR);
default:
syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)",
printer, format, status.w_retcode);
return(FILTERERR);
}
}
@ -1022,47 +1046,54 @@ sendmail(user, bombed)
cp = _PATH_SENDMAIL;
sprintf(buf, "%s@%s", user, fromhost);
execl(_PATH_SENDMAIL, cp, buf, 0);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "cannot execl %s", _PATH_SENDMAIL);
exit(0);
} else if (s > 0) { /* parent */
dup2(p[1], 1);
printf("To: %s@%s\n", user, fromhost);
printf("Subject: printer job\n\n");
printf("Subject: %s printer job \"%s\"\n", printer,
*jobname ? jobname : "<unknown>");
printf("Reply-To: root@%s\n\n", host);
printf("Your printer job ");
if (*jobname)
printf("(%s) ", jobname);
switch (bombed) {
case OK:
printf("\ncompleted successfully\n");
cp = "OK";
break;
default:
case FATALERR:
printf("\ncould not be printed\n");
cp = "FATALERR";
break;
case NOACCT:
printf("\ncould not be printed without an account on %s\n", host);
cp = "NOACCT";
break;
case FILTERERR:
if (stat(tempfile, &stb) < 0 || stb.st_size == 0 ||
(fp = fopen(tempfile, "r")) == NULL) {
printf("\nwas printed but had some errors\n");
printf("\nhad some errors and may not have printed\n");
break;
}
printf("\nwas printed but had the following errors:\n");
printf("\nhad the following errors and may not have printed:\n");
while ((i = getc(fp)) != EOF)
putchar(i);
(void) fclose(fp);
cp = "FILTERERR";
break;
case ACCESS:
printf("\nwas not printed because it was not linked to the original file\n");
cp = "ACCESS";
}
fflush(stdout);
(void) close(1);
}
(void) close(p[0]);
(void) close(p[1]);
wait(&s);
wait(NULL);
syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)",
user, *jobname ? jobname : "<unknown>", printer, cp);
}
/*
@ -1073,7 +1104,6 @@ dofork(action)
int action;
{
register int i, pid;
struct passwd *pwd;
for (i = 0; i < 20; i++) {
if ((pid = fork()) < 0) {
@ -1083,15 +1113,8 @@ dofork(action)
/*
* Child should run as daemon instead of root
*/
if (pid == 0) {
if ((pwd = getpwuid(DU)) == NULL) {
syslog(LOG_ERR, "Can't lookup default uid in password file");
break;
}
initgroups(pwd->pw_name, pwd->pw_gid);
setgid(pwd->pw_gid);
if (pid == 0)
setuid(DU);
}
return(pid);
}
syslog(LOG_ERR, "can't fork");
@ -1202,60 +1225,27 @@ init()
static void
openpr()
{
register int i, n;
int resp;
register int i;
char *cp;
if (!sendtorem && *LP) {
for (i = 1; ; i = i < 32 ? i << 1 : i) {
pfd = open(LP, RW ? O_RDWR : O_WRONLY);
if (pfd >= 0)
break;
if (errno == ENOENT) {
syslog(LOG_ERR, "%s: %m", LP);
exit(1);
}
if (i == 1)
pstatus("waiting for %s to become ready (offline ?)", printer);
sleep(i);
}
if (isatty(pfd))
setty();
pstatus("%s is ready and printing", printer);
} else if (RM != NULL) {
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
pfd = getport(RM);
if (pfd >= 0) {
(void) sprintf(line, "\2%s\n", RP);
n = strlen(line);
if (write(pfd, line, n) == n &&
(resp = response()) == '\0')
break;
(void) close(pfd);
}
if (i == 1) {
if (resp < 0)
pstatus("waiting for %s to come up", RM);
else {
pstatus("waiting for queue to be enabled on %s", RM);
i = 256;
}
}
sleep(i);
}
pstatus("sending to %s", RM);
remote = 1;
if (!remote && *LP) {
if (cp = index(LP, '@'))
opennet(cp);
else
opentty();
} else if (remote) {
openrem();
} else {
syslog(LOG_ERR, "%s: no line printer device or host name",
printer);
exit(1);
}
/*
* Start up an output filter, if needed.
*/
if (!remote && OF) {
int p[2];
char *cp;
pipe(p);
if ((ofilter = dofork(DOABORT)) == 0) { /* child */
@ -1269,7 +1259,6 @@ openpr()
else
cp++;
execl(OF, cp, width, length, 0);
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "%s: %s: %m", printer, OF);
exit(1);
}
@ -1281,6 +1270,115 @@ openpr()
}
}
/*
* Printer connected directly to the network
* or to a terminal server on the net
*/
static void
opennet(cp)
char *cp;
{
register int i;
int resp, port;
char save_ch;
save_ch = *cp;
*cp = '\0';
port = atoi(LP);
if (port <= 0) {
syslog(LOG_ERR, "%s: bad port number: %s", printer, LP);
exit(1);
}
*cp++ = save_ch;
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
pfd = getport(cp, port);
if (pfd < 0 && errno == ECONNREFUSED)
resp = 1;
else if (pfd >= 0) {
/*
* need to delay a bit for rs232 lines
* to stabilize in case printer is
* connected via a terminal server
*/
delay(500);
break;
}
if (i == 1) {
if (resp < 0)
pstatus("waiting for %s to come up", LP);
else
pstatus("waiting for access to printer on %s", LP);
}
sleep(i);
}
pstatus("sending to %s port %d", cp, port);
}
/*
* Printer is connected to an RS232 port on this host
*/
static void
opentty()
{
register int i;
int resp, port;
for (i = 1; ; i = i < 32 ? i << 1 : i) {
pfd = open(LP, RW ? O_RDWR : O_WRONLY);
if (pfd >= 0) {
delay(500);
break;
}
if (errno == ENOENT) {
syslog(LOG_ERR, "%s: %m", LP);
exit(1);
}
if (i == 1)
pstatus("waiting for %s to become ready (offline ?)",
printer);
sleep(i);
}
if (isatty(pfd))
setty();
pstatus("%s is ready and printing", printer);
}
/*
* Printer is on a remote host
*/
static void
openrem()
{
register int i, n;
int resp, port;
for (i = 1; ; i = i < 256 ? i << 1 : i) {
resp = -1;
pfd = getport(RM, 0);
if (pfd >= 0) {
(void) sprintf(line, "\2%s\n", RP);
n = strlen(line);
if (write(pfd, line, n) == n &&
(resp = response()) == '\0')
break;
(void) close(pfd);
}
if (i == 1) {
if (resp < 0)
pstatus("waiting for %s to come up", RM);
else {
pstatus("waiting for queue to be enabled on %s",
RM);
i = 256;
}
}
sleep(i);
}
pstatus("sending to %s", RM);
}
struct bauds {
int baud;
int speed;
@ -1352,7 +1450,7 @@ setty()
#include <varargs.h>
#endif
void
static void
#if __STDC__
pstatus(const char *msg, ...)
#else