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