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