1*22426Sdist /* 2*22426Sdist * Copyright (c) 1983 Regents of the University of California. 3*22426Sdist * All rights reserved. The Berkeley software License Agreement 4*22426Sdist * specifies the terms and conditions for redistribution. 5*22426Sdist */ 6*22426Sdist 713952Ssam #ifndef lint 8*22426Sdist static char sccsid[] = "@(#)common.c 5.1 (Berkeley) 06/06/85"; 9*22426Sdist #endif not lint 1013952Ssam 1112117Sralph /* 1212117Sralph * Routines and data common to all the line printer functions. 1312117Sralph */ 1412117Sralph 1512117Sralph #include "lp.h" 1612117Sralph 1712117Sralph int DU; /* daeomon user-id */ 1812117Sralph int MX; /* maximum number of blocks to copy */ 1913170Sralph int MC; /* maximum number of copies allowed */ 2012117Sralph char *LP; /* line printer device name */ 2112117Sralph char *RM; /* remote machine name */ 2212117Sralph char *RP; /* remote printer name */ 2312117Sralph char *LO; /* lock file name */ 2412117Sralph char *ST; /* status file name */ 2512117Sralph char *SD; /* spool directory */ 2612117Sralph char *AF; /* accounting file */ 2712117Sralph char *LF; /* log file for error messages */ 2812117Sralph char *OF; /* name of output filter (created once) */ 2912117Sralph char *IF; /* name of input filter (created per job) */ 3012433Sralph char *RF; /* name of fortran text filter (per job) */ 3112117Sralph char *TF; /* name of troff filter (per job) */ 3213235Sralph char *NF; /* name of ditroff filter (per job) */ 3312117Sralph char *DF; /* name of tex filter (per job) */ 3412117Sralph char *GF; /* name of graph(1G) filter (per job) */ 3512117Sralph char *VF; /* name of vplot filter (per job) */ 3612117Sralph char *CF; /* name of cifplot filter (per job) */ 3712117Sralph char *PF; /* name of vrast filter (per job) */ 3812117Sralph char *FF; /* form feed string */ 3912117Sralph char *TR; /* trailer string to be output when Q empties */ 4013170Sralph short SC; /* suppress multiple copies */ 4112117Sralph short SF; /* suppress FF on each print job */ 4212117Sralph short SH; /* suppress header page */ 4312117Sralph short SB; /* short banner instead of normal header */ 4418128Sralph short HL; /* print header last */ 4512117Sralph short RW; /* open LP for reading and writing */ 4612117Sralph short PW; /* page width */ 4712117Sralph short PL; /* page length */ 4812433Sralph short PX; /* page width in pixels */ 4912433Sralph short PY; /* page length in pixels */ 5012117Sralph short BR; /* baud rate if lp is a tty */ 5113170Sralph int FC; /* flags to clear if lp is a tty */ 5213170Sralph int FS; /* flags to set if lp is a tty */ 5313170Sralph int XC; /* flags to clear for local mode */ 5413170Sralph int XS; /* flags to set for local mode */ 5512433Sralph short RS; /* restricted to those with local accounts */ 5612117Sralph 5712117Sralph char line[BUFSIZ]; 5812117Sralph char pbuf[BUFSIZ/2]; /* buffer for printcap strings */ 5912117Sralph char *bp = pbuf; /* pointer into pbuf for pgetent() */ 6012117Sralph char *name; /* program name */ 6112117Sralph char *printer; /* printer name */ 6212117Sralph char host[32]; /* host machine name */ 6312117Sralph char *from = host; /* client's machine name */ 6412117Sralph 6512117Sralph /* 6612117Sralph * Create a connection to the remote printer server. 6712117Sralph * Most of this code comes from rcmd.c. 6812117Sralph */ 6912528Sralph getport(rhost) 7012528Sralph char *rhost; 7112117Sralph { 7212117Sralph struct hostent *hp; 7312117Sralph struct servent *sp; 7412117Sralph struct sockaddr_in sin; 7512117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1; 7612874Sralph int err; 7712117Sralph 7812117Sralph /* 7912117Sralph * Get the host address and port number to connect to. 8012117Sralph */ 8112528Sralph if (rhost == NULL) 8212117Sralph fatal("no remote host to connect to"); 8312528Sralph hp = gethostbyname(rhost); 8412117Sralph if (hp == NULL) 8512528Sralph fatal("unknown host %s", rhost); 8612117Sralph sp = getservbyname("printer", "tcp"); 8712117Sralph if (sp == NULL) 8812117Sralph fatal("printer/tcp: unknown service"); 8912117Sralph bzero((char *)&sin, sizeof(sin)); 9012117Sralph bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 9112117Sralph sin.sin_family = hp->h_addrtype; 9212117Sralph sin.sin_port = sp->s_port; 9312117Sralph 9412117Sralph /* 9512117Sralph * Try connecting to the server. 9612117Sralph */ 9712117Sralph retry: 9812117Sralph s = rresvport(&lport); 9912117Sralph if (s < 0) 10012117Sralph return(-1); 10112117Sralph if (connect(s, (caddr_t)&sin, sizeof(sin), 0) < 0) { 10212874Sralph err = errno; 10312874Sralph (void) close(s); 10412874Sralph errno = err; 10512117Sralph if (errno == EADDRINUSE) { 10612117Sralph lport--; 10712117Sralph goto retry; 10812117Sralph } 10912117Sralph if (errno == ECONNREFUSED && timo <= 16) { 11012117Sralph sleep(timo); 11112117Sralph timo *= 2; 11212117Sralph goto retry; 11312117Sralph } 11412117Sralph return(-1); 11512117Sralph } 11612117Sralph return(s); 11712117Sralph } 11812117Sralph 11912117Sralph rresvport(alport) 12012117Sralph int *alport; 12112117Sralph { 12212117Sralph struct sockaddr_in sin; 12312117Sralph int s; 12412117Sralph 12512117Sralph sin.sin_family = AF_INET; 12612117Sralph sin.sin_addr.s_addr = 0; 12712117Sralph s = socket(AF_INET, SOCK_STREAM, 0); 12812117Sralph if (s < 0) 12912117Sralph return(-1); 13012874Sralph for (; *alport > IPPORT_RESERVED/2; (*alport)--) { 13112117Sralph sin.sin_port = htons((u_short) *alport); 13212117Sralph if (bind(s, (caddr_t)&sin, sizeof(sin), 0) >= 0) 13312117Sralph return(s); 13412117Sralph if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) 13512874Sralph break; 13612117Sralph } 13712874Sralph (void) close(s); 13812874Sralph return(-1); 13912117Sralph } 14012117Sralph 14112117Sralph /* 14212117Sralph * Getline reads a line from the control file cfp, removes tabs, converts 14312117Sralph * new-line to null and leaves it in line. 14412117Sralph * Returns 0 at EOF or the number of characters read. 14512117Sralph */ 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 */ 17512117Sralph getq(namelist) 17612117Sralph struct queue *(*namelist[]); 17712117Sralph { 17812117Sralph register struct direct *d; 17912117Sralph register struct queue *q, **queue; 18012117Sralph register int nitems; 18112117Sralph struct stat stbuf; 18212117Sralph int arraysz, compar(); 18312117Sralph DIR *dirp; 18412117Sralph 18513170Sralph if ((dirp = opendir(SD)) == NULL) 18612117Sralph return(-1); 18712117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0) 18812874Sralph goto errdone; 18912117Sralph 19012117Sralph /* 19112117Sralph * Estimate the array size by taking the size of the directory file 19212117Sralph * and dividing it by a multiple of the minimum size entry. 19312117Sralph */ 19412117Sralph arraysz = (stbuf.st_size / 24); 19512117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 19612117Sralph if (queue == NULL) 19712874Sralph goto errdone; 19812117Sralph 19912117Sralph nitems = 0; 20012117Sralph while ((d = readdir(dirp)) != NULL) { 20112117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 20212117Sralph continue; /* daemon control files only */ 20312117Sralph if (stat(d->d_name, &stbuf) < 0) 20412117Sralph continue; /* Doesn't exist */ 20512117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 20612117Sralph if (q == NULL) 20712874Sralph goto errdone; 20812117Sralph q->q_time = stbuf.st_mtime; 20912117Sralph strcpy(q->q_name, d->d_name); 21012117Sralph /* 21112117Sralph * Check to make sure the array has space left and 21212117Sralph * realloc the maximum size. 21312117Sralph */ 21412117Sralph if (++nitems > arraysz) { 21512117Sralph queue = (struct queue **)realloc((char *)queue, 21612117Sralph (stbuf.st_size/12) * sizeof(struct queue *)); 21712117Sralph if (queue == NULL) 21812874Sralph goto errdone; 21912117Sralph } 22012117Sralph queue[nitems-1] = q; 22112117Sralph } 22212117Sralph closedir(dirp); 22312117Sralph if (nitems) 22412117Sralph qsort(queue, nitems, sizeof(struct queue *), compar); 22512117Sralph *namelist = queue; 22612117Sralph return(nitems); 22712874Sralph 22812874Sralph errdone: 22912874Sralph closedir(dirp); 23012874Sralph return(-1); 23112117Sralph } 23212117Sralph 23312117Sralph /* 23412117Sralph * Compare modification times. 23512117Sralph */ 23612117Sralph static 23712117Sralph compar(p1, p2) 23812117Sralph register struct queue **p1, **p2; 23912117Sralph { 24012117Sralph if ((*p1)->q_time < (*p2)->q_time) 24112117Sralph return(-1); 24212117Sralph if ((*p1)->q_time > (*p2)->q_time) 24312117Sralph return(1); 24412117Sralph return(0); 24512117Sralph } 24612117Sralph 24712117Sralph /*VARARGS1*/ 24812117Sralph fatal(msg, a1, a2, a3) 24912117Sralph char *msg; 25012117Sralph { 25112117Sralph if (from != host) 25212117Sralph printf("%s: ", host); 25312117Sralph printf("%s: ", name); 25412117Sralph if (printer) 25512117Sralph printf("%s: ", printer); 25612117Sralph printf(msg, a1, a2, a3); 25712117Sralph putchar('\n'); 25812117Sralph exit(1); 25912117Sralph } 260