/* common.c 4.2 83/05/13 */ /* * Routines and data common to all the line printer functions. */ #include "lp.h" int DU; /* daeomon user-id */ int MX; /* maximum number of blocks to copy */ char *LP; /* line printer device name */ char *RM; /* remote machine name */ char *RP; /* remote printer name */ char *LO; /* lock file name */ char *ST; /* status file name */ char *SD; /* spool directory */ char *AF; /* accounting file */ char *LF; /* log file for error messages */ char *OF; /* name of output filter (created once) */ char *IF; /* name of input filter (created per job) */ char *RF; /* name of fortran text filter (per job) */ char *TF; /* name of troff filter (per job) */ char *DF; /* name of tex filter (per job) */ char *GF; /* name of graph(1G) filter (per job) */ char *VF; /* name of vplot filter (per job) */ char *CF; /* name of cifplot filter (per job) */ char *PF; /* name of vrast filter (per job) */ char *FF; /* form feed string */ char *TR; /* trailer string to be output when Q empties */ short SF; /* suppress FF on each print job */ short SH; /* suppress header page */ short SB; /* short banner instead of normal header */ short RW; /* open LP for reading and writing */ short PW; /* page width */ short PL; /* page length */ short PX; /* page width in pixels */ short PY; /* page length in pixels */ short BR; /* baud rate if lp is a tty */ short FC; /* flags to clear if lp is a tty */ short FS; /* flags to set if lp is a tty */ short XC; /* flags to clear for local mode */ short XS; /* flags to set for local mode */ short RS; /* restricted to those with local accounts */ char line[BUFSIZ]; char pbuf[BUFSIZ/2]; /* buffer for printcap strings */ char *bp = pbuf; /* pointer into pbuf for pgetent() */ char *name; /* program name */ char *printer; /* printer name */ char host[32]; /* host machine name */ char *from = host; /* client's machine name */ /* * Create a connection to the remote printer server. * Most of this code comes from rcmd.c. */ getport() { struct hostent *hp; struct servent *sp; struct sockaddr_in sin; int s, timo = 1, lport = IPPORT_RESERVED - 1; /* * Get the host address and port number to connect to. */ if (RM == NULL) fatal("no remote host to connect to"); hp = gethostbyname(RM); if (hp == NULL) fatal("unknown host %s", RM); sp = getservbyname("printer", "tcp"); if (sp == NULL) fatal("printer/tcp: unknown service"); bzero((char *)&sin, sizeof(sin)); bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); sin.sin_family = hp->h_addrtype; sin.sin_port = sp->s_port; /* * Try connecting to the server. */ retry: s = rresvport(&lport); if (s < 0) return(-1); if (connect(s, (caddr_t)&sin, sizeof(sin), 0) < 0) { if (errno == EADDRINUSE) { close(s); lport--; goto retry; } if (errno == ECONNREFUSED && timo <= 16) { (void) close(s); sleep(timo); timo *= 2; goto retry; } return(-1); } return(s); } rresvport(alport) int *alport; { struct sockaddr_in sin; int s; sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) return(-1); for (;;) { sin.sin_port = htons((u_short) *alport); if (bind(s, (caddr_t)&sin, sizeof(sin), 0) >= 0) return(s); if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) return(-1); (*alport)--; if (*alport == IPPORT_RESERVED/2) { printf("%s: All ports in use\n", name); return(-1); } } } /* * Getline reads a line from the control file cfp, removes tabs, converts * new-line to null and leaves it in line. * Returns 0 at EOF or the number of characters read. */ getline(cfp) FILE *cfp; { register int linel = 0; register char *lp = line; register c; while ((c = getc(cfp)) != '\n') { if (c == EOF) return(0); if (c == '\t') { do { *lp++ = ' '; linel++; } while ((linel & 07) != 0); continue; } *lp++ = c; linel++; } *lp++ = '\0'; return(linel); } /* * Scan the current directory and make a list of daemon files sorted by * creation time. * Return the number of entries and a pointer to the list. */ getq(namelist) struct queue *(*namelist[]); { register struct direct *d; register struct queue *q, **queue; register int nitems; struct stat stbuf; int arraysz, compar(); DIR *dirp; if ((dirp = opendir(".")) == NULL) return(-1); if (fstat(dirp->dd_fd, &stbuf) < 0) return(-1); /* * Estimate the array size by taking the size of the directory file * and dividing it by a multiple of the minimum size entry. */ arraysz = (stbuf.st_size / 24); queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); if (queue == NULL) return(-1); nitems = 0; while ((d = readdir(dirp)) != NULL) { if (d->d_name[0] != 'c' || d->d_name[1] != 'f') continue; /* daemon control files only */ if (stat(d->d_name, &stbuf) < 0) continue; /* Doesn't exist */ q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); if (q == NULL) return(-1); q->q_time = stbuf.st_mtime; strcpy(q->q_name, d->d_name); /* * Check to make sure the array has space left and * realloc the maximum size. */ if (++nitems > arraysz) { queue = (struct queue **)realloc((char *)queue, (stbuf.st_size/12) * sizeof(struct queue *)); if (queue == NULL) return(-1); } queue[nitems-1] = q; } closedir(dirp); if (nitems) qsort(queue, nitems, sizeof(struct queue *), compar); *namelist = queue; return(nitems); } /* * Compare modification times. */ static compar(p1, p2) register struct queue **p1, **p2; { if ((*p1)->q_time < (*p2)->q_time) return(-1); if ((*p1)->q_time > (*p2)->q_time) return(1); return(0); } /*VARARGS1*/ fatal(msg, a1, a2, a3) char *msg; { if (from != host) printf("%s: ", host); printf("%s: ", name); if (printer) printf("%s: ", printer); printf(msg, a1, a2, a3); putchar('\n'); exit(1); } fatalerror(msg) char *msg; { extern int sys_nerr; extern char *sys_errlist[]; printf("%s: ", name); if (*msg) printf("%s: ", msg); fputs(errno < sys_nerr ? sys_errlist[errno] : "Unknown error" , stdout); putchar('\n'); exit(1); }