/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include "stdio.h" #include "string.h" #include "pwd.h" #include "sys/types.h" #include "errno.h" #include "lp.h" #include "printers.h" #include "form.h" #include "class.h" #define WHO_AM_I I_AM_LPADMIN #include "oam.h" #include "lpadmin.h" #define PPDZIP ".gz" extern PRINTER *printer_pointer; extern PWHEEL *pwheel_pointer; extern struct passwd *getpwnam(); void chkopts2(), chkopts3(); static void chksys(); FORM formbuf; char **f_allow, **f_deny, **u_allow, **u_deny, **p_add, **p_remove; PRINTER *oldp = 0; PWHEEL *oldS = 0; short daisy = 0; static int root_can_write(); static char *unpack_sdn(); static char ** bad_list; #if defined(__STDC__) static unsigned long sum_chkprinter ( char ** , char * , char * , char * , char * , char * ); static int isPPD(char *ppd_file); #else static unsigned long sum_chkprinter(); static int isPPD(); #endif /** ** chkopts() -- CHECK LEGALITY OF COMMAND LINE OPTIONS **/ void chkopts () { short isfAuto = 0; /* * Check -d. */ if (d) { if ( a || c || f || P || j || m || M || t || p || r || u || x #if defined(DIRECT_ACCESS) || C #endif #ifdef LP_USE_PAPI_ATTR || n_opt #endif || strlen(modifications) ) { LP_ERRMSG (ERROR, E_ADM_DALONE); done (1); } if ( *d && !STREQU(d, NAME_NONE) && !isprinter(d) && !isclass(d) ) { LP_ERRMSG1 (ERROR, E_ADM_NODEST, d); done (1); } return; } /* * Check -x. */ if (x) { if ( /* MR bl88-02718 */ A || a || c || f || P || j || m || M || t || p || r || u || d #if defined(DIRECT_ACCESS) || C #endif #ifdef LP_USE_PAPI_ATTR || n_opt #endif || strlen(modifications) ) { LP_ERRMSG (ERROR, E_ADM_XALONE); done (1); } if ( !STREQU(NAME_ALL, x) && !STREQU(NAME_ANY, x) && !isprinter(x) && !isclass(x) ) { LP_ERRMSG1 (ERROR, E_ADM_NODEST, x); done (1); } return; } /* * Problems common to both -p and -S (-S alone). */ if (A && STREQU(A, NAME_LIST) && (W != -1 || Q != -1)) { LP_ERRMSG (ERROR, E_ADM_LISTWQ); done (1); } /* * Check -S. */ if (!p && S) { if ( M || t || a || f || P || c || r || e || i || m || H || h || l || v || I || T || D || F || u || U || j || o #ifdef LP_USE_PAPI_ATTR || n_opt #endif ) { LP_ERRMSG (ERROR, E_ADM_SALONE); done (1); } if (!A && W == -1 && Q == -1) { LP_ERRMSG (ERROR, E_ADM_NOAWQ); done (1); } if (S[0] && S[1]) LP_ERRMSG (WARNING, E_ADM_ASINGLES); if (!STREQU(NAME_ALL, *S) && !STREQU(NAME_ANY, *S)) chkopts3(1); return; } /* * At this point we must have a printer (-p option). */ if (!p) { LP_ERRMSG (ERROR, E_ADM_NOACT); done (1); } if (STREQU(NAME_NONE, p)) { LP_ERRMSG1 (ERROR, E_LP_NULLARG, "p"); done (1); } /* * Mount but nothing to mount? */ if (M && (!f && !S)) { LP_ERRMSG (ERROR, E_ADM_MNTNONE); done (1); } /* * -Q isn't allowed with -p. */ if (Q != -1) { LP_ERRMSG (ERROR, E_ADM_PNOQ); done (1); } /* * Fault recovery. */ if ( F && !STREQU(F, NAME_WAIT) && !STREQU(F, NAME_BEGINNING) && ( !STREQU(F, NAME_CONTINUE) || j && STREQU(F, NAME_CONTINUE) ) ) { #if defined(J_OPTION) if (j) LP_ERRMSG (ERROR, E_ADM_FBADJ); else #endif LP_ERRMSG (ERROR, E_ADM_FBAD); done (1); } #if defined(J_OPTION) /* * The -j option is used only with the -F option. */ if (j) { if (M || t || a || f || P || c || r || e || i || m || H || h || #ifdef LP_USE_PAPI_ATTR n_opt || #endif l || v || I || T || D || u || U || o) { LP_ERRMSG (ERROR, E_ADM_JALONE); done (1); } if (j && !F) { LP_ERRMSG (ERROR, E_ADM_JNOF); done (1); } return; } #endif #if defined(DIRECT_ACCESS) /* * -C is only used to modify -u */ if (C && !u) { LP_ERRMSG (ERROR, E_ADM_CNOU); done (1); } #endif /* * The -a option needs the -M and -f options, * Also, -ofilebreak is used only with -a. */ if (a && (!M || !f)) { LP_ERRMSG (ERROR, E_ADM_MALIGN); done (1); } if (filebreak && !a) LP_ERRMSG (WARNING, E_ADM_FILEBREAK); /* * The "-p all" case is restricted to certain options. */ if ( (STREQU(NAME_ANY, p) || STREQU(NAME_ALL, p)) && ( a || h || l || M || t || D || e || f || P || H || s #ifdef LP_USE_PAPI_ATTR || n_opt #endif || i || I || m || S || T || u || U || v || banner != -1 || cpi || lpi || width || length || stty_opt ) ) { LP_ERRMSG (ERROR, E_ADM_ANYALLNONE); done (1); } /* * Allow giving -v or -U option as way of making * remote printer into local printer. * Note: "!s" here means the user has not given the -s; * later it means the user gave -s local-system. */ if (!s && (v || U)) s = Local_System; /* * Be careful about checking "s" before getting here. * We want "s == 0" to mean this is a local printer; however, * if the user wants to change a remote printer to a local * printer, we have to have "s == Local_System" long enough * to get into "chkopts2()" where a special check is made. * After "chkopts2()", "s == 0" means local. */ if (!STREQU(NAME_ALL, p) && !STREQU(NAME_ANY, p)) /* * If old printer, make sure it exists. If new printer, * check that the name is okay, and that enough is given. * (This stuff has been moved to "chkopts2()".) */ chkopts2(1); if (!s) { /* * Only one of -i, -m, -e. */ if ((i && e) || (m && e) || (i && m)) { LP_ERRMSG (ERROR, E_ADM_INTCONF); done (1); } /* * Check -e arg. */ if (e) { if (!isprinter(e)) { LP_ERRMSG1 (ERROR, E_ADM_NOPR, e); done (1); } if (strcmp(e, p) == 0) { LP_ERRMSG (ERROR, E_ADM_SAMEPE); done (1); } } /* * Check -m arg. */ if (m && !ismodel(m)) { LP_ERRMSG1 (ERROR, E_ADM_NOMODEL, m); done (1); } #ifdef LP_USE_PAPI_ATTR /* * Check -n arg. The ppd file exists. */ if ((n_opt != NULL) && !isPPD(n_opt)) { LP_ERRMSG1 (ERROR, E_ADM_NOPPD, n_opt); done (1); } #endif /* * Need exactly one of -h or -l (but will default -h). */ if (h && l) { LP_ERRMSG2 (ERROR, E_ADM_CONFLICT, 'h', 'l'); done (1); } if (!h && !l) h = 1; /* * Check -c and -r. */ if (c && r && strcmp(c, r) == 0) { LP_ERRMSG (ERROR, E_ADM_SAMECR); done (1); } /* * Are we creating a class with the same name as a printer? */ if (c) { if (STREQU(c, p)) { LP_ERRMSG1 (ERROR, E_ADM_CLNPR, c); done (1); } if (isprinter(c)) { LP_ERRMSG1 (ERROR, E_ADM_CLPR, c); done (1); } } if (v && (is_printer_uri(v) < 0)) { /* * The device must be writeable by root. */ if (v && root_can_write(v) == -1) done (1); } /* * Can't have both device and dial-out. */ if (v && U) { LP_ERRMSG (ERROR, E_ADM_BOTHUV); done (1); } } else if ( A || a || e || H || h || i || l || m || ( t && !M) || ( M && !t) || o || U || v || Q != -1 || W != -1 #ifdef LP_USE_PAPI_ATTR || n_opt #endif ) { LP_ERRMSG (ERROR, E_ADM_NOTLOCAL); done(1); } /* * We need the printer type for some things, and the boolean * "daisy" (from Terminfo) for other things. */ if (!T && oldp) T = oldp->printer_types; if (T) { short a_daisy; char ** pt; if (lenlist(T) > 1 && searchlist(NAME_UNKNOWN, T)) { LP_ERRMSG (ERROR, E_ADM_MUNKNOWN); done (1); } for (pt = T; *pt; pt++) if (tidbit(*pt, (char *)0) == -1) { LP_ERRMSG1 (ERROR, E_ADM_BADTYPE, *pt); done (1); } /* * All the printer types had better agree on whether the * printer takes print wheels! */ daisy = a_daisy = -1; for (pt = T; *pt; pt++) { tidbit (*pt, "daisy", &daisy); if (daisy == -1) daisy = 0; if (a_daisy == -1) a_daisy = daisy; else if (a_daisy != daisy) { LP_ERRMSG (ERROR, E_ADM_MIXEDTYPES); done (1); } } } if (cpi || lpi || length || width || S || f || filebreak) if (!T) { LP_ERRMSG (ERROR, E_ADM_TOPT); done (1); } /* * Check -o cpi=, -o lpi=, -o length=, -o width= */ if (cpi || lpi || length || width) { unsigned long rc; if ((rc = sum_chkprinter(T, cpi, lpi, length, width, NULL)) == 0) { if (bad_list) LP_ERRMSG1 ( INFO, E_ADM_NBADCAPS, sprintlist(bad_list) ); } else { if ((rc & PCK_CPI) && cpi) LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "cpi="); if ((rc & PCK_LPI) && lpi) LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "lpi="); if ((rc & PCK_WIDTH) && width) LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "width="); if ((rc & PCK_LENGTH) && length) LP_ERRMSG1 (ERROR, E_ADM_BADCAP, "length="); LP_ERRMSG (ERROR, E_ADM_BADCAPS); done(1); } } /* * Check -I (old or new): */ if (T && lenlist(T) > 1) { #define BADILIST(X) (lenlist(X) > 1 || X && *X && !STREQU(NAME_SIMPLE, *X)) if ( I && BADILIST(I) || !I && oldp && BADILIST(oldp->input_types) ) { LP_ERRMSG (ERROR, E_ADM_ONLYSIMPLE); done (1); } } /* * MOUNT: * Only one print wheel can be mounted at a time. */ if (M && S && S[0] && S[1]) LP_ERRMSG (WARNING, E_ADM_MSINGLES); /* * NO MOUNT: * If the printer takes print wheels, the -S argument * should be a simple list; otherwise, it must be a * mapping list. (EXCEPT: In either case, "none" alone * means delete the existing list.) */ if (S && !M) { register char **item, *cp; /* * For us to be here, "daisy" must have been set. * (-S requires knowing printer type (T), and knowing * T caused call to "tidbit()" to set "daisy"). */ if (!STREQU(S[0], NAME_NONE) || S[1]) if (daisy) { for (item = S; *item; item++) { if (strchr(*item, '=')) { LP_ERRMSG (ERROR, E_ADM_PWHEELS); done (1); } if (!syn_name(*item)) { LP_ERRMSG1 (ERROR, E_LP_NOTNAME, *item); done (1); } } } else { register int die = 0; for (item = S; *item; item++) { if (!(cp = strchr(*item, '='))) { LP_ERRMSG (ERROR, E_ADM_CHARSETS); done (1); } *cp = 0; if (!syn_name(*item)) { LP_ERRMSG1 (ERROR, E_LP_NOTNAME, *item); done (1); } if (PCK_CHARSET & sum_chkprinter(T, (char *)0, (char *)0, (char *)0, (char *)0, *item)) { LP_ERRMSG1 (ERROR, E_ADM_BADSET, *item); die = 1; } else { if (bad_list) LP_ERRMSG2 ( INFO, E_ADM_NBADSET, *item, sprintlist(bad_list) ); } *cp++ = '='; if (!syn_name(cp)) { LP_ERRMSG1 (ERROR, E_LP_NOTNAME, cp); done (1); } } if (die) { LP_ERRMSG (ERROR, E_ADM_BADSETS); done (1); } } } if (P) { int createForm = 0; char **plist; if (getform(P, &formbuf, (FALERT *)0, (FILE **)0) != -1) { if ((!formbuf.paper) || (!STREQU(formbuf.paper,P)) ) { LP_ERRMSG (ERROR, E_ADM_ALSO_SEP_FORM); done (1); } } else createForm = 1; if (*P == '~') { /* removing types of papers */ P++; p_remove = getlist(P, LP_WS, LP_SEP); p_add = NULL; } else { /* adding types of papers */ p_add = getlist(P, LP_WS, LP_SEP); p_remove = NULL; if (createForm) { char cmdBuf[200]; for (plist = p_add; *plist; plist++) { snprintf(cmdBuf, sizeof (cmdBuf), "lpforms -f %s -d\n", *plist); system(cmdBuf); } } } if (!f && !M) { /* make paper allowed on printer too */ f = Malloc(strlen(P) + strlen(NAME_ALLOW) + strlen(": ")); sprintf(f, "%s:%s", NAME_ALLOW, P); isfAuto = 1; } } /* * NO MOUNT: * The -f option restricts the forms that can be used with * the printer. * - construct the allow/deny lists * - check each allowed form to see if it'll work * on the printer */ if (f && !M) { register char *type = strtok(f, ":"), *str = strtok((char *)0, ":"), **pf; register int die = 0; if (STREQU(type, NAME_ALLOW) && str) { if ((pf = f_allow = getlist(str, LP_WS, LP_SEP)) != NULL) { while (*pf) { if ((!isfAuto) && !STREQU(*pf, NAME_NONE) && verify_form(*pf) < 0 ) die = 1; pf++; } if (die) { LP_ERRMSG (ERROR, E_ADM_FORMCAPS); done (1); } } else LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_ALLOW); } else if (STREQU(type, NAME_DENY) && str) { if ((pf = f_deny = getlist(str, LP_WS, LP_SEP)) != NULL) { if (!STREQU(*pf, NAME_ALL)) { while (*pf) { if ((!isfAuto) && !STREQU(*pf, NAME_NONE) && getform(*pf, &formbuf, (FALERT *)0, (FILE **)0) < 0 ) { LP_ERRMSG2(WARNING, E_ADM_ICKFORM, *pf, p); die = 1; } pf++; } } if (die) { done (1); } } else LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_DENY); } else { LP_ERRMSG (ERROR, E_ADM_FALLOWDENY); done (1); } } /* * The -u option is setting use restrictions on printers. * - construct the allow/deny lists */ if (u) { register char *type = strtok(u, ":"), *str = strtok((char *)0, ":"); if (STREQU(type, NAME_ALLOW) && str) { if (!(u_allow = getlist(str, LP_WS, LP_SEP))) LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_ALLOW); } else if (STREQU(type, NAME_DENY) && str) { if (!(u_deny = getlist(str, LP_WS, LP_SEP))) LP_ERRMSG1 (WARNING, E_ADM_MISSING, NAME_DENY); } else { LP_ERRMSG (ERROR, E_LP_UALLOWDENY); done (1); } } return; } /** ** root_can_write() - CHECK THAT "root" CAN SENSIBLY WRITE TO PATH **/ static int root_can_write (path) char *path; { static int lp_uid = -1; struct passwd *ppw; struct stat statbuf; if (lstat(path, &statbuf) == -1) { LP_ERRMSG1 (ERROR, E_ADM_NOENT, v); return (-1); } /* * If the device is a symlink (and it is not a root owned symlink), * verify that the owner matches the destination owner. */ if (S_ISLNK(statbuf.st_mode) && statbuf.st_uid != 0) { uid_t uid = statbuf.st_uid; if (Stat(path, &statbuf) == -1) { LP_ERRMSG1 (ERROR, E_ADM_NOENT, v); return (-1); } if (statbuf.st_uid != uid) { LP_ERRMSG1 (ERROR, E_ADM_ISMISMATCH, v); done(1); } LP_ERRMSG1(WARNING, E_ADM_ISNOTROOTOWNED, v); } if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { LP_ERRMSG1 (WARNING, E_ADM_ISDIR, v); } else if ((statbuf.st_mode & S_IFMT) == S_IFBLK) LP_ERRMSG1 (WARNING, E_ADM_ISBLK, v); if (lp_uid == -1) { if (!(ppw = getpwnam(LPUSER))) ppw = getpwnam(ROOTUSER); endpwent (); if (ppw) lp_uid = ppw->pw_uid; else lp_uid = 0; } if (!STREQU(v, "/dev/null")) if ((statbuf.st_uid && statbuf.st_uid != lp_uid) || (statbuf.st_mode & (S_IWGRP|S_IRGRP|S_IWOTH|S_IROTH))) LP_ERRMSG1 (WARNING, E_ADM_DEVACCESS, v); return (0); } /** ** unpack_sdn() - TURN SCALED TYPE INTO char* TYPE **/ static char *unpack_sdn (sdn) SCALED sdn; { register char *cp; extern char *malloc(); if (sdn.val <= 0 || 99999 < sdn.val) cp = 0; else if (sdn.val == N_COMPRESSED) cp = strdup(NAME_COMPRESSED); else if ((cp = malloc(sizeof("99999.999x")))) (void) sprintf(cp, "%.3f%c", sdn.val, sdn.sc); return (cp); } /** ** verify_form() - SEE IF PRINTER CAN HANDLE FORM **/ int verify_form (form) char *form; { register char *cpi_f, *lpi_f, *width_f, *length_f, *chset; register int rc = 0; char **paperAllowed = NULL; char **paperDenied = NULL; register unsigned long checks; if (STREQU(form, NAME_ANY)) form = NAME_ALL; while (getform(form, &formbuf, (FALERT *)0, (FILE **)0) != -1) { if (formbuf.paper) { if (!paperAllowed) { load_paperprinter_access(p, &paperAllowed, &paperDenied); freelist(paperDenied); } if (!allowed(formbuf.paper,paperAllowed,NULL)) { LP_ERRMSG1 (INFO, E_ADM_BADCAP, gettext("printer doesn't support paper type")); rc = -1; } } else { cpi_f = unpack_sdn(formbuf.cpi); lpi_f = unpack_sdn(formbuf.lpi); width_f = unpack_sdn(formbuf.pwid); length_f = unpack_sdn(formbuf.plen); if ( formbuf.mandatory && !daisy && !search_cslist( formbuf.chset, (S && !M? S : (oldp? oldp->char_sets : (char **)0)) ) ) chset = formbuf.chset; else chset = 0; if ((checks = sum_chkprinter( T, cpi_f, lpi_f, length_f, width_f, chset ))) { rc = -1; if ((checks & PCK_CPI) && cpi_f) LP_ERRMSG1 (INFO, E_ADM_BADCAP, "cpi"); if ((checks & PCK_LPI) && lpi_f) LP_ERRMSG1 (INFO, E_ADM_BADCAP, "lpi"); if ((checks & PCK_WIDTH) && width_f) LP_ERRMSG1 (INFO, E_ADM_BADCAP, "width"); if ((checks & PCK_LENGTH) && length_f) LP_ERRMSG1 (INFO, E_ADM_BADCAP, "length"); if ((checks & PCK_CHARSET) && formbuf.chset) { LP_ERRMSG1 (INFO, E_ADM_BADSET, formbuf.chset); rc = -2; } LP_ERRMSG1 (INFO, E_ADM_FORMCAP, formbuf.name); } else { if (bad_list) LP_ERRMSG2 ( INFO, E_ADM_NBADMOUNT, formbuf.name, sprintlist(bad_list) ); } } if (!STREQU(form, NAME_ALL)) { if (paperAllowed) freelist(paperAllowed); return (rc); } } if (paperAllowed) freelist(paperAllowed); if (!STREQU(form, NAME_ALL)) { LP_ERRMSG1 (ERROR, E_LP_NOFORM, form); done (1); } return (rc); } /* Second phase of parsing for -p option. In a seperate routine so we can call it from other routines. This is used when any or all are used as a printer name. main() loops over each printer, and must call this function for each printer found. */ void chkopts2(called_from_chkopts) int called_from_chkopts; { /* Only do the getprinter() if we are not being called from lpadmin.c. Otherwise we mess up our arena for "all" processing. */ if (!called_from_chkopts) oldp = printer_pointer; else if (!(oldp = getprinter(p)) && errno != ENOENT) { LP_ERRMSG2 (ERROR, E_LP_GETPRINTER, p, PERROR); done(1); } if (oldp) { if ( !c && !d && !f && !P && !M && !t && !r && !u && !x && !A && !strlen(modifications) ) { LP_ERRMSG (ERROR, E_ADM_PLONELY); done (1); } /* * For the case "-s local-system", we need to keep * "s != 0" long enough to get here, where it keeps * us from taking the old value. After this, we make * "s == 0" to indicate this is a local printer. */ if (s && s != Local_System) chksys(s); if (!s && oldp->remote && *(oldp->remote)) s = strdup(oldp->remote); if (s == Local_System) s = 0; /* * A remote printer converted to a local printer * requires device or dial info. */ if (!s && oldp->remote && !v && !U) { LP_ERRMSG (ERROR, E_ADM_NOUV); done (1); } } else { if (getclass(p)) { LP_ERRMSG1 (ERROR, E_ADM_PRCL, p); done (1); } if (!syn_name(p)) { LP_ERRMSG1 (ERROR, E_LP_NOTNAME, p); done (1); } if (s == Local_System) s = 0; if (s) chksys(s); #ifdef LP_USE_PAPI_ATTR /* * New printer - if no model and a PPD file is defined then * use 'standard_foomatic' otherwise use * the 'standard' model. */ if (!(e || i || m) && !s) { if (n_opt != NULL) { m = STANDARD_FOOMATIC; } else { m = STANDARD; } } #else /* * New printer - if no model, use standard */ if (!(e || i || m) && !s) m = STANDARD; #endif /* * A new printer requires device or dial info. */ if (!v && !U && !s) { LP_ERRMSG (ERROR, E_ADM_NOUV); done (1); } /* * Can't quiet a new printer, * can't list the alerting for a new printer. */ if ( A && (STREQU(A, NAME_QUIET) || STREQU(A, NAME_LIST)) ) { LP_ERRMSG1 (ERROR, E_ADM_BADQUIETORLIST, p); done (1); } /* * New printer - if no input types given, assume "simple". */ if (!I) { I = getlist(NAME_SIMPLE, LP_WS, LP_SEP); strcat (modifications, "I"); } } } /* Second phase of parsing for -S option. In a seperate routine so we can call it from other routines. This is used when any or all are used as a print wheel name. main() loops over each print wheel, and must call this function for each print wheel found. */ void chkopts3(called_from_chkopts) int called_from_chkopts; { /* Only do the getpwheel() if we are not being called from lpadmin.c. Otherwise we mess up our arena for "all" processing. */ if (!called_from_chkopts) oldS = pwheel_pointer; else oldS = getpwheel(*S); if (!oldS) { if (!syn_name(*S)) { LP_ERRMSG1 (ERROR, E_LP_NOTNAME, *S); done (1); } /* * Can't quiet a new print wheel, * can't list the alerting for a new print wheel. */ if ( A && (STREQU(A, NAME_QUIET) || STREQU(A, NAME_LIST)) ) { LP_ERRMSG1 (ERROR, E_ADM_BADQUIETORLIST, *S); done (1); } } } static void chksys(s) char *s; { char *cp; if (STREQU(s, NAME_ALL) || STREQU(s, NAME_ANY)) { LP_ERRMSG (ERROR, E_ADM_ANYALLSYS); done(1); } if ((cp = strchr(s, '!')) != NULL) *cp = '\0'; if (cp) *cp = '!'; return; } /** ** sum_chkprinter() - CHECK TERMINFO STUFF FOR A LIST OF PRINTER TYPES **/ #include "lp.set.h" static unsigned long #if defined(__STDC__) sum_chkprinter ( char ** types, char * cpi, char * lpi, char * len, char * wid, char * cs ) #else sum_chkprinter (types, cpi, lpi, len, wid, cs) char ** types; char * cpi; char * lpi; char * len; char * wid; char * cs; #endif { char ** pt; unsigned long worst = 0; unsigned long this = 0; /* * Check each printer type, to see if any won't work with * the attributes requested. However, return ``success'' * if at least one type works. Keep a list of the failed * types for the caller to report. */ bad_list = 0; for (pt = types; *pt; pt++) { this = chkprinter(*pt, cpi, lpi, len, wid, cs); if (this != 0) addlist (&bad_list, *pt); worst |= this; } if (lenlist(types) == lenlist(bad_list)) return (worst); else return (0); } /* * Function: isPPD() * * Description: Check that the given PPD file exists. The argument given can * either be a relative path or a full path to the file. * * Returns: 1 = PPD file found * 0 = PPD file not found */ static int isPPD(char *ppd_file) { int result = 0; char *ppd = NULL; if (ppd_file != NULL) { if (*ppd_file == '/') { ppd = strdup(ppd_file); } else { ppd = makepath(Lp_Model, "ppd", ppd_file, (char *)0); } /* * now check the file exists */ if ((ppd != NULL) && (Access(ppd, 04) != -1)) { result = 1; } else { /* * files does not exist so append .gz and check if * that exist */ ppd = Realloc(ppd, strlen(ppd)+ strlen(PPDZIP)+2); if (ppd != NULL) { ppd = strcat(ppd, PPDZIP); if (Access(ppd, 04) != -1) { result = 1; } } } if (ppd != NULL) { free(ppd); } } return (result); } /* isPPD() */