122426Sdist /* 222426Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*56120Selan * Redistribution and use in source and binary forms, with or without 6*56120Selan * modification, are permitted provided that the following conditions 7*56120Selan * are met: 8*56120Selan * 1. Redistributions of source code must retain the above copyright 9*56120Selan * notice, this list of conditions and the following disclaimer. 10*56120Selan * 2. Redistributions in binary form must reproduce the above copyright 11*56120Selan * notice, this list of conditions and the following disclaimer in the 12*56120Selan * documentation and/or other materials provided with the distribution. 13*56120Selan * 3. All advertising materials mentioning features or use of this software 14*56120Selan * must display the following acknowledgement: 15*56120Selan * This product includes software developed by the University of 16*56120Selan * California, Berkeley and its contributors. 17*56120Selan * 4. Neither the name of the University nor the names of its contributors 18*56120Selan * may be used to endorse or promote products derived from this software 19*56120Selan * without specific prior written permission. 20*56120Selan * 21*56120Selan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22*56120Selan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*56120Selan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*56120Selan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25*56120Selan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*56120Selan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*56120Selan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*56120Selan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*56120Selan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*56120Selan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*56120Selan * SUCH DAMAGE. 3222426Sdist */ 3322426Sdist 3413952Ssam #ifndef lint 35*56120Selan static char sccsid[] = "@(#)common.c 5.9 (Berkeley) 8/6/92"; 3634203Sbostic #endif /* not lint */ 3713952Ssam 3855470Sbostic #include <sys/param.h> 3955470Sbostic #include <sys/stat.h> 4055470Sbostic 4155470Sbostic #include <sys/socket.h> 4255470Sbostic #include <netinet/in.h> 4355470Sbostic #include <netdb.h> 4455470Sbostic 4555470Sbostic #include <dirent.h> 4655470Sbostic #include <errno.h> 4755470Sbostic #include <unistd.h> 4855470Sbostic #include <stdlib.h> 4955470Sbostic #include <stdio.h> 5055470Sbostic #include <string.h> 5155470Sbostic #include "lp.h" 52*56120Selan #include "pathnames.h" 5355470Sbostic 5412117Sralph /* 5512117Sralph * Routines and data common to all the line printer functions. 5612117Sralph */ 5712117Sralph 58*56120Selan char *AF; /* accounting file */ 59*56120Selan long BR; /* baud rate if lp is a tty */ 60*56120Selan char *CF; /* name of cifplot filter (per job) */ 61*56120Selan char *DF; /* name of tex filter (per job) */ 62*56120Selan long DU; /* daeomon user-id */ 63*56120Selan long FC; /* flags to clear if lp is a tty */ 64*56120Selan char *FF; /* form feed string */ 65*56120Selan long FS; /* flags to set if lp is a tty */ 66*56120Selan char *GF; /* name of graph(1G) filter (per job) */ 67*56120Selan long HL; /* print header last */ 68*56120Selan char *IF; /* name of input filter (created per job) */ 69*56120Selan char *LF; /* log file for error messages */ 70*56120Selan char *LO; /* lock file name */ 7112117Sralph char *LP; /* line printer device name */ 72*56120Selan long MC; /* maximum number of copies allowed */ 73*56120Selan long MX; /* maximum number of blocks to copy */ 74*56120Selan char *NF; /* name of ditroff filter (per job) */ 75*56120Selan char *OF; /* name of output filter (created once) */ 76*56120Selan char *PF; /* name of vrast filter (per job) */ 77*56120Selan long PL; /* page length */ 78*56120Selan long PW; /* page width */ 79*56120Selan long PX; /* page width in pixels */ 80*56120Selan long PY; /* page length in pixels */ 81*56120Selan char *RF; /* name of fortran text filter (per job) */ 82*56120Selan char *RG; /* resricted group */ 8312117Sralph char *RM; /* remote machine name */ 8412117Sralph char *RP; /* remote printer name */ 85*56120Selan long RS; /* restricted to those with local accounts */ 86*56120Selan long RW; /* open LP for reading and writing */ 87*56120Selan long SB; /* short banner instead of normal header */ 88*56120Selan long SC; /* suppress multiple copies */ 89*56120Selan char *SD; /* spool directory */ 90*56120Selan long SF; /* suppress FF on each print job */ 91*56120Selan long SH; /* suppress header page */ 9212117Sralph char *ST; /* status file name */ 9312117Sralph char *TF; /* name of troff filter (per job) */ 94*56120Selan char *TR; /* trailer string to be output when Q empties */ 9512117Sralph char *VF; /* name of vplot filter (per job) */ 96*56120Selan long XC; /* flags to clear for local mode */ 97*56120Selan long XS; /* flags to set for local mode */ 9812117Sralph 9912117Sralph char line[BUFSIZ]; 100*56120Selan char *bp; /* pointer into printcap buffer. */ 10112117Sralph char *name; /* program name */ 10212117Sralph char *printer; /* printer name */ 10355470Sbostic /* host machine name */ 10455470Sbostic char host[MAXHOSTNAMELEN]; 10512117Sralph char *from = host; /* client's machine name */ 10638736Stef int sendtorem; /* are we sending to a remote? */ 107*56120Selan char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; 10812117Sralph 10955470Sbostic static int compar __P((const void *, const void *)); 11055470Sbostic 11112117Sralph /* 11212117Sralph * Create a connection to the remote printer server. 11312117Sralph * Most of this code comes from rcmd.c. 11412117Sralph */ 11555470Sbostic int 11612528Sralph getport(rhost) 11712528Sralph char *rhost; 11812117Sralph { 11912117Sralph struct hostent *hp; 12012117Sralph struct servent *sp; 12112117Sralph struct sockaddr_in sin; 12212117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1; 12312874Sralph int err; 12412117Sralph 12512117Sralph /* 12612117Sralph * Get the host address and port number to connect to. 12712117Sralph */ 12812528Sralph if (rhost == NULL) 12912117Sralph fatal("no remote host to connect to"); 13012528Sralph hp = gethostbyname(rhost); 13112117Sralph if (hp == NULL) 13212528Sralph fatal("unknown host %s", rhost); 13312117Sralph sp = getservbyname("printer", "tcp"); 13412117Sralph if (sp == NULL) 13512117Sralph fatal("printer/tcp: unknown service"); 13612117Sralph bzero((char *)&sin, sizeof(sin)); 13712117Sralph bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 13812117Sralph sin.sin_family = hp->h_addrtype; 13912117Sralph sin.sin_port = sp->s_port; 14012117Sralph 14112117Sralph /* 14212117Sralph * Try connecting to the server. 14312117Sralph */ 14412117Sralph retry: 14512117Sralph s = rresvport(&lport); 14612117Sralph if (s < 0) 14712117Sralph return(-1); 14846910Sbostic if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 14912874Sralph err = errno; 15012874Sralph (void) close(s); 15112874Sralph errno = err; 15212117Sralph if (errno == EADDRINUSE) { 15312117Sralph lport--; 15412117Sralph goto retry; 15512117Sralph } 15612117Sralph if (errno == ECONNREFUSED && timo <= 16) { 15712117Sralph sleep(timo); 15812117Sralph timo *= 2; 15912117Sralph goto retry; 16012117Sralph } 16112117Sralph return(-1); 16212117Sralph } 16312117Sralph return(s); 16412117Sralph } 16512117Sralph 16612117Sralph /* 16712117Sralph * Getline reads a line from the control file cfp, removes tabs, converts 16812117Sralph * new-line to null and leaves it in line. 16912117Sralph * Returns 0 at EOF or the number of characters read. 17012117Sralph */ 17155470Sbostic int 17212117Sralph getline(cfp) 17312117Sralph FILE *cfp; 17412117Sralph { 17512117Sralph register int linel = 0; 17612117Sralph register char *lp = line; 17712117Sralph register c; 17812117Sralph 17912117Sralph while ((c = getc(cfp)) != '\n') { 18012117Sralph if (c == EOF) 18112117Sralph return(0); 18212117Sralph if (c == '\t') { 18312117Sralph do { 18412117Sralph *lp++ = ' '; 18512117Sralph linel++; 18612117Sralph } while ((linel & 07) != 0); 18712117Sralph continue; 18812117Sralph } 18912117Sralph *lp++ = c; 19012117Sralph linel++; 19112117Sralph } 19212117Sralph *lp++ = '\0'; 19312117Sralph return(linel); 19412117Sralph } 19512117Sralph 19612117Sralph /* 19712117Sralph * Scan the current directory and make a list of daemon files sorted by 19812117Sralph * creation time. 19912117Sralph * Return the number of entries and a pointer to the list. 20012117Sralph */ 20155470Sbostic int 20212117Sralph getq(namelist) 20312117Sralph struct queue *(*namelist[]); 20412117Sralph { 20555470Sbostic register struct dirent *d; 20612117Sralph register struct queue *q, **queue; 20712117Sralph register int nitems; 20812117Sralph struct stat stbuf; 20912117Sralph DIR *dirp; 21046910Sbostic int arraysz; 21112117Sralph 21213170Sralph if ((dirp = opendir(SD)) == NULL) 21312117Sralph return(-1); 21412117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0) 21512874Sralph goto errdone; 21612117Sralph 21712117Sralph /* 21812117Sralph * Estimate the array size by taking the size of the directory file 21912117Sralph * and dividing it by a multiple of the minimum size entry. 22012117Sralph */ 22112117Sralph arraysz = (stbuf.st_size / 24); 22212117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 22312117Sralph if (queue == NULL) 22412874Sralph goto errdone; 22512117Sralph 22612117Sralph nitems = 0; 22712117Sralph while ((d = readdir(dirp)) != NULL) { 22812117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 22912117Sralph continue; /* daemon control files only */ 23012117Sralph if (stat(d->d_name, &stbuf) < 0) 23112117Sralph continue; /* Doesn't exist */ 23212117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 23312117Sralph if (q == NULL) 23412874Sralph goto errdone; 23512117Sralph q->q_time = stbuf.st_mtime; 23612117Sralph strcpy(q->q_name, d->d_name); 23712117Sralph /* 23812117Sralph * Check to make sure the array has space left and 23912117Sralph * realloc the maximum size. 24012117Sralph */ 24112117Sralph if (++nitems > arraysz) { 24212117Sralph queue = (struct queue **)realloc((char *)queue, 24312117Sralph (stbuf.st_size/12) * sizeof(struct queue *)); 24412117Sralph if (queue == NULL) 24512874Sralph goto errdone; 24612117Sralph } 24712117Sralph queue[nitems-1] = q; 24812117Sralph } 24912117Sralph closedir(dirp); 25012117Sralph if (nitems) 25112117Sralph qsort(queue, nitems, sizeof(struct queue *), compar); 25212117Sralph *namelist = queue; 25312117Sralph return(nitems); 25412874Sralph 25512874Sralph errdone: 25612874Sralph closedir(dirp); 25712874Sralph return(-1); 25812117Sralph } 25912117Sralph 26012117Sralph /* 26112117Sralph * Compare modification times. 26212117Sralph */ 26355470Sbostic static int 26412117Sralph compar(p1, p2) 26555470Sbostic const void *p1, *p2; 26612117Sralph { 26755470Sbostic if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time) 26812117Sralph return(-1); 26955470Sbostic if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time) 27012117Sralph return(1); 27112117Sralph return(0); 27212117Sralph } 27312117Sralph 27438736Stef /* 27538736Stef * Figure out whether the local machine is the same 27638736Stef * as the remote machine (RM) entry (if it exists). 27738736Stef */ 27838736Stef char * 27938736Stef checkremote() 28038736Stef { 28138736Stef char name[MAXHOSTNAMELEN]; 28238736Stef register struct hostent *hp; 28338736Stef static char errbuf[128]; 28438736Stef 28538736Stef sendtorem = 0; /* assume printer is local */ 28638736Stef if (RM != (char *)NULL) { 28738736Stef /* get the official name of the local host */ 28838736Stef gethostname(name, sizeof(name)); 28938736Stef name[sizeof(name)-1] = '\0'; 29038736Stef hp = gethostbyname(name); 29138736Stef if (hp == (struct hostent *) NULL) { 29255470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 29338736Stef "unable to get official name for local machine %s", 29438736Stef name); 29538736Stef return errbuf; 29638736Stef } else (void) strcpy(name, hp->h_name); 29738736Stef 29838736Stef /* get the official name of RM */ 29938736Stef hp = gethostbyname(RM); 30038736Stef if (hp == (struct hostent *) NULL) { 30155470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 30238736Stef "unable to get official name for remote machine %s", 30338736Stef RM); 30438736Stef return errbuf; 30538736Stef } 30638736Stef 30738736Stef /* 30838736Stef * if the two hosts are not the same, 30938736Stef * then the printer must be remote. 31038736Stef */ 31138736Stef if (strcmp(name, hp->h_name) != 0) 31238736Stef sendtorem = 1; 31338736Stef } 31438736Stef return (char *)0; 31538736Stef } 31638736Stef 31755470Sbostic #if __STDC__ 31855470Sbostic #include <stdarg.h> 31955470Sbostic #else 32055470Sbostic #include <varargs.h> 32155470Sbostic #endif 32255470Sbostic 32355470Sbostic void 32455470Sbostic #if __STDC__ 32555470Sbostic fatal(const char *msg, ...) 32655470Sbostic #else 32755470Sbostic fatal(msg, va_alist) 32812117Sralph char *msg; 32955470Sbostic va_dcl 33055470Sbostic #endif 33112117Sralph { 33255470Sbostic va_list ap; 33355470Sbostic #if __STDC__ 33455470Sbostic va_start(ap, msg); 33555470Sbostic #else 33655470Sbostic va_start(ap); 33755470Sbostic #endif 33812117Sralph if (from != host) 33955470Sbostic (void)printf("%s: ", host); 34055470Sbostic (void)printf("%s: ", name); 34112117Sralph if (printer) 34255470Sbostic (void)printf("%s: ", printer); 34355470Sbostic (void)vprintf(msg, ap); 34455470Sbostic va_end(ap); 34555470Sbostic (void)putchar('\n'); 34612117Sralph exit(1); 34712117Sralph } 348