xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/files.c (revision cb6207858a9fcc2feaee22e626912fba281ac969)
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 2006 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 %d, gid %d, 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