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