/* * 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) 2016 by Delphix. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* SVr4.0 1.11.1.10 */ /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */ #include "lpsched.h" #include "validate.h" #include #include #include #include #include #define register auto int pickfilter ( RSTATUS * , CANDIDATE * , FSTATUS * ); unsigned long chkprinter_result = 0; char * o_cpi = 0; char * o_lpi = 0; char * o_width = 0; char * o_length = 0; static int wants_nobanner = 0; static int wants_nolabels = 0; static int lp_or_root = 0; static int _chkopts ( RSTATUS *, CANDIDATE * , FSTATUS * ); static void free_candidate ( CANDIDATE * ); static int tsol_check_printer_label_range(char *, const char *); static int tsol_lpauth(char *, char *); static int secpolicy_chkpolicy(char *policyp); /** ** _validate() - FIND A PRINTER TO HANDLE A REQUEST **/ short _validate(RSTATUS *prs, PSTATUS *pps, PSTATUS *stop_pps, char **prefixp, int moving) { register CANDIDATE *pc = 0, *pcend, *best_pc = 0; register FSTATUS *pfs = 0; register CLSTATUS *pcs = 0; CANDIDATE *arena = 0, single; size_t n; int i; short ret; chkprinter_result = 0; o_cpi = o_lpi = o_width = o_length = 0; wants_nobanner = 0; memset (&single, 0, sizeof(single)); wants_nolabels = 0; /* * If the system is labeled, the printing of postscript files * is restricted. All users can print postscript files if the * file /etc/default/print contains "PRINT_POSTSCRIPT=1". * (this is checked by secpolicy_chkpolicy). Otherwise the * user must have PRINT_POSTSCRIPT_AUTH to print postscript files. */ if ((is_system_labeled() && strcmp(prs->request->input_type, "postscript") == 0) && (secpolicy_chkpolicy("PRINT_POSTSCRIPT=") == 0)) { if (tsol_lpauth(PRINT_POSTSCRIPT_AUTH, prs->secure->user) == 0) { ret = MDENYDEST; goto Return; } } lp_or_root = 0; if (bangequ(prs->secure->user, "root") || bangequ(prs->secure->user, "lp")) lp_or_root = 1; if (prefixp) *prefixp = prs->request->destination; /* * If a destination other than "any" was given, * see if it exists in our internal tables. */ if (!pps && prs->request->destination && !STREQU(prs->request->destination, NAME_ANY)) if (((pps = search_pstatus(prs->request->destination)) != NULL) || ((pcs = search_cstatus(prs->request->destination)) != NULL) && pcs->class->members) /*EMPTY*/; else { ret = MNODEST; goto Return; } /* * If we are trying to avoid a printer, but the request * was destined for just that printer, we're out. */ if (pps && pps == stop_pps) { ret = MERRDEST; goto Return; } /* * If a form was given, see if it exists; if so, * see if the user is allowed to use it. * If a remote printer was specified, then don't use any local * form knowledge. */ if (prs && prs->request && prs->request->form && (pps || pcs)) { if ((pfs = search_fstatus(prs->request->form))) { if (lp_or_root || allowed(prs->secure->user, pfs->users_allowed, pfs->users_denied)) /*EMPTY*/; else { ret = MDENYMEDIA; goto Return; } } else { ret = MNOMEDIA; goto Return; } } /* * If the request includes -o options there may be pitch and * size and no-banner requests that have to be checked. One * could argue that this shouldn't be in the Spooler, because * the Spooler's job is SPOOLING, not PRINTING. That's right, * except that the Spooler will be making a choice of printers * so it has to evaluate carefully: E.g. user wants ANY printer, * so we should pick one that can handle what they want. * * Parse out the important stuff here so we have it when we * need it. */ { register char **list, **pl; if ( prs->request->options && (list = dashos(prs->request->options)) ) { for (pl = list ; *pl; pl++) if (STRNEQU(*pl, "cpi=", 4)) o_cpi = Strdup(*pl + 4); else if (STRNEQU(*pl, "lpi=", 4)) o_lpi = Strdup(*pl + 4); else if (STRNEQU(*pl, "width=", 6)) o_width = Strdup(*pl + 6); else if (STRNEQU(*pl, "length=", 7)) o_length = Strdup(*pl + 7); else if (STREQU(*pl, "nobanner")) wants_nobanner = 1; else if (STREQU(*pl, "nolabels")) wants_nolabels = 1; freelist (list); } } /* * This macro checks that a form has a mandatory print wheel * (or character set). */ #define CHKMAND(PFS) \ ( \ (PFS) \ && (PFS)->form->chset \ && !STREQU((PFS)->form->chset, NAME_ANY) \ && (PFS)->form->mandatory \ ) /* * This macro checks that the user is allowed to use the * printer. */ #define CHKU(PRS,PPS) \ ( \ lp_or_root \ || allowed( \ (PRS)->secure->user, \ (PPS)->users_allowed, \ (PPS)->users_denied \ ) \ ) /* * This macro checks that the form is allowed on the printer, * or is already mounted there. * Note: By doing this check we don't have to check that the * characteristics of the form, such as pitch, size, or * character set, against the printer's capabilities, ASSUMING, * of course, that the allow list is correct. That is, the * allow list lists forms that have already been checked against * the printer! */ #define CHKF(PFS,PPS) \ ( \ isFormMountedOnPrinter(PPS,PFS) \ || allowed( \ (PFS)->form->name, \ (PPS)->forms_allowed, \ (PPS)->forms_denied \ ) \ ) /* * This macro checks that the print wheel is acceptable * for the printer or is mounted. Note: If the printer doesn't * take print wheels, the check passes. The check for printers * that don't take print wheels is below. */ #define CHKPW(PW,PPS) \ ( \ !(PPS)->printer->daisy \ || ( \ (PPS)->pwheel_name \ && STREQU((PPS)->pwheel_name, (PW)) \ ) \ || searchlist((PW), (PPS)->printer->char_sets) \ ) /* * This macro checks the pitch, page size, and (if need be) * the character set. The character set isn't checked if the * printer takes print wheels, or if the character set is * listed in the printer's alias list. * The form has to be checked as well; while we're sure that * at least one type for each printer can handle the form's * cpi/lpi/etc. characteristics (lpadmin made sure), we aren't * sure that ALL the types work. */ #define CHKOPTS(PRS,PC,PFS) _chkopts((PRS),(PC),(PFS)) /* was a macro */ /* * This macro checks the acceptance status of a printer. * If the request is already assigned to that printer, * then it's okay. It's ambiguous what should happen if * originally a "-d any" request was accepted, temporarily * assigned one printer, then the administrator (1) rejected * further requests for the printers and (2) made the * temporarily assigned printer unusable for the request. * What will happen, of course, is that the request will * be canceled, even though the other printers would be okay * if not rejecting....but if we were to say, gee it's okay, * the request has already been accepted, we may be allowing * it on printers that were NEVER accepting. Thus we can * continue to accept it only for the printer already assigned. */ #define CHKACCEPT(PRS,PPS) \ ( \ !((PPS)->status & PS_REJECTED) \ || (PRS)->printer == (PPS) \ || moving \ ) /* * If a print wheel or character set is given, see if it * is allowed on the form. */ if (prs->request->charset) if ( !CHKMAND(pfs) || STREQU(prs->request->charset, pfs->form->chset) ) /*EMPTY*/; else { ret = MDENYMEDIA; chkprinter_result |= PCK_CHARSET; goto Return; } /* * If a single printer was named, check the request against it. * Do the accept/reject check late so that we give the most * useful information to the user. */ if (pps) { (pc = &single)->pps = pps; /* Does the printer allow the user? */ if (!CHKU(prs, pps)) { ret = MDENYDEST; goto Return; } /* Check printer label range */ if (is_system_labeled() && prs->secure->slabel != NULL) { if (tsol_check_printer_label_range( prs->secure->slabel, pps->printer->name) == 0) { ret = MDENYDEST; goto Return; } } /* Does the printer allow the form? */ if (pfs && !CHKF(pfs, pps)) { ret = MNOMOUNT; goto Return; } /* Does the printer allow the pwheel? */ if ( prs->request->charset && !CHKPW(prs->request->charset, pps) ) { ret = MNOMOUNT; goto Return; } /* Can printer handle the pitch/size/charset/nobanner? */ if (!CHKOPTS(prs, pc, pfs)) { ret = MDENYDEST; goto Return; } /* Is the printer allowing requests? */ if (!CHKACCEPT(prs, pps)) { ret = MERRDEST; goto Return; } /* Is there a filter which will convert the input? */ if (!pickfilter(prs, pc, pfs)) { ret = MNOFILTER; goto Return; } best_pc = pc; ret = MOK; goto Return; } /* * Do the acceptance check on the class (if we have one) * now so we can proceed with checks on individual printers * in the class. Don't toss out the request if it is already * assigned a printer just because the class is NOW rejecting. */ if ( pcs && (pcs->status & CS_REJECTED) && !moving && !prs->printer ) { ret = MERRDEST; goto Return; } /* * Construct a list of printers based on the destination * given. Cross off those that aren't accepting requests, * that can't take the form, or which the user can't use. * See if the list becomes empty. */ if (pcs) n = lenlist(pcs->class->members); else { for (n = 0; PStatus != NULL && PStatus[n] != NULL; n++) ; } pcend = arena = (CANDIDATE *)Calloc(n, sizeof(CANDIDATE)); /* * Start with a list of printers that are accepting requests. * Don't skip a printer if it's rejecting but the request * has already been accepted for it. */ if (pcs) { register char **pn; for (pn = pcs->class->members; *pn; pn++) if ( ((pps = search_pstatus(*pn)) != NULL) && pps != stop_pps ) (pcend++)->pps = pps; } else for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) { pps = PStatus[i]; if (CHKACCEPT(prs, pps) && pps != stop_pps) (pcend++)->pps = pps; } if (pcend == arena) { ret = MERRDEST; goto Return; } /* * Clean out printers that the user can't use. We piggy-back * the pitch/size/banner checks here because the same error return * is given (strange, eh?). */ { register CANDIDATE *pcend2; for (pcend2 = pc = arena; pc < pcend; pc++) { if (CHKU(prs, pc->pps) && CHKOPTS(prs, pc, pfs)) *pcend2++ = *pc; else free_candidate (pc); } if (pcend2 == arena) { ret = MDENYDEST; goto Return; } pcend = pcend2; } /* * Clean out printers that can't mount the form, * EXCEPT for printers that already have it mounted: */ if (pfs) { register CANDIDATE *pcend2; for (pcend2 = pc = arena; pc < pcend; pc++) if (CHKF(pfs, pc->pps)) *pcend2++ = *pc; else free_candidate (pc); if (pcend2 == arena) { ret = MNOMOUNT; goto Return; } pcend = pcend2; } /* * Clean out printers that can't take the print wheel * EXCEPT for printers that already have it mounted * or printers for which it is a selectable character set: */ if (prs->request->charset) { register CANDIDATE *pcend2; for (pcend2 = pc = arena; pc < pcend; pc++) if (CHKPW(prs->request->charset, pc->pps)) *pcend2++ = *pc; else free_candidate (pc); if (pcend2 == arena) { ret = MNOMOUNT; goto Return; } pcend = pcend2; } /* * Clean out printers that can't handle the printing * and for which there's no filter to convert the input. * */ /* * Is the form mounted, or is none needed? */ #define CHKFMNT(PFS,PPS) (isFormUsableOnPrinter(PPS,PFS)) /* * Is the print-wheel mounted, or is none needed? */ #define CHKPWMNT(PRS,PPS) SAME((PPS)->pwheel_name, (PRS)->request->charset) /* * Do we NOT need a special character set, or can we select * it on the printer? Note: Getting this far means that IF * the printer has selectable character sets (!daisy) then * it can select the one we want. */ #define CHKCHSET(PRS,PPS) \ ( \ !(PRS)->request->charset \ || !(PPS)->printer->daisy \ ) /* * Is the printer able to print now? */ #define CHKENB(PPS) (!((PPS)->status & (PS_DISABLED|PS_FAULTED))) /* * Is the printer not busy printing another request, or * not awaiting an auto-retry after a fault? */ #define CHKFREE(PPS) (!((PPS)->status & (PS_BUSY|PS_LATER))) { register CANDIDATE *pcend2; for (pcend2 = pc = arena; pc < pcend; pc++) if (pickfilter(prs, pc, pfs)) { /* * Compute a ``weight'' for this printer, * based on its status. We'll later pick * the printer with the highest weight. */ pc->weight = 0; if (!pc->fast && !pc->slow) pc->weight += WEIGHT_NOFILTER; if (CHKFREE(pc->pps)) pc->weight += WEIGHT_FREE; if (CHKENB(pc->pps)) pc->weight += WEIGHT_ENABLED; if (CHKFMNT(pfs, pc->pps)) pc->weight += WEIGHT_MOUNTED; if (CHKPWMNT(prs, pc->pps)) pc->weight += WEIGHT_MOUNTED; if (CHKCHSET(prs, pc->pps)) pc->weight += WEIGHT_SELECTS; #if defined(FILTER_EARLY_OUT) if (pc->weight == WEIGHT_MAX) { /* * This is the one! */ best_pc = pc; ret = MOK; goto Return; } #endif /* * This is a candidate! */ *pcend2++ = *pc; } else /* * No filter for this one! */ free_candidate (pc); if (pcend2 == arena) { ret = MNOFILTER; goto Return; } pcend = pcend2; } if (pcend - arena == 1) { best_pc = arena; ret = MOK; goto Return; } /* * Clean out local printers * where the request is outside the printer label range. */ { register CANDIDATE *pcend2 = pcend; if (is_system_labeled()) { for (pcend2 = pc = arena; pc < pcend; pc++) { if (tsol_check_printer_label_range( prs->secure->slabel, pps->printer->name) == 1) *pcend2++ = *pc; else free_candidate(pc); } } if (pcend2 == arena) { ret = MDENYDEST; goto Return; } pcend = pcend2; } #if defined(OTHER_FACTORS) /* * Here you might want to add code that considers * other factors: the size of the file(s) to be * printed ("prs->secure->size") in relation to the * printer (e.g. printer A gets mostly large * files, printer B gets mostly small files); the * number/total-size of requests currently queued * for the printer; etc. * * If your code includes eliminating printers drop them * from the list (as done in several places above). * Otherwise, your code should add weights to the weight * already computed. Change the WEIGHT_MAX, increase the * other WEIGHT_X values to compensate, etc., as appropriate. */ ; #endif /* * Pick the best printer from a list of eligible candidates. */ best_pc = arena; for (pc = arena + 1; pc < pcend; pc++) if (pc->weight > best_pc->weight) best_pc = pc; ret = MOK; /* * Branch to here if MOK and/or if things have been allocated. */ Return: if (ret == MOK) { register USER *pu = Getuser(prs->secure->user); register char *pwheel_name; PSTATUS *oldpps = prs->printer; /* * We are going to accept this print request, having * found a printer for it. This printer will be assigned * to the request, although this assignment may be * temporary if other printers qualify and this printer * is changed to no longer qualify. Qualification in * this context includes being ready to print! */ prs->printer = best_pc->pps; load_str (&(prs->printer_type), best_pc->printer_type); /* * Assign the form (if any) to the request. Adjust * the number of requests queued for old and new form * accordingly. */ if (prs->form != pfs) { unqueue_form (prs); queue_form (prs, pfs); } /* * Ditto for the print wheel, except include here the * print wheel needed by the form. * CAUTION: When checking this request later, don't * refuse to service it if the print wheel for the * form isn't mounted but the form is; a mounted form * overrides its other needs. Don't be confused by the * name of the bit, RSS_PWMAND; a printer that prints * this request MUST have the print wheel mounted * (if it takes print wheels) if the user asked for * a particular print wheel. */ prs->status &= ~RSS_PWMAND; if (CHKMAND(pfs)) pwheel_name = pfs->form->chset; else if ((pwheel_name = prs->request->charset) != NULL) prs->status |= RSS_PWMAND; if (!SAME(pwheel_name, prs->pwheel_name)) { unqueue_pwheel (prs); queue_pwheel (prs, pwheel_name); } /* * Adjust the priority to lie within the limits allowed * for the user (this is a silent adjustment as required). * CURRENTLY, ONLY NEW REQUESTS WILL GET QUEUED ACCORDING * TO THIS PRIORITY. EXISTING REQUESTS BEING (RE)EVALUATED * WILL NOT BE REQUEUED. * A wild priority is changed to the default, or the * limit, whichever is the lower priority (higher value). */ if (prs->request->priority < 0 || 39 < prs->request->priority) prs->request->priority = getdfltpri(); if (pu && prs->request->priority < pu->priority_limit) prs->request->priority = pu->priority_limit; /* * If a filter is involved, change the number of * copies to 1 (if the filter handles it). */ if ( (best_pc->fast || best_pc->slow) && (best_pc->flags & FPARM_COPIES) && prs->request->copies > 1 ) prs->copies = 1; else /* * We use two ".copies" because we don't * want to lose track of the number requested, * but do want to mark the number the interface * program is to handle. Here is the best * place to know this. */ prs->copies = prs->request->copies; if (best_pc->slow) { /* * If the filter has changed, the request will * have to be refiltered. This may mean stopping * a currently running filter or interface. */ if (!SAME(best_pc->slow, prs->slow)) { if (prs->request->outcome & RS_FILTERED) prs->request->outcome &= ~RS_FILTERED; if ( prs->request->outcome & RS_FILTERING && !(prs->request->outcome & RS_STOPPED) ) { prs->request->outcome |= RS_REFILTER; prs->request->outcome |= RS_STOPPED; terminate (prs->exec); } else if ( prs->request->outcome & RS_PRINTING && !(prs->request->outcome & RS_STOPPED) ) { prs->request->outcome |= RS_STOPPED; terminate (oldpps->exec); } } load_str (&(prs->slow), best_pc->slow); /* Assumption: if there is a slow filter, * there is an output_type */ load_str (&(prs->output_type), best_pc->output_type); } else unload_str (&(prs->slow)); load_str (&(prs->fast), best_pc->fast); if (prs->request->actions & ACT_FAST && prs->slow) { if (prs->fast) { prs->fast = makestr( prs->slow, "|", prs->fast, (char *)0 ); Free (prs->slow); } else prs->fast = prs->slow; prs->slow = 0; } } /* * Free the space allocated for the candidates, INCLUDING * the one chosen. Any allocated space in the chosen candidate * that has to be saved should have been COPIED already. */ if (arena) { for (pc = arena; pc < pcend; pc++) free_candidate (pc); Free ((char *)arena); } else if (best_pc) free_candidate (best_pc); if (o_length) Free (o_length); if (o_width) Free (o_width); if (o_lpi) Free (o_lpi); if (o_cpi) Free (o_cpi); /* * The following value is valid ONLY IF the request * is canceled or rejected. Not all requests that * we fail in this routine are tossed out! */ prs->reason = ret; return (ret); } /** ** _chkopts() - CHECK -o OPTIONS **/ static int _chkopts(RSTATUS *prs, CANDIDATE *pc, FSTATUS *pfs) { unsigned long ret = 0; unsigned long chk = 0; char * charset; char * cpi = 0; char * lpi = 0; char * width = 0; char * length = 0; char * paper = NULL; char ** pt; int nobanner_not_allowed = 0; /* * If we have a form, it overrides whatever print characteristics * the user gave. */ if (pfs) { cpi = pfs->cpi; lpi = pfs->lpi; width = pfs->pwid; length = pfs->plen; paper = pfs->form->paper; } else { cpi = o_cpi; lpi = o_lpi; width = o_width; length = o_length; } /* * If the printer takes print wheels, or the character set * the user wants is listed in the character set map for this * printer, we needn't check if the printer can handle the * character set. (Note: The check for the print wheel case * is done elsewhere.) */ if (pc->pps->printer->daisy || search_cslist(prs->request->charset, pc->pps->printer->char_sets)) charset = 0; else charset = prs->request->charset; pc->printer_types = 0; for (pt = pc->pps->printer->printer_types; *pt; pt++) { unsigned long this; if (paper) { if (allowed(paper,pc->pps->paper_allowed,NULL)) { addlist (&(pc->printer_types), *pt); } else { ret |= PCK_PAPER; } } else { this = chkprinter(*pt, cpi, lpi, length, width, charset); if (this == 0) addlist(&(pc->printer_types), *pt); chk |= this; } } if (!pc->printer_types) ret |= chk; /* * If the system is labeled, then user who wants 'nolabels' must * have PRINT_UNLABELED_AUTH authorizations to allow it. */ if (is_system_labeled() && (wants_nolabels == 1)) { if (!tsol_lpauth(PRINT_UNLABELED_AUTH, prs->secure->user)) { /* if not authorized, remove "nolabels" from options */ register char **list; if (prs->request->options && (list = dashos(prs->request->options))) { dellist(&list, "nolabels"); free(prs->request->options); prs->request->options = sprintlist(list); } } } if (pc->pps->printer->banner == BAN_ALWAYS) { /* delete "nobanner" */ char **list; /* * If the system is labeled, users must have * PRINT_NOBANNER_AUTH authorization to print * without a banner. */ if (is_system_labeled()) { if (wants_nobanner == 1) { if (tsol_lpauth(PRINT_NOBANNER_AUTH, prs->secure->user) == 0) { nobanner_not_allowed = 1; } } } else if ((wants_nobanner == 1) && (lp_or_root != 1)) { nobanner_not_allowed = 1; } if (nobanner_not_allowed == 1) { /* Take out 'nobanner' from request options. */ if (prs->request->options && (list = dashos(prs->request->options))) { dellist(&list, "nobanner"); free(prs->request->options); prs->request->options = sprintlist(list); } } } else if (pc->pps->printer->banner == BAN_NEVER) { if (wants_nobanner == 0) { /* add "nobanner" */ char **list = NULL; if (prs->request->options) { list = dashos(prs->request->options); free(prs->request->options); } appendlist(&list, "nobanner"); prs->request->options = sprintlist(list); } } else /* if (pc->pps->printer->banner == BAN_OPTIONAL) */ { /* it is optional, leave it alone */ } chkprinter_result |= ret; return (ret == 0); } /** ** free_candidate() **/ static void free_candidate(CANDIDATE *pc) { if (pc->slow) unload_str (&(pc->slow)); if (pc->fast) unload_str (&(pc->fast)); if (pc->printer_types) { freelist (pc->printer_types); pc->printer_types = 0; } if (pc->printer_type) unload_str (&(pc->printer_type)); if (pc->output_type) unload_str (&(pc->output_type)); return; } static int tsol_check_printer_label_range(char *slabel, const char *printer) { int in_range = 0; int err = 0; m_range_t *range; m_label_t *sl = NULL; if (slabel == NULL) return (0); if ((err = (str_to_label(slabel, &sl, USER_CLEAR, L_NO_CORRECTION, &in_range))) == -1) { /* stobsl error on printer max label */ return (0); } if ((range = getdevicerange(printer)) == NULL) { m_label_free(sl); return (0); } /* blinrange returns true (1) if in range, false (0) if not */ in_range = blinrange(sl, range); m_label_free(sl); m_label_free(range->lower_bound); m_label_free(range->upper_bound); free(range); return (in_range); } /* * Given a character string with a "username" or "system!username" * this function returns a pointer to "username" */ static int tsol_lpauth(char *auth, char *in_name) { char *cp; int res; if ((cp = strchr(in_name, '@')) != NULL) { /* user@system */ *cp = '\0'; res = chkauthattr(auth, in_name); *cp = '@'; } else if ((cp = strchr(in_name, '!')) != NULL) /* system!user */ res = chkauthattr(auth, cp+1); else /* user */ res = chkauthattr(auth, in_name); return (res); } #define POLICY_FILE "/etc/default/print" int secpolicy_chkpolicy(char *policyp) { char *option; int opt_val; if (policyp == NULL) return (0); opt_val = 0; if (defopen(POLICY_FILE) == 0) { defcntl(DC_SETFLAGS, DC_STD & ~DC_CASE); /* ignore case */ if ((option = defread(policyp)) != NULL) opt_val = atoi(option); } (void) defopen((char *)NULL); syslog(LOG_DEBUG, "--- Policy %s, opt_val==%d", policyp ? policyp : "NULL", opt_val); return (opt_val); }