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