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