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