1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */ 32 33 #include "stdio.h" 34 #include "string.h" 35 #include "errno.h" 36 #include "stdlib.h" 37 #include "unistd.h" 38 39 #include "lp.h" 40 #include "filters.h" 41 42 _FILTER *filters; 43 44 size_t nfilters; 45 46 static int getfields (int, char *[], char *, int, int, char *); 47 static int fs_cmp(const void *, const void *); 48 49 /** 50 ** loadfilters() - READ FILTERS FROM FILTER TABLE INTO INTERNAL STRUCTURE 51 **/ 52 53 int 54 loadfilters(char *file) 55 { 56 register _FILTER *pf; 57 int fd; 58 char *filt[FL_MAX], 59 buf[3 * BUFSIZ]; 60 size_t nalloc; 61 62 if (filters) { 63 nalloc = nfilters; 64 trash_filters (); 65 } else 66 nalloc = FL_MAX_GUESS; 67 68 if ((fd = open_filtertable(file, "r")) < 0) 69 return (-1); 70 71 /* 72 * Preallocate space for the internal filter table. 73 * Our guess is the number of filters previously read in, 74 * if any have been read in before (see above). 75 */ 76 filters = (_FILTER *)Malloc((nalloc + 1) * sizeof(_FILTER)); 77 if (!filters) { 78 close(fd); 79 errno = ENOMEM; 80 return (-1); 81 } 82 83 for ( 84 pf = filters, nfilters = 0; 85 getfields(fd, filt, buf, sizeof(buf), FL_MAX, FL_SEP) != -1; 86 pf++ 87 ) { 88 89 char **list; 90 91 /* 92 * Allocate more space if needed. 93 */ 94 if (++nfilters > nalloc) { 95 nalloc = nfilters; 96 filters = (_FILTER *)Realloc( 97 filters, 98 (nalloc + 1) * sizeof(_FILTER) 99 ); 100 if (!filters) { 101 close(fd); 102 errno = ENOMEM; 103 return (-1); 104 } 105 pf = &filters[nfilters - 1]; 106 } 107 108 #define DFLT(X) (filt[X] && *filt[X]? filt[X] : NAME_ANY) 109 110 pf->name = Strdup(filt[FL_NAME]); 111 pf->type = s_to_filtertype(filt[FL_TYPE]); 112 pf->command = Strdup(filt[FL_CMD]); 113 114 pf->printers = getlist(DFLT(FL_PRTRS), LP_WS, LP_SEP); 115 116 list = getlist(DFLT(FL_PTYPS), LP_WS, LP_SEP); 117 pf->printer_types = sl_to_typel(list); 118 freelist (list); 119 120 list = getlist(DFLT(FL_ITYPS), LP_WS, LP_SEP); 121 pf->input_types = sl_to_typel(list); 122 freelist (list); 123 124 list = getlist(DFLT(FL_OTYPS), LP_WS, LP_SEP); 125 pf->output_types = sl_to_typel(list); 126 freelist (list); 127 128 /* 129 * Note the use of "" instead of LP_WS. The 130 * "sl_to_templatel()" routine will take care 131 * of stripping leading blanks. Stripping trailing 132 * blanks would be nice but shouldn't matter. 133 */ 134 135 /* quote reason #3 (in "getlist()") */ 136 list = getlist(filt[FL_TMPS], "", LP_SEP); 137 138 /* quote reason #4 (in "s_to_template()") */ 139 pf->templates = sl_to_templatel(list); 140 freelist (list); 141 142 } 143 if (errno != 0) { 144 int save_errno = errno; 145 146 free_filter (pf); 147 close(fd); 148 errno = save_errno; 149 return (-1); 150 } 151 close(fd); 152 153 /* 154 * If we have more space allocated than we need, 155 * return the extra. 156 */ 157 if (nfilters != nalloc) { 158 filters = (_FILTER *)Realloc( 159 filters, 160 (nfilters + 1) * sizeof(_FILTER) 161 ); 162 if (!filters) { 163 errno = ENOMEM; 164 return (-1); 165 } 166 } 167 filters[nfilters].name = 0; 168 169 /* 170 * Sort the filters, putting ``fast'' filters before 171 * ``slow'' filters. This preps the list for "insfilter()" 172 * so that it can easily pick fast filters over otherwise 173 * equivalent slow filters. This sorting is done every 174 * time we read in the table; one might think that if 175 * "putfilter()" would insert in the correct order then 176 * the table, when written out to disk, would be sorted 177 * already--removing the need to sort it here. We don't 178 * take that approach, because (1) sorting it isn't that 179 * expensive and (2) someone might tamper with the table 180 * file. 181 */ 182 qsort ((char *)filters, nfilters, sizeof(_FILTER), fs_cmp); 183 184 return (0); 185 } 186 187 /** 188 ** getfields() - PARSE NON-COMMENT LINE FROM FILE INTO FIELDS 189 **/ 190 191 static int 192 getfields(int fd, char *fields[], char *buf, int bufsiz, int max, char *seps) 193 { 194 register char *p, 195 *q; 196 197 register int n = 0; 198 enum ParsingMode {CHECK_LEAD_DBL_QUOTE, NORMAL_PARSING, LITERAL_READ} eMode; 199 errno = 0; 200 while (fdgets(buf, bufsiz, fd) != NULL) { 201 buf[strlen(buf) - 1] = 0; 202 p = buf + strspn(buf, " \t"); 203 if (*p && *p != '#') { 204 for (eMode = CHECK_LEAD_DBL_QUOTE, fields[n++] = q = p; *p; ) { 205 switch (eMode) { 206 case CHECK_LEAD_DBL_QUOTE: /* check for leading double quote */ 207 if (*p == '"') { 208 eMode = LITERAL_READ; 209 p++; 210 break; 211 } 212 eMode = NORMAL_PARSING; 213 /* FALLTHROUGH */ 214 215 case NORMAL_PARSING: /* default legacy editing */ 216 if (*p == '\\') { 217 if ( 218 /* quote reason #1 */ p[1] == '\\' 219 /* quote reason #2 */ || strchr(seps, p[1]) 220 ) 221 p++; 222 *q++ = *p++; 223 } else if (strchr(seps, *p)) { 224 *q++ = 0; 225 p++; 226 if (n < max) { 227 fields[n++] = q; 228 eMode = CHECK_LEAD_DBL_QUOTE; 229 } 230 } else 231 *q++ = *p++; 232 break; 233 234 case LITERAL_READ: /* read literally until another double quote */ 235 if (*p == '\\' && p[1] == '"') { /* embedded double quote */ 236 p++; 237 *q++ = *p++; 238 } else if (*p == '"') { /* end of literal read */ 239 p++; 240 eMode = NORMAL_PARSING; 241 } else { 242 *q++ = *p++; /* capture as is */ 243 } 244 break; 245 } 246 } 247 *q = 0; 248 while (n < max) 249 fields[n++] = ""; 250 return (n); 251 } 252 } 253 return (-1); 254 } 255 256 /** 257 ** fs_cmp() - COMPARE TWO FILTERS BY "FILTERTYPE" 258 **/ 259 260 static int 261 fs_cmp(const void *pfa, const void *pfb) 262 { 263 if (((_FILTER *)pfa)->type == ((_FILTER *)pfb)->type) 264 return (0); 265 else if (((_FILTER *)pfa)->type == fl_fast) 266 return (-1); 267 else 268 return (1); 269 } 270