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