xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/files.c (revision 355b4669e025ff377602b6fc7caaf30dbc218371)
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