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