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*69009Stef static char sccsid[] = "@(#)common.c 8.4 (Berkeley) 04/28/95"; 1534203Sbostic #endif /* not lint */ 1613952Ssam 1755470Sbostic #include <sys/param.h> 1855470Sbostic #include <sys/stat.h> 1955470Sbostic 2055470Sbostic #include <sys/socket.h> 2155470Sbostic #include <netinet/in.h> 2255470Sbostic #include <netdb.h> 2355470Sbostic 2455470Sbostic #include <dirent.h> 2555470Sbostic #include <errno.h> 2655470Sbostic #include <unistd.h> 2755470Sbostic #include <stdlib.h> 2855470Sbostic #include <stdio.h> 2955470Sbostic #include <string.h> 3055470Sbostic #include "lp.h" 3156120Selan #include "pathnames.h" 3255470Sbostic 3312117Sralph /* 3412117Sralph * Routines and data common to all the line printer functions. 3512117Sralph */ 3612117Sralph 3756120Selan char *AF; /* accounting file */ 3856120Selan long BR; /* baud rate if lp is a tty */ 3956120Selan char *CF; /* name of cifplot filter (per job) */ 4056120Selan char *DF; /* name of tex filter (per job) */ 4156120Selan long DU; /* daeomon user-id */ 4256120Selan long FC; /* flags to clear if lp is a tty */ 4356120Selan char *FF; /* form feed string */ 4456120Selan long FS; /* flags to set if lp is a tty */ 4556120Selan char *GF; /* name of graph(1G) filter (per job) */ 4656120Selan long HL; /* print header last */ 4756120Selan char *IF; /* name of input filter (created per job) */ 4856120Selan char *LF; /* log file for error messages */ 4956120Selan char *LO; /* lock file name */ 5012117Sralph char *LP; /* line printer device name */ 5156120Selan long MC; /* maximum number of copies allowed */ 5256120Selan long MX; /* maximum number of blocks to copy */ 5356120Selan char *NF; /* name of ditroff filter (per job) */ 5456120Selan char *OF; /* name of output filter (created once) */ 5556120Selan char *PF; /* name of vrast filter (per job) */ 5656120Selan long PL; /* page length */ 5756120Selan long PW; /* page width */ 5856120Selan long PX; /* page width in pixels */ 5956120Selan long PY; /* page length in pixels */ 6056120Selan char *RF; /* name of fortran text filter (per job) */ 6156120Selan char *RG; /* resricted group */ 6212117Sralph char *RM; /* remote machine name */ 6312117Sralph char *RP; /* remote printer name */ 6456120Selan long RS; /* restricted to those with local accounts */ 6556120Selan long RW; /* open LP for reading and writing */ 6656120Selan long SB; /* short banner instead of normal header */ 6756120Selan long SC; /* suppress multiple copies */ 6856120Selan char *SD; /* spool directory */ 6956120Selan long SF; /* suppress FF on each print job */ 7056120Selan long SH; /* suppress header page */ 7112117Sralph char *ST; /* status file name */ 7212117Sralph char *TF; /* name of troff filter (per job) */ 7356120Selan char *TR; /* trailer string to be output when Q empties */ 7412117Sralph char *VF; /* name of vplot filter (per job) */ 7556120Selan long XC; /* flags to clear for local mode */ 7656120Selan long XS; /* flags to set for local mode */ 7712117Sralph 7812117Sralph char line[BUFSIZ]; 7956120Selan char *bp; /* pointer into printcap buffer. */ 8012117Sralph char *name; /* program name */ 8112117Sralph char *printer; /* printer name */ 8255470Sbostic /* host machine name */ 8355470Sbostic char host[MAXHOSTNAMELEN]; 8412117Sralph char *from = host; /* client's machine name */ 85*69009Stef int remote; /* true if sending files to a remote host */ 8656120Selan char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; 8712117Sralph 8855470Sbostic static int compar __P((const void *, const void *)); 8955470Sbostic 9012117Sralph /* 91*69009Stef * Create a TCP connection to host "rhost" at port "rport". 92*69009Stef * If rport == 0, then use the printer service port. 9312117Sralph * Most of this code comes from rcmd.c. 9412117Sralph */ 9555470Sbostic int 96*69009Stef getport(rhost, rport) 9712528Sralph char *rhost; 98*69009Stef int rport; 9912117Sralph { 10012117Sralph struct hostent *hp; 10112117Sralph struct servent *sp; 10212117Sralph struct sockaddr_in sin; 10312117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1; 10412874Sralph int err; 10512117Sralph 10612117Sralph /* 10712117Sralph * Get the host address and port number to connect to. 10812117Sralph */ 10912528Sralph if (rhost == NULL) 11012117Sralph fatal("no remote host to connect to"); 11112117Sralph bzero((char *)&sin, sizeof(sin)); 112*69009Stef sin.sin_addr.s_addr = inet_addr(rhost); 113*69009Stef if (sin.sin_addr.s_addr != INADDR_NONE) 114*69009Stef sin.sin_family = AF_INET; 115*69009Stef else { 116*69009Stef hp = gethostbyname(rhost); 117*69009Stef if (hp == NULL) 118*69009Stef fatal("unknown host %s", rhost); 119*69009Stef bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 120*69009Stef sin.sin_family = hp->h_addrtype; 121*69009Stef } 122*69009Stef if (rport == 0) { 123*69009Stef sp = getservbyname("printer", "tcp"); 124*69009Stef if (sp == NULL) 125*69009Stef fatal("printer/tcp: unknown service"); 126*69009Stef sin.sin_port = sp->s_port; 127*69009Stef } else 128*69009Stef sin.sin_port = htons(rport); 12912117Sralph 13012117Sralph /* 13112117Sralph * Try connecting to the server. 13212117Sralph */ 13312117Sralph retry: 13412117Sralph s = rresvport(&lport); 13512117Sralph if (s < 0) 13612117Sralph return(-1); 13746910Sbostic if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 13812874Sralph err = errno; 13912874Sralph (void) close(s); 14012874Sralph errno = err; 14112117Sralph if (errno == EADDRINUSE) { 14212117Sralph lport--; 14312117Sralph goto retry; 14412117Sralph } 14512117Sralph if (errno == ECONNREFUSED && timo <= 16) { 14612117Sralph sleep(timo); 14712117Sralph timo *= 2; 14812117Sralph goto retry; 14912117Sralph } 15012117Sralph return(-1); 15112117Sralph } 15212117Sralph return(s); 15312117Sralph } 15412117Sralph 15512117Sralph /* 15612117Sralph * Getline reads a line from the control file cfp, removes tabs, converts 15712117Sralph * new-line to null and leaves it in line. 15812117Sralph * Returns 0 at EOF or the number of characters read. 15912117Sralph */ 16055470Sbostic int 16112117Sralph getline(cfp) 16212117Sralph FILE *cfp; 16312117Sralph { 16412117Sralph register int linel = 0; 16512117Sralph register char *lp = line; 16612117Sralph register c; 16712117Sralph 16812117Sralph while ((c = getc(cfp)) != '\n') { 16912117Sralph if (c == EOF) 17012117Sralph return(0); 17112117Sralph if (c == '\t') { 17212117Sralph do { 17312117Sralph *lp++ = ' '; 17412117Sralph linel++; 17512117Sralph } while ((linel & 07) != 0); 17612117Sralph continue; 17712117Sralph } 17812117Sralph *lp++ = c; 17912117Sralph linel++; 18012117Sralph } 18112117Sralph *lp++ = '\0'; 18212117Sralph return(linel); 18312117Sralph } 18412117Sralph 18512117Sralph /* 18612117Sralph * Scan the current directory and make a list of daemon files sorted by 18712117Sralph * creation time. 18812117Sralph * Return the number of entries and a pointer to the list. 18912117Sralph */ 19055470Sbostic int 19112117Sralph getq(namelist) 19212117Sralph struct queue *(*namelist[]); 19312117Sralph { 19455470Sbostic register struct dirent *d; 19512117Sralph register struct queue *q, **queue; 19612117Sralph register int nitems; 19712117Sralph struct stat stbuf; 19812117Sralph DIR *dirp; 19946910Sbostic int arraysz; 20012117Sralph 20113170Sralph if ((dirp = opendir(SD)) == NULL) 20212117Sralph return(-1); 20312117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0) 20412874Sralph goto errdone; 20512117Sralph 20612117Sralph /* 20712117Sralph * Estimate the array size by taking the size of the directory file 20812117Sralph * and dividing it by a multiple of the minimum size entry. 20912117Sralph */ 21012117Sralph arraysz = (stbuf.st_size / 24); 21112117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 21212117Sralph if (queue == NULL) 21312874Sralph goto errdone; 21412117Sralph 21512117Sralph nitems = 0; 21612117Sralph while ((d = readdir(dirp)) != NULL) { 21712117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 21812117Sralph continue; /* daemon control files only */ 21912117Sralph if (stat(d->d_name, &stbuf) < 0) 22012117Sralph continue; /* Doesn't exist */ 22112117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 22212117Sralph if (q == NULL) 22312874Sralph goto errdone; 22412117Sralph q->q_time = stbuf.st_mtime; 22512117Sralph strcpy(q->q_name, d->d_name); 22612117Sralph /* 22712117Sralph * Check to make sure the array has space left and 22812117Sralph * realloc the maximum size. 22912117Sralph */ 23012117Sralph if (++nitems > arraysz) { 23168971Stef arraysz *= 2; 23212117Sralph queue = (struct queue **)realloc((char *)queue, 23368971Stef arraysz * sizeof(struct queue *)); 23412117Sralph if (queue == NULL) 23512874Sralph goto errdone; 23612117Sralph } 23712117Sralph queue[nitems-1] = q; 23812117Sralph } 23912117Sralph closedir(dirp); 24012117Sralph if (nitems) 24112117Sralph qsort(queue, nitems, sizeof(struct queue *), compar); 24212117Sralph *namelist = queue; 24312117Sralph return(nitems); 24412874Sralph 24512874Sralph errdone: 24612874Sralph closedir(dirp); 24712874Sralph return(-1); 24812117Sralph } 24912117Sralph 25012117Sralph /* 25112117Sralph * Compare modification times. 25212117Sralph */ 25355470Sbostic static int 25412117Sralph compar(p1, p2) 25555470Sbostic const void *p1, *p2; 25612117Sralph { 25755470Sbostic if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time) 25812117Sralph return(-1); 25955470Sbostic if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time) 26012117Sralph return(1); 26112117Sralph return(0); 26212117Sralph } 26312117Sralph 26438736Stef /* 26538736Stef * Figure out whether the local machine is the same 26638736Stef * as the remote machine (RM) entry (if it exists). 26738736Stef */ 26838736Stef char * 26938736Stef checkremote() 27038736Stef { 27138736Stef char name[MAXHOSTNAMELEN]; 27238736Stef register struct hostent *hp; 27338736Stef static char errbuf[128]; 27438736Stef 275*69009Stef remote = 0; /* assume printer is local */ 276*69009Stef if (RM != NULL) { 27738736Stef /* get the official name of the local host */ 27838736Stef gethostname(name, sizeof(name)); 27938736Stef name[sizeof(name)-1] = '\0'; 28038736Stef hp = gethostbyname(name); 28138736Stef if (hp == (struct hostent *) NULL) { 28255470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 28338736Stef "unable to get official name for local machine %s", 28438736Stef name); 28538736Stef return errbuf; 28638736Stef } else (void) strcpy(name, hp->h_name); 28738736Stef 28838736Stef /* get the official name of RM */ 28938736Stef hp = gethostbyname(RM); 29038736Stef if (hp == (struct hostent *) NULL) { 29155470Sbostic (void) snprintf(errbuf, sizeof(errbuf), 29238736Stef "unable to get official name for remote machine %s", 29338736Stef RM); 29438736Stef return errbuf; 29538736Stef } 29638736Stef 29738736Stef /* 29838736Stef * if the two hosts are not the same, 29938736Stef * then the printer must be remote. 30038736Stef */ 30168971Stef if (strcasecmp(name, hp->h_name) != 0) 302*69009Stef remote = 1; 30338736Stef } 30468971Stef return NULL; 30538736Stef } 30638736Stef 307*69009Stef /* sleep n milliseconds */ 308*69009Stef void 309*69009Stef delay(n) 310*69009Stef { 311*69009Stef struct timeval tdelay; 312*69009Stef 313*69009Stef if (n <= 0 || n > 10000) 314*69009Stef fatal("unreasonable delay period (%d)", n); 315*69009Stef tdelay.tv_sec = n / 1000; 316*69009Stef tdelay.tv_usec = n * 1000 % 1000000; 317*69009Stef (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay); 318*69009Stef } 319*69009Stef 32055470Sbostic #if __STDC__ 32155470Sbostic #include <stdarg.h> 32255470Sbostic #else 32355470Sbostic #include <varargs.h> 32455470Sbostic #endif 32555470Sbostic 32655470Sbostic void 32755470Sbostic #if __STDC__ 32855470Sbostic fatal(const char *msg, ...) 32955470Sbostic #else 33055470Sbostic fatal(msg, va_alist) 33112117Sralph char *msg; 33255470Sbostic va_dcl 33355470Sbostic #endif 33412117Sralph { 33555470Sbostic va_list ap; 33655470Sbostic #if __STDC__ 33755470Sbostic va_start(ap, msg); 33855470Sbostic #else 33955470Sbostic va_start(ap); 34055470Sbostic #endif 34112117Sralph if (from != host) 34255470Sbostic (void)printf("%s: ", host); 34355470Sbostic (void)printf("%s: ", name); 34412117Sralph if (printer) 34555470Sbostic (void)printf("%s: ", printer); 34655470Sbostic (void)vprintf(msg, ap); 34755470Sbostic va_end(ap); 34855470Sbostic (void)putchar('\n'); 34912117Sralph exit(1); 35012117Sralph } 351