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