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