122426Sdist /* 222426Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 542801Sbostic * %sccs.include.redist.c% 622426Sdist */ 722426Sdist 813952Ssam #ifndef lint 9*55470Sbostic static char sccsid[] = "@(#)common.c 5.8 (Berkeley) 07/21/92"; 1034203Sbostic #endif /* not lint */ 1113952Ssam 12*55470Sbostic #include <sys/param.h> 13*55470Sbostic #include <sys/stat.h> 14*55470Sbostic 15*55470Sbostic #include <sys/socket.h> 16*55470Sbostic #include <netinet/in.h> 17*55470Sbostic #include <netdb.h> 18*55470Sbostic 19*55470Sbostic #include <dirent.h> 20*55470Sbostic #include <errno.h> 21*55470Sbostic #include <unistd.h> 22*55470Sbostic #include <stdlib.h> 23*55470Sbostic #include <stdio.h> 24*55470Sbostic #include <string.h> 25*55470Sbostic #include "lp.h" 26*55470Sbostic 2712117Sralph /* 2812117Sralph * Routines and data common to all the line printer functions. 2912117Sralph */ 3012117Sralph 3112117Sralph int DU; /* daeomon user-id */ 3212117Sralph int MX; /* maximum number of blocks to copy */ 3313170Sralph int MC; /* maximum number of copies allowed */ 3412117Sralph char *LP; /* line printer device name */ 3512117Sralph char *RM; /* remote machine name */ 3612117Sralph char *RP; /* remote printer name */ 3712117Sralph char *LO; /* lock file name */ 3812117Sralph char *ST; /* status file name */ 3912117Sralph char *SD; /* spool directory */ 4012117Sralph char *AF; /* accounting file */ 4112117Sralph char *LF; /* log file for error messages */ 4212117Sralph char *OF; /* name of output filter (created once) */ 4312117Sralph char *IF; /* name of input filter (created per job) */ 4412433Sralph char *RF; /* name of fortran text filter (per job) */ 4512117Sralph char *TF; /* name of troff filter (per job) */ 4613235Sralph char *NF; /* name of ditroff filter (per job) */ 4712117Sralph char *DF; /* name of tex filter (per job) */ 4812117Sralph char *GF; /* name of graph(1G) filter (per job) */ 4912117Sralph char *VF; /* name of vplot filter (per job) */ 5012117Sralph char *CF; /* name of cifplot filter (per job) */ 5112117Sralph char *PF; /* name of vrast filter (per job) */ 5212117Sralph char *FF; /* form feed string */ 5312117Sralph char *TR; /* trailer string to be output when Q empties */ 5413170Sralph short SC; /* suppress multiple copies */ 5512117Sralph short SF; /* suppress FF on each print job */ 5612117Sralph short SH; /* suppress header page */ 5712117Sralph short SB; /* short banner instead of normal header */ 5818128Sralph short HL; /* print header last */ 5912117Sralph short RW; /* open LP for reading and writing */ 6012117Sralph short PW; /* page width */ 6112117Sralph short PL; /* page length */ 6212433Sralph short PX; /* page width in pixels */ 6312433Sralph short PY; /* page length in pixels */ 6412117Sralph short BR; /* baud rate if lp is a tty */ 6513170Sralph int FC; /* flags to clear if lp is a tty */ 6613170Sralph int FS; /* flags to set if lp is a tty */ 6713170Sralph int XC; /* flags to clear for local mode */ 6813170Sralph int XS; /* flags to set for local mode */ 6912433Sralph short RS; /* restricted to those with local accounts */ 7012117Sralph 7112117Sralph char line[BUFSIZ]; 7212117Sralph char pbuf[BUFSIZ/2]; /* buffer for printcap strings */ 7312117Sralph char *bp = pbuf; /* pointer into pbuf for pgetent() */ 7412117Sralph char *name; /* program name */ 7512117Sralph char *printer; /* printer name */ 76*55470Sbostic /* host machine name */ 77*55470Sbostic char host[MAXHOSTNAMELEN]; 7812117Sralph char *from = host; /* client's machine name */ 7938736Stef int sendtorem; /* are we sending to a remote? */ 8012117Sralph 81*55470Sbostic static int compar __P((const void *, const void *)); 82*55470Sbostic 8312117Sralph /* 8412117Sralph * Create a connection to the remote printer server. 8512117Sralph * Most of this code comes from rcmd.c. 8612117Sralph */ 87*55470Sbostic int 8812528Sralph getport(rhost) 8912528Sralph char *rhost; 9012117Sralph { 9112117Sralph struct hostent *hp; 9212117Sralph struct servent *sp; 9312117Sralph struct sockaddr_in sin; 9412117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1; 9512874Sralph int err; 9612117Sralph 9712117Sralph /* 9812117Sralph * Get the host address and port number to connect to. 9912117Sralph */ 10012528Sralph if (rhost == NULL) 10112117Sralph fatal("no remote host to connect to"); 10212528Sralph hp = gethostbyname(rhost); 10312117Sralph if (hp == NULL) 10412528Sralph fatal("unknown host %s", rhost); 10512117Sralph sp = getservbyname("printer", "tcp"); 10612117Sralph if (sp == NULL) 10712117Sralph fatal("printer/tcp: unknown service"); 10812117Sralph bzero((char *)&sin, sizeof(sin)); 10912117Sralph bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 11012117Sralph sin.sin_family = hp->h_addrtype; 11112117Sralph sin.sin_port = sp->s_port; 11212117Sralph 11312117Sralph /* 11412117Sralph * Try connecting to the server. 11512117Sralph */ 11612117Sralph retry: 11712117Sralph s = rresvport(&lport); 11812117Sralph if (s < 0) 11912117Sralph return(-1); 12046910Sbostic if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 12112874Sralph err = errno; 12212874Sralph (void) close(s); 12312874Sralph errno = err; 12412117Sralph if (errno == EADDRINUSE) { 12512117Sralph lport--; 12612117Sralph goto retry; 12712117Sralph } 12812117Sralph if (errno == ECONNREFUSED && timo <= 16) { 12912117Sralph sleep(timo); 13012117Sralph timo *= 2; 13112117Sralph goto retry; 13212117Sralph } 13312117Sralph return(-1); 13412117Sralph } 13512117Sralph return(s); 13612117Sralph } 13712117Sralph 13812117Sralph /* 13912117Sralph * Getline reads a line from the control file cfp, removes tabs, converts 14012117Sralph * new-line to null and leaves it in line. 14112117Sralph * Returns 0 at EOF or the number of characters read. 14212117Sralph */ 143*55470Sbostic int 14412117Sralph getline(cfp) 14512117Sralph FILE *cfp; 14612117Sralph { 14712117Sralph register int linel = 0; 14812117Sralph register char *lp = line; 14912117Sralph register c; 15012117Sralph 15112117Sralph while ((c = getc(cfp)) != '\n') { 15212117Sralph if (c == EOF) 15312117Sralph return(0); 15412117Sralph if (c == '\t') { 15512117Sralph do { 15612117Sralph *lp++ = ' '; 15712117Sralph linel++; 15812117Sralph } while ((linel & 07) != 0); 15912117Sralph continue; 16012117Sralph } 16112117Sralph *lp++ = c; 16212117Sralph linel++; 16312117Sralph } 16412117Sralph *lp++ = '\0'; 16512117Sralph return(linel); 16612117Sralph } 16712117Sralph 16812117Sralph /* 16912117Sralph * Scan the current directory and make a list of daemon files sorted by 17012117Sralph * creation time. 17112117Sralph * Return the number of entries and a pointer to the list. 17212117Sralph */ 173*55470Sbostic int 17412117Sralph getq(namelist) 17512117Sralph struct queue *(*namelist[]); 17612117Sralph { 177*55470Sbostic register struct dirent *d; 17812117Sralph register struct queue *q, **queue; 17912117Sralph register int nitems; 18012117Sralph struct stat stbuf; 18112117Sralph DIR *dirp; 18246910Sbostic int arraysz; 18312117Sralph 18413170Sralph if ((dirp = opendir(SD)) == NULL) 18512117Sralph return(-1); 18612117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0) 18712874Sralph goto errdone; 18812117Sralph 18912117Sralph /* 19012117Sralph * Estimate the array size by taking the size of the directory file 19112117Sralph * and dividing it by a multiple of the minimum size entry. 19212117Sralph */ 19312117Sralph arraysz = (stbuf.st_size / 24); 19412117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 19512117Sralph if (queue == NULL) 19612874Sralph goto errdone; 19712117Sralph 19812117Sralph nitems = 0; 19912117Sralph while ((d = readdir(dirp)) != NULL) { 20012117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 20112117Sralph continue; /* daemon control files only */ 20212117Sralph if (stat(d->d_name, &stbuf) < 0) 20312117Sralph continue; /* Doesn't exist */ 20412117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 20512117Sralph if (q == NULL) 20612874Sralph goto errdone; 20712117Sralph q->q_time = stbuf.st_mtime; 20812117Sralph strcpy(q->q_name, d->d_name); 20912117Sralph /* 21012117Sralph * Check to make sure the array has space left and 21112117Sralph * realloc the maximum size. 21212117Sralph */ 21312117Sralph if (++nitems > arraysz) { 21412117Sralph queue = (struct queue **)realloc((char *)queue, 21512117Sralph (stbuf.st_size/12) * sizeof(struct queue *)); 21612117Sralph if (queue == NULL) 21712874Sralph goto errdone; 21812117Sralph } 21912117Sralph queue[nitems-1] = q; 22012117Sralph } 22112117Sralph closedir(dirp); 22212117Sralph if (nitems) 22312117Sralph qsort(queue, nitems, sizeof(struct queue *), compar); 22412117Sralph *namelist = queue; 22512117Sralph return(nitems); 22612874Sralph 22712874Sralph errdone: 22812874Sralph closedir(dirp); 22912874Sralph return(-1); 23012117Sralph } 23112117Sralph 23212117Sralph /* 23312117Sralph * Compare modification times. 23412117Sralph */ 235*55470Sbostic static int 23612117Sralph compar(p1, p2) 237*55470Sbostic const void *p1, *p2; 23812117Sralph { 239*55470Sbostic if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time) 24012117Sralph return(-1); 241*55470Sbostic if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time) 24212117Sralph return(1); 24312117Sralph return(0); 24412117Sralph } 24512117Sralph 24638736Stef /* 24738736Stef * Figure out whether the local machine is the same 24838736Stef * as the remote machine (RM) entry (if it exists). 24938736Stef */ 25038736Stef char * 25138736Stef checkremote() 25238736Stef { 25338736Stef char name[MAXHOSTNAMELEN]; 25438736Stef register struct hostent *hp; 25538736Stef static char errbuf[128]; 25638736Stef 25738736Stef sendtorem = 0; /* assume printer is local */ 25838736Stef if (RM != (char *)NULL) { 25938736Stef /* get the official name of the local host */ 26038736Stef gethostname(name, sizeof(name)); 26138736Stef name[sizeof(name)-1] = '\0'; 26238736Stef hp = gethostbyname(name); 26338736Stef if (hp == (struct hostent *) NULL) { 264*55470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 26538736Stef "unable to get official name for local machine %s", 26638736Stef name); 26738736Stef return errbuf; 26838736Stef } else (void) strcpy(name, hp->h_name); 26938736Stef 27038736Stef /* get the official name of RM */ 27138736Stef hp = gethostbyname(RM); 27238736Stef if (hp == (struct hostent *) NULL) { 273*55470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 27438736Stef "unable to get official name for remote machine %s", 27538736Stef RM); 27638736Stef return errbuf; 27738736Stef } 27838736Stef 27938736Stef /* 28038736Stef * if the two hosts are not the same, 28138736Stef * then the printer must be remote. 28238736Stef */ 28338736Stef if (strcmp(name, hp->h_name) != 0) 28438736Stef sendtorem = 1; 28538736Stef } 28638736Stef return (char *)0; 28738736Stef } 28838736Stef 289*55470Sbostic #if __STDC__ 290*55470Sbostic #include <stdarg.h> 291*55470Sbostic #else 292*55470Sbostic #include <varargs.h> 293*55470Sbostic #endif 294*55470Sbostic 295*55470Sbostic void 296*55470Sbostic #if __STDC__ 297*55470Sbostic fatal(const char *msg, ...) 298*55470Sbostic #else 299*55470Sbostic fatal(msg, va_alist) 30012117Sralph char *msg; 301*55470Sbostic va_dcl 302*55470Sbostic #endif 30312117Sralph { 304*55470Sbostic va_list ap; 305*55470Sbostic #if __STDC__ 306*55470Sbostic va_start(ap, msg); 307*55470Sbostic #else 308*55470Sbostic va_start(ap); 309*55470Sbostic #endif 31012117Sralph if (from != host) 311*55470Sbostic (void)printf("%s: ", host); 312*55470Sbostic (void)printf("%s: ", name); 31312117Sralph if (printer) 314*55470Sbostic (void)printf("%s: ", printer); 315*55470Sbostic (void)vprintf(msg, ap); 316*55470Sbostic va_end(ap); 317*55470Sbostic (void)putchar('\n'); 31812117Sralph exit(1); 31912117Sralph } 320