122426Sdist /*
261840Sbostic * Copyright (c) 1983, 1993
361840Sbostic * The Regents of the University of California. All rights reserved.
465779Sbostic * (c) UNIX System Laboratories, Inc.
565779Sbostic * All or some portions of this file are derived from material licensed
665779Sbostic * to the University of California by American Telephone and Telegraph
765779Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with
865779Sbostic * the permission of UNIX System Laboratories, Inc.
934203Sbostic *
1056248Selan * %sccs.include.redist.c%
1122426Sdist */
1222426Sdist
1313952Ssam #ifndef lint
14*69060Stef static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 04/28/95";
1534203Sbostic #endif /* not lint */
1613952Ssam
1755470Sbostic #include <sys/param.h>
1855470Sbostic #include <sys/stat.h>
19*69060Stef #include <sys/time.h>
2055470Sbostic
2155470Sbostic #include <sys/socket.h>
2255470Sbostic #include <netinet/in.h>
2355470Sbostic #include <netdb.h>
2455470Sbostic
2555470Sbostic #include <dirent.h>
2655470Sbostic #include <errno.h>
2755470Sbostic #include <unistd.h>
2855470Sbostic #include <stdlib.h>
2955470Sbostic #include <stdio.h>
3055470Sbostic #include <string.h>
3155470Sbostic #include "lp.h"
3256120Selan #include "pathnames.h"
3355470Sbostic
3412117Sralph /*
3512117Sralph * Routines and data common to all the line printer functions.
3612117Sralph */
3712117Sralph
3856120Selan char *AF; /* accounting file */
3956120Selan long BR; /* baud rate if lp is a tty */
4056120Selan char *CF; /* name of cifplot filter (per job) */
4156120Selan char *DF; /* name of tex filter (per job) */
4256120Selan long DU; /* daeomon user-id */
4356120Selan long FC; /* flags to clear if lp is a tty */
4456120Selan char *FF; /* form feed string */
4556120Selan long FS; /* flags to set if lp is a tty */
4656120Selan char *GF; /* name of graph(1G) filter (per job) */
4756120Selan long HL; /* print header last */
4856120Selan char *IF; /* name of input filter (created per job) */
4956120Selan char *LF; /* log file for error messages */
5056120Selan char *LO; /* lock file name */
5112117Sralph char *LP; /* line printer device name */
5256120Selan long MC; /* maximum number of copies allowed */
5356120Selan long MX; /* maximum number of blocks to copy */
5456120Selan char *NF; /* name of ditroff filter (per job) */
5556120Selan char *OF; /* name of output filter (created once) */
5656120Selan char *PF; /* name of vrast filter (per job) */
5756120Selan long PL; /* page length */
5856120Selan long PW; /* page width */
5956120Selan long PX; /* page width in pixels */
6056120Selan long PY; /* page length in pixels */
6156120Selan char *RF; /* name of fortran text filter (per job) */
6256120Selan char *RG; /* resricted group */
6312117Sralph char *RM; /* remote machine name */
6412117Sralph char *RP; /* remote printer name */
6556120Selan long RS; /* restricted to those with local accounts */
6656120Selan long RW; /* open LP for reading and writing */
6756120Selan long SB; /* short banner instead of normal header */
6856120Selan long SC; /* suppress multiple copies */
6956120Selan char *SD; /* spool directory */
7056120Selan long SF; /* suppress FF on each print job */
7156120Selan long SH; /* suppress header page */
7212117Sralph char *ST; /* status file name */
7312117Sralph char *TF; /* name of troff filter (per job) */
7456120Selan char *TR; /* trailer string to be output when Q empties */
7512117Sralph char *VF; /* name of vplot filter (per job) */
7656120Selan long XC; /* flags to clear for local mode */
7756120Selan long XS; /* flags to set for local mode */
7812117Sralph
7912117Sralph char line[BUFSIZ];
8056120Selan char *bp; /* pointer into printcap buffer. */
8112117Sralph char *name; /* program name */
8212117Sralph char *printer; /* printer name */
8355470Sbostic /* host machine name */
8455470Sbostic char host[MAXHOSTNAMELEN];
8512117Sralph char *from = host; /* client's machine name */
8669009Stef int remote; /* true if sending files to a remote host */
8756120Selan char *printcapdb[2] = { _PATH_PRINTCAP, 0 };
8812117Sralph
8955470Sbostic static int compar __P((const void *, const void *));
9055470Sbostic
9112117Sralph /*
9269009Stef * Create a TCP connection to host "rhost" at port "rport".
9369009Stef * If rport == 0, then use the printer service port.
9412117Sralph * Most of this code comes from rcmd.c.
9512117Sralph */
9655470Sbostic int
getport(rhost,rport)9769009Stef getport(rhost, rport)
9812528Sralph char *rhost;
9969009Stef int rport;
10012117Sralph {
10112117Sralph struct hostent *hp;
10212117Sralph struct servent *sp;
10312117Sralph struct sockaddr_in sin;
10412117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1;
10512874Sralph int err;
10612117Sralph
10712117Sralph /*
10812117Sralph * Get the host address and port number to connect to.
10912117Sralph */
11012528Sralph if (rhost == NULL)
11112117Sralph fatal("no remote host to connect to");
11212117Sralph bzero((char *)&sin, sizeof(sin));
11369009Stef sin.sin_addr.s_addr = inet_addr(rhost);
11469009Stef if (sin.sin_addr.s_addr != INADDR_NONE)
11569009Stef sin.sin_family = AF_INET;
11669009Stef else {
11769009Stef hp = gethostbyname(rhost);
11869009Stef if (hp == NULL)
11969009Stef fatal("unknown host %s", rhost);
12069009Stef bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
12169009Stef sin.sin_family = hp->h_addrtype;
12269009Stef }
12369009Stef if (rport == 0) {
12469009Stef sp = getservbyname("printer", "tcp");
12569009Stef if (sp == NULL)
12669009Stef fatal("printer/tcp: unknown service");
12769009Stef sin.sin_port = sp->s_port;
12869009Stef } else
12969009Stef sin.sin_port = htons(rport);
13012117Sralph
13112117Sralph /*
13212117Sralph * Try connecting to the server.
13312117Sralph */
13412117Sralph retry:
13512117Sralph s = rresvport(&lport);
13612117Sralph if (s < 0)
13712117Sralph return(-1);
13846910Sbostic if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
13912874Sralph err = errno;
14012874Sralph (void) close(s);
14112874Sralph errno = err;
14212117Sralph if (errno == EADDRINUSE) {
14312117Sralph lport--;
14412117Sralph goto retry;
14512117Sralph }
14612117Sralph if (errno == ECONNREFUSED && timo <= 16) {
14712117Sralph sleep(timo);
14812117Sralph timo *= 2;
14912117Sralph goto retry;
15012117Sralph }
15112117Sralph return(-1);
15212117Sralph }
15312117Sralph return(s);
15412117Sralph }
15512117Sralph
15612117Sralph /*
15712117Sralph * Getline reads a line from the control file cfp, removes tabs, converts
15812117Sralph * new-line to null and leaves it in line.
15912117Sralph * Returns 0 at EOF or the number of characters read.
16012117Sralph */
16155470Sbostic int
getline(cfp)16212117Sralph getline(cfp)
16312117Sralph FILE *cfp;
16412117Sralph {
16512117Sralph register int linel = 0;
16612117Sralph register char *lp = line;
16712117Sralph register c;
16812117Sralph
16912117Sralph while ((c = getc(cfp)) != '\n') {
17012117Sralph if (c == EOF)
17112117Sralph return(0);
17212117Sralph if (c == '\t') {
17312117Sralph do {
17412117Sralph *lp++ = ' ';
17512117Sralph linel++;
17612117Sralph } while ((linel & 07) != 0);
17712117Sralph continue;
17812117Sralph }
17912117Sralph *lp++ = c;
18012117Sralph linel++;
18112117Sralph }
18212117Sralph *lp++ = '\0';
18312117Sralph return(linel);
18412117Sralph }
18512117Sralph
18612117Sralph /*
18712117Sralph * Scan the current directory and make a list of daemon files sorted by
18812117Sralph * creation time.
18912117Sralph * Return the number of entries and a pointer to the list.
19012117Sralph */
19155470Sbostic int
19212117Sralph getq(namelist)
19312117Sralph struct queue *(*namelist[]);
19412117Sralph {
19555470Sbostic register struct dirent *d;
19612117Sralph register struct queue *q, **queue;
19712117Sralph register int nitems;
19812117Sralph struct stat stbuf;
19912117Sralph DIR *dirp;
20046910Sbostic int arraysz;
20112117Sralph
20213170Sralph if ((dirp = opendir(SD)) == NULL)
20312117Sralph return(-1);
20412117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0)
20512874Sralph goto errdone;
20612117Sralph
20712117Sralph /*
20812117Sralph * Estimate the array size by taking the size of the directory file
20912117Sralph * and dividing it by a multiple of the minimum size entry.
21012117Sralph */
21112117Sralph arraysz = (stbuf.st_size / 24);
21212117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *));
21312117Sralph if (queue == NULL)
21412874Sralph goto errdone;
21512117Sralph
21612117Sralph nitems = 0;
21712117Sralph while ((d = readdir(dirp)) != NULL) {
21812117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f')
21912117Sralph continue; /* daemon control files only */
22012117Sralph if (stat(d->d_name, &stbuf) < 0)
22112117Sralph continue; /* Doesn't exist */
22212117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1);
22312117Sralph if (q == NULL)
22412874Sralph goto errdone;
22512117Sralph q->q_time = stbuf.st_mtime;
22612117Sralph strcpy(q->q_name, d->d_name);
22712117Sralph /*
22812117Sralph * Check to make sure the array has space left and
22912117Sralph * realloc the maximum size.
23012117Sralph */
23112117Sralph if (++nitems > arraysz) {
23268971Stef arraysz *= 2;
23312117Sralph queue = (struct queue **)realloc((char *)queue,
23468971Stef arraysz * sizeof(struct queue *));
23512117Sralph if (queue == NULL)
23612874Sralph goto errdone;
23712117Sralph }
23812117Sralph queue[nitems-1] = q;
23912117Sralph }
24012117Sralph closedir(dirp);
24112117Sralph if (nitems)
24212117Sralph qsort(queue, nitems, sizeof(struct queue *), compar);
24312117Sralph *namelist = queue;
24412117Sralph return(nitems);
24512874Sralph
24612874Sralph errdone:
24712874Sralph closedir(dirp);
24812874Sralph return(-1);
24912117Sralph }
25012117Sralph
25112117Sralph /*
25212117Sralph * Compare modification times.
25312117Sralph */
25455470Sbostic static int
compar(p1,p2)25512117Sralph compar(p1, p2)
25655470Sbostic const void *p1, *p2;
25712117Sralph {
25855470Sbostic if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time)
25912117Sralph return(-1);
26055470Sbostic if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time)
26112117Sralph return(1);
26212117Sralph return(0);
26312117Sralph }
26412117Sralph
26538736Stef /*
26638736Stef * Figure out whether the local machine is the same
26738736Stef * as the remote machine (RM) entry (if it exists).
26838736Stef */
26938736Stef char *
checkremote()27038736Stef checkremote()
27138736Stef {
27238736Stef char name[MAXHOSTNAMELEN];
27338736Stef register struct hostent *hp;
27438736Stef static char errbuf[128];
27538736Stef
27669009Stef remote = 0; /* assume printer is local */
27769009Stef if (RM != NULL) {
27838736Stef /* get the official name of the local host */
27938736Stef gethostname(name, sizeof(name));
28038736Stef name[sizeof(name)-1] = '\0';
28138736Stef hp = gethostbyname(name);
28238736Stef if (hp == (struct hostent *) NULL) {
28355470Sbostic (void) snprintf(errbuf, sizeof(errbuf),
28438736Stef "unable to get official name for local machine %s",
28538736Stef name);
28638736Stef return errbuf;
28738736Stef } else (void) strcpy(name, hp->h_name);
28838736Stef
28938736Stef /* get the official name of RM */
29038736Stef hp = gethostbyname(RM);
29138736Stef if (hp == (struct hostent *) NULL) {
29255470Sbostic (void) snprintf(errbuf, sizeof(errbuf),
29338736Stef "unable to get official name for remote machine %s",
29438736Stef RM);
29538736Stef return errbuf;
29638736Stef }
29738736Stef
29838736Stef /*
29938736Stef * if the two hosts are not the same,
30038736Stef * then the printer must be remote.
30138736Stef */
30268971Stef if (strcasecmp(name, hp->h_name) != 0)
30369009Stef remote = 1;
30438736Stef }
30568971Stef return NULL;
30638736Stef }
30738736Stef
30869009Stef /* sleep n milliseconds */
30969009Stef void
delay(n)31069009Stef delay(n)
31169009Stef {
31269009Stef struct timeval tdelay;
31369009Stef
31469009Stef if (n <= 0 || n > 10000)
31569009Stef fatal("unreasonable delay period (%d)", n);
31669009Stef tdelay.tv_sec = n / 1000;
31769009Stef tdelay.tv_usec = n * 1000 % 1000000;
31869009Stef (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay);
31969009Stef }
32069009Stef
32155470Sbostic #if __STDC__
32255470Sbostic #include <stdarg.h>
32355470Sbostic #else
32455470Sbostic #include <varargs.h>
32555470Sbostic #endif
32655470Sbostic
32755470Sbostic void
32855470Sbostic #if __STDC__
fatal(const char * msg,...)32955470Sbostic fatal(const char *msg, ...)
33055470Sbostic #else
33155470Sbostic fatal(msg, va_alist)
33212117Sralph char *msg;
33355470Sbostic va_dcl
33455470Sbostic #endif
33512117Sralph {
33655470Sbostic va_list ap;
33755470Sbostic #if __STDC__
33855470Sbostic va_start(ap, msg);
33955470Sbostic #else
34055470Sbostic va_start(ap);
34155470Sbostic #endif
34212117Sralph if (from != host)
34355470Sbostic (void)printf("%s: ", host);
34455470Sbostic (void)printf("%s: ", name);
34512117Sralph if (printer)
34655470Sbostic (void)printf("%s: ", printer);
34755470Sbostic (void)vprintf(msg, ap);
34855470Sbostic va_end(ap);
34955470Sbostic (void)putchar('\n');
35012117Sralph exit(1);
35112117Sralph }
352