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