Home | History | Annotate | Download | only in lpsched
      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 
     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 %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
    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