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