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
chfiles(char ** list,uid_t uid,gid_t gid)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
rmfiles(RSTATUS * rp,int log_it)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
_alloc_req_id(void)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 *
_alloc_files(int num,char * prefix,uid_t uid,gid_t gid)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
extractReqno(char * req_file)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