1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #include "lpsched.h" 31 #include <syslog.h> 32 #include <strings.h> 33 34 static char time_buf[50]; 35 #ifdef LP_USE_PAPI_ATTR 36 static char *extractReqno(char *req_file); 37 #endif 38 39 /** 40 ** chfiles() - CHANGE OWNERSHIP OF FILES, RETURN TOTAL SIZE 41 **/ 42 43 off_t chfiles ( char * * list, uid_t uid, gid_t gid ) /* funcdef */ 44 { 45 size_t total; 46 struct stat stbuf; 47 char *file; 48 49 total = 0; 50 51 while(file = *list++) 52 { 53 if (STRNEQU(Lp_Temp, file, strlen(Lp_Temp)) || 54 STRNEQU(Lp_Tmp, file, strlen(Lp_Tmp))) 55 { 56 /* 57 * Once this routine (chfiles) is called for a request, 58 * any temporary files are ``ours'', i.e. they are on our 59 * machine. A user running on an RFS-connected remote machine 60 * can't necessarily know our machine name, so can't put 61 * the files where they belong (Lp_Tmp/machine). But now we 62 * can. Of course, this is all done with mirrors, as Lp_Temp 63 * and Lp_Tmp/local-machine are symbolicly linked. So we just 64 * change the name. This saves on wear and tear later. 65 */ 66 if (STRNEQU(Lp_Temp, file, strlen(Lp_Temp))) 67 { 68 char *newfile = makepath(Lp_Tmp, Local_System, 69 file + strlen(Lp_Temp) + 1, NULL); 70 71 Free(file); 72 list[-1] = file = newfile; 73 } 74 75 (void) chownmod(file, uid, gid, 0600); 76 } 77 78 if (Stat(file, &stbuf) == -1) 79 return(-1); 80 81 switch (stbuf.st_mode & S_IFMT) { 82 case 0: 83 case S_IFREG: 84 break; 85 86 case S_IFIFO: 87 if (!isadmin(uid)) 88 return(-1); 89 /* 90 * If any of the files is a FIFO, the size indicator 91 * becomes meaningless. On the other hand, returning 92 * a total of zero causes the request to be rejected, 93 * so we return something > 0. 94 */ 95 stbuf.st_size = 1; 96 break; 97 98 case S_IFDIR: 99 case S_IFCHR: 100 case S_IFBLK: 101 default: 102 return(-1); 103 } 104 105 total += stbuf.st_size; 106 } 107 return(total); 108 } 109 110 /** 111 ** rmfiles() - DELETE/LOG FILES FOR DEFUNCT REQUEST 112 **/ 113 114 void rmfiles ( RSTATUS * rp, int log_it ) /* funcdef */ 115 { 116 char **file = rp->request->file_list; 117 char *path; 118 char num[STRSIZE(MOST_FILES) + 1]; 119 static int fd = -1; 120 int reqfd; 121 int count = 0; 122 #ifdef LP_USE_PAPI_ATTR 123 struct stat tmpBuf; 124 char *idno = NULL; 125 char tmpName[BUFSIZ]; 126 #endif 127 128 129 if (rp->req_file) { 130 char *p, *q; 131 132 /* 133 * The secure request file is removed first to prevent 134 * reloading should the system crash while in rmfiles(). 135 */ 136 path = makepath(Lp_Requests, rp->req_file, (char *)0); 137 (void) Unlink(path); 138 Free(path); 139 140 /* 141 * Copy the request file to the log file, if asked, 142 * or simply remove it. 143 */ 144 path = makepath(Lp_Tmp, rp->req_file, (char *)0); 145 if (log_it && rp->secure && rp->secure->req_id) { 146 if (fd == -1) 147 fd = open_locked(Lp_ReqLog, "a", MODE_NOREAD); 148 if ((fd >= 0) && (reqfd = Open(path, O_RDONLY, 0)) != -1) { 149 register int n; 150 char buf[BUFSIZ]; 151 152 (void) strftime(time_buf, sizeof (time_buf), 153 NULL, localtime(&(rp->secure->date))); 154 fdprintf(fd, "= %s, uid %u, gid %u, size %ld, %s\n", 155 rp->secure->req_id, rp->secure->uid, rp->secure->gid, 156 rp->secure->size, time_buf); 157 if (rp->slow) 158 fdprintf(fd, "x %s\n", rp->slow); 159 if (rp->fast) 160 fdprintf(fd, "y %s\n", rp->fast); 161 if (rp->printer && rp->printer->printer) 162 fdprintf(fd, "z %s\n", rp->printer->printer->name); 163 while ((n = Read(reqfd, buf, BUFSIZ)) > 0) 164 write (fd, buf, n); 165 Close (reqfd); 166 } 167 } 168 (void)Unlink (path); /* remove request file */ 169 Free (path); 170 171 p = strdup(rp->req_file); /* remove host/id file */ 172 if (q = strrchr(p, '-')) { 173 *q = '\0'; 174 path = makepath(Lp_Tmp, p, NULL); 175 (void) Unlink(path); 176 Free(path); 177 } 178 Free(p); 179 180 #ifdef LP_USE_PAPI_ATTR 181 /* Look for a PAPI job attribute file, if it exists remove it */ 182 idno = extractReqno(rp->req_file); 183 snprintf(tmpName, sizeof (tmpName), "%s-%s", idno, LP_PAPIATTRNAME); 184 path = makepath(Lp_Temp, tmpName, (char *)0); 185 186 if (((path != NULL) && (idno != NULL)) && (stat(path, &tmpBuf) == 0)) 187 { 188 /* PAPI job attribute file exists for this job so remove it */ 189 (void) Unlink(path); 190 } 191 192 Free(idno); 193 Free(path); 194 #endif 195 } 196 197 if (file) /* remove file in filelist */ 198 while(*file) 199 { 200 /* 201 * The copies of user files. 202 */ 203 if ((STRNEQU(Lp_Temp, *file, strlen(Lp_Temp)) || 204 STRNEQU(Lp_Tmp, *file, strlen(Lp_Tmp))) && 205 (! strstr(*file, "../"))) 206 207 (void) Unlink(*file); 208 209 count++; 210 file++; 211 } 212 213 if (rp->secure && rp->secure->req_id) { 214 char *p; 215 p = getreqno(rp->secure->req_id); 216 217 /* 218 * The filtered files. We can't rely on just the RS_FILTERED 219 * flag, since the request may have been cancelled while 220 * filtering. On the other hand, just checking "rp->slow" 221 * doesn't mean that the files exist, because the request 222 * may have been canceled BEFORE filtering started. Oh well. 223 */ 224 if (rp->slow) 225 while(count > 0) 226 { 227 sprintf(num, "%d", count--); 228 path = makestr(Lp_Temp, "/F", p, "-", num, (char *)0); 229 Unlink(path); 230 Free(path); 231 } 232 233 /* 234 * The notify/error file. 235 */ 236 path = makepath(Lp_Temp, p, (char *)0); 237 (void) Unlink(path); 238 Free(path); 239 } 240 } 241 242 /** 243 ** _alloc_req_id(void) - ALLOCATE NEXT REQUEST ID 244 **/ 245 246 #define SEQF_DEF_START 1 247 #define SEQF_DEF_END 59999 248 #define SEQF_DEF_INCR 1 249 #define SEQF ".SEQF" 250 251 252 long 253 _alloc_req_id ( void ) 254 { 255 static short started = 0; 256 257 static int fd; 258 259 static long start; 260 static long end; 261 static long incr; 262 static long curr; 263 static long wrap; 264 265 static char fmt[ 266 STRSIZE(BIGGEST_REQID_S)/* start */ 267 + 1 /* : */ 268 + STRSIZE(BIGGEST_REQID_S)/* end */ 269 + 1 /* : */ 270 + STRSIZE(BIGGEST_REQID_S)/* incr */ 271 + 1 /* : */ 272 + 4 /* %ld\n */ 273 + 1 /* (nul) */ 274 ]; 275 276 char buf[256]; 277 int len; 278 279 long ret; 280 281 282 if (!started) { 283 snprintf(buf, sizeof (buf), "%s/%s", Lp_Temp, SEQF); 284 if (((fd = open_locked(buf, "r+", 0644)) < 0) && 285 ((fd = open_locked(buf, "w", 0644)) < 0)) 286 fail ("Can't open file %s (%s).\n", buf, PERROR); 287 288 lseek(fd, 0, SEEK_SET); 289 290 read(fd, buf, sizeof (buf)); 291 if (sscanf(buf, "%ld:%ld:%ld:%ld\n", &start, &end, &incr, &curr) != 4) { 292 start = SEQF_DEF_START; 293 end = SEQF_DEF_END; 294 curr = start; 295 incr = SEQF_DEF_INCR; 296 } 297 298 if (start < 0) 299 start = SEQF_DEF_START; 300 if (end > SEQF_DEF_END) 301 end = SEQF_DEF_END; 302 if (curr < start || curr > end) 303 curr = start; 304 305 sprintf (fmt, "%ld:%ld:%ld:%%ld\n", start, end, incr); 306 started = 1; 307 } 308 309 wrap = curr; 310 do { 311 ret = curr; 312 if ((curr += incr) > end) 313 curr = start; 314 315 } while ( wrap != curr && ((RSTATUS *)request_by_id_num(ret)) ) ; 316 317 /* write the new id file */ 318 lseek(fd, 0, SEEK_SET); 319 len = sprintf(buf, fmt, curr); 320 write(fd, buf, len); 321 ftruncate(fd, len); 322 323 if (curr == wrap) { 324 note("alloc_req_id(): out of ids\n"); 325 errno = EEXIST; 326 return(SEQF_DEF_START-1); 327 } else 328 return (ret); 329 } 330 331 /** 332 ** _alloc_file() - ALLOCATE FILES FOR A REQUEST 333 **/ 334 335 char * 336 _alloc_files ( 337 int num, 338 char * prefix, 339 uid_t uid, 340 gid_t gid 341 ) 342 { 343 static char base[ 344 1 /* F */ 345 + STRSIZE(BIGGEST_REQID_S)/* req-id */ 346 + 1 /* - */ 347 + STRSIZE(MOST_FILES_S) /* file-no */ 348 + 1 /* (nul) */ 349 ]; 350 351 char * file; 352 char * cp; 353 354 int fd; 355 int plus; 356 357 358 if (num > BIGGEST_REQID) 359 return (0); 360 361 if (!prefix) { 362 int id; 363 364 if ((id = _alloc_req_id()) < SEQF_DEF_START ) 365 return(NULL); /* Out of request IDs (errno = EEXIST) */ 366 snprintf (base, sizeof (base), "%d-%d", id, MOST_FILES); 367 plus = 0; 368 } else { 369 if (strlen(prefix) > (size_t) 6) 370 return (0); 371 snprintf (base, sizeof (base), "F%s-%d", prefix, MOST_FILES); 372 plus = 1; 373 } 374 375 file = makepath(Lp_Temp, base, (char *)0); 376 377 cp = strrchr(file, '-') + 1; 378 while (num--) { 379 sprintf (cp, "%d", num + plus); 380 if ((fd = Open(file, O_CREAT|O_TRUNC, 0600)) == -1) { 381 Free (file); 382 return (0); 383 } else { 384 Close (fd); 385 (void) chownmod(file, uid, gid, 0600); 386 } 387 } 388 389 #ifdef LP_USE_PAPI_ATTR 390 if (prefix == NULL) 391 { 392 /* 393 * Initial job request (s_alloc_files) so create an empty PAPI 394 * Attribute file; note, this file will only be used if the 395 * print job has been submitted via the PAPI interface. 396 */ 397 398 file = (char *)Realloc(file, strlen(file) + 399 strlen(LP_PAPIATTRNAME) + 1); 400 if (file != NULL) 401 { 402 cp = strrchr(file, '-') + 1; 403 sprintf(cp, "%s", LP_PAPIATTRNAME); 404 405 if ((fd = Open(file, O_CREAT|O_TRUNC, 0600)) == -1) 406 { 407 Free(file); 408 return (0); 409 } 410 else 411 { 412 Close(fd); 413 (void) chownmod(file, uid, gid, 0600); 414 } 415 416 Free(file); 417 } 418 } 419 #endif 420 421 422 if ((cp = strrchr(base, '-'))) 423 *cp = 0; 424 425 return (base); 426 } 427 428 429 #ifdef LP_USE_PAPI_ATTR 430 static char *extractReqno(char *req_file) 431 432 { 433 char *start = NULL; 434 char *end = NULL; 435 char *result = NULL; 436 437 start = strrchr(req_file, '/'); 438 end = strrchr(req_file, '-'); 439 440 if ((start != NULL) && (end != NULL)) 441 { 442 start++; 443 if (end > start) 444 { 445 int n = end - start; 446 result = (char *)Malloc(n+1); 447 strncpy(result, start, n); 448 result[n] = '\0'; 449 } 450 } 451 452 return (result); 453 } /* extractReqno() */ 454 #endif 455