view usr/src/cmd/lp/cmd/lpsched/files.c @ 13:f60a82e85167 default tip

Revert NEC's changes to fix krb5 build
author Andrew Stormont <andyjstormont@gmail.com>
date Fri, 02 Mar 2012 22:25:26 +0000
parents 1a15d5aaf794
children
line wrap: on
line source

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include "lpsched.h"
#include <syslog.h>
#include <strings.h>

static char time_buf[50];
#ifdef LP_USE_PAPI_ATTR
static char *extractReqno(char *req_file);
#endif

/**
 ** chfiles() - CHANGE OWNERSHIP OF FILES, RETURN TOTAL SIZE
 **/

off_t chfiles ( char * * list, uid_t uid, gid_t gid )	/* funcdef */
{
    size_t	total;
    struct stat	stbuf;
    char	*file;
    
    total = 0;

    while(file = *list++)
    {
	if (STRNEQU(Lp_Temp, file, strlen(Lp_Temp)) ||
	    STRNEQU(Lp_Tmp, file, strlen(Lp_Tmp)))
	{
	    /*
	     * Once this routine (chfiles) is called for a request,
	     * any temporary files are ``ours'', i.e. they are on our
	     * machine. A user running on an RFS-connected remote machine
	     * can't necessarily know our machine name, so can't put
	     * the files where they belong (Lp_Tmp/machine). But now we
	     * can. Of course, this is all done with mirrors, as Lp_Temp
	     * and Lp_Tmp/local-machine are symbolicly linked. So we just
	     * change the name. This saves on wear and tear later.
	     */
	    if (STRNEQU(Lp_Temp, file, strlen(Lp_Temp)))
	    {
		char *newfile = makepath(Lp_Tmp, Local_System,
				file + strlen(Lp_Temp) + 1, NULL);

		Free(file);
		list[-1] = file = newfile;
	    }
	    
	    (void) chownmod(file, uid, gid, 0600);
	}

	if (Stat(file, &stbuf) == -1)
	    return(-1);

	switch (stbuf.st_mode & S_IFMT) {
	case 0:
	case S_IFREG:
	    break;

	case S_IFIFO:
	    if (!isadmin(uid))
		return(-1);
	    /*
	     * If any of the files is a FIFO, the size indicator
	     * becomes meaningless. On the other hand, returning
	     * a total of zero causes the request to be rejected,
	     * so we return something > 0.
	     */
	    stbuf.st_size = 1;
	    break;

	case S_IFDIR:
	case S_IFCHR:
	case S_IFBLK:
	default:
	    return(-1);
	}

	total += stbuf.st_size;
    }
    return(total);
}

/**
 ** rmfiles() - DELETE/LOG FILES FOR DEFUNCT REQUEST
 **/

void rmfiles ( RSTATUS * rp, int log_it )	/* funcdef */
{
    char	**file	= rp->request->file_list;
    char	*path;
    char	num[STRSIZE(MOST_FILES) + 1];
    static int	fd	= -1;
    int		reqfd;
    int		count	= 0;
#ifdef LP_USE_PAPI_ATTR
    struct stat	tmpBuf;
    char	*idno = NULL;
    char 	tmpName[BUFSIZ];
#endif


    if (rp->req_file) {
	    char *p, *q;

	   /*
	    * The secure request file is removed first to prevent
	    * reloading should the system crash while in rmfiles().
	    */
	    path = makepath(Lp_Requests, rp->req_file, (char *)0);
	    (void) Unlink(path);
	    Free(path);

	    /*
	     * Copy the request file to the log file, if asked,
	     * or simply remove it.
	     */
	    path = makepath(Lp_Tmp, rp->req_file, (char *)0);
	    if (log_it && rp->secure && rp->secure->req_id) {
		if (fd == -1)
		    fd = open_locked(Lp_ReqLog, "a", MODE_NOREAD);
		if ((fd  >= 0) && (reqfd = Open(path, O_RDONLY, 0)) != -1) {
		    register int	n;
		    char		buf[BUFSIZ];

		    (void) strftime(time_buf, sizeof (time_buf),
			NULL, localtime(&(rp->secure->date)));
		    fdprintf(fd, "= %s, uid %u, gid %u, size %ld, %s\n",
			rp->secure->req_id, rp->secure->uid, rp->secure->gid,
			rp->secure->size, time_buf);
		    if (rp->slow)
			fdprintf(fd, "x %s\n", rp->slow);
		    if (rp->fast)
			fdprintf(fd, "y %s\n", rp->fast);
		    if (rp->printer && rp->printer->printer)
			fdprintf(fd, "z %s\n", rp->printer->printer->name);
		    while ((n = Read(reqfd, buf, BUFSIZ)) > 0)
			write (fd, buf, n);
		    Close (reqfd);
		}
	    }
	    (void)Unlink (path);		/* remove request file */
	    Free (path);

	    p = strdup(rp->req_file);		/* remove host/id file */
	    if (q = strrchr(p, '-')) {
		    *q = NULL;
		    path = makepath(Lp_Tmp, p, NULL);
		    (void) Unlink(path);
		    Free(path);
	    }
	    Free(p);

#ifdef LP_USE_PAPI_ATTR
	/* Look for a PAPI job attribute file, if it exists remove it */
	idno = extractReqno(rp->req_file);
	snprintf(tmpName, sizeof (tmpName), "%s-%s", idno, LP_PAPIATTRNAME);
	path = makepath(Lp_Temp, tmpName, (char *)0);

	if (((path != NULL) && (idno != NULL)) && (stat(path, &tmpBuf) == 0))
	{
	    /* PAPI job attribute file exists for this job so remove it */
	    (void) Unlink(path);
	}

	Free(idno);
	Free(path);
#endif
    }

    if (file)					/* remove file in filelist */
	while(*file)
	{
		/*
		 * The copies of user files.
		 */
		if ((STRNEQU(Lp_Temp, *file, strlen(Lp_Temp)) ||
		    STRNEQU(Lp_Tmp, *file, strlen(Lp_Tmp))) &&
		    (! strstr(*file, "../")))

		    (void) Unlink(*file);

		count++;
		file++;
	}

    if (rp->secure && rp->secure->req_id) {
	char *p;
	p = getreqno(rp->secure->req_id);

	/*
	 * The filtered files. We can't rely on just the RS_FILTERED
	 * flag, since the request may have been cancelled while
	 * filtering. On the other hand, just checking "rp->slow"
	 * doesn't mean that the files exist, because the request
	 * may have been canceled BEFORE filtering started. Oh well.
	 */
	if (rp->slow)
	    while(count > 0)
	    {
		sprintf(num, "%d", count--);
		path = makestr(Lp_Temp, "/F", p, "-", num, (char *)0);
		Unlink(path);
		Free(path);
	    }

	/*
	 * The notify/error file.
	 */
	path = makepath(Lp_Temp, p, (char *)0);
	(void) Unlink(path);
	Free(path);
    }
}

/**
 ** _alloc_req_id(void) - ALLOCATE NEXT REQUEST ID
 **/

#define	SEQF_DEF_START	1
#define	SEQF_DEF_END	59999
#define	SEQF_DEF_INCR	1
#define	SEQF		".SEQF"


long
_alloc_req_id ( void )
{
	static short		started	= 0;

	static int		fd;

	static long		start;
	static long		end;
	static long		incr;
	static long		curr;
	static long		wrap;

	static char		fmt[
				STRSIZE(BIGGEST_REQID_S)/* start   */
			      + 1			/* :       */
			      + STRSIZE(BIGGEST_REQID_S)/* end     */
			      + 1			/* :       */
			      + STRSIZE(BIGGEST_REQID_S)/* incr    */
			      + 1			/* :       */
			      + 4			/* %ld\n   */
			      + 1			/* (nul)   */
				];

	char 			buf[256];
	int len;

	long			ret;


	if (!started) {
		snprintf(buf, sizeof (buf), "%s/%s", Lp_Temp, SEQF);
		if (((fd = open_locked(buf, "r+", 0644)) < 0) &&
		    ((fd = open_locked(buf, "w", 0644)) < 0))
			fail ("Can't open file %s (%s).\n", buf, PERROR);

		lseek(fd, 0, SEEK_SET);

		read(fd, buf, sizeof (buf));
		if (sscanf(buf, "%ld:%ld:%ld:%ld\n", &start, &end, &incr, &curr) != 4) {
			start = SEQF_DEF_START;
			end = SEQF_DEF_END;
			curr = start;
			incr = SEQF_DEF_INCR;
		}

		if (start < 0)
			start = SEQF_DEF_START;
		if (end > SEQF_DEF_END)
			end = SEQF_DEF_END;
		if (curr < start || curr > end)
			curr = start;

		sprintf (fmt, "%ld:%ld:%ld:%%ld\n", start, end, incr);
		started = 1;
	}

	wrap = curr;
	do {	
		ret = curr;
		if ((curr += incr) > end)
	    	curr = start;

	} while ( wrap != curr && ((RSTATUS *)request_by_id_num(ret)) ) ; 

	/* write the new id file */
	lseek(fd, 0, SEEK_SET);
	len = sprintf(buf, fmt, curr);
	write(fd, buf, len);
	ftruncate(fd, len);

	if (curr == wrap) {
		note("alloc_req_id(): out of ids\n");
		errno = EEXIST;
		return(SEQF_DEF_START-1);
	} else
		return (ret);
}

/**
 ** _alloc_file() - ALLOCATE FILES FOR A REQUEST
 **/

char *
_alloc_files (
	int			num,
	char *			prefix,
	uid_t			uid,
	gid_t			gid
)
{
	static char		base[
				1			/* F       */
			      + STRSIZE(BIGGEST_REQID_S)/* req-id  */
			      + 1			/* -       */
			      + STRSIZE(MOST_FILES_S)	/* file-no */
			      + 1			/* (nul)   */
				];

	char *			file;
	char *			cp;

	int			fd;
	int			plus;


	if (num > BIGGEST_REQID)
		return (0);

	if (!prefix) {
		int id;

		if ((id = _alloc_req_id()) < SEQF_DEF_START )
			return(NULL); /* Out of request IDs (errno = EEXIST) */
		snprintf (base, sizeof (base), "%d-%d", id, MOST_FILES);
		plus = 0;
	} else {
		if (strlen(prefix) > (size_t) 6)
			return (0);
		snprintf (base, sizeof (base), "F%s-%d", prefix, MOST_FILES);
		plus = 1;
	}

	file = makepath(Lp_Temp, base, (char *)0);
        
	cp = strrchr(file, '-') + 1;
	while (num--) {
		sprintf (cp, "%d", num + plus);
		if ((fd = Open(file, O_CREAT|O_TRUNC, 0600)) == -1) {
			Free (file);
			return (0);
		} else {
			Close (fd);
			(void) chownmod(file, uid, gid, 0600);
		}
	}

#ifdef LP_USE_PAPI_ATTR
	if (prefix == NULL)
	{
		/*
		 * Initial job request (s_alloc_files) so create an empty PAPI
		 * Attribute file; note, this file will only be used if the
		 * print job has been submitted via the PAPI interface.
		 */

		file = (char *)Realloc(file, strlen(file) +
					strlen(LP_PAPIATTRNAME) + 1);
		if (file != NULL)
		{
			cp = strrchr(file, '-') + 1;
			sprintf(cp, "%s", LP_PAPIATTRNAME);

			if ((fd = Open(file, O_CREAT|O_TRUNC, 0600)) == -1)
			{
				Free(file);
				return (0);
			}
			else
			{
				Close(fd);
				(void) chownmod(file, uid, gid, 0600);
			}

			Free(file);
		}
	}
#endif


	if ((cp = strrchr(base, '-')))
		*cp = 0;

	return (base);
}


#ifdef LP_USE_PAPI_ATTR
static char *extractReqno(char *req_file)

{
	char *start = NULL;
	char *end = NULL;
	char *result = NULL;

	start = strrchr(req_file, '/');
	end = strrchr(req_file, '-');

	if ((start != NULL) && (end != NULL))
	{
		start++;
		if (end > start)
		{
			int n = end - start;
			result = (char *)Malloc(n+1);
			strncpy(result, start, n);
			result[n] = '\0';
		}
	}

	return (result);
} /* extractReqno() */
#endif