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