1*12117Sralph /* common.c 4.1 83/04/29 */ 2*12117Sralph /* 3*12117Sralph * Routines and data common to all the line printer functions. 4*12117Sralph */ 5*12117Sralph 6*12117Sralph #include "lp.h" 7*12117Sralph 8*12117Sralph int DU; /* daeomon user-id */ 9*12117Sralph int MX; /* maximum number of blocks to copy */ 10*12117Sralph char *LP; /* line printer device name */ 11*12117Sralph char *RM; /* remote machine name */ 12*12117Sralph char *RP; /* remote printer name */ 13*12117Sralph char *LO; /* lock file name */ 14*12117Sralph char *ST; /* status file name */ 15*12117Sralph char *SD; /* spool directory */ 16*12117Sralph char *AF; /* accounting file */ 17*12117Sralph char *LF; /* log file for error messages */ 18*12117Sralph char *OF; /* name of output filter (created once) */ 19*12117Sralph char *IF; /* name of input filter (created per job) */ 20*12117Sralph char *TF; /* name of troff filter (per job) */ 21*12117Sralph char *DF; /* name of tex filter (per job) */ 22*12117Sralph char *GF; /* name of graph(1G) filter (per job) */ 23*12117Sralph char *VF; /* name of vplot filter (per job) */ 24*12117Sralph char *CF; /* name of cifplot filter (per job) */ 25*12117Sralph char *PF; /* name of vrast filter (per job) */ 26*12117Sralph char *FF; /* form feed string */ 27*12117Sralph char *TR; /* trailer string to be output when Q empties */ 28*12117Sralph short SF; /* suppress FF on each print job */ 29*12117Sralph short SH; /* suppress header page */ 30*12117Sralph short SB; /* short banner instead of normal header */ 31*12117Sralph short RW; /* open LP for reading and writing */ 32*12117Sralph short PW; /* page width */ 33*12117Sralph short PL; /* page length */ 34*12117Sralph short BR; /* baud rate if lp is a tty */ 35*12117Sralph short FC; /* flags to clear if lp is a tty */ 36*12117Sralph short FS; /* flags to set if lp is a tty */ 37*12117Sralph short XC; /* flags to clear for local mode */ 38*12117Sralph short XS; /* flags to set for local mode */ 39*12117Sralph 40*12117Sralph char line[BUFSIZ]; 41*12117Sralph char pbuf[BUFSIZ/2]; /* buffer for printcap strings */ 42*12117Sralph char *bp = pbuf; /* pointer into pbuf for pgetent() */ 43*12117Sralph char *name; /* program name */ 44*12117Sralph char *printer; /* printer name */ 45*12117Sralph char host[32]; /* host machine name */ 46*12117Sralph char *from = host; /* client's machine name */ 47*12117Sralph 48*12117Sralph /* 49*12117Sralph * Create a connection to the remote printer server. 50*12117Sralph * Most of this code comes from rcmd.c. 51*12117Sralph */ 52*12117Sralph getport() 53*12117Sralph { 54*12117Sralph struct hostent *hp; 55*12117Sralph struct servent *sp; 56*12117Sralph struct sockaddr_in sin; 57*12117Sralph int s, timo = 1, lport = IPPORT_RESERVED - 1; 58*12117Sralph 59*12117Sralph /* 60*12117Sralph * Get the host address and port number to connect to. 61*12117Sralph */ 62*12117Sralph if (RM == NULL) 63*12117Sralph fatal("no remote host to connect to"); 64*12117Sralph hp = gethostbyname(RM); 65*12117Sralph if (hp == NULL) 66*12117Sralph fatal("unknown host %s", RM); 67*12117Sralph sp = getservbyname("printer", "tcp"); 68*12117Sralph if (sp == NULL) 69*12117Sralph fatal("printer/tcp: unknown service"); 70*12117Sralph bzero((char *)&sin, sizeof(sin)); 71*12117Sralph bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 72*12117Sralph sin.sin_family = hp->h_addrtype; 73*12117Sralph sin.sin_port = sp->s_port; 74*12117Sralph 75*12117Sralph /* 76*12117Sralph * Try connecting to the server. 77*12117Sralph */ 78*12117Sralph retry: 79*12117Sralph s = rresvport(&lport); 80*12117Sralph if (s < 0) 81*12117Sralph return(-1); 82*12117Sralph if (connect(s, (caddr_t)&sin, sizeof(sin), 0) < 0) { 83*12117Sralph if (errno == EADDRINUSE) { 84*12117Sralph close(s); 85*12117Sralph lport--; 86*12117Sralph goto retry; 87*12117Sralph } 88*12117Sralph if (errno == ECONNREFUSED && timo <= 16) { 89*12117Sralph (void) close(s); 90*12117Sralph sleep(timo); 91*12117Sralph timo *= 2; 92*12117Sralph goto retry; 93*12117Sralph } 94*12117Sralph return(-1); 95*12117Sralph } 96*12117Sralph return(s); 97*12117Sralph } 98*12117Sralph 99*12117Sralph rresvport(alport) 100*12117Sralph int *alport; 101*12117Sralph { 102*12117Sralph struct sockaddr_in sin; 103*12117Sralph int s; 104*12117Sralph 105*12117Sralph sin.sin_family = AF_INET; 106*12117Sralph sin.sin_addr.s_addr = 0; 107*12117Sralph s = socket(AF_INET, SOCK_STREAM, 0); 108*12117Sralph if (s < 0) 109*12117Sralph return(-1); 110*12117Sralph for (;;) { 111*12117Sralph sin.sin_port = htons((u_short) *alport); 112*12117Sralph if (bind(s, (caddr_t)&sin, sizeof(sin), 0) >= 0) 113*12117Sralph return(s); 114*12117Sralph if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) 115*12117Sralph return(-1); 116*12117Sralph (*alport)--; 117*12117Sralph if (*alport == IPPORT_RESERVED/2) { 118*12117Sralph printf("%s: All ports in use\n", name); 119*12117Sralph return(-1); 120*12117Sralph } 121*12117Sralph } 122*12117Sralph } 123*12117Sralph 124*12117Sralph /* 125*12117Sralph * Getline reads a line from the control file cfp, removes tabs, converts 126*12117Sralph * new-line to null and leaves it in line. 127*12117Sralph * Returns 0 at EOF or the number of characters read. 128*12117Sralph */ 129*12117Sralph getline(cfp) 130*12117Sralph FILE *cfp; 131*12117Sralph { 132*12117Sralph register int linel = 0; 133*12117Sralph register char *lp = line; 134*12117Sralph register c; 135*12117Sralph 136*12117Sralph while ((c = getc(cfp)) != '\n') { 137*12117Sralph if (c == EOF) 138*12117Sralph return(0); 139*12117Sralph if (c == '\t') { 140*12117Sralph do { 141*12117Sralph *lp++ = ' '; 142*12117Sralph linel++; 143*12117Sralph } while ((linel & 07) != 0); 144*12117Sralph continue; 145*12117Sralph } 146*12117Sralph *lp++ = c; 147*12117Sralph linel++; 148*12117Sralph } 149*12117Sralph *lp++ = '\0'; 150*12117Sralph return(linel); 151*12117Sralph } 152*12117Sralph 153*12117Sralph /* 154*12117Sralph * Scan the current directory and make a list of daemon files sorted by 155*12117Sralph * creation time. 156*12117Sralph * Return the number of entries and a pointer to the list. 157*12117Sralph */ 158*12117Sralph getq(namelist) 159*12117Sralph struct queue *(*namelist[]); 160*12117Sralph { 161*12117Sralph register struct direct *d; 162*12117Sralph register struct queue *q, **queue; 163*12117Sralph register int nitems; 164*12117Sralph struct stat stbuf; 165*12117Sralph int arraysz, compar(); 166*12117Sralph DIR *dirp; 167*12117Sralph 168*12117Sralph if ((dirp = opendir(".")) == NULL) 169*12117Sralph return(-1); 170*12117Sralph if (fstat(dirp->dd_fd, &stbuf) < 0) 171*12117Sralph return(-1); 172*12117Sralph 173*12117Sralph /* 174*12117Sralph * Estimate the array size by taking the size of the directory file 175*12117Sralph * and dividing it by a multiple of the minimum size entry. 176*12117Sralph */ 177*12117Sralph arraysz = (stbuf.st_size / 24); 178*12117Sralph queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 179*12117Sralph if (queue == NULL) 180*12117Sralph return(-1); 181*12117Sralph 182*12117Sralph nitems = 0; 183*12117Sralph while ((d = readdir(dirp)) != NULL) { 184*12117Sralph if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 185*12117Sralph continue; /* daemon control files only */ 186*12117Sralph if (stat(d->d_name, &stbuf) < 0) 187*12117Sralph continue; /* Doesn't exist */ 188*12117Sralph q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 189*12117Sralph if (q == NULL) 190*12117Sralph return(-1); 191*12117Sralph q->q_time = stbuf.st_mtime; 192*12117Sralph strcpy(q->q_name, d->d_name); 193*12117Sralph /* 194*12117Sralph * Check to make sure the array has space left and 195*12117Sralph * realloc the maximum size. 196*12117Sralph */ 197*12117Sralph if (++nitems > arraysz) { 198*12117Sralph queue = (struct queue **)realloc((char *)queue, 199*12117Sralph (stbuf.st_size/12) * sizeof(struct queue *)); 200*12117Sralph if (queue == NULL) 201*12117Sralph return(-1); 202*12117Sralph } 203*12117Sralph queue[nitems-1] = q; 204*12117Sralph } 205*12117Sralph closedir(dirp); 206*12117Sralph if (nitems) 207*12117Sralph qsort(queue, nitems, sizeof(struct queue *), compar); 208*12117Sralph *namelist = queue; 209*12117Sralph return(nitems); 210*12117Sralph } 211*12117Sralph 212*12117Sralph /* 213*12117Sralph * Compare modification times. 214*12117Sralph */ 215*12117Sralph static 216*12117Sralph compar(p1, p2) 217*12117Sralph register struct queue **p1, **p2; 218*12117Sralph { 219*12117Sralph if ((*p1)->q_time < (*p2)->q_time) 220*12117Sralph return(-1); 221*12117Sralph if ((*p1)->q_time > (*p2)->q_time) 222*12117Sralph return(1); 223*12117Sralph return(0); 224*12117Sralph } 225*12117Sralph 226*12117Sralph /*VARARGS1*/ 227*12117Sralph status(msg, a1, a2, a3) 228*12117Sralph char *msg; 229*12117Sralph { 230*12117Sralph register int fd; 231*12117Sralph char buf[BUFSIZ]; 232*12117Sralph 233*12117Sralph umask(0); 234*12117Sralph if ((fd = open(ST, FWRONLY|FCREATE|FTRUNCATE|FEXLOCK, 0664)) < 0) 235*12117Sralph fatal("cannot create status file"); 236*12117Sralph sprintf(buf, msg, a1, a2, a3); 237*12117Sralph strcat(buf, "\n"); 238*12117Sralph (void) write(fd, buf, strlen(buf)); 239*12117Sralph (void) close(fd); 240*12117Sralph } 241*12117Sralph 242*12117Sralph /*VARARGS1*/ 243*12117Sralph fatal(msg, a1, a2, a3) 244*12117Sralph char *msg; 245*12117Sralph { 246*12117Sralph if (from != host) 247*12117Sralph printf("%s: ", host); 248*12117Sralph printf("%s: ", name); 249*12117Sralph if (printer) 250*12117Sralph printf("%s: ", printer); 251*12117Sralph printf(msg, a1, a2, a3); 252*12117Sralph putchar('\n'); 253*12117Sralph exit(1); 254*12117Sralph } 255*12117Sralph 256*12117Sralph fatalerror(msg) 257*12117Sralph char *msg; 258*12117Sralph { 259*12117Sralph extern int sys_nerr; 260*12117Sralph extern char *sys_errlist[]; 261*12117Sralph 262*12117Sralph printf("%s: ", name); 263*12117Sralph if (*msg) 264*12117Sralph printf("%s: ", msg); 265*12117Sralph fputs(errno < sys_nerr ? sys_errlist[errno] : "Unknown error" , stdout); 266*12117Sralph putchar('\n'); 267*12117Sralph exit(1); 268*12117Sralph } 269