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