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 /* 41 static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95"; 42 */ 43 static const char rcsid[] = 44 "$FreeBSD$"; 45 #endif /* not lint */ 46 47 #include <sys/param.h> 48 #include <sys/stat.h> 49 #include <sys/time.h> 50 51 #include <dirent.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 57 #include "lp.h" 58 #include "lp.local.h" 59 #include "pathnames.h" 60 61 /* 62 * Routines and data common to all the line printer functions. 63 */ 64 char line[BUFSIZ]; 65 char *name; /* program name */ 66 67 extern uid_t uid, euid; 68 69 static int compar __P((const void *, const void *)); 70 71 /* 72 * Getline reads a line from the control file cfp, removes tabs, converts 73 * new-line to null and leaves it in line. 74 * Returns 0 at EOF or the number of characters read. 75 */ 76 int 77 getline(cfp) 78 FILE *cfp; 79 { 80 register int linel = 0; 81 register char *lp = line; 82 register int c; 83 84 while ((c = getc(cfp)) != '\n' && linel+1 < sizeof(line)) { 85 if (c == EOF) 86 return(0); 87 if (c == '\t') { 88 do { 89 *lp++ = ' '; 90 linel++; 91 } while ((linel & 07) != 0 && linel+1 < sizeof(line)); 92 continue; 93 } 94 *lp++ = c; 95 linel++; 96 } 97 *lp++ = '\0'; 98 return(linel); 99 } 100 101 /* 102 * Scan the current directory and make a list of daemon files sorted by 103 * creation time. 104 * Return the number of entries and a pointer to the list. 105 */ 106 int 107 getq(pp, namelist) 108 const struct printer *pp; 109 struct queue *(*namelist[]); 110 { 111 register struct dirent *d; 112 register struct queue *q, **queue; 113 register int nitems; 114 struct stat stbuf; 115 DIR *dirp; 116 int arraysz; 117 118 seteuid(euid); 119 if ((dirp = opendir(pp->spool_dir)) == NULL) 120 return(-1); 121 if (fstat(dirp->dd_fd, &stbuf) < 0) 122 goto errdone; 123 seteuid(uid); 124 125 /* 126 * Estimate the array size by taking the size of the directory file 127 * and dividing it by a multiple of the minimum size entry. 128 */ 129 arraysz = (stbuf.st_size / 24); 130 queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); 131 if (queue == NULL) 132 goto errdone; 133 134 nitems = 0; 135 while ((d = readdir(dirp)) != NULL) { 136 if (d->d_name[0] != 'c' || d->d_name[1] != 'f') 137 continue; /* daemon control files only */ 138 seteuid(euid); 139 if (stat(d->d_name, &stbuf) < 0) 140 continue; /* Doesn't exist */ 141 seteuid(uid); 142 q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); 143 if (q == NULL) 144 goto errdone; 145 q->q_time = stbuf.st_mtime; 146 strcpy(q->q_name, d->d_name); 147 /* 148 * Check to make sure the array has space left and 149 * realloc the maximum size. 150 */ 151 if (++nitems > arraysz) { 152 arraysz *= 2; 153 queue = (struct queue **)realloc((char *)queue, 154 arraysz * sizeof(struct queue *)); 155 if (queue == NULL) 156 goto errdone; 157 } 158 queue[nitems-1] = q; 159 } 160 closedir(dirp); 161 if (nitems) 162 qsort(queue, nitems, sizeof(struct queue *), compar); 163 *namelist = queue; 164 return(nitems); 165 166 errdone: 167 closedir(dirp); 168 return(-1); 169 } 170 171 /* 172 * Compare modification times. 173 */ 174 static int 175 compar(p1, p2) 176 const void *p1, *p2; 177 { 178 if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time) 179 return(-1); 180 if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time) 181 return(1); 182 return(0); 183 } 184 185 /* sleep n milliseconds */ 186 void 187 delay(n) 188 int n; 189 { 190 struct timeval tdelay; 191 192 if (n <= 0 || n > 10000) 193 fatal((struct printer *)0, /* fatal() knows how to deal */ 194 "unreasonable delay period (%d)", n); 195 tdelay.tv_sec = n / 1000; 196 tdelay.tv_usec = n * 1000 % 1000000; 197 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay); 198 } 199 200 char * 201 lock_file_name(pp, buf, len) 202 const struct printer *pp; 203 char *buf; 204 size_t len; 205 { 206 static char staticbuf[MAXPATHLEN]; 207 208 if (buf == 0) 209 buf = staticbuf; 210 if (len == 0) 211 len = MAXPATHLEN; 212 213 if (pp->lock_file[0] == '/') { 214 buf[0] = '\0'; 215 strncpy(buf, pp->lock_file, len); 216 } else { 217 snprintf(buf, len, "%s/%s", pp->spool_dir, pp->lock_file); 218 } 219 return buf; 220 } 221 222 char * 223 status_file_name(pp, buf, len) 224 const struct printer *pp; 225 char *buf; 226 size_t len; 227 { 228 static char staticbuf[MAXPATHLEN]; 229 230 if (buf == 0) 231 buf = staticbuf; 232 if (len == 0) 233 len = MAXPATHLEN; 234 235 if (pp->status_file[0] == '/') { 236 buf[0] = '\0'; 237 strncpy(buf, pp->status_file, len); 238 } else { 239 snprintf(buf, len, "%s/%s", pp->spool_dir, pp->status_file); 240 } 241 return buf; 242 } 243 244 #ifdef __STDC__ 245 #include <stdarg.h> 246 #else 247 #include <varargs.h> 248 #endif 249 250 void 251 #ifdef __STDC__ 252 fatal(const struct printer *pp, const char *msg, ...) 253 #else 254 fatal(pp, msg, va_alist) 255 const struct printer *pp; 256 char *msg; 257 va_dcl 258 #endif 259 { 260 va_list ap; 261 #ifdef __STDC__ 262 va_start(ap, msg); 263 #else 264 va_start(ap); 265 #endif 266 if (from != host) 267 (void)printf("%s: ", host); 268 (void)printf("%s: ", name); 269 if (pp && pp->printer) 270 (void)printf("%s: ", pp->printer); 271 (void)vprintf(msg, ap); 272 va_end(ap); 273 (void)putchar('\n'); 274 exit(1); 275 } 276 277 /* 278 * Close all file descriptors from START on up. 279 * This is a horrific kluge, since getdtablesize() might return 280 * ``infinity'', in which case we will be spending a long time 281 * closing ``files'' which were never open. Perhaps it would 282 * be better to close the first N fds, for some small value of N. 283 */ 284 void 285 closeallfds(start) 286 int start; 287 { 288 int stop = getdtablesize(); 289 for (; start < stop; start++) 290 close(start); 291 } 292 293