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