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