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