1*12433Sralph /* common.c 4.2 83/05/13 */ 212117Sralph /* 312117Sralph * Routines and data common to all the line printer functions. 412117Sralph */ 512117Sralph 612117Sralph #include "lp.h" 712117Sralph 812117Sralph int DU; /* daeomon user-id */ 912117Sralph int MX; /* maximum number of blocks to copy */ 1012117Sralph char *LP; /* line printer device name */ 1112117Sralph char *RM; /* remote machine name */ 1212117Sralph char *RP; /* remote printer name */ 1312117Sralph char *LO; /* lock file name */ 1412117Sralph char *ST; /* status file name */ 1512117Sralph char *SD; /* spool directory */ 1612117Sralph char *AF; /* accounting file */ 1712117Sralph char *LF; /* log file for error messages */ 1812117Sralph char *OF; /* name of output filter (created once) */ 1912117Sralph char *IF; /* name of input filter (created per job) */ 20*12433Sralph char *RF; /* name of fortran text filter (per job) */ 2112117Sralph char *TF; /* name of troff filter (per job) */ 2212117Sralph char *DF; /* name of tex filter (per job) */ 2312117Sralph char *GF; /* name of graph(1G) filter (per job) */ 2412117Sralph char *VF; /* name of vplot filter (per job) */ 2512117Sralph char *CF; /* name of cifplot filter (per job) */ 2612117Sralph char *PF; /* name of vrast filter (per job) */ 2712117Sralph char *FF; /* form feed string */ 2812117Sralph char *TR; /* trailer string to be output when Q empties */ 2912117Sralph short SF; /* suppress FF on each print job */ 3012117Sralph short SH; /* suppress header page */ 3112117Sralph short SB; /* short banner instead of normal header */ 3212117Sralph short RW; /* open LP for reading and writing */ 3312117Sralph short PW; /* page width */ 3412117Sralph short PL; /* page length */ 35*12433Sralph short PX; /* page width in pixels */ 36*12433Sralph short PY; /* page length in pixels */ 3712117Sralph short BR; /* baud rate if lp is a tty */ 3812117Sralph short FC; /* flags to clear if lp is a tty */ 3912117Sralph short FS; /* flags to set if lp is a tty */ 4012117Sralph short XC; /* flags to clear for local mode */ 4112117Sralph short XS; /* flags to set for local mode */ 42*12433Sralph short RS; /* restricted to those with local accounts */ 4312117Sralph 4412117Sralph char line[BUFSIZ]; 4512117Sralph char pbuf[BUFSIZ/2]; /* buffer for printcap strings */ 4612117Sralph char *bp = pbuf; /* pointer into pbuf for pgetent() */ 4712117Sralph char *name; /* program name */ 4812117Sralph char *printer; /* printer name */ 4912117Sralph char host[32]; /* host machine name */ 5012117Sralph char *from = host; /* client's machine name */ 5112117Sralph 5212117Sralph /* 5312117Sralph * Create a connection to the remote printer server. 5412117Sralph * Most of this code comes from rcmd.c. 5512117Sralph */ 5612117Sralph getport() 5712117Sralph { 5812117Sralph struct hostent *hp; 5912117Sralph struct servent *sp; 6012117Sralph struct sockaddr_in sin; 6112117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1; 6212117Sralph 6312117Sralph /* 6412117Sralph * Get the host address and port number to connect to. 6512117Sralph */ 6612117Sralph if (RM == NULL) 6712117Sralph fatal("no remote host to connect to"); 6812117Sralph hp = gethostbyname(RM); 6912117Sralph if (hp == NULL) 7012117Sralph fatal("unknown host %s", RM); 7112117Sralph sp = getservbyname("printer", "tcp"); 7212117Sralph if (sp == NULL) 7312117Sralph fatal("printer/tcp: unknown service"); 7412117Sralph bzero((char *)&sin, sizeof(sin)); 7512117Sralph bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 7612117Sralph sin.sin_family = hp->h_addrtype; 7712117Sralph sin.sin_port = sp->s_port; 7812117Sralph 7912117Sralph /* 8012117Sralph * Try connecting to the server. 8112117Sralph */ 8212117Sralph retry: 8312117Sralph s = rresvport(&lport); 8412117Sralph if (s < 0) 8512117Sralph return(-1); 8612117Sralph if (connect(s, (caddr_t)&sin, sizeof(sin), 0) < 0) { 8712117Sralph if (errno == EADDRINUSE) { 8812117Sralph close(s); 8912117Sralph lport--; 9012117Sralph goto retry; 9112117Sralph } 9212117Sralph if (errno == ECONNREFUSED && timo <= 16) { 9312117Sralph (void) close(s); 9412117Sralph sleep(timo); 9512117Sralph timo *= 2; 9612117Sralph goto retry; 9712117Sralph } 9812117Sralph return(-1); 9912117Sralph } 10012117Sralph return(s); 10112117Sralph } 10212117Sralph 10312117Sralph rresvport(alport) 10412117Sralph int *alport; 10512117Sralph { 10612117Sralph struct sockaddr_in sin; 10712117Sralph int s; 10812117Sralph 10912117Sralph sin.sin_family = AF_INET; 11012117Sralph sin.sin_addr.s_addr = 0; 11112117Sralph s = socket(AF_INET, SOCK_STREAM, 0); 11212117Sralph if (s < 0) 11312117Sralph return(-1); 11412117Sralph for (;;) { 11512117Sralph sin.sin_port = htons((u_short) *alport); 11612117Sralph if (bind(s, (caddr_t)&sin, sizeof(sin), 0) >= 0) 11712117Sralph return(s); 11812117Sralph if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) 11912117Sralph return(-1); 12012117Sralph (*alport)--; 12112117Sralph if (*alport == IPPORT_RESERVED/2) { 12212117Sralph printf("%s: All ports in use\n", name); 12312117Sralph return(-1); 12412117Sralph } 12512117Sralph } 12612117Sralph } 12712117Sralph 12812117Sralph /* 12912117Sralph * Getline reads a line from the control file cfp, removes tabs, converts 13012117Sralph * new-line to null and leaves it in line. 13112117Sralph * Returns 0 at EOF or the number of characters read. 13212117Sralph */ 13312117Sralph getline(cfp) 13412117Sralph FILE *cfp; 13512117Sralph { 13612117Sralph register int linel = 0; 13712117Sralph register char *lp = line; 13812117Sralph register c; 13912117Sralph 14012117Sralph while ((c = getc(cfp)) != '\n') { 14112117Sralph if (c == EOF) 14212117Sralph return(0); 14312117Sralph if (c == '\t') { 14412117Sralph do { 14512117Sralph *lp++ = ' '; 14612117Sralph linel++; 14712117Sralph } while ((linel & 07) != 0); 14812117Sralph continue; 14912117Sralph } 15012117Sralph *lp++ = c; 15112117Sralph linel++; 15212117Sralph } 15312117Sralph *lp++ = '\0'; 15412117Sralph return(linel); 15512117Sralph } 15612117Sralph 15712117Sralph /* 15812117Sralph * Scan the current directory and make a list of daemon files sorted by 15912117Sralph * creation time. 16012117Sralph * Return the number of entries and a pointer to the list. 16112117Sralph */ 16212117Sralph getq(namelist) 16312117Sralph struct queue *(*namelist[]); 16412117Sralph { 16512117Sralph register struct direct *d; 16612117Sralph register struct queue *q, **queue; 16712117Sralph register int nitems; 16812117Sralph struct stat stbuf; 16912117Sralph int arraysz, compar(); 17012117Sralph DIR *dirp; 17112117Sralph 17212117Sralph if ((dirp = opendir(".")) == NULL) 17312117Sralph return(-1); 17412117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0) 17512117Sralph return(-1); 17612117Sralph 17712117Sralph /* 17812117Sralph * Estimate the array size by taking the size of the directory file 17912117Sralph * and dividing it by a multiple of the minimum size entry. 18012117Sralph */ 18112117Sralph arraysz = (stbuf.st_size / 24); 18212117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 18312117Sralph if (queue == NULL) 18412117Sralph return(-1); 18512117Sralph 18612117Sralph nitems = 0; 18712117Sralph while ((d = readdir(dirp)) != NULL) { 18812117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 18912117Sralph continue; /* daemon control files only */ 19012117Sralph if (stat(d->d_name, &stbuf) < 0) 19112117Sralph continue; /* Doesn't exist */ 19212117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 19312117Sralph if (q == NULL) 19412117Sralph return(-1); 19512117Sralph q->q_time = stbuf.st_mtime; 19612117Sralph strcpy(q->q_name, d->d_name); 19712117Sralph /* 19812117Sralph * Check to make sure the array has space left and 19912117Sralph * realloc the maximum size. 20012117Sralph */ 20112117Sralph if (++nitems > arraysz) { 20212117Sralph queue = (struct queue **)realloc((char *)queue, 20312117Sralph (stbuf.st_size/12) * sizeof(struct queue *)); 20412117Sralph if (queue == NULL) 20512117Sralph return(-1); 20612117Sralph } 20712117Sralph queue[nitems-1] = q; 20812117Sralph } 20912117Sralph closedir(dirp); 21012117Sralph if (nitems) 21112117Sralph qsort(queue, nitems, sizeof(struct queue *), compar); 21212117Sralph *namelist = queue; 21312117Sralph return(nitems); 21412117Sralph } 21512117Sralph 21612117Sralph /* 21712117Sralph * Compare modification times. 21812117Sralph */ 21912117Sralph static 22012117Sralph compar(p1, p2) 22112117Sralph register struct queue **p1, **p2; 22212117Sralph { 22312117Sralph if ((*p1)->q_time < (*p2)->q_time) 22412117Sralph return(-1); 22512117Sralph if ((*p1)->q_time > (*p2)->q_time) 22612117Sralph return(1); 22712117Sralph return(0); 22812117Sralph } 22912117Sralph 23012117Sralph /*VARARGS1*/ 23112117Sralph fatal(msg, a1, a2, a3) 23212117Sralph char *msg; 23312117Sralph { 23412117Sralph if (from != host) 23512117Sralph printf("%s: ", host); 23612117Sralph printf("%s: ", name); 23712117Sralph if (printer) 23812117Sralph printf("%s: ", printer); 23912117Sralph printf(msg, a1, a2, a3); 24012117Sralph putchar('\n'); 24112117Sralph exit(1); 24212117Sralph } 24312117Sralph 24412117Sralph fatalerror(msg) 24512117Sralph char *msg; 24612117Sralph { 24712117Sralph extern int sys_nerr; 24812117Sralph extern char *sys_errlist[]; 24912117Sralph 25012117Sralph printf("%s: ", name); 25112117Sralph if (*msg) 25212117Sralph printf("%s: ", msg); 25312117Sralph fputs(errno < sys_nerr ? sys_errlist[errno] : "Unknown error" , stdout); 25412117Sralph putchar('\n'); 25512117Sralph exit(1); 25612117Sralph } 257