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