Exemple #1
0
/*-----------------------------------------------------------------------------
 * ConvertChannelName --
 *
 *   Convert a requested channel name to one of the standard channel ids.
 * 
 * Parameters:
 *   o interp - Errors are returned in result.
 *   o channelName - Desired channel, one of "stdin", "stdout" or "stderr".
 *   o handleIdPtr - One of STD_{INPUT|OUTPUT|ERROR}_HANDLE is returned.
 * Returns:
 *   TCL_OK or TCL_ERROR.
 * FIX: Make Unix version parallel this one.
 *-----------------------------------------------------------------------------
 */
static int
ConvertChannelName (Tcl_Interp *interp,
                    char       *channelName,
                    DWORD      *handleIdPtr)
{
    if (channelName [0] == 's') {
        if (STREQU (channelName, "stdin"))
            *handleIdPtr = STD_INPUT_HANDLE;
        else if (STREQU (channelName, "stdout"))
            *handleIdPtr = STD_OUTPUT_HANDLE;
        else if (STREQU (channelName, "stderr"))
            *handleIdPtr = STD_ERROR_HANDLE;
    } else if (STRNEQU (channelName, "file", 4) ||
               STRNEQU (channelName, "sock", 4)) {
        TclX_AppendObjResult (interp, "on MS Windows, only stdin, ",
                              "stdout or stderr maybe the dup target",
                              (char *) NULL);
        return TCL_ERROR;
    } else {
        TclX_AppendObjResult (interp, "invalid channel id: ",
                              channelName, (char *) NULL);
        return TCL_ERROR;
    }
    return TCL_OK;
}
Exemple #2
0
USER * getuser ( char * user )
{
    int limit;

    /* root and lp do not get a limit */
    if (STREQU(user, "root") || STREQU(user, LPUSER))
    {
	usr.priority_limit = 0;
	return(&usr);
    }

    if (!loaded)
    {
	if (!(ppri_tbl = ld_priority_file(Lp_Users)))
	    return((USER *)0);

	loaded = 1;
    }

    for (limit = PRI_MIN; limit <= PRI_MAX; limit++)
	if (bang_searchlist(user, ppri_tbl->users[limit - PRI_MIN]))
	{
	    usr.priority_limit = limit;
	    return(&usr);
	}

    usr.priority_limit = ppri_tbl->deflt_limit;
    return(&usr);
}
Exemple #3
0
void
s_move_dest(char *m, MESG *md)
{
	char		*dest;
	char		*fromdest;
	RSTATUS		*rp;
	char		*found = (char *)0;
	short		num_ok = 0;

	(void) getmessage(m, S_MOVE_DEST, &fromdest, &dest);
	syslog(LOG_DEBUG, "s_move_dest(%s, %s)", (fromdest ? fromdest : "NULL"),
	    (dest ? dest : "NULL"));

	if (!search_pstatus(fromdest) && !search_cstatus(fromdest)) {
		mputm(md, R_MOVE_DEST, MNODEST, fromdest, 0);
		return;
	}

	if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
		mputm(md, R_MOVE_DEST, MNODEST, dest, 0);
		return;
	}

	if (STREQU(dest, fromdest)) {
		mputm(md, R_MOVE_DEST, MOK, "", 0);
		return;
	}

	for (rp = Request_List; rp != NULL; rp = rp->next) {
		if ((STREQU(rp->request->destination, fromdest)) &&
		    (!(rp->request->outcome &
		    (RS_DONE|RS_CHANGING|RS_NOTIFYING)))) {
			if (mv_file(rp, dest) == MOK) {
				num_ok++;
				continue;
			}
		}

		if (found)
			mputm(md, R_MOVE_DEST, MMORERR, found, 0);

		found = rp->secure->req_id;
	}

	if (found)
		mputm(md, R_MOVE_DEST, MERRDEST, found, num_ok);
	else
		mputm(md, R_MOVE_DEST, MOK, "", num_ok);
}
Exemple #4
0
/*-----------------------------------------------------------------------------
 * SigNameToNum --
 *    Converts a UNIX signal name to its number, returns -1 if not found.
 * the name may be upper or lower case and may optionally have the leading
 * "SIG" omitted.
 *
 * Parameters:
 *   o interp - Errors are returned in result.
 *   o sigName - Name of signal to convert.
 *   o sigNumPtr - Signal number is returned here.
 * Returns:
 *   TCL_OK or TCL_ERROR.
 *-----------------------------------------------------------------------------
 */
static int
SigNameToNum (Tcl_Interp *interp, char *sigName, int *sigNumPtr)
{
    char  sigNameUp [SIG_NAME_MAX+1];  /* Upshifted signal name */
    char *sigNamePtr; 
    int   idx;

    /*
     * Copy and upshift requested name.
     */
    if (strlen (sigName) > SIG_NAME_MAX)
        goto invalidSignal;   /* Name too long */

    TclX_UpShift (sigNameUp, sigName);

    if (STRNEQU (sigNameUp, "SIG", 3))
        sigNamePtr = &sigNameUp [3];
    else
        sigNamePtr = sigNameUp;

    for (idx = 0; sigNameTable [idx].num != -1; idx++) {
        if (STREQU (sigNamePtr, sigNameTable [idx].name)) {
            *sigNumPtr = sigNameTable [idx].num;
            return TCL_OK;
        }
    }

  invalidSignal:
    TclX_AppendObjResult (interp, "invalid signal \"", sigName, "\"",
                          (char *) NULL);
    return TCL_ERROR;
}
Exemple #5
0
void
s_cancel(char *m, MESG *md)
{
	char	*req_id;
	char	*user;
	char	*destination;
	char	*rid;
	char	*nrid;
	int		nerrno;
	int		oerrno;

	(void) getmessage(m, S_CANCEL, &destination, &user, &req_id);
	syslog(LOG_DEBUG, "s_cancel(%s, %s, %s)",
	    (destination ? destination : "NULL"), (user ? user : "******"),
	    (req_id ? req_id : "NULL"));

	if (STREQU(destination, NAME_ALL))
		destination = "";
	if (STREQU(req_id, NAME_ALL))
		req_id = "";

	if (rid = _cancel(md, destination, user, req_id)) {
		oerrno = errno;

		while ((nrid = _cancel(md, NULL, NULL, NULL)) != NULL) {
			nerrno = errno;
			mputm(md, R_CANCEL, MOKMORE, oerrno, rid);
			Free(rid);
			rid = nrid;
			oerrno = nerrno;
		}
		mputm(md, R_CANCEL, MOK, oerrno, rid);
		Free(rid);
		return;
	}

	mputm(md, R_CANCEL, MOK, MUNKNOWN, "");
}
Exemple #6
0
int
one_printer_with_charsets(RSTATUS *prs)
{
	/*
	 * This little function answers the question: Is a request
	 * that needs a character set destined for a particular
	 * printer that has selectable character sets instead of
	 * mountable print wheels?
	 */
	return (
	    STREQU(prs->request->destination, prs->printer->printer->name)
	 && !prs->printer->printer->daisy
	);
}
Exemple #7
0
/*
 * s_paper_changed()
 */
void
s_paper_changed(char *m, MESG *md)
{
	short			trayNum, mode, pagesPrinted;
	char			*printer, *paper;
	ushort			status;
	short			chgd = 0;
	register PSTATUS	*pps;
	register FSTATUS	*pfs,*pfsWas;

	getmessage(m, S_PAPER_CHANGED, &printer, &trayNum, &paper, &mode,
		&pagesPrinted);
	syslog(LOG_DEBUG, "s_paper_changed(%s, %d, %s, %d, %d)",
	       (printer ? printer : "NULL"), trayNum, (paper ? paper : "NULL"),
	       mode, pagesPrinted);

	if (!(pps = search_ptable(printer)))
		status = MNODEST;
	else if ((trayNum <=0) || (trayNum > pps->numForms))
		status = MNOTRAY;
	else {
		status = MOK;
		if (*paper && (pfsWas = pps->forms[trayNum-1].form) && 
		    (!STREQU(pfsWas->form->paper,paper))) {
			pfs = search_fptable(paper);
			if (pfs) {
				remount_form(pps, pfs, trayNum);
				chgd = 1;
			} else
				status = MNOMEDIA;
		}
		if ( status == MOK ) {
			pps->forms[trayNum].isAvailable = mode;
			if ((chgd || !mode) && (!pagesPrinted) &&
			    LP_KILL_NO_PAPER && pps->exec) {
				if (pps->request)
					pps->request->request->outcome |=
						RS_STOPPED;
				terminate(pps->exec);
				schedule(EV_LATER, 1, EV_INTERF, pps);
			}
		}
	}
	mputm(md, R_PAPER_CHANGED, status);
}
Exemple #8
0
static int
max_requests_needing_pwheel_mounted(char *pwheel_name)
{
	PSTATUS *		pps;
	RSTATUS *		prs;
	int			max	= 0;
	int			i;


	/*
	 * For each printer that doesn't have this print-wheel mounted,
	 * count the number of requests needing this print-wheel and
	 * assigned to the printer. Find the maximum across all such
	 * printers. Sorry, the code actually has a different loop
	 * (it steps through the requests) but the description of what
	 * happens below is easier to understand as given. (Looping
	 * through the printers would result in #printers x #requests
	 * steps, whereas this entails #requests steps.)
	 */
	for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
		PStatus[i]->nrequests = 0;

	for (prs = Request_List; prs != NULL; prs = prs->next)
		if ((prs->pwheel_name != NULL) &&
		    (STREQU(prs->pwheel_name, pwheel_name)) &&
		    ((pps = prs->printer) != NULL) && pps->printer->daisy &&
		    (!SAME(pps->pwheel_name, pwheel_name)))
			if (++pps->nrequests >= max)
				max = pps->nrequests;

	if (NewRequest)
		if (
			((pps = NewRequest->printer) != NULL)
		     && pps->printer->daisy
		     && !SAME(pps->pwheel_name, pwheel_name)
		)
			if (++pps->nrequests >= max)
				max = pps->nrequests;
	return (max);
}
Exemple #9
0
void
s_move_request(char *m, MESG *md)
{
	RSTATUS	*rp;
	short	err;
	char	*req_id;
	char	*dest;

	(void) getmessage(m, S_MOVE_REQUEST, &req_id, &dest);
	syslog(LOG_DEBUG, "s_move_request(%s, %s)", (req_id ? req_id : "NULL"),
	    (dest ? dest : "NULL"));


	if (!(search_pstatus(dest)) && !(search_cstatus(dest))) {
		mputm(md, R_MOVE_REQUEST, MNODEST, 0L);
		return;
	}

	if ((rp = request_by_id(req_id))) {
		if (STREQU(rp->request->destination, dest)) {
			mputm(md, R_MOVE_REQUEST, MOK, 0L);
			return;
		}
		if (rp->request->outcome & (RS_DONE|RS_NOTIFYING)) {
			mputm(md, R_MOVE_REQUEST, M2LATE, 0L);
			return;
		}
		if (rp->request->outcome & RS_CHANGING)	{
			mputm(md, R_MOVE_REQUEST, MBUSY, 0L);
			return;
		}
		if ((err = mv_file(rp, dest)) == MOK) {
			mputm(md, R_MOVE_REQUEST, MOK, 0L);
			return;
		}
		mputm(md, R_MOVE_REQUEST, err, chkprinter_result);
		return;
	}
	mputm(md, R_MOVE_REQUEST, MUNKNOWN, 0L);
}
Exemple #10
0
int
putclass(char *name, CLASS *clsbufp)
{
	char			*file;
	int fd;

	if (!name || !*name) {
		errno = EINVAL;
		return (-1);
	}

	if (STREQU(NAME_ALL, name)) {
		errno = EINVAL;
		return (-1);
	}

	/*
	 * Open the class file and write out the class members.
	 */

	if (!(file = getclassfile(name)))
		return (-1);

	if ((fd = open_locked(file, "w", MODE_READ)) < 0) {
		Free (file);
		return (-1);
	}
	Free (file);

	errno = 0;
	fdprintlist(fd, clsbufp->members);
	if (errno != 0) {
		close(fd);
		return (-1);
	}
	close(fd);

	return (0);
}
Exemple #11
0
/*-----------------------------------------------------------------------------
 * ParseSignalList --
 *  
 *   Parse a list of signal names or numbers.  Also handles the special case
 * of the signal being a single entry of "*".
 * 
 * Parameters:
 *   o interp - Interpreter for returning errors.
 *   o signalListObjPtr - The Tcl list object of signals to convert.
 *   o signals - Boolean array indexed by signal number that indicates
 *     which signals are set.
 * Returns:
 *   TCL_OK or TCL_ERROR.
 *-----------------------------------------------------------------------------
 */
static int
ParseSignalList (Tcl_Interp    *interp,
                 Tcl_Obj       *signalListObjPtr,
                 unsigned char  signals [MAXSIG])
{
    Tcl_Obj **signalObjv;
    char     *signalStr;
    int       signalObjc, signalNum, idx;

    if (Tcl_ListObjGetElements (interp, signalListObjPtr,
                                &signalObjc, &signalObjv) != TCL_OK)
        return TCL_ERROR;

    if (signalObjc == 0) {
        TclX_AppendObjResult (interp, "signal list may not be empty",
                              (char *) NULL);
        return TCL_ERROR;
    }

    memset (signals, FALSE, sizeof (unsigned char) * MAXSIG);

    /*
     * Handle the wild card signal.  Don't return signals that can't be
     * modified.
     */
    signalStr = Tcl_GetStringFromObj (signalObjv [0], NULL);
    if (STREQU (signalStr, "*")) {
        if (signalObjc != 1)
            goto wildMustBeAlone;
        for (idx = 0; sigNameTable [idx].name != NULL; idx++) {
            signalNum = sigNameTable [idx].num;
#ifdef SIGKILL
            if ((signalNum == SIGKILL) || (signalNum == SIGSTOP))
                continue;
#endif
            signals [signalNum] = TRUE;
        }
        goto okExit;
    }

    /*
     * Handle individually specified signals.
     */
    for (idx = 0; idx < signalObjc; idx++) {
        signalStr = Tcl_GetStringFromObj (signalObjv [idx], NULL);
        if (STREQU (signalStr, "*"))
            goto wildMustBeAlone;

        signalNum = ParseSignalSpec (interp,
                                     signalStr,
                                     FALSE);  /* Zero not valid */
        if (signalNum < 0)
            return TCL_ERROR;
        signals [signalNum] = TRUE;
    }

  okExit:
    return TCL_OK;

  wildMustBeAlone:
    TclX_AppendObjResult (interp, "when \"*\" is specified in the signal ",
                          "list, no other signals may be specified",
                          (char *) NULL);
    return TCL_ERROR;
}
Exemple #12
0
static char *
_cancel(MESG *md, char *dest, char *user, char *req_id)
{
	static RSTATUS	*rp;
	static char		*s_dest;
	static char		*s_user;
	static char		*s_req_id;
	static int		current;
	RSTATUS		*crp;
	char		*creq_id;

	syslog(LOG_DEBUG, "_cancel(%s, %s, %s)", (dest ? dest : "NULL"),
	    (user ? user : "******"), (req_id ? req_id : "NULL"));

	if (dest || user || req_id) {
		s_dest = dest;
		if (STREQU(user, "!"))
			s_user = strdup("all!all");
		else
			s_user = user;
		s_req_id = req_id;
		rp = Request_List;
		current = 0;
		if (STREQU(s_req_id, CURRENT_REQ)) {
			current = 1;
			s_req_id = NULL;
		}
	}

	while (rp != NULL) {
		crp = rp;
		rp = rp->next;

		if (*s_dest && !STREQU(s_dest, crp->request->destination))
			continue;

		if (current && !(crp->request->outcome & RS_PRINTING))
			continue;

		if (s_req_id && *s_req_id &&
		    !STREQU(s_req_id, crp->secure->req_id))
			continue;

		if (*s_user && !bangequ(s_user, crp->secure->user))
			continue;

		if (!md->admin && md->uid != crp->secure->uid) {
			errno = MNOPERM;
			return (Strdup(crp->secure->req_id));
		}

		/*
		 * For Trusted Extensions, we need to check the
		 * sensitivity label of the
		 * connection and job before we try to cancel it.
		 */
		if ((md->admin == 0) && (is_system_labeled()) &&
		    (md->slabel != NULL) && (crp->secure->slabel != NULL) &&
		    (!STREQU(md->slabel, crp->secure->slabel)))
			continue;

		crp->reason = MOK;
		creq_id = Strdup(crp->secure->req_id);

		syslog(LOG_DEBUG, "cancel reqid (%s) uid: %d, secureuid: %d",
		    creq_id, md->uid, crp->secure->uid);

		if (cancel(crp, (md->uid != crp->secure->uid)))
			errno = MOK;
		else
			errno = M2LATE;
		return (creq_id);
	}

	errno = MUNKNOWN;
	return (NULL);
}
Exemple #13
0
void
s_end_change_request(char *m, MESG *md)
{
	char		*req_id;
	RSTATUS		*rp;
	off_t		size;
	off_t		osize;
	short		err;
	short		status;
	REQUEST		*r = 0;
	REQUEST		oldr;
	int		call_schedule = 0;
	int		move_ok	= 0;
	char		*path;
	char		tmpName[BUFSIZ];
	struct stat	tmpBuf;

	(void) getmessage(m, S_END_CHANGE_REQUEST, &req_id);
	syslog(LOG_DEBUG, "s_end_change_request(%s)",
	    (req_id ? req_id : "NULL"));

	if (!(rp = request_by_id(req_id)))
		status = MUNKNOWN;
	else if ((md->admin == 0) && (is_system_labeled()) &&
	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
	    (!STREQU(md->slabel, rp->secure->slabel)))
		status = MUNKNOWN;
	else if (!(rp->request->outcome & RS_CHANGING))
		status = MNOSTART;
	else {
		path = makepath(Lp_Tmp, rp->req_file, (char *)0);
		(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
		Free(path);

#ifdef LP_USE_PAPI_ATTR

		/*
		 * Check if the PAPI job attribute file exists,
		 * if it does change the permission and the ownership
		 * of the file to be "Lp_Uid".
		 */

		snprintf(tmpName, sizeof (tmpName),
		    "%s-%s", strtok(strdup(rp->req_file), "-"),
		    LP_PAPIATTRNAME);

		path = makepath(Lp_Tmp, tmpName, (char *)0);

		if (stat(path, &tmpBuf) == 0) {
			syslog(LOG_DEBUG,
			    "s_end_change_request: attribute file ='%s'",
			    path);

			/*
			 * IPP job attribute file exists for this job so
			 * change permissions and ownership of the file
			 */
			(void) chownmod(path, Lp_Uid, Lp_Gid, 0644);
			Free(path);
		}
		else
		{
			syslog(LOG_DEBUG,
			    "s_end_change_request: no attribute file");
		}
#endif
		rp->request->outcome &= ~(RS_CHANGING);
		del_flt_act(md, FLT_CHANGE);
		/*
		 * The RS_CHANGING bit may have been the only thing
		 * preventing this request from filtering or printing,
		 * so regardless of what happens below,
		 * we must check to see if the request can proceed.
		 */
		call_schedule = 1;

		if (!(r = Getrequest(rp->req_file)))
			status = MNOOPEN;
		else {
			oldr = *(rp->request);
			*(rp->request) = *r;

			move_ok =
			    STREQU(oldr.destination, r->destination);

			/*
			 * Preserve the current request status!
			 */
			rp->request->outcome = oldr.outcome;

			/*
			 * Here's an example of the dangers one meets
			 * when public flags are used for private
			 * purposes. ".actions" (indeed, anything in the
			 * REQUEST structure) is set by the person
			 * changing the job. However, lpsched uses
			 * ".actions" as place to indicate that a job
			 * came from a remote system and we must send
			 * back job completion--this is a strictly
			 * private flag that we must preserve.
			 */
			rp->request->actions |=
			    (oldr.actions & ACT_NOTIFY);

			if ((rp->request->actions & ACT_SPECIAL) ==
			    ACT_HOLD) {
				rp->request->outcome |= RS_HELD;
				/*
				 * To be here means either the user owns
				 * the request or he or she is the
				 * administrator. Since we don't want to
				 * set the RS_ADMINHELD flag if the user
				 * is the administrator, the following
				 * compare will work.
				 */
				if (md->uid != rp->secure->uid)
					rp->request->outcome |=
					    RS_ADMINHELD;
			}

			if ((rp->request->actions & ACT_SPECIAL) ==
			    ACT_RESUME) {
				if ((rp->request->outcome & RS_ADMINHELD) &&
				    !md->admin) {
					status = MNOPERM;
					goto Return;
				}
				rp->request->outcome &=
				    ~(RS_ADMINHELD|RS_HELD);
			}

			if ((rp->request->actions & ACT_SPECIAL)
			    == ACT_IMMEDIATE) {
				if (!md->admin) {
					status = MNOPERM;
					goto Return;
				}
				rp->request->outcome |= RS_IMMEDIATE;
			}

			size = chfiles(rp->request->file_list, Lp_Uid,
			    Lp_Gid);
			if (size < 0) {
				status = MUNKNOWN;
				goto Return;
			}
			if (!(rp->request->outcome & RS_HELD) &&
			    size == 0) {
				status = MNOPERM;
				goto Return;
			}

			osize = rp->secure->size;
			rp->secure->size = size;

			if (move_ok == 0) {
				char *dest = strdup(r->destination);
				if ((status = mv_file(rp, dest)) == MOK)
					rp->secure->size = osize;
				free(dest);
			} else if ((err = validate_request(rp, (char **)0,
			    move_ok)) != MOK) {
				status = err;
				rp->secure->size = osize;
			} else {
				status = MOK;

				if ((rp->request->outcome & RS_IMMEDIATE) ||
				    (rp->request->priority != oldr.priority)) {
					remover(rp);
					insertr(rp);
				}

				freerequest(&oldr);
				(void) putrequest(rp->req_file, rp->request);
				/*
				 * fix for bugid 1103890.
				 * use Putsecure instead.
				 */
				(void) Putsecure(rp->req_file, rp->secure);
			}
		}
	}

Return:
	if (status != MOK && rp) {
		if (r) {
			freerequest(r);
			*(rp->request) = oldr;
		}
		if (status != MNOSTART)
			(void) putrequest(rp->req_file, rp->request);
	}

	if (call_schedule)
		maybe_schedule(rp);

	mputm(md, R_END_CHANGE_REQUEST, status, chkprinter_result);
}
Exemple #14
0
void
s_start_change_request(char *m, MESG *md)
{
	char		*req_id;
	char		*req_file	= "";
	short		status;
	RSTATUS		*rp;
	char		*path;
	char		tmpName[BUFSIZ];
	struct stat	tmpBuf;

	(void) getmessage(m, S_START_CHANGE_REQUEST, &req_id);
	syslog(LOG_DEBUG, "s_start_change_request(%s)",
	    (req_id ? req_id : "NULL"));

	if (!(rp = request_by_id(req_id)))
		status = MUNKNOWN;
	else if ((md->admin == 0) && (is_system_labeled()) &&
	    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
	    (!STREQU(md->slabel, rp->secure->slabel)))
		status = MUNKNOWN;
	else if (rp->request->outcome & RS_DONE)
		status = M2LATE;
	else if (!md->admin && md->uid != rp->secure->uid)
		status = MNOPERM;
	else if (rp->request->outcome & RS_CHANGING)
		status = MNOOPEN;
	else if (rp->request->outcome & RS_NOTIFYING)
		status = MBUSY;
	else {
		status = MOK;

		if (rp->request->outcome & RS_FILTERING &&
		    !(rp->request->outcome & RS_STOPPED)) {
			rp->request->outcome |= (RS_REFILTER|RS_STOPPED);
			terminate(rp->exec);
		}

		if (rp->request->outcome & RS_PRINTING &&
		    !(rp->request->outcome & RS_STOPPED)) {
			rp->request->outcome |= RS_STOPPED;
			terminate(rp->printer->exec);
		}

		rp->request->outcome |= RS_CHANGING;

		/*
		 * Change the ownership of the request file to be "md->uid".
		 * Either this is identical to "rp->secure->uid", or it is
		 * "Lp_Uid" or it is root. The idea is that the
		 * person at the other end needs access, and that may not
		 * be who queued the request.
		 */

		path = makepath(Lp_Tmp, rp->req_file, (char *)0);
		(void) Chown(path, md->uid, rp->secure->gid);
		Free(path);

#ifdef LP_USE_PAPI_ATTR

		/*
		 * Check if the PAPI job attribute file exists, if it does
		 * change the ownership of the file to be "md->uid".
		 * Either this is identical to "rp->secure->uid", or it is
		 * "Lp_Uid" or it is root. The idea is that the
		 * person at the other end needs access, and that may not
		 * be who queued the request.
		 */

		snprintf(tmpName, sizeof (tmpName),
		    "%s-%s", strtok(strdup(rp->req_file), "-"),
		    LP_PAPIATTRNAME);

		path = makepath(Lp_Tmp, tmpName, (char *)0);

		if (stat(path, &tmpBuf) == 0) {
			syslog(LOG_DEBUG,
			    "s_start_change_request: attribute file ='%s'",
			    path);

			/*
			 * IPP job attribute file exists for this job so
			 * change permissions and ownership of the file
			 */
			(void) Chown(path, md->uid, rp->secure->gid);
			Free(path);
		}
		else
		{
			syslog(LOG_DEBUG,
			    "s_start_change_request: no attribute file");
		}
#endif

		add_flt_act(md, FLT_CHANGE, rp);
		req_file = rp->req_file;

	}

	mputm(md, R_START_CHANGE_REQUEST, status, req_file);
}
Exemple #15
0
SCALED
_getsdn(char *str, char **p_after, int is_cpi)
{
	static SCALED		sdn	= { 0.0 , 0 };

	char *			rest;


	/*
	 * A nonzero "errno" is our only method of indicating error.
	 */
	errno = 0;

	if (is_cpi && STREQU(str, NAME_PICA)) {
		sdn.val = 10;
		sdn.sc = 0;
		if (p_after)
			*p_after = str + strlen(NAME_PICA);

	} else if (is_cpi && STREQU(str, NAME_ELITE)) {
		sdn.val = 12;
		sdn.sc = 0;
		if (p_after)
			*p_after = str + strlen(NAME_ELITE);

	} else if (is_cpi && STREQU(str, NAME_COMPRESSED)) {
		sdn.val = N_COMPRESSED;
		sdn.sc = 0;
		if (p_after)
			*p_after = str + strlen(NAME_COMPRESSED);

	} else {
		sdn.val = strtod(str, &rest);
		if (sdn.val <= 0) {
			lp_errno = LP_EBADSDN;
			errno = EINVAL;
			return (sdn);
		}

		while (*rest && *rest == ' ')
			rest++;

		switch (*rest) {
		case 0:
			sdn.sc = 0;
			if (p_after)
				*p_after = rest;
			break;
		case 'i':
		case 'c':
			sdn.sc = *rest++;
			if (p_after)
				*p_after = rest;
			break;
		default:
			lp_errno = LP_EBADSDN;
			errno = EINVAL;
			sdn.sc = 0;
			break;
		}
	}

	return (sdn);
}
Exemple #16
0
int
pickfilter(RSTATUS *prs, CANDIDATE *pc, FSTATUS *pfs)
{
	register char **	pp;
	register char **	pl;

	register PSTATUS *	pps		= pc->pps;

	char *			pipes[2]	= { 0 , 0 };
	char *			cp;
	char *			output_type;

	char **			modes		= 0;
	char **			parms		= 0;
	char **			valid_printer_types;
	char **			p_cpi		= 0;
	char **			p_lpi		= 0;
	char **			p_pwid		= 0;
	char **			p_plen		= 0;

	FILTERTYPE		ret		= fl_none;

	int			got_cpi		= 0;
	int			got_lpi		= 0;
	int			got_plen	= 0;
	int			got_pwid	= 0;
	int			must_have_filter= 0;

	unsigned long		chk;


	/* fix for bugid 1097387	*/
	output_type = (char *) NULL;

	/*
	 * The bulk of the code below is building a parameter list "parms"
	 * to send to "insfilter()".
	 */

	if (prs->request->modes) {
		cp = Strdup(prs->request->modes);
		transform_WS_to_SEP(cp);
		modes = getlist(cp, "", LP_SEP);
		Free (cp);
	}

	pp = parms = (char **)Malloc(
		2 * (NPARM_SPEC + lenlist(modes) + 1) * sizeof(char *)
	);

	/*
	 * Add to the parameter list the appropriate cpi/lpi/etc.
	 * characteristics (aka ``stuff'') that will be used for
	 * this job. The printer defaults are questionable.
	 * Take this opportunity to also save the ``stuff'' in
	 * the request structure.
	 */

	unload_str (&(prs->cpi));
	unload_str (&(prs->lpi));
	unload_str (&(prs->plen));
	unload_str (&(prs->pwid));

	/*
	 * If a form is involved, pick up its page size and print
	 * spacing requirements.
	 */
	if (pfs) {
		if (pfs->cpi) {
			*pp++ = PARM_CPI;
			*pp++ = prs->cpi = pfs->cpi;
			got_cpi = 1;
		}
		if (pfs->lpi) {
			*pp++ = PARM_LPI;
			*pp++ = prs->lpi = pfs->lpi;
			got_lpi = 1;
		}
		if (pfs->plen) {
			*pp++ = PARM_LENGTH;
			*pp++ = prs->plen = pfs->plen;
			got_plen = 1;
		}
		if (pfs->pwid) {
			*pp++ = PARM_WIDTH;
			*pp++ = prs->pwid = pfs->pwid;
			got_pwid = 1;
		}

	/*
	 * If no form is involved, pick up whatever page size and print
	 * spacing requirements were given by the user.
	 */
	} else {
		if (o_cpi) {
			*pp++ = PARM_CPI;
			*pp++ = prs->cpi = o_cpi;
			got_cpi = 1;
		}
		if (o_lpi) {
			*pp++ = PARM_LPI;
			*pp++ = prs->lpi = o_lpi;
			got_lpi = 1;
		}
		if (o_length) {
			*pp++ = PARM_LENGTH;
			*pp++ = prs->plen = o_length;
			got_plen = 1;
		}
		if (o_width) {
			*pp++ = PARM_WIDTH;
			*pp++ = prs->pwid = o_width;
			got_pwid = 1;
		}
	}

	/*
	 * Pick up whatever page size and print spacing requirements
	 * haven't been specified yet from the printer defaults.
	 *
	 * Note: The following cpi/lpi/etc are guaranteed to work
	 * for at least one type of the printer at hand, but not
	 * necessarily all types. Once we pick a type that works
	 * we'll verify that the cpi/lpi/etc stuff works, too.
	 * The code that does that assumes that we do the following last,
	 * after picking up the form and/or user stuff. If this changes,
	 * then the later code will have to be changed, too.
	 */
	if (!got_cpi && pps->cpi) {
		*pp++ = PARM_CPI;
		*(p_cpi = pp++) = prs->cpi = pps->cpi;
	}
	if (!got_lpi && pps->lpi) {
		*pp++ = PARM_LPI;
		*(p_lpi = pp++) = prs->lpi = pps->lpi;
	}
	if (!got_plen && pps->plen) {
		*pp++ = PARM_LENGTH;
		*(p_plen = pp++) = prs->plen = pps->plen;
	}
	if (!got_pwid && pps->pwid) {
		*pp++ = PARM_WIDTH;
		*(p_pwid = pp++) = prs->pwid = pps->pwid;
	}

	/*
	 * Pick up the number of pages, character set (the form's
	 * or the user's), the form name, the number of copies,
	 * and the modes.
	 */

	if (prs->request->pages) {
		*pp++ = PARM_PAGES;
		*pp++ = prs->request->pages;
		must_have_filter = 1;
	}

	if (prs->request->charset) {
		*pp++ = PARM_CHARSET;
		*pp++ = prs->request->charset;

	} else if (pfs && pfs->form->chset) {
		*pp++ = PARM_CHARSET;
		*pp++ = pfs->form->chset;
	}

	if (prs->request->form) {
		*pp++ = PARM_FORM;
		*pp++ = prs->request->form;
	}

	if (prs->request->copies > 1) {
		*pp++ = PARM_COPIES;
		sprintf ((*pp++ = BIGGEST_NUMBER_S), "%d", prs->request->copies);
	}

	if (modes) {
		for (pl = modes; *pl; pl++) {
			*pp++ = PARM_MODES;
			*pp++ = *pl;
		}
		must_have_filter = 1;
	}

	*pp = 0;	/* null terminated list! */


	/*
	 * If the printer type(s) are not ``unknown'', then include
	 * them as possible ``output'' type(s) to match
	 * with the user's input type (directly, or through a filter).
	 */
	if (!STREQU(*(pps->printer->printer_types), NAME_UNKNOWN))
		valid_printer_types = pc->printer_types;
	else {
		valid_printer_types = 0;
		must_have_filter = 0;
	}

	pc->fast = 0;
	pc->slow = 0;
	pc->output_type = 0;
	pc->flags = 0;
	ret = fl_none;

	/*
	 * If we don't really need a filter and the types match,
	 * then that's good enough. Some ``broadly defined''
	 * filters might match our needs, but if the printer
	 * can do what we need, then why pull in a filter?



	 * Besides, Section 3.40 in the requirements imply
	 * that we don't use a filter if the printer can handle
	 * the file.
	 */
	if (!must_have_filter ) {

		if (
			valid_printer_types
		     && searchlist_with_terminfo(
				prs->request->input_type,
				valid_printer_types
			)
		) {
			ret = fl_both;	/* not really, but ok */
			pc->printer_type = Strdup(prs->request->input_type);

		} else if (
			pps->printer->input_types
		     && searchlist_with_terminfo(
				prs->request->input_type,
				pps->printer->input_types
			)
		) {
			ret = fl_both;	/* not really, but ok */

			/*
			 * (1) There is one printer type, might even
			 *     be ``unknown'';
			 * (2) There are several printer types, but that
			 *     means only one input type, ``simple'',
			 *     which any of the printer types can handle.
			 */
			pc->printer_type = Strdup(*(pc->printer_types));

		}
	}

	/*
	 * Don't try using a filter if the user doesn't want
	 * a filter to be used! He or she would rather see an
	 * error message than (heaven forbid!) a filter being
	 * used.
	 */
	if (ret == fl_none && !(prs->request->actions & ACT_RAW)) {

		/*
		 * For each printer type, and each input type the printer
		 * accepts, see if we have a filter that matches the
		 * request to the printer. Each time we try, save the
		 * output type we use in case of success; we just might
		 * need that value later....
		 */

		for (
			pl = valid_printer_types;
			pl && *pl && ret == fl_none;
			pl++
		)
			ret = insfilter(
				pipes,
				prs->request->input_type,
				(output_type = *pl),
				*pl,
				pps->printer->name,
				parms,
				&(pc->flags)
			);
		if (ret != fl_none)
			pc->printer_type = Strdup(*pl);

		for (
			pl = pps->printer->input_types;
			pl && *pl && ret == fl_none;
			pl++
		)
			/*
			 * Don't waste time with check we've already made.
			 */
			if ((must_have_filter == 1) ||
				!valid_printer_types
			     || !searchlist(*pl, valid_printer_types)
			)
				/*
				 * Either we have one (or less) printer
				 * types and many input types, or we have
				 * one input type, ``simple''; regardless,
				 * using the first printer type is OK.
				 */
				ret = insfilter(
					pipes,
					prs->request->input_type,
					(output_type = *pl),
					*(pc->printer_types),
					pps->printer->name,
					parms,
					&(pc->flags)
				);
		if (ret != fl_none)
			pc->printer_type = Strdup(*(pc->printer_types));

	}

	/*
	 * If we were successful, check that the printer type
	 * we picked can handle the PRINTER'S cpi/lpi/etc. defaults.
	 * (We know that ALL the printer's types can handle the stuff
	 * the user gave or the stuff in the form.)
	 * Each printer's default that doesn't pass muster gets dropped.
	 * This may mean re-instantiating the filter(s) (if any).
	 */
	if (ret != fl_none && (p_cpi || p_lpi || p_pwid || p_plen)) {

#define	NZ(X)	((X)? *(X) : (char *)0)
		chk = chkprinter(
			pc->printer_type,
			NZ(p_cpi),
			NZ(p_lpi),
			NZ(p_plen),
			NZ(p_pwid),
			(char *)0
		);

		if (chk) {
			register char **	_pp;

			char *			hole	= "";


			/*
			 * Remove the offending printer defaults from the
			 * request list of cpi/lpi/etc. stuff, and punch
			 * (non-null!) holes in the parameter list.
			 */
#define DROP(P,R)	if (P) {P[-1] = P[0] = hole; R = 0;} else/*EMPTY*/
			if (chk & PCK_CPI)	DROP (p_cpi, prs->cpi);
			if (chk & PCK_LPI)	DROP (p_lpi, prs->lpi);
			if (chk & PCK_WIDTH)	DROP (p_pwid, prs->pwid);
			if (chk & PCK_LENGTH)	DROP (p_plen, prs->plen);

			/*
			 * If there are filters, we have to re-instantiate
			 * them. (Can't check "ret" here, because it may
			 * be misleading.)
			 */
			if (pipes[0] || pipes[1]) {

				/*
				 * First, close up the gaps we punched in
				 * the parameter list.
				 */
				for (pp = _pp = parms; *pp; pp++)
					if (*pp != hole)
						*_pp++ = *pp;
				*_pp = 0;

				/*
				 * Re-instantiate the filter(s). This
				 * CAN'T fail, because it is not mandatory
				 * that filters handle cpi/lpi/etc. stuff.
				 */
				ret = insfilter(
					pipes,
					prs->request->input_type,
					output_type,
					pc->printer_type,
					pps->printer->name,
					parms,
					&(pc->flags)
				);
			}
		}
	}

	/*
	 * Save the filters, if any. Note: although "ret" can be
	 * misleading, i.e. set to "fl_both" when there really aren't
	 * any filters, the declaration of "pipes" ensured they'd be
	 * zero if not set.
	 */
	if (ret == fl_both || ret == fl_slow)
		pc->slow = pipes[0];
	if (ret == fl_both || ret == fl_fast)
		pc->fast = pipes[1];

	if (ret != fl_none)
		pc->output_type = Strdup (output_type);

	/*
	 * Wait until now to allocate storage for the cpi/etc.
	 * stuff, to make life easier above.
	 */
	if (prs->cpi)	prs->cpi = Strdup(prs->cpi);
	if (prs->lpi)	prs->lpi = Strdup(prs->lpi);
	if (prs->plen)	prs->plen = Strdup(prs->plen);
	if (prs->pwid)	prs->pwid = Strdup(prs->pwid);


	if (parms)
		Free ((char *)parms);
	if (modes)
		freelist (modes);

	return ((ret != fl_none));
}
Exemple #17
0
/*-----------------------------------------------------------------------------
 * TclX_ServerAcceptCmd --
 *     Implements the TCL server_accept command:
 *
 *        server_accept ?options? file
 *
 *  Accepts an IP connection request to a socket created by server_create.
 *  Options maybe -buf orr -nobuf.
 *
 * Results:
 *   If successful, a Tcl fileid.
 *-----------------------------------------------------------------------------
 */
static int
TclX_ServerAcceptCmd (ClientData clientData,
                      Tcl_Interp *interp,
                      int argc,
                      const char **argv)
{
    Tcl_Channel          channel;
    unsigned             options;
    int                  acceptSocketFD;
    socklen_t            addrLen;
    int                  socketFD = -1;
    int                  nextArg;
    struct sockaddr_in   connectSocket;

    /*
     * Parse arguments.
     */

    nextArg = 1;
    options = SERVER_BUF;

    while ((nextArg < argc) && (argv [nextArg][0] == '-')) {
        if (STREQU ("-buf", argv [nextArg])) {
            options &= ~SERVER_NOBUF;
            options |= SERVER_BUF;
        } else if (STREQU ("-nobuf", argv [nextArg])) {
            options &= ~SERVER_BUF;
            options |= SERVER_NOBUF;
        } else {
            TclX_AppendObjResult (interp, "expected \"-buf\" or \"-nobuf\", ",
                                  "got \"", argv [nextArg], "\"",
                                  (char *) NULL);
            return TCL_ERROR;
        }
        nextArg++;
    }

    if (nextArg != argc - 1) {
        TclX_AppendObjResult (interp, tclXWrongArgs, argv[0],
                              " ?options? fileid", (char *) NULL);
        return TCL_ERROR;
    }

    /*
     * Accept a socket connection on the socket created by server_create.
     */
    bzero ((VOID *) &connectSocket, sizeof (connectSocket));

    channel = TclX_GetOpenChannel (interp, argv [nextArg], 0);
    if (channel == NULL)
        return TCL_ERROR;

    if (Tcl_GetChannelHandle (channel, 
			      TCL_READABLE, 
			      (ClientData *)&acceptSocketFD) 
	== TCL_ERROR) {
        if (Tcl_GetChannelHandle (channel, 
				  TCL_WRITABLE,
				  (ClientData *)&acceptSocketFD) 
	    == TCL_ERROR)
	        return TCL_ERROR;
    }
    if (acceptSocketFD < 0)
	return TCL_ERROR;

    addrLen = sizeof (connectSocket);
    socketFD = accept (acceptSocketFD, 
                       (struct sockaddr *)&connectSocket, 
                       &addrLen);
    if (socketFD < 0)
        goto unixError;

    /*
     * Set up channels and we are done.
     */
    return BindFileHandles (interp, options, socketFD);

    /*
     * Exit points for errors.
     */
  unixError:
    TclX_AppendObjResult (interp, Tcl_PosixError (interp), (char *) NULL);
    if (socketFD >= 0)
        close (socketFD);
    return TCL_ERROR;
}
Exemple #18
0
/*VARARGS1*/
int
exec(int type, ...)
{
	va_list			args;

	int			i;
	int			procuid;
	int			procgid;
	int			ret;
	int			fr_flg;

	char			*cp;
	char			*infile;
	char			*outfile;
	char			*errfile;
	char			*sep;

	char			**listp;
	char			**file_list;
	char			*printerName;
	char			*printerNameToShow;
	static char		nameBuf[100];
	char			*clean_title;

	PSTATUS			*printer;

	RSTATUS			*request;

	FSTATUS			*form;

	EXEC			*ep;

	PWSTATUS		*pwheel;
	time_t			now;
	struct passwd		*pwp;
#ifdef LP_USE_PAPI_ATTR
	struct stat		tmpBuf;
	char 			tmpName[BUFSIZ];
	char			*path = NULL;
#endif
	char *av[ARG_MAX];
	char **envp = NULL;
	int ac = 0;
	char	*mail_zonename = NULL;
	char	*slabel = NULL;

	syslog(LOG_DEBUG, "exec(%s)", _exec_name(type));

	memset(av, 0, sizeof (*av));

	va_start (args, type);

	switch (type) {

	case EX_INTERF:
		printer = va_arg(args, PSTATUS *);
		request = printer->request;
		ep = printer->exec;
		break;
		
	case EX_FAULT_MESSAGE:
		printer = va_arg(args, PSTATUS *);
		request = va_arg(args, RSTATUS *);
		if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) {
			return(0);
		}
		ep = printer->fault_exec;
		printerName = (printer->printer && printer->printer->name 
				  ? printer->printer->name : "??");
			snprintf(nameBuf, sizeof (nameBuf),
				"%s (on %s)\n", printerName, Local_System);

		printerNameToShow = nameBuf;

		(void) time(&now);
		(void) strftime(time_buf, sizeof (time_buf),
			NULL, localtime(&now));
		break;

	case EX_SLOWF:
		request = va_arg(args, RSTATUS *);
		ep = request->exec;
		break;

	case EX_NOTIFY:
		request = va_arg(args, RSTATUS *);
		if (request->request->actions & ACT_NOTIFY) {
			errno = EINVAL;
			return (-1);
		}
		ep = request->exec;
		break;

	case EX_ALERT:
		printer = va_arg(args, PSTATUS *);
		if (!(printer->printer->fault_alert.shcmd)) {
			errno = EINVAL;
			return(-1);
		}
		ep = printer->alert->exec;
		break;

	case EX_PALERT:
		pwheel = va_arg(args, PWSTATUS *);
		ep = pwheel->alert->exec;
		break;

	case EX_FORM_MESSAGE:
		(void) time(&now);
		(void) strftime(time_buf, sizeof (time_buf),
			NULL, localtime(&now));

		/*FALLTHRU*/
	case EX_FALERT:
		form = va_arg(args, FSTATUS *);
		ep = form->alert->exec;
		break;

	default:
		errno = EINVAL;
		return(-1);

	}
	va_end (args);

	if (!ep || (ep->pid > 0)) {
		errno = EBUSY;
		return(-1);
	}

	ep->flags = 0;

	key = ep->key = getkey();

	switch ((ep->pid = Fork1(ep))) {

	case -1:
		relock ();
		return(-1);

	case 0:
		/*
		 * We want to be able to tell our parent how we died.
		 */
		lp_alloc_fail_handler = child_mallocfail;
		break;

	default:
		switch(type) {

		case EX_INTERF:
			request->request->outcome |= RS_PRINTING;
			break;

		case EX_NOTIFY:
			request->request->outcome |= RS_NOTIFYING;
			break;

		case EX_SLOWF:
			request->request->outcome |= RS_FILTERING;
			request->request->outcome &= ~RS_REFILTER;
			break;

		}
		return(0);

	}

	for (i = 0; i < NSIG; i++)
		(void)signal (i, SIG_DFL);
	(void)signal (SIGALRM, SIG_IGN);
	(void)signal (SIGTERM, sigtrap);

	closelog();
	for (i = 0; i < OpenMax; i++)
		if (i != ChildMd->writefd)
			Close (i);
	openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR);

	setpgrp();

	/* Set a default path */
	addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin");
	/* copy locale related variables */
	addenv (&envp, "TZ", getenv("TZ"));
	addenv (&envp, "LANG", getenv("LANG"));
	addenv (&envp, "LC_ALL", getenv("LC_ALL"));
	addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE"));
	addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE"));
	addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES"));
	addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY"));
	addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC"));
	addenv (&envp, "LC_TIME", getenv("LC_TIME"));

	sprintf ((cp = BIGGEST_NUMBER_S), "%ld", key);
	addenv (&envp, "SPOOLER_KEY", cp);

#if	defined(DEBUG)
	addenv (&envp, "LPDEBUG", (debug? "1" : "0"));
#endif

	/*
	 * Open the standard input, standard output, and standard error.
	 */
	switch (type) {
		
	case EX_SLOWF:
	case EX_INTERF:
		/*
		 * stdin:  /dev/null
		 * stdout: /dev/null (EX_SLOWF), printer port (EX_INTERF)
		 * stderr: req#
		 */
		infile = 0;
		outfile = 0;
		errfile = makereqerr(request);
		break;

	case EX_NOTIFY:
		/*
		 * stdin:  req#
		 * stdout: /dev/null
		 * stderr: /dev/null
		 */
		infile = makereqerr(request);
		outfile = 0;
		errfile = 0;

		break;

	case EX_ALERT:
	case EX_FALERT:
	case EX_PALERT:
	case EX_FAULT_MESSAGE:
	case EX_FORM_MESSAGE:
		/*
		 * stdin:  /dev/null
		 * stdout: /dev/null
		 * stderr: /dev/null
		 */
		infile = 0;
		outfile = 0;
		errfile = 0;
		break;

	}

	if (infile) {
		if (Open(infile, O_RDONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		if (Open("/dev/null", O_RDONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	if (outfile) {
		if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		/*
		 * If EX_INTERF, this is still needed to cause the
		 * standard error channel to be #2.
		 */
		if (Open("/dev/null", O_WRONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	if (errfile) {
		if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	} else {
		if (Open("/dev/null", O_WRONLY) == -1)
			Done (EXEC_EXIT_NOPEN, errno);
	}

	switch (type) {

	case EX_INTERF:
		/*
		 * Opening a ``port'' can be dangerous to our health:
		 *
		 *	- Hangups can occur if the line is dropped.
		 *	- The printer may send an interrupt.
		 *	- A FIFO may be closed, generating SIGPIPE.
		 *
		 * We catch these so we can complain nicely.
		 */
		trap_fault_signals ();

		(void)Close (1);

		if (strchr (request->request->user, '@'))
		{
			procuid = Lp_Uid;
			procgid = Lp_Gid;
		}
		else
		{
			procuid = request->secure->uid;
			procgid = request->secure->gid;
		}
		if (printer->printer->dial_info)
		{
			ret = open_dialup(request->printer_type,
				printer->printer);
			if (ret == 0)
				do_undial = 1;
		}
		else
		{
			ret = open_direct(request->printer_type,
				printer->printer);
			do_undial = 0;
			/* this is a URI */
			if (is_printer_uri(printer->printer->device) == 0)
				addenv(&envp, "DEVICE_URI",
					 printer->printer->device);
		}
				addenv(&envp, "DEVICE_URI",
					 printer->printer->device);
		if (ret != 0)
			Done (ret, errno);
			
		if (!(request->request->outcome & RS_FILTERED))
			file_list = request->request->file_list;

		else {
			register int		count	= 0;
			register char *		num	= BIGGEST_REQID_S;
			register char *		prefix;

			prefix = makestr(
				Lp_Temp,
				"/F",
				getreqno(request->secure->req_id),
				"-",
				(char *)0
			);

			file_list = (char **)Malloc(
				(lenlist(request->request->file_list) + 1)
			      * sizeof(char *)
			);

			for (
				listp = request->request->file_list;
				*listp;
				listp++
			) {
				sprintf (num, "%d", count + 1);
				file_list[count] = makestr(
					prefix,
					num,
					(char *)0
				);
				count++;
			}
			file_list[count] = 0;
		}

#ifdef LP_USE_PAPI_ATTR
		/*
		 * Check if the PAPI job attribute file exists, if it does
		 * pass the file's pathname to the printer interface script
		 * in an environment variable. This file is created when
		 * print jobs are submitted via the PAPI interface.
		 */
		snprintf(tmpName, sizeof (tmpName), "%s-%s",
			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
		path = makepath(Lp_Temp, tmpName, (char *)0);
		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
		{
			/*
			 * IPP job attribute file exists for this job so
			 * set the environment variable
			 */
			addenv(&envp, "ATTRPATH", path);
		}
		Free(path);

		/*
		 * now set environment variable for the printer's PostScript
		 * Printer Description (PPD) file, this is used by the filter
		 * when forming the print data for this printer.
		 */
		if ((request->printer != NULL) &&
		    (request->printer->printer != NULL) &&
		    (request->printer->printer->name != NULL))
		{
			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
				request->printer->printer->name);
			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
			{
				addenv(&envp, "PPD", path);
			}
			Free(path);
		}
#endif

		if (request->printer_type)
			addenv(&envp, "TERM", request->printer_type);

		if (!(printer->printer->daisy)) {
			register char *	chset = 0;
			register char *	csp;

			if (
				request->form
			     && request->form->form->chset
			     && request->form->form->mandatory
			     && !STREQU(NAME_ANY, request->form->form->chset)
			)
				chset = request->form->form->chset;

			else if (
				request->request->charset
			     && !STREQU(NAME_ANY, request->request->charset)
			)
				chset = request->request->charset;

			if (chset) {
				csp = search_cslist(
					chset,
					printer->printer->char_sets
				);

				/*
				 * The "strtok()" below wrecks the string
				 * for future use, but this is a child
				 * process where it won't be needed again.
				 */
				addenv (&envp, "CHARSET",
					(csp? strtok(csp, "=") : chset)
				);
			}
		}

		if (request->fast)
			addenv(&envp, "FILTER", request->fast);

		/*
		 * Add the sensitivity label to the environment for
		 * banner page and header/footer processing
		 */

		if (is_system_labeled() && request->secure->slabel != NULL)
			addenv(&envp, "SLABEL", request->secure->slabel);

		/*
		 * Add the system name to the user name (ala system!user)
		 * unless it is already there. RFS users may have trouble
		 * here, sorry!
		 */
		cp = strchr(request->secure->user, '@');

		allTraysWithForm(printer, request->form); 

		/*
		 * Fix for 4137389
		 * Remove double quotes from title string.
		 */
		fr_flg = 1;
		clean_title = strdup(NB(request->request->title));
		if (clean_title == NULL) {
			/*
			 * strdup failed. We're probably hosed
			 * but try setting clean_title
			 * to original title and continuing.
			 */
			clean_title = NB(request->request->title);
			fr_flg = 0;
		} else if (strcmp(clean_title, "") != 0) {
			char *ct_p;

			for (ct_p = clean_title; *ct_p != NULL; ct_p++) {
				if (*ct_p == '"')
					*ct_p = ' ';
			}
		}

		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces,
					printer->printer->name);
		av[ac++] = arg_string(TRUSTED, "%s", request->secure->req_id);
		av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user);
		av[ac++] = arg_string(TRUSTED, "%s", clean_title);
		av[ac++] = arg_string(TRUSTED, "%d", request->copies);

		if (fr_flg)
			free (clean_title);

		sep = "";

		/*
		 * Do the administrator defined key=value pair options
		 */

		argbuf[0] = '\0';
				
		if (printer->printer->options) {
			char **tmp = printer->printer->options;
			while(*tmp != NULL) {
				STRLCAT(argbuf, sep, sizeof (argbuf));
				sep = " ";
				STRLCAT(argbuf, *tmp++, sizeof (argbuf));
			}
		}

		/*
		 * Do the administrator defined ``stty'' stuff before
		 * the user's -o options, to allow the user to override.
		 */
		if (printer->printer->stty) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "stty='", sizeof (argbuf));
			STRLCAT (argbuf, printer->printer->stty,
			    sizeof (argbuf));
			STRLCAT (argbuf, "'", sizeof (argbuf));
		}

		/*
		 * Do all of the user's options except the cpi/lpi/etc.
		 * stuff, which is done separately.
		 */
		if (request->request->options) {
			listp = dashos(request->request->options);
			while (*listp) {
				if (
					!STRNEQU(*listp, "cpi=", 4)
				     && !STRNEQU(*listp, "lpi=", 4)
				     && !STRNEQU(*listp, "width=", 6)
				     && !STRNEQU(*listp, "length=", 7)
				) {
					STRLCAT (argbuf, sep, sizeof (argbuf));
					sep = " ";
					STRLCAT (argbuf, *listp,
					    sizeof (argbuf));
				}
				listp++;
			}
		}

		/*
		 * The "pickfilter()" routine (from "validate()")
		 * stored the cpi/lpi/etc. stuff that should be
		 * used for this request. It chose form over user,
		 * and user over printer.
		 */
		if (request->cpi) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "cpi=", sizeof (argbuf));
			STRLCAT (argbuf, request->cpi, sizeof (argbuf));
		}
		if (request->lpi) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "lpi=", sizeof (argbuf));
			STRLCAT (argbuf, request->lpi, sizeof (argbuf));
		}
		if (request->pwid) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "width=", sizeof (argbuf));
			STRLCAT (argbuf, request->pwid, sizeof (argbuf));
		}
		if (request->plen) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "length=", sizeof (argbuf));
			STRLCAT (argbuf, request->plen, sizeof (argbuf));
		}

		/*
		 * Do the ``raw'' bit last, to ensure it gets
		 * done. If the user doesn't want this, then he or
		 * she can do the correct thing using -o stty=
		 * and leaving out the -r option.
		 */
		if (request->request->actions & ACT_RAW) {
			STRLCAT (argbuf, sep, sizeof (argbuf));
			sep = " ";
			STRLCAT (argbuf, "stty=-opost", sizeof (argbuf));
		}


		/* the "options" */
		av[ac++] = arg_string(UNTRUSTED, "%s", argbuf);

		for (listp = file_list; *listp; listp++)
			av[ac++] = arg_string(TRUSTED, "%s", *listp);

		(void)chfiles (file_list, procuid, procgid);

		break;


	case EX_SLOWF:
		if (request->slow)
			addenv(&envp, "FILTER", request->slow);

		if (strchr (request->request->user, '@'))
		{
			procuid = Lp_Uid;
			procgid = Lp_Gid;
		}
		else
		{
			procuid = request->secure->uid;
			procgid = request->secure->gid;
		}
		cp = _alloc_files(
			lenlist(request->request->file_list),
			getreqno(request->secure->req_id),
			procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter);
		av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp);
		for (listp = request->request->file_list; *listp; listp++)
			av[ac++] = arg_string(TRUSTED, "%s", *listp);

		(void)chfiles (request->request->file_list, procuid, procgid);

#ifdef LP_USE_PAPI_ATTR
		/*
		 * Check if the PAPI job attribute file exists, if it does
		 * pass the file's pathname to the slow-filters in an
		 * environment variable. Note: this file is created when
		 * print jobs are submitted via the PAPI interface.
		 */
		snprintf(tmpName, sizeof (tmpName), "%s-%s",
			getreqno(request->secure->req_id), LP_PAPIATTRNAME);
		path = makepath(Lp_Temp, tmpName, (char *)0);
		if ((path != NULL) && (stat(path, &tmpBuf) == 0))
		{
			/*
			 * IPP job attribute file exists for this job so
			 * set the environment variable
			 */
			addenv(&envp, "ATTRPATH", path);
		}
		Free(path);


		/*
		 * now set environment variable for the printer's PostScript
		 * Printer Description (PPD) file, this is used by the filter
		 * when forming the print data for this printer.
		 */
		if ((request->printer != NULL) &&
		    (request->printer->printer != NULL) &&
		    (request->printer->printer->name != NULL))
		{
			snprintf(tmpName, sizeof (tmpName), "%s.ppd",
				request->printer->printer->name);
			path = makepath(ETCDIR, "ppd", tmpName, (char *)0);
			if ((path != NULL) && (stat(path, &tmpBuf) == 0))
			{
				addenv(&envp, "PPD", path);
			}
			Free(path);
		}
#endif
		break;

	case EX_ALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (printer->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
				printer->printer->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_PALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (pwheel->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels,
				pwheel->pwheel->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_FALERT:
		procuid = Lp_Uid;
		procgid = Lp_Gid;
		(void)Chown (form->alert->msgfile, procuid, procgid);

		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
				form->form->name, ALERTSHFILE);
		av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile);

		break;

	case EX_FORM_MESSAGE:
		procuid = Lp_Uid;
		procgid = Lp_Gid;

		av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults);
		av[ac++] = arg_string(TRUSTED, "%s", form->form->name);
		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms,
				form->form->name, FORMMESSAGEFILE);

		break;

	case EX_FAULT_MESSAGE:
		procuid = Lp_Uid;
		procgid = Lp_Gid;

		av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults);
		av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow);
		av[ac++] = arg_string(TRUSTED, "%s", time_buf);
		av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers,
				printerName, FAULTMESSAGEFILE);

		break;

	case EX_NOTIFY:
		if (request->request->alert) {
			if (strchr(request->request->user, '@')) {
				procuid = Lp_Uid;
				procgid = Lp_Gid;
			} else {
				procuid = request->secure->uid;
				procgid = request->secure->gid;
			}
			av[ac++] = arg_string(TRUSTED, "%s",
					request->request->alert);
		} else {
			char *user = strdup(request->request->user);
			clean_string(user);
			slabel = request->secure->slabel;

			if (request->request->actions & ACT_WRITE) {
				av[ac++] = arg_string(TRUSTED, "%s", BINWRITE);
				snprintf(argbuf, sizeof (argbuf),
					"%s %s || %s %s",
					BINWRITE, user,
					BINMAIL, user
				);
				av[ac++] = arg_string(TRUSTED, "/bin/sh");
				av[ac++] = arg_string(TRUSTED, "-c");
				av[ac++] = arg_string(TRUSTED, "%s", argbuf);
			} else if ((getzoneid() == GLOBAL_ZONEID) &&
				   is_system_labeled() && (slabel != NULL)) {
				/*
				 * If in the global zone and the system is
				 * labeled, mail is handled via a local
				 * labeled zone that is the same label as
				 * the request.
				 */
				if ((mail_zonename =
				    get_labeled_zonename(slabel)) ==
				    (char *)-1) {
					/*
					 * Cannot find labeled zone, just
					 * return 0.
					 */
					return(0);
				}
			}
			if (mail_zonename == NULL) {
				procuid = Lp_Uid;
				procgid = Lp_Gid;
				av[ac++] = arg_string(TRUSTED, "%s", BINMAIL);
				av[ac++] = arg_string(UNTRUSTED, "%s", user);
			} else {
				procuid = getuid();
				procgid = getgid();
				av[ac++] = arg_string(TRUSTED, "%s",
				    "/usr/sbin/zlogin");
				av[ac++] = arg_string(TRUSTED, "%s",
				    mail_zonename);
				av[ac++] = arg_string(TRUSTED, "%s",
				    BINMAIL);
				av[ac++] = arg_string(UNTRUSTED, "%s",
				    user);
				Free(mail_zonename);
			}

			free(user);
		}
		break;
	}

	av[ac++] = NULL;

	Fork2 ();
	/* only the child returns */

	/*
	 * Correctly set up the supplemental group list
	 * for proper file access (before execl the interface program)
	 */

	pwp = getpwuid(procuid);
	if (pwp == NULL) {
		note("getpwuid(%d) call failed\n", procuid);
	} else if (initgroups(pwp->pw_name, procgid) < 0) {
		note("initgroups() call failed %d\n", errno);
	}
	
	setgid (procgid);
	setuid (procuid);

	/*
	 * The shell doesn't allow the "trap" builtin to set a trap
	 * for a signal ignored when the shell is started. Thus, don't
	 * turn off signals in the last child!
	 */

#ifdef DEBUG
	for (i = 0; av[i] != NULL; i++)
		note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]);
	for (i = 0; envp[i] != NULL; i++)
		note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]);
#endif

	execvpe(av[0], av, envp);
	Done (EXEC_EXIT_NEXEC, errno);
	/*NOTREACHED*/
	return (0);
}
Exemple #19
0
void
s_inquire_request_rank(char *m, MESG *md)
{
	char		*form;
	char		*dest;
	char		*pwheel;
	char		*user;
	char		*req_id;
	RSTATUS		*rp;
	RSTATUS		*found = NULL;
	int		found_rank = 0;
	short		prop;
	char		files[BUFSIZ];
	int 		i;

	(void) getmessage(m, S_INQUIRE_REQUEST_RANK, &prop, &form, &dest,
	    &req_id, &user, &pwheel);
	syslog(LOG_DEBUG, "s_inquire_request_rank(%d, %s, %s, %s, %s, %s)",
	    prop, (form ? form : "NULL"), (dest ? dest : "NULL"),
	    (req_id ? req_id : "NULL"), (user ? user : "******"),
	    (pwheel ? pwheel : "NULL"));

	for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
		PStatus[i]->nrequests = 0;

	for (rp = Request_List; rp != NULL; rp = rp->next) {
		if (rp->printer && !(rp->request->outcome & RS_DONE))
			rp->printer->nrequests++;

		if (*form && !SAME(form, rp->request->form))
			continue;

		if (*dest && !STREQU(dest, rp->request->destination)) {
			if (!rp->printer)
				continue;
			if (!STREQU(dest, rp->printer->printer->name))
				continue;
		}

		if (*req_id && !STREQU(req_id, rp->secure->req_id))
			continue;

		if (*user && !bangequ(user, rp->secure->user))
			continue;

		if (*pwheel && !SAME(pwheel, rp->pwheel_name))
			continue;
		/*
		 * For Trusted Extensions, we need to check the sensitivity
		 * label of the connection and job before we return it to the
		 * client.
		 */
		if ((md->admin <= 0) && (is_system_labeled()) &&
		    (md->slabel != NULL) && (rp->secure->slabel != NULL) &&
		    (!STREQU(md->slabel, rp->secure->slabel)))
			continue;

		if (found) {
			GetRequestFiles(found->request, files, sizeof (files));
			mputm(md, R_INQUIRE_REQUEST_RANK,
			    MOKMORE,
			    found->secure->req_id,
			    found->request->user,
			    /* bgolden 091996, bug 1257405 */
			    found->secure->slabel,
			    found->secure->size,
			    found->secure->date,
			    found->request->outcome,
			    found->printer->printer->name,
			    (found->form? found->form->form->name : ""),
			    NB(found->pwheel_name),
			    found_rank,
			    files);
		}
		found = rp;
		found_rank = found->printer->nrequests;
	}

	if (found) {
		GetRequestFiles(found->request, files, sizeof (files));
		mputm(md, R_INQUIRE_REQUEST_RANK,
		    MOK,
		    found->secure->req_id,
		    found->request->user, /* bgolden 091996, bug 1257405 */
		    found->secure->slabel,
		    found->secure->size,
		    found->secure->date,
		    found->request->outcome,
		    found->printer->printer->name,
		    (found->form? found->form->form->name : ""),
		    NB(found->pwheel_name),
		    found_rank,
		    files);
	} else
		mputm(md, R_INQUIRE_REQUEST_RANK, MNOINFO, "", "", "", 0L, 0L,
		    0, "", "", "", 0, "");
}
Exemple #20
0
/*-----------------------------------------------------------------------------
 * ProcessSignalListEntry --
 *     
 *    Parse a keyed list entry used to describe a signal state and set the
 * signal to that state.  If the signal action is specified as "unknown",
 * it is ignored.
 *
 * Parameters::
 *   o interp - Error messages are returned here.
 *   o signalName - Signal name.
 *   o stateObjPtr - Signal state information from keyed list.
 * Returns:
 *   TCL_OK or TCL_ERROR;
 *-----------------------------------------------------------------------------
 */
static int
ProcessSignalListEntry (Tcl_Interp *interp,
                        char       *signalName,
                        Tcl_Obj    *stateObjPtr)
{
    Tcl_Obj **stateObjv;
    int stateObjc;
    char *actionStr, *cmdStr;
    int signalNum, blocked;
    signalProcPtr_t  actionFunc = NULL;
    int restart = FALSE;
    unsigned char signals [MAXSIG];

    /*
     * Get state list.
     */
    if (Tcl_ListObjGetElements (interp, stateObjPtr,
                                &stateObjc, &stateObjv) != TCL_OK)
        return TCL_ERROR;
    if (stateObjc < 2 || stateObjc > 4)
        goto invalidEntry;
    
    /*
     * Parse the signal name and action.
     */
    if (SigNameToNum (interp, signalName, &signalNum) != TCL_OK)
        return TCL_ERROR;
    
    actionStr = Tcl_GetStringFromObj (stateObjv [0], NULL);
    cmdStr = NULL;
    if (stateObjc > 2) {
        cmdStr = Tcl_GetStringFromObj (stateObjv [2], NULL);
        if (cmdStr[0] == '\0') {
            cmdStr = NULL;
        }
    }
    if (STREQU (actionStr, SIGACT_DEFAULT)) {
        actionFunc = SIG_DFL;
        if (cmdStr != NULL)
            goto invalidEntry;
    } else if (STREQU (actionStr, SIGACT_IGNORE)) {
        actionFunc = SIG_IGN;
        if (cmdStr != NULL)
            goto invalidEntry;
    } else if (STREQU (actionStr, SIGACT_ERROR)) {
        actionFunc = SignalTrap;
        if (cmdStr != NULL)
            goto invalidEntry;
    } else if (STREQU (actionStr, SIGACT_TRAP)) {
        actionFunc = SignalTrap;
        if (cmdStr == NULL)    /* Must have command */
            goto invalidEntry;
    } else if (STREQU (actionStr, SIGACT_UNKNOWN)) {
        if (cmdStr != NULL)
            goto invalidEntry;
        return TCL_OK;  /* Ignore non-Tcl signals */
    }

    if (Tcl_GetBooleanFromObj (interp, stateObjv [1], &blocked) != TCL_OK)
        return TCL_ERROR;
    if (stateObjc > 3) {
        if (Tcl_GetBooleanFromObj (interp, stateObjv [3], &restart) != TCL_OK)
            return TCL_ERROR;
    }
    
    memset (signals, FALSE, sizeof (unsigned char) * MAXSIG);
    signals [signalNum] = TRUE;

    /*
     * Set signal actions and handle blocking if its supported on this
     * system.  If the signal is to be blocked, we do it before setting up
     * the handler.  If its to be unblocked, we do it after.
     */
#ifndef NO_SIGACTION
    if (blocked) {
        if (BlockSignals (interp, SIG_BLOCK, signals) != TCL_OK)
            return TCL_ERROR;
    }
#endif
    if (SetSignalActions (interp, signals, actionFunc, restart,
                          cmdStr) != TCL_OK)
        return TCL_ERROR;
#ifndef NO_SIGACTION
    if (!blocked) {
        if (BlockSignals (interp, SIG_UNBLOCK, signals) != TCL_OK)
            return TCL_ERROR;
    }
#endif
    
    return TCL_OK;

  invalidEntry:
    TclX_AppendObjResult (interp, "invalid signal keyed list entry for ",
                          signalName, (char *) NULL);
    return TCL_ERROR;
}
Exemple #21
0
/*-----------------------------------------------------------------------------
 * ReturnStatItem --
 *
 *   Return a single file status item.
 *
 * Parameters:
 *   o interp (I) - Item or error returned in result.
 *   o channel (I) - Channel the file is assoicated with.
 *   o ttyDev (O) - A boolean indicating if the device is associated with a
 *     tty.
 *   o statBufPtr (I) - Pointer to a buffer initialized by stat or fstat.
 *   o itemName (I) - The name of the desired item.
 * Returns:
 *   TCL_OK or TCL_ERROR.
 *-----------------------------------------------------------------------------
 */
static int
ReturnStatItem (Tcl_Interp   *interp,
                Tcl_Channel   channel,
                int           ttyDev,
                struct stat  *statBufPtr,
                char         *itemName)
{
    Tcl_Obj *objPtr;

    if (STREQU (itemName, "dev"))
        objPtr = Tcl_NewIntObj ((int) statBufPtr->st_dev);
    else if (STREQU (itemName, "ino"))
        objPtr = Tcl_NewIntObj ((int) statBufPtr->st_ino);
    else if (STREQU (itemName, "mode"))
        objPtr = Tcl_NewIntObj ((int) statBufPtr->st_mode);
    else if (STREQU (itemName, "nlink"))
        objPtr = Tcl_NewIntObj ((int) statBufPtr->st_nlink);
    else if (STREQU (itemName, "uid"))
        objPtr = Tcl_NewIntObj ((int) statBufPtr->st_uid);
    else if (STREQU (itemName, "gid"))
        objPtr = Tcl_NewIntObj ((int) statBufPtr->st_gid);
    else if (STREQU (itemName, "size"))
        objPtr = Tcl_NewLongObj ((long) statBufPtr->st_size);
    else if (STREQU (itemName, "atime"))
        objPtr = Tcl_NewLongObj ((long) statBufPtr->st_atime);
    else if (STREQU (itemName, "mtime"))
        objPtr = Tcl_NewLongObj ((long) statBufPtr->st_mtime);
    else if (STREQU (itemName, "ctime"))
        objPtr = Tcl_NewLongObj ((long) statBufPtr->st_ctime);
    else if (STREQU (itemName, "type"))
        objPtr = Tcl_NewStringObj (StrFileType (statBufPtr), -1);
    else if (STREQU (itemName, "tty"))
        objPtr = Tcl_NewBooleanObj (ttyDev);
    else if (STREQU (itemName, "remotehost")) {
        objPtr = TclXGetHostInfo (interp, channel, TRUE);
        if (objPtr == NULL)
            return TCL_ERROR;
    } else if (STREQU (itemName, "localhost")) {
        objPtr = TclXGetHostInfo (interp, channel, FALSE);
        if (objPtr == NULL)
            return TCL_ERROR;
    } else {
        TclX_AppendObjResult (interp, "Got \"", itemName,
                              "\", expected one of ",
                              "\"atime\", \"ctime\", \"dev\", \"gid\", ",
                              "\"ino\", \"mode\", \"mtime\", \"nlink\", ",
                              "\"size\", \"tty\", \"type\", \"uid\", ",
                              "\"remotehost\", or \"localhost\"",
                              (char *) NULL);
        return TCL_ERROR;
    }

    Tcl_SetObjResult (interp, objPtr);
    return TCL_OK;
}
Exemple #22
0
int
putprinter(char *name, PRINTER *prbufp)
{
	register char *		path;
	register char *		stty;
	register char *		speed;

	int fdin, fdout;

	int			fld;

	char			buf[BUFSIZ];

	struct stat		statbuf1,
				statbuf2;


	badprinter = 0;

	if (!name || !*name) {
		errno = EINVAL;
		return (-1);
	}

	if (STREQU(NAME_ALL, name)) {
		errno = EINVAL;
		return (-1);
	}

	/*
	 * First go through the structure and see if we have
	 * anything strange.
	 */
	if (!okprinter(name, prbufp, 1)) {
		errno = EINVAL;
		return (-1);
	}

	if (!Lp_A_Printers || !Lp_A_Interfaces) {
		getadminpaths (LPUSER);
		if (!Lp_A_Printers || !Lp_A_Interfaces)
			return (0);
	}

	/*
	 * Create the parent directory for this printer
	 * if it doesn't yet exist.
	 */
	if (!(path = getprinterfile(name, (char *)0)))
		return (-1);
	if (Stat(path, &statbuf1) == 0) {
		if (!S_ISDIR(statbuf1.st_mode)) {
			Free (path);
			errno = ENOTDIR;
			return (-1);
		}
	} else if (errno != ENOENT || mkdir_lpdir(path, MODE_DIR) == -1) {
		Free (path);
		return (-1);
	}
	Free (path);

	/*
	 * Create the copy of the interface program, unless
	 * that would be silly or not desired.
	 * Conversely, make sure the interface program doesn't
	 * exist for a remote printer.
	 */
	if (prbufp->remote) {
		if (!(path = makepath(Lp_A_Interfaces, name, (char *)0)))
			return (-1);
		(void)rmfile (path);
		Free (path);
	}
	if (prbufp->interface && (ignprinter & BAD_INTERFACE) == 0) {
		if (Stat(prbufp->interface, &statbuf1) == -1)
			return (-1);
		if (!(path = makepath(Lp_A_Interfaces, name, (char *)0)))
			return (-1);
		if (
			Stat(path, &statbuf2) == -1
		     || statbuf1.st_dev != statbuf2.st_dev
		     || statbuf1.st_ino != statbuf2.st_ino
		) {
			register int		n;

			if ((fdin = open_locked(prbufp->interface, "r", 0)) < 0) {
				Free (path);
				return (-1);
			}
			if ((fdout = open_locked(path, "w", MODE_EXEC)) < 0) {
				Free (path);
				close(fdin);
				return (-1);
			}
			while ((n = read(fdin, buf, BUFSIZ)) > 0)
				write (fdout, buf,  n);
			close(fdout);
			close(fdin);
		}
		Free (path);
	}

#ifdef LP_USE_PAPI_ATTR
	/*
	 * Handle PPD (Postscript Printer Definition) file for printer
	 * if this printer has been configured with one
	 */
	if ((prbufp->ppd != NULL) && (ppdopt))
	{
		if (addPrintersPPD(name, prbufp) != 0)
		{
			/* failed to added the printers PPD file */
			return (-1);
		}
	}
#endif

	/*
	 * If this printer is dialed up, remove any baud rates
	 * from the stty option list and move the last one to
	 * the ".speed" member if the ".speed" member isn't already
	 * set. Conversely, if this printer is directly connected,
	 * move any value from the ".speed" member to the stty list.
	 */

	stty = (prbufp->stty? Strdup(prbufp->stty) : 0);
	if (prbufp->speed)
		speed = Strdup(prbufp->speed);
	else
		speed = 0;

	if (prbufp->dial_info && stty) {
		register char		*newstty,
					*p,
					*q;

		register int		len;

		if (!(q = newstty = Malloc(strlen(stty) + 1))) {
			Free (stty);
			errno = ENOMEM;
			return (-1);
		}
		newstty[0] = 0;	/* start with empty copy */

		for (
			p = strtok(stty, " ");
			p;
			p = strtok((char *)0, " ")
		) {
			len = strlen(p);
			if (strspn(p, "0123456789") == len) {
				/*
				 * If "prbufp->speed" isn't set, then
				 * use the speed we just found. Don't
				 * check "speed", because if more than
				 * one speed was given in the list, we
				 * want the last one.
				 */
				if (!prbufp->speed) {
					if (speed)
						Free (speed);
					speed = Strdup(p);
				}

			} else {
				/*
				 * Not a speed, so copy it to the
				 * new stty string.
				 */
				if (q != newstty)
					*q++ = ' ';
				strcpy (q, p);
				q += len;
			}
		}

		Free (stty);
		stty = newstty;

	} else if (!prbufp->dial_info && speed) {
		register char		*newstty;

		newstty = Malloc(strlen(stty) + 1 + strlen(speed) + 1);
		if (!newstty) {
			if (stty)
				Free (stty);
			errno = ENOMEM;
			return (-1);
		}

		if (stty) {
			strcpy (newstty, stty);
			strcat (newstty, " ");
			strcat (newstty, speed);
			Free (stty);
		} else
			strcpy (newstty, speed);
		Free (speed);
		speed = 0;

		stty = newstty;

	}

	/*
	 * Open the configuration file and write out the printer
	 * configuration.
	 */

	if (!(path = getprinterfile(name, CONFIGFILE))) {
		if (stty)
			Free (stty);
		if (speed)
			Free (speed);
		return (-1);
	}
	if ((fdout = open_locked(path, "w", MODE_READ)) < 0) {
		Free (path);
		if (stty)
			Free (stty);
		if (speed)
			Free (speed);
		return (-1);
	}
	Free (path);

	errno = 0;
	for (fld = 0; fld < PR_MAX; fld++) {
		if (prbufp->remote && !prtrheadings[fld].okremote)
			continue;

		switch (fld) {

#define HEAD	prtrheadings[fld].v

		case PR_BAN:
			{
				char *ptr = NAME_ON;

				switch (prbufp->banner) {
				case BAN_ALWAYS:
					ptr = NAME_ON;
					break;
				case BAN_NEVER:
					ptr = NAME_OFF;
					break;
				case BAN_OPTIONAL:
					ptr = NAME_OPTIONAL;
					break;
				}
				(void)fdprintf(fdout, "%s %s\n", HEAD, ptr);
			}
			break;

		case PR_CPI:
			print_sdn(fdout, HEAD, prbufp->cpi);
			break;

		case PR_CS:
			if (!emptylist(prbufp->char_sets))
				print_l(fdout, HEAD, prbufp->char_sets);
			break;

		case PR_ITYPES:
			/*
			 * Put out the header even if the list is empty,
			 * to distinguish no input types from the default.
			 */
			print_l(fdout, HEAD, prbufp->input_types);
			break;

		case PR_DEV:
			print_str(fdout, HEAD, prbufp->device);
			break;

		case PR_DIAL:
			print_str(fdout, HEAD, prbufp->dial_info);
			break;

		case PR_RECOV:
			print_str(fdout, HEAD, prbufp->fault_rec);
			break;

		case PR_INTFC:
			print_str(fdout, HEAD, prbufp->interface);
			break;

		case PR_LPI:
			print_sdn(fdout, HEAD, prbufp->lpi);
			break;

		case PR_LEN:
			print_sdn(fdout, HEAD, prbufp->plen);
			break;

		case PR_LOGIN:
			if (prbufp->login & LOG_IN)
				(void)fdprintf(fdout, "%s\n", HEAD);
			break;

		case PR_PTYPE:
		{
			char			**printer_types;

			/*
			 * For backward compatibility for those who
			 * use only "->printer_type", we have to play
			 * some games here.
			 */
			if (prbufp->printer_type && !prbufp->printer_types)
				printer_types = getlist(
					prbufp->printer_type,
					LP_WS,
					LP_SEP
				);
			else
				printer_types = prbufp->printer_types;

			if (!printer_types || !*printer_types)
				print_str(fdout, HEAD, NAME_UNKNOWN);
			else
				print_l(fdout, HEAD, printer_types);

			if (printer_types != prbufp->printer_types)
				freelist (printer_types);
			break;
		}

		case PR_REMOTE:
			print_str(fdout, HEAD, prbufp->remote);
			break;

		case PR_SPEED:
			print_str(fdout, HEAD, speed);
			break;

		case PR_STTY:
			print_str(fdout, HEAD, stty);
			break;

		case PR_WIDTH:
			print_sdn(fdout, HEAD, prbufp->pwid);
			break;

#if	defined(CAN_DO_MODULES)
		case PR_MODULES:
			/*
			 * Put out the header even if the list is empty,
			 * to distinguish no modules from the default.
			 */
			print_l(fdout, HEAD, prbufp->modules);
			break;
#endif

		case PR_OPTIONS:
			print_l(fdout, HEAD, prbufp->options);
			break;

		case PR_PPD:
		{
			print_str(fdout, HEAD, prbufp->ppd);
			break;
		}
		}

	}
	if (stty)
		Free (stty);
	if (speed)
		Free (speed);
	if (errno != 0) {
		close(fdout);
		return (-1);
	}
	close(fdout);

	/*
	 * If we have a description of the printer,
	 * write it out to a separate file.
	 */
	if (prbufp->description) {

		if (!(path = getprinterfile(name, COMMENTFILE)))
			return (-1);

		if (dumpstring(path, prbufp->description) == -1) {
			Free (path);
			return (-1);
		}
		Free (path);
	
	}

	/*
	 * Now write out the alert condition.
	 */
	if (
		prbufp->fault_alert.shcmd
	     && putalert(Lp_A_Printers, name, &(prbufp->fault_alert)) == -1
	)
		return (-1);

	return (0);
}
Exemple #23
0
void
notify(register RSTATUS *prs, char *errbuf, int k, int e, int slow)
{
	register char		*cp;
	char			*file;
	int			fd;


	/*
	 * Screen out cases where no notification is needed.
	 */
	if (!(prs->request->outcome & RS_NOTIFY))
		return;
	if (
		!(prs->request->actions & (ACT_MAIL|ACT_WRITE|ACT_NOTIFY))
	     && !prs->request->alert
	     && !(prs->request->outcome & RS_CANCELLED)
	     && !e && !k && !errbuf       /* exited normally */
	)
		return;

	/*
	 * Create the notification message to the user.
	 */
	file = makereqerr(prs);
	if ((fd = open_locked(file, "w", MODE_NOREAD)) >= 0) {
		fdprintf(fd, N_Msg[0], prs->secure->req_id, prs->secure->req_id,
			prs->request->destination,
			STREQU(prs->request->destination, NAME_ANY)? " printer"
				: "");

		if (prs->request) {
			char file[BUFSIZ];
			
			GetRequestFiles(prs->request, file, sizeof(file));
			fdprintf(fd, "\nThe job title was:\t%s\n", file);
			fdprintf(fd, "     submitted by:\t%s\n",
				prs->request->user);
			fdprintf(fd, "               at:\t%s\n",
				ctime(&prs->secure->date));
		}
	
		if (prs->request->outcome & RS_PRINTED)
			fdprintf(fd, N_Msg[1], prs->printer->printer->name);

		if (prs->request->outcome & RS_CANCELLED)
			fdprintf(fd, N_Msg[2],
				(prs->request->outcome & RS_FAILED)? ", and"
					: ".");
		
	
		if (prs->request->outcome & RS_FAILED) {
			if (slow)
				fdprintf(fd, N_Msg[3]);
			else
				fdprintf(fd, N_Msg[4],
					prs->printer->printer->name);
	
			if (e > 0)
				fdprintf(fd, N_Msg[slow? 5 : 6], e);
			else if (k)
				fdprintf(fd, N_Msg[slow? 7 : 8], k);
		}
	
		if (errbuf) {
			for (cp = errbuf; *cp && *cp == '\n'; cp++)
				;
			fdprintf(fd, N_Msg[9], cp);
			if (prs->request->outcome & RS_CANCELLED)
				fdprintf(fd, "\n");
		}

		/* start fix for bugid 1100252	*/
		if (prs->request->outcome & RS_CANCELLED) {
			print_reason (fd, prs->reason);
		}

		close(fd);
		schedule (EV_NOTIFY, prs);

	}
	if (file)
		Free (file);

	return;
}
Exemple #24
0
/*-----------------------------------------------------------------------------
 * TclX_ServerCreateCmd --
 *     Implements the TCL server_create command:
 *
 *        server_create ?options?
 *
 *  Creates a socket, binds the address and port on the local machine 
 * (optionally specified by the caller), and starts the port listening 
 * for connections by calling listen (2).
 *
 *  Options may be "-myip ip_address", "-myport port_number",
 * "-myport reserved", and "-backlog backlog".
 *
 * Results:
 *   If successful, a Tcl fileid is returned.
 *
 *-----------------------------------------------------------------------------
 */
static int
TclX_ServerCreateCmd (ClientData clientData,
                      Tcl_Interp *interp,
                      int argc,
                      const char **argv)
{
    int socketFD = -1, nextArg;
    struct sockaddr_in  local;
    int myPort, value;
    int backlog = 5;
    int getReserved = FALSE;
    Tcl_Channel channel = NULL;

    /*
     * Parse arguments.
     */
    bzero ((VOID *) &local, sizeof (local));
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = INADDR_ANY;
    nextArg = 1;

    while ((nextArg < argc) && (argv [nextArg][0] == '-')) {
        if (STREQU ("-myip", argv [nextArg])) {
            if (nextArg >= argc - 1)
                goto missingArg;
            nextArg++;
            if (TclXOSInetAtoN (interp, argv [nextArg],
                                &local.sin_addr) == TCL_ERROR)
                return TCL_ERROR;
        } else if (STREQU ("-myport", argv [nextArg])) {
            if (nextArg >= argc - 1)
                goto missingArg;
            nextArg++;
            if (STREQU (argv [nextArg], "reserved")) {
                getReserved = TRUE;
            } else {
                if (Tcl_GetInt (interp, argv [nextArg], &myPort) != TCL_OK)
                    return TCL_ERROR;
                local.sin_port = htons (myPort);
            }
        } else if (STREQU ("-backlog", argv [nextArg])) {
            if (nextArg >= argc - 1)
                goto missingArg;
            nextArg++;
            if (Tcl_GetInt (interp, argv [nextArg], &backlog) != TCL_OK)
                return TCL_ERROR;
        } else if (STREQU ("-reuseaddr", argv [nextArg])) {
            /* Ignore for compatibility */
        } else {
            TclX_AppendObjResult (interp, "expected ",
                                  "\"-myip\", \"-myport\", or \"-backlog\", ",
                                  "got \"", argv [nextArg], "\"",
                                  (char *) NULL);
            return TCL_ERROR;
        }
        nextArg++;
    }

    if (nextArg != argc) {
        TclX_AppendObjResult (interp, tclXWrongArgs, argv[0],
                              " ?options?", (char *) NULL);
        return TCL_ERROR;
    }

    /*
     * Allocate a reserved port if requested.
     */
    if (getReserved) {
        int port;
        if (rresvport (&port) < 0)
            goto unixError;
        local.sin_port = port;
    }

    /*
     * Open a socket and bind an address and port to it.
     */
    socketFD = socket (local.sin_family, SOCK_STREAM, 0);
    if (socketFD < 0)
        goto unixError;

    value = 1;
    if (setsockopt (socketFD, SOL_SOCKET, SO_REUSEADDR,
                    (void*) &value, sizeof (value)) < 0) {
        goto unixError;
    }
    if (bind (socketFD, (struct sockaddr *) &local, sizeof (local)) < 0) {
        goto unixError;
    }

    if (listen (socketFD, backlog) < 0)
        goto unixError;

    channel = Tcl_MakeTcpClientChannel ((ClientData) socketFD);
    Tcl_RegisterChannel (interp, channel);

    TclX_AppendObjResult (interp, Tcl_GetChannelName (channel), (char *) NULL);
    return TCL_OK;

    /*
     * Exit points for errors.
     */
  missingArg:
    TclX_AppendObjResult (interp, "missing argument for ", argv [nextArg],
                          (char *) NULL);
    return TCL_ERROR;

  unixError:
    TclX_AppendObjResult (interp, Tcl_PosixError (interp), (char *) NULL);
    CloseForError (interp, channel, socketFD);
    return TCL_ERROR;
}