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