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