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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */ 33 34 #include "stdio.h" 35 #include "string.h" 36 #include "errno.h" 37 #include "sys/types.h" 38 #include "stdlib.h" 39 #include <syslog.h> 40 41 #include "lp.h" 42 #include "printers.h" 43 44 extern struct { 45 char *v; 46 short len, 47 okremote; 48 } prtrheadings[]; 49 50 /** 51 ** getprinter() - EXTRACT PRINTER STRUCTURE FROM DISK FILE 52 **/ 53 54 PRINTER * 55 getprinter(char *name) 56 { 57 static long lastdir = -1; 58 59 PRINTER *prp; 60 61 char buf[BUFSIZ]; 62 63 short daisy; 64 65 int fld; 66 67 int fd; 68 69 FALERT *pa; 70 71 register char * p; 72 register char ** pp; 73 register char *** ppp; 74 register char * path; 75 int isNameAll; 76 77 78 79 if (!name || !*name) { 80 errno = EINVAL; 81 return (0); 82 } 83 84 syslog(LOG_DEBUG, "getprinter(%s)", name ? name : ""); 85 /* 86 * Getting ``all''? If so, jump into the directory 87 * wherever we left off. 88 */ 89 isNameAll = STREQU(NAME_ALL, name); 90 for (; ; ) { 91 /* fix for bug 1117241 92 * occasionally when a printer is removed, a printer directory 93 * is left behind, but the CONFIGFILE is removed. In this 94 * case this directory terminates the search for additional 95 * printers as we have been returning 0 in this case. 96 * Now, we loop back and try the next directory until 97 * we have no more directories or we find a directory with 98 * a CONFIGFILE 99 */ 100 if (isNameAll) { 101 if (!(name = next_dir(Lp_A_Printers, &lastdir))) 102 return (0); 103 } else 104 lastdir = -1; 105 106 /* 107 * Get the printer configuration information. 108 */ 109 110 path = getprinterfile(name, CONFIGFILE); 111 if (!path) { 112 if (isNameAll) 113 Free(name); 114 return (0); 115 } 116 117 if ((fd = open_locked(path, "r", 0)) < 0) { 118 Free(path); /* 119 * go around to loop again for 120 * NAME_ALL case 121 */ 122 123 if (!isNameAll) /* fix for bug 1117241 */ 124 return(0); 125 else 126 Free(name); 127 } 128 else 129 break; 130 } 131 Free (path); 132 133 /* 134 * Initialize the entire structure, to ensure no random 135 * values get in it. However, make sure some values won't 136 * be null or empty. Do the latter here as opposed to 137 * after reading the file, because sometimes the file 138 * contains an empty header to FORCE a null/empty value. 139 */ 140 prp = calloc(sizeof (*prp), 1); 141 prp->name = Strdup(name); 142 if (isNameAll) 143 Free(name); 144 prp->printer_types = getlist(NAME_UNKNOWN, LP_WS, LP_SEP); 145 prp->input_types = getlist(NAME_SIMPLE, LP_WS, LP_SEP); 146 #if defined(CAN_DO_MODULES) 147 prp->modules = getlist(NAME_DEFAULT, LP_WS, LP_SEP); 148 #endif 149 150 /* 151 * Read the file. 152 */ 153 errno = 0; 154 while (fdgets(buf, BUFSIZ, fd) != NULL) { 155 156 buf[strlen(buf) - 1] = 0; 157 158 for (fld = 0; fld < PR_MAX; fld++) 159 if ( 160 prtrheadings[fld].v 161 && prtrheadings[fld].len 162 && STRNEQU( 163 buf, 164 prtrheadings[fld].v, 165 prtrheadings[fld].len 166 ) 167 ) { 168 p = buf + prtrheadings[fld].len; 169 while (*p && *p == ' ') 170 p++; 171 break; 172 } 173 174 /* 175 * To allow future extensions to not impact applications 176 * using old versions of this routine, ignore strange 177 * fields. 178 */ 179 if (fld >= PR_MAX) 180 continue; 181 182 switch (fld) { 183 184 case PR_BAN: 185 if ((pp = getlist(p, LP_WS, ":"))) { 186 if (pp[0] != NULL) { 187 if (strcmp(pp[0], NAME_OPTIONAL) == 0) 188 prp->banner = BAN_OPTIONAL; 189 else if (strcmp(pp[0], NAME_OFF) == 0) 190 prp->banner = BAN_NEVER; 191 else if (strcmp(pp[0], NAME_ON) == 0) 192 prp->banner = BAN_ALWAYS; 193 else /* default to the LP default */ 194 prp->banner = BAN_ALWAYS; 195 } 196 if (pp[1] && CS_STREQU(pp[1], NAME_ALWAYS)) 197 prp->banner |= BAN_ALWAYS; 198 freelist (pp); 199 } 200 break; 201 202 case PR_LOGIN: 203 prp->login = LOG_IN; 204 break; 205 206 case PR_CPI: 207 prp->cpi = getcpi(p); 208 break; 209 210 case PR_LPI: 211 prp->lpi = getsdn(p); 212 break; 213 214 case PR_LEN: 215 prp->plen = getsdn(p); 216 break; 217 218 case PR_WIDTH: 219 prp->pwid = getsdn(p); 220 break; 221 222 case PR_CS: 223 ppp = &(prp->char_sets); 224 goto CharStarStar; 225 226 case PR_ITYPES: 227 ppp = &(prp->input_types); 228 CharStarStar: if (*ppp) 229 freelist (*ppp); 230 *ppp = getlist(p, LP_WS, LP_SEP); 231 break; 232 233 case PR_DEV: 234 pp = &(prp->device); 235 goto CharStar; 236 237 case PR_DIAL: 238 pp = &(prp->dial_info); 239 goto CharStar; 240 241 case PR_RECOV: 242 pp = &(prp->fault_rec); 243 goto CharStar; 244 245 case PR_INTFC: 246 pp = &(prp->interface); 247 goto CharStar; 248 249 case PR_PTYPE: 250 ppp = &(prp->printer_types); 251 goto CharStarStar; 252 253 case PR_REMOTE: 254 pp = &(prp->remote); 255 goto CharStar; 256 257 case PR_SPEED: 258 pp = &(prp->speed); 259 goto CharStar; 260 261 case PR_STTY: 262 pp = &(prp->stty); 263 CharStar: if (*pp) 264 Free (*pp); 265 *pp = Strdup(p); 266 break; 267 268 #if defined(CAN_DO_MODULES) 269 case PR_MODULES: 270 ppp = &(prp->modules); 271 goto CharStarStar; 272 #endif 273 274 case PR_OPTIONS: 275 ppp = &(prp->options); 276 goto CharStarStar; 277 break; 278 279 case PR_PPD: 280 { 281 pp = &(prp->ppd); 282 goto CharStar; 283 } 284 } 285 286 } 287 if (errno != 0) { 288 int save_errno = errno; 289 290 freeprinter (prp); 291 close(fd); 292 errno = save_errno; 293 return (0); 294 } 295 close(fd); 296 297 /* 298 * Get the printer description (if it exists). 299 */ 300 if (!(path = getprinterfile(prp->name, COMMENTFILE))) 301 return (0); 302 if (!(prp->description = loadstring(path)) && errno != ENOENT) { 303 Free (path); 304 freeprinter (prp); 305 return (0); 306 } 307 Free (path); 308 309 /* 310 * Get the information for the alert. Don't fail if we can't 311 * read it because of access permission UNLESS we're "root" 312 * or "lp" 313 */ 314 if (!(pa = getalert(Lp_A_Printers, prp->name))) { 315 if ( 316 errno != ENOENT 317 && ( 318 errno != EACCES 319 || !getpid() /* we be root */ 320 || STREQU(getname(), LPUSER) /* we be lp */ 321 ) 322 ) { 323 freeprinter (prp); 324 return (0); 325 } 326 } else 327 prp->fault_alert = *pa; 328 329 /* 330 * Now go through the structure and see if we have 331 * anything strange. 332 */ 333 if (!okprinter(prp->name, prp, 0)) { 334 freeprinter (prp); 335 errno = EBADF; 336 return (0); 337 } 338 339 /* 340 * Just in case somebody tried to pull a fast one 341 * by giving a printer type header by itself.... 342 */ 343 if (!prp->printer_types) 344 prp->printer_types = getlist(NAME_UNKNOWN, LP_WS, LP_SEP); 345 346 /* 347 * If there are more than one printer type, then we can't 348 * have any input types, except perhaps ``simple''. 349 */ 350 if ( 351 lenlist(prp->printer_types) > 1 352 && prp->input_types 353 && ( 354 lenlist(prp->input_types) > 1 355 || !STREQU(NAME_SIMPLE, *prp->input_types) 356 ) 357 ) { 358 freeprinter (prp); 359 badprinter = BAD_ITYPES; 360 errno = EBADF; 361 return (0); 362 } 363 364 /* 365 * If there are more than one printer types, none can 366 * be ``unknown''. 367 */ 368 if ( 369 lenlist(prp->printer_types) > 1 370 && searchlist(NAME_UNKNOWN, prp->printer_types) 371 ) { 372 freeprinter (prp); 373 badprinter = BAD_PTYPES; 374 errno = EBADF; 375 return (0); 376 } 377 378 /* 379 * All the printer types had better agree on whether the 380 * printer takes print wheels! 381 */ 382 prp->daisy = -1; 383 for (pp = prp->printer_types; *pp; pp++) { 384 tidbit (*pp, "daisy", &daisy); 385 if (daisy == -1) 386 daisy = 0; 387 if (prp->daisy == -1) 388 prp->daisy = daisy; 389 else if (prp->daisy != daisy) { 390 freeprinter (prp); 391 badprinter = BAD_DAISY; 392 errno = EBADF; 393 return (0); 394 } 395 } 396 397 /* 398 * Help out those who are still using the obsolete 399 * "printer_type" member. 400 */ 401 prp->printer_type = Strdup(*prp->printer_types); 402 403 return (prp); 404 } 405