1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * %sccs.include.redist.c% 11 */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 04/28/95"; 15 #endif /* not lint */ 16 17 #include <sys/param.h> 18 #include <sys/stat.h> 19 #include <sys/time.h> 20 21 #include <sys/socket.h> 22 #include <netinet/in.h> 23 #include <netdb.h> 24 25 #include <dirent.h> 26 #include <errno.h> 27 #include <unistd.h> 28 #include <stdlib.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include "lp.h" 32 #include "pathnames.h" 33 34 /* 35 * Routines and data common to all the line printer functions. 36 */ 37 38 char *AF; /* accounting file */ 39 long BR; /* baud rate if lp is a tty */ 40 char *CF; /* name of cifplot filter (per job) */ 41 char *DF; /* name of tex filter (per job) */ 42 long DU; /* daeomon user-id */ 43 long FC; /* flags to clear if lp is a tty */ 44 char *FF; /* form feed string */ 45 long FS; /* flags to set if lp is a tty */ 46 char *GF; /* name of graph(1G) filter (per job) */ 47 long HL; /* print header last */ 48 char *IF; /* name of input filter (created per job) */ 49 char *LF; /* log file for error messages */ 50 char *LO; /* lock file name */ 51 char *LP; /* line printer device name */ 52 long MC; /* maximum number of copies allowed */ 53 long MX; /* maximum number of blocks to copy */ 54 char *NF; /* name of ditroff filter (per job) */ 55 char *OF; /* name of output filter (created once) */ 56 char *PF; /* name of vrast filter (per job) */ 57 long PL; /* page length */ 58 long PW; /* page width */ 59 long PX; /* page width in pixels */ 60 long PY; /* page length in pixels */ 61 char *RF; /* name of fortran text filter (per job) */ 62 char *RG; /* resricted group */ 63 char *RM; /* remote machine name */ 64 char *RP; /* remote printer name */ 65 long RS; /* restricted to those with local accounts */ 66 long RW; /* open LP for reading and writing */ 67 long SB; /* short banner instead of normal header */ 68 long SC; /* suppress multiple copies */ 69 char *SD; /* spool directory */ 70 long SF; /* suppress FF on each print job */ 71 long SH; /* suppress header page */ 72 char *ST; /* status file name */ 73 char *TF; /* name of troff filter (per job) */ 74 char *TR; /* trailer string to be output when Q empties */ 75 char *VF; /* name of vplot filter (per job) */ 76 long XC; /* flags to clear for local mode */ 77 long XS; /* flags to set for local mode */ 78 79 char line[BUFSIZ]; 80 char *bp; /* pointer into printcap buffer. */ 81 char *name; /* program name */ 82 char *printer; /* printer name */ 83 /* host machine name */ 84 char host[MAXHOSTNAMELEN]; 85 char *from = host; /* client's machine name */ 86 int remote; /* true if sending files to a remote host */ 87 char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; 88 89 static int compar __P((const void *, const void *)); 90 91 /* 92 * Create a TCP connection to host "rhost" at port "rport". 93 * If rport == 0, then use the printer service port. 94 * Most of this code comes from rcmd.c. 95 */ 96 int 97 getport(rhost, rport) 98 char *rhost; 99 int rport; 100 { 101 struct hostent *hp; 102 struct servent *sp; 103 struct sockaddr_in sin; 104 int s, timo = 1, lport = IPPORT_RESERVED - 1; 105 int err; 106 107 /* 108 * Get the host address and port number to connect to. 109 */ 110 if (rhost == NULL) 111 fatal("no remote host to connect to"); 112 bzero((char *)&sin, sizeof(sin)); 113 sin.sin_addr.s_addr = inet_addr(rhost); 114 if (sin.sin_addr.s_addr != INADDR_NONE) 115 sin.sin_family = AF_INET; 116 else { 117 hp = gethostbyname(rhost); 118 if (hp == NULL) 119 fatal("unknown host %s", rhost); 120 bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 121 sin.sin_family = hp->h_addrtype; 122 } 123 if (rport == 0) { 124 sp = getservbyname("printer", "tcp"); 125 if (sp == NULL) 126 fatal("printer/tcp: unknown service"); 127 sin.sin_port = sp->s_port; 128 } else 129 sin.sin_port = htons(rport); 130 131 /* 132 * Try connecting to the server. 133 */ 134 retry: 135 s = rresvport(&lport); 136 if (s < 0) 137 return(-1); 138 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 139 err = errno; 140 (void) close(s); 141 errno = err; 142 if (errno == EADDRINUSE) { 143 lport--; 144 goto retry; 145 } 146 if (errno == ECONNREFUSED && timo <= 16) { 147 sleep(timo); 148 timo *= 2; 149 goto retry; 150 } 151 return(-1); 152 } 153 return(s); 154 } 155 156 /* 157 * Getline reads a line from the control file cfp, removes tabs, converts 158 * new-line to null and leaves it in line. 159 * Returns 0 at EOF or the number of characters read. 160 */ 161 int 162 getline(cfp) 163 FILE *cfp; 164 { 165 register int linel = 0; 166 register char *lp = line; 167 register c; 168 169 while ((c = getc(cfp)) != '\n') { 170 if (c == EOF) 171 return(0); 172 if (c == '\t') { 173 do { 174 *lp++ = ' '; 175 linel++; 176 } while ((linel & 07) != 0); 177 continue; 178 } 179 *lp++ = c; 180 linel++; 181 } 182 *lp++ = '\0'; 183 return(linel); 184 } 185 186 /* 187 * Scan the current directory and make a list of daemon files sorted by 188 * creation time. 189 * Return the number of entries and a pointer to the list. 190 */ 191 int 192 getq(namelist) 193 struct queue *(*namelist[]); 194 { 195 register struct dirent *d; 196 register struct queue *q, **queue; 197 register int nitems; 198 struct stat stbuf; 199 DIR *dirp; 200 int arraysz; 201 202 if ((dirp = opendir(SD)) == NULL) 203 return(-1); 204 if (fstat(dirp->dd_fd, &stbuf) < 0) 205 goto errdone; 206 207 /* 208 * Estimate the array size by taking the size of the directory file 209 * and dividing it by a multiple of the minimum size entry. 210 */ 211 arraysz = (stbuf.st_size / 24); 212 queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 213 if (queue == NULL) 214 goto errdone; 215 216 nitems = 0; 217 while ((d = readdir(dirp)) != NULL) { 218 if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 219 continue; /* daemon control files only */ 220 if (stat(d->d_name, &stbuf) < 0) 221 continue; /* Doesn't exist */ 222 q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 223 if (q == NULL) 224 goto errdone; 225 q->q_time = stbuf.st_mtime; 226 strcpy(q->q_name, d->d_name); 227 /* 228 * Check to make sure the array has space left and 229 * realloc the maximum size. 230 */ 231 if (++nitems > arraysz) { 232 arraysz *= 2; 233 queue = (struct queue **)realloc((char *)queue, 234 arraysz * sizeof(struct queue *)); 235 if (queue == NULL) 236 goto errdone; 237 } 238 queue[nitems-1] = q; 239 } 240 closedir(dirp); 241 if (nitems) 242 qsort(queue, nitems, sizeof(struct queue *), compar); 243 *namelist = queue; 244 return(nitems); 245 246 errdone: 247 closedir(dirp); 248 return(-1); 249 } 250 251 /* 252 * Compare modification times. 253 */ 254 static int 255 compar(p1, p2) 256 const void *p1, *p2; 257 { 258 if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time) 259 return(-1); 260 if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time) 261 return(1); 262 return(0); 263 } 264 265 /* 266 * Figure out whether the local machine is the same 267 * as the remote machine (RM) entry (if it exists). 268 */ 269 char * 270 checkremote() 271 { 272 char name[MAXHOSTNAMELEN]; 273 register struct hostent *hp; 274 static char errbuf[128]; 275 276 remote = 0; /* assume printer is local */ 277 if (RM != NULL) { 278 /* get the official name of the local host */ 279 gethostname(name, sizeof(name)); 280 name[sizeof(name)-1] = '\0'; 281 hp = gethostbyname(name); 282 if (hp == (struct hostent *) NULL) { 283 (void) snprintf(errbuf, sizeof(errbuf), 284 "unable to get official name for local machine %s", 285 name); 286 return errbuf; 287 } else (void) strcpy(name, hp->h_name); 288 289 /* get the official name of RM */ 290 hp = gethostbyname(RM); 291 if (hp == (struct hostent *) NULL) { 292 (void) snprintf(errbuf, sizeof(errbuf), 293 "unable to get official name for remote machine %s", 294 RM); 295 return errbuf; 296 } 297 298 /* 299 * if the two hosts are not the same, 300 * then the printer must be remote. 301 */ 302 if (strcasecmp(name, hp->h_name) != 0) 303 remote = 1; 304 } 305 return NULL; 306 } 307 308 /* sleep n milliseconds */ 309 void 310 delay(n) 311 { 312 struct timeval tdelay; 313 314 if (n <= 0 || n > 10000) 315 fatal("unreasonable delay period (%d)", n); 316 tdelay.tv_sec = n / 1000; 317 tdelay.tv_usec = n * 1000 % 1000000; 318 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay); 319 } 320 321 #if __STDC__ 322 #include <stdarg.h> 323 #else 324 #include <varargs.h> 325 #endif 326 327 void 328 #if __STDC__ 329 fatal(const char *msg, ...) 330 #else 331 fatal(msg, va_alist) 332 char *msg; 333 va_dcl 334 #endif 335 { 336 va_list ap; 337 #if __STDC__ 338 va_start(ap, msg); 339 #else 340 va_start(ap); 341 #endif 342 if (from != host) 343 (void)printf("%s: ", host); 344 (void)printf("%s: ", name); 345 if (printer) 346 (void)printf("%s: ", printer); 347 (void)vprintf(msg, ap); 348 va_end(ap); 349 (void)putchar('\n'); 350 exit(1); 351 } 352