122426Sdist /* 222426Sdist * Copyright (c) 1983 Regents of the University of California. 334203Sbostic * All rights reserved. 434203Sbostic * 5*56248Selan * %sccs.include.redist.c% 622426Sdist */ 722426Sdist 813952Ssam #ifndef lint 9*56248Selan static char sccsid[] = "@(#)common.c 5.10 (Berkeley) 09/15/92"; 1034203Sbostic #endif /* not lint */ 1113952Ssam 1255470Sbostic #include <sys/param.h> 1355470Sbostic #include <sys/stat.h> 1455470Sbostic 1555470Sbostic #include <sys/socket.h> 1655470Sbostic #include <netinet/in.h> 1755470Sbostic #include <netdb.h> 1855470Sbostic 1955470Sbostic #include <dirent.h> 2055470Sbostic #include <errno.h> 2155470Sbostic #include <unistd.h> 2255470Sbostic #include <stdlib.h> 2355470Sbostic #include <stdio.h> 2455470Sbostic #include <string.h> 2555470Sbostic #include "lp.h" 2656120Selan #include "pathnames.h" 2755470Sbostic 2812117Sralph /* 2912117Sralph * Routines and data common to all the line printer functions. 3012117Sralph */ 3112117Sralph 3256120Selan char *AF; /* accounting file */ 3356120Selan long BR; /* baud rate if lp is a tty */ 3456120Selan char *CF; /* name of cifplot filter (per job) */ 3556120Selan char *DF; /* name of tex filter (per job) */ 3656120Selan long DU; /* daeomon user-id */ 3756120Selan long FC; /* flags to clear if lp is a tty */ 3856120Selan char *FF; /* form feed string */ 3956120Selan long FS; /* flags to set if lp is a tty */ 4056120Selan char *GF; /* name of graph(1G) filter (per job) */ 4156120Selan long HL; /* print header last */ 4256120Selan char *IF; /* name of input filter (created per job) */ 4356120Selan char *LF; /* log file for error messages */ 4456120Selan char *LO; /* lock file name */ 4512117Sralph char *LP; /* line printer device name */ 4656120Selan long MC; /* maximum number of copies allowed */ 4756120Selan long MX; /* maximum number of blocks to copy */ 4856120Selan char *NF; /* name of ditroff filter (per job) */ 4956120Selan char *OF; /* name of output filter (created once) */ 5056120Selan char *PF; /* name of vrast filter (per job) */ 5156120Selan long PL; /* page length */ 5256120Selan long PW; /* page width */ 5356120Selan long PX; /* page width in pixels */ 5456120Selan long PY; /* page length in pixels */ 5556120Selan char *RF; /* name of fortran text filter (per job) */ 5656120Selan char *RG; /* resricted group */ 5712117Sralph char *RM; /* remote machine name */ 5812117Sralph char *RP; /* remote printer name */ 5956120Selan long RS; /* restricted to those with local accounts */ 6056120Selan long RW; /* open LP for reading and writing */ 6156120Selan long SB; /* short banner instead of normal header */ 6256120Selan long SC; /* suppress multiple copies */ 6356120Selan char *SD; /* spool directory */ 6456120Selan long SF; /* suppress FF on each print job */ 6556120Selan long SH; /* suppress header page */ 6612117Sralph char *ST; /* status file name */ 6712117Sralph char *TF; /* name of troff filter (per job) */ 6856120Selan char *TR; /* trailer string to be output when Q empties */ 6912117Sralph char *VF; /* name of vplot filter (per job) */ 7056120Selan long XC; /* flags to clear for local mode */ 7156120Selan long XS; /* flags to set for local mode */ 7212117Sralph 7312117Sralph char line[BUFSIZ]; 7456120Selan char *bp; /* pointer into printcap buffer. */ 7512117Sralph char *name; /* program name */ 7612117Sralph char *printer; /* printer name */ 7755470Sbostic /* host machine name */ 7855470Sbostic char host[MAXHOSTNAMELEN]; 7912117Sralph char *from = host; /* client's machine name */ 8038736Stef int sendtorem; /* are we sending to a remote? */ 8156120Selan char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; 8212117Sralph 8355470Sbostic static int compar __P((const void *, const void *)); 8455470Sbostic 8512117Sralph /* 8612117Sralph * Create a connection to the remote printer server. 8712117Sralph * Most of this code comes from rcmd.c. 8812117Sralph */ 8955470Sbostic int 9012528Sralph getport(rhost) 9112528Sralph char *rhost; 9212117Sralph { 9312117Sralph struct hostent *hp; 9412117Sralph struct servent *sp; 9512117Sralph struct sockaddr_in sin; 9612117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1; 9712874Sralph int err; 9812117Sralph 9912117Sralph /* 10012117Sralph * Get the host address and port number to connect to. 10112117Sralph */ 10212528Sralph if (rhost == NULL) 10312117Sralph fatal("no remote host to connect to"); 10412528Sralph hp = gethostbyname(rhost); 10512117Sralph if (hp == NULL) 10612528Sralph fatal("unknown host %s", rhost); 10712117Sralph sp = getservbyname("printer", "tcp"); 10812117Sralph if (sp == NULL) 10912117Sralph fatal("printer/tcp: unknown service"); 11012117Sralph bzero((char *)&sin, sizeof(sin)); 11112117Sralph bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 11212117Sralph sin.sin_family = hp->h_addrtype; 11312117Sralph sin.sin_port = sp->s_port; 11412117Sralph 11512117Sralph /* 11612117Sralph * Try connecting to the server. 11712117Sralph */ 11812117Sralph retry: 11912117Sralph s = rresvport(&lport); 12012117Sralph if (s < 0) 12112117Sralph return(-1); 12246910Sbostic if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 12312874Sralph err = errno; 12412874Sralph (void) close(s); 12512874Sralph errno = err; 12612117Sralph if (errno == EADDRINUSE) { 12712117Sralph lport--; 12812117Sralph goto retry; 12912117Sralph } 13012117Sralph if (errno == ECONNREFUSED && timo <= 16) { 13112117Sralph sleep(timo); 13212117Sralph timo *= 2; 13312117Sralph goto retry; 13412117Sralph } 13512117Sralph return(-1); 13612117Sralph } 13712117Sralph return(s); 13812117Sralph } 13912117Sralph 14012117Sralph /* 14112117Sralph * Getline reads a line from the control file cfp, removes tabs, converts 14212117Sralph * new-line to null and leaves it in line. 14312117Sralph * Returns 0 at EOF or the number of characters read. 14412117Sralph */ 14555470Sbostic int 14612117Sralph getline(cfp) 14712117Sralph FILE *cfp; 14812117Sralph { 14912117Sralph register int linel = 0; 15012117Sralph register char *lp = line; 15112117Sralph register c; 15212117Sralph 15312117Sralph while ((c = getc(cfp)) != '\n') { 15412117Sralph if (c == EOF) 15512117Sralph return(0); 15612117Sralph if (c == '\t') { 15712117Sralph do { 15812117Sralph *lp++ = ' '; 15912117Sralph linel++; 16012117Sralph } while ((linel & 07) != 0); 16112117Sralph continue; 16212117Sralph } 16312117Sralph *lp++ = c; 16412117Sralph linel++; 16512117Sralph } 16612117Sralph *lp++ = '\0'; 16712117Sralph return(linel); 16812117Sralph } 16912117Sralph 17012117Sralph /* 17112117Sralph * Scan the current directory and make a list of daemon files sorted by 17212117Sralph * creation time. 17312117Sralph * Return the number of entries and a pointer to the list. 17412117Sralph */ 17555470Sbostic int 17612117Sralph getq(namelist) 17712117Sralph struct queue *(*namelist[]); 17812117Sralph { 17955470Sbostic register struct dirent *d; 18012117Sralph register struct queue *q, **queue; 18112117Sralph register int nitems; 18212117Sralph struct stat stbuf; 18312117Sralph DIR *dirp; 18446910Sbostic int arraysz; 18512117Sralph 18613170Sralph if ((dirp = opendir(SD)) == NULL) 18712117Sralph return(-1); 18812117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0) 18912874Sralph goto errdone; 19012117Sralph 19112117Sralph /* 19212117Sralph * Estimate the array size by taking the size of the directory file 19312117Sralph * and dividing it by a multiple of the minimum size entry. 19412117Sralph */ 19512117Sralph arraysz = (stbuf.st_size / 24); 19612117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 19712117Sralph if (queue == NULL) 19812874Sralph goto errdone; 19912117Sralph 20012117Sralph nitems = 0; 20112117Sralph while ((d = readdir(dirp)) != NULL) { 20212117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 20312117Sralph continue; /* daemon control files only */ 20412117Sralph if (stat(d->d_name, &stbuf) < 0) 20512117Sralph continue; /* Doesn't exist */ 20612117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 20712117Sralph if (q == NULL) 20812874Sralph goto errdone; 20912117Sralph q->q_time = stbuf.st_mtime; 21012117Sralph strcpy(q->q_name, d->d_name); 21112117Sralph /* 21212117Sralph * Check to make sure the array has space left and 21312117Sralph * realloc the maximum size. 21412117Sralph */ 21512117Sralph if (++nitems > arraysz) { 21612117Sralph queue = (struct queue **)realloc((char *)queue, 21712117Sralph (stbuf.st_size/12) * sizeof(struct queue *)); 21812117Sralph if (queue == NULL) 21912874Sralph goto errdone; 22012117Sralph } 22112117Sralph queue[nitems-1] = q; 22212117Sralph } 22312117Sralph closedir(dirp); 22412117Sralph if (nitems) 22512117Sralph qsort(queue, nitems, sizeof(struct queue *), compar); 22612117Sralph *namelist = queue; 22712117Sralph return(nitems); 22812874Sralph 22912874Sralph errdone: 23012874Sralph closedir(dirp); 23112874Sralph return(-1); 23212117Sralph } 23312117Sralph 23412117Sralph /* 23512117Sralph * Compare modification times. 23612117Sralph */ 23755470Sbostic static int 23812117Sralph compar(p1, p2) 23955470Sbostic const void *p1, *p2; 24012117Sralph { 24155470Sbostic if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time) 24212117Sralph return(-1); 24355470Sbostic if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time) 24412117Sralph return(1); 24512117Sralph return(0); 24612117Sralph } 24712117Sralph 24838736Stef /* 24938736Stef * Figure out whether the local machine is the same 25038736Stef * as the remote machine (RM) entry (if it exists). 25138736Stef */ 25238736Stef char * 25338736Stef checkremote() 25438736Stef { 25538736Stef char name[MAXHOSTNAMELEN]; 25638736Stef register struct hostent *hp; 25738736Stef static char errbuf[128]; 25838736Stef 25938736Stef sendtorem = 0; /* assume printer is local */ 26038736Stef if (RM != (char *)NULL) { 26138736Stef /* get the official name of the local host */ 26238736Stef gethostname(name, sizeof(name)); 26338736Stef name[sizeof(name)-1] = '\0'; 26438736Stef hp = gethostbyname(name); 26538736Stef if (hp == (struct hostent *) NULL) { 26655470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 26738736Stef "unable to get official name for local machine %s", 26838736Stef name); 26938736Stef return errbuf; 27038736Stef } else (void) strcpy(name, hp->h_name); 27138736Stef 27238736Stef /* get the official name of RM */ 27338736Stef hp = gethostbyname(RM); 27438736Stef if (hp == (struct hostent *) NULL) { 27555470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 27638736Stef "unable to get official name for remote machine %s", 27738736Stef RM); 27838736Stef return errbuf; 27938736Stef } 28038736Stef 28138736Stef /* 28238736Stef * if the two hosts are not the same, 28338736Stef * then the printer must be remote. 28438736Stef */ 28538736Stef if (strcmp(name, hp->h_name) != 0) 28638736Stef sendtorem = 1; 28738736Stef } 28838736Stef return (char *)0; 28938736Stef } 29038736Stef 29155470Sbostic #if __STDC__ 29255470Sbostic #include <stdarg.h> 29355470Sbostic #else 29455470Sbostic #include <varargs.h> 29555470Sbostic #endif 29655470Sbostic 29755470Sbostic void 29855470Sbostic #if __STDC__ 29955470Sbostic fatal(const char *msg, ...) 30055470Sbostic #else 30155470Sbostic fatal(msg, va_alist) 30212117Sralph char *msg; 30355470Sbostic va_dcl 30455470Sbostic #endif 30512117Sralph { 30655470Sbostic va_list ap; 30755470Sbostic #if __STDC__ 30855470Sbostic va_start(ap, msg); 30955470Sbostic #else 31055470Sbostic va_start(ap); 31155470Sbostic #endif 31212117Sralph if (from != host) 31355470Sbostic (void)printf("%s: ", host); 31455470Sbostic (void)printf("%s: ", name); 31512117Sralph if (printer) 31655470Sbostic (void)printf("%s: ", printer); 31755470Sbostic (void)vprintf(msg, ap); 31855470Sbostic va_end(ap); 31955470Sbostic (void)putchar('\n'); 32012117Sralph exit(1); 32112117Sralph } 322