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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /*LINTLIBRARY*/ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <sys/types.h> 34 #include <stdarg.h> 35 #include <string.h> 36 #include <syslog.h> 37 38 #include <ns.h> 39 #include <list.h> 40 #include <misc.h> 41 42 /* 43 * Manipulate bsd_addr structures 44 */ 45 ns_bsd_addr_t * 46 bsd_addr_create(const char *server, const char *printer, const char *extension) 47 { 48 ns_bsd_addr_t *addr = NULL; 49 50 if ((server != NULL) && 51 ((addr = calloc(1, sizeof (*addr))) != NULL)) { 52 addr->printer = (char *)printer; 53 addr->server = (char *)server; 54 addr->extension = (char *)extension; 55 } 56 57 return (addr); 58 } 59 60 static char * 61 bsd_addr_to_string(const ns_bsd_addr_t *addr) 62 { 63 char buf[BUFSIZ]; 64 65 if ((addr == NULL) || (addr->server == NULL)) 66 return (NULL); 67 68 if (snprintf(buf, sizeof (buf), "%s", addr->server) >= sizeof (buf)) { 69 syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow"); 70 return (NULL); 71 } 72 73 if ((addr->printer != NULL) || (addr->extension != NULL)) 74 (void) strlcat(buf, ",", sizeof (buf)); 75 if (addr->printer != NULL) 76 if (strlcat(buf, addr->printer, sizeof (buf)) >= sizeof (buf)) { 77 syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow"); 78 return (NULL); 79 } 80 if (addr->extension != NULL) { 81 (void) strlcat(buf, ",", sizeof (buf)); 82 if (strlcat(buf, addr->extension, sizeof (buf)) 83 >= sizeof (buf)) { 84 syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow"); 85 return (NULL); 86 } 87 } 88 89 return (strdup(buf)); 90 } 91 92 ns_bsd_addr_t * 93 string_to_bsd_addr(const char *string) 94 { 95 char **list, *tmp, *printer = NULL, *extension = NULL; 96 97 if (string == NULL) 98 return (NULL); 99 100 tmp = strdup(string); 101 list = strsplit(tmp, ","); 102 103 if (list[1] != NULL) { 104 printer = list[1]; 105 if (list[2] != NULL) 106 extension = list[2]; 107 } 108 109 return (bsd_addr_create(list[0], printer, extension)); 110 } 111 112 static char * 113 list_to_string(const char **list) 114 { 115 char buf[BUFSIZ]; 116 117 if ((list == NULL) || (*list == NULL)) 118 return (NULL); 119 120 if (snprintf(buf, sizeof (buf), "%s", *list) >= sizeof (buf)) { 121 syslog(LOG_ERR, "list_to_string: buffer overflow"); 122 return (NULL); 123 } 124 125 while (*++list != NULL) { 126 (void) strlcat(buf, ",", sizeof (buf)); 127 if (strlcat(buf, *list, sizeof (buf)) >= sizeof (buf)) { 128 syslog(LOG_ERR, "list_to_string: buffer overflow"); 129 return (NULL); 130 } 131 } 132 133 return (strdup(buf)); 134 } 135 136 static char * 137 internal_list_to_string(const ns_printer_t **list) 138 { 139 char buf[BUFSIZ]; 140 141 if ((list == NULL) || (*list == NULL)) 142 return (NULL); 143 144 if (snprintf(buf, sizeof (buf), "%s", (*list)->name) >= sizeof (buf)) { 145 syslog(LOG_ERR, "internal_list_to_string:buffer overflow"); 146 return (NULL); 147 } 148 149 while (*++list != NULL) { 150 (void) strlcat(buf, ",", sizeof (buf)); 151 if (strlcat(buf, (*list)->name, sizeof (buf)) >= sizeof (buf)) { 152 syslog(LOG_ERR, 153 "internal_list_to_string:buffer overflow"); 154 return (NULL); 155 } 156 } 157 158 return (strdup(buf)); 159 } 160 161 162 char * 163 value_to_string(const char *key, void *value) 164 { 165 char *string = NULL; 166 167 if ((key != NULL) && (value != NULL)) { 168 if (strcmp(key, NS_KEY_BSDADDR) == 0) { 169 string = bsd_addr_to_string(value); 170 } else if ((strcmp(key, NS_KEY_ALL) == 0) || 171 (strcmp(key, NS_KEY_GROUP) == 0)) { 172 string = list_to_string(value); 173 } else if (strcmp(key, NS_KEY_LIST) == 0) { 174 string = internal_list_to_string(value); 175 } else { 176 string = strdup((char *)value); 177 } 178 } 179 180 return (string); 181 } 182 183 184 void * 185 string_to_value(const char *key, char *string) 186 { 187 void *value = NULL; 188 189 if ((key != NULL) && (string != NULL) && (string[0] != NULL)) { 190 if (strcmp(key, NS_KEY_BSDADDR) == 0) { 191 value = (void *)string_to_bsd_addr(string); 192 } else if ((strcmp(key, NS_KEY_ALL) == 0) || 193 (strcmp(key, NS_KEY_GROUP) == 0)) { 194 value = (void *)strsplit(string, ","); 195 } else { 196 value = (void *)string; 197 } 198 } 199 200 return (value); 201 } 202 203 static void 204 split_name(char *name, const char *delimiter, char **p1, char **p2, char **p3) 205 { 206 char *tmp, *junk = NULL; 207 208 if (p1 != NULL) 209 *p1 = NULL; 210 if (p2 != NULL) 211 *p2 = NULL; 212 if (p3 != NULL) 213 *p3 = NULL; 214 215 if ((name == NULL) || (delimiter == NULL)) { 216 syslog(LOG_DEBUG, "split_name(): name/delimter invalid\n"); 217 return; 218 } 219 220 for (tmp = (char *)strtok_r(name, delimiter, &junk); tmp != NULL; 221 tmp = (char *)strtok_r(NULL, delimiter, &junk)) 222 if ((p1 != NULL) && (*p1 == NULL)) 223 *p1 = tmp; 224 else if ((p2 != NULL) && (*p2 == NULL)) { 225 *p2 = tmp; 226 if (p3 == NULL) 227 break; 228 } else if ((p3 != NULL) && (*p3 == NULL)) { 229 *p3 = tmp; 230 break; 231 } 232 } 233 234 /* 235 * This implements support for printer names that are fully resolvable 236 * on their own. These "complete" names are converted into a ns_printer_t 237 * structure containing an appropriate "bsdaddr" attribute. The supported 238 * formats are as follows: 239 * POSIX style (server:printer[:conformance]). 240 * This format is an adaptation of the format originally 241 * described in POSIX 1387.4. The POSIX draft has since been 242 * squashed, but this particular component lives on. The 243 * conformace field has been added to allow further identification 244 * of the the server. 245 */ 246 ns_printer_t * 247 posix_name(const char *name) 248 { 249 ns_printer_t *printer = NULL; 250 char *tmp = NULL; 251 252 if ((name != NULL) && ((tmp = strpbrk(name, ":")) != NULL)) { 253 char *server = NULL; 254 char *queue = NULL; 255 char *extension = NULL; 256 char *addr = strdup(name); 257 char buf[BUFSIZ]; 258 259 if (*tmp == ':') 260 split_name(addr, ": \t", &server, &queue, &extension); 261 262 memset(buf, 0, sizeof (buf)); 263 if ((server != NULL) && (queue != NULL)) 264 snprintf(buf, sizeof (buf), "%s,%s%s%s", server, 265 queue, (extension != NULL ? "," : ""), 266 (extension != NULL ? extension : "")); 267 268 /* build the structure here */ 269 if (buf[0] != NULL) { 270 ns_kvp_t **list, *kvp; 271 272 kvp = ns_kvp_create(NS_KEY_BSDADDR, buf); 273 list = (ns_kvp_t **)list_append(NULL, kvp); 274 if (list != NULL) 275 printer = ns_printer_create(strdup(name), NULL, 276 "posix", list); 277 } 278 } 279 280 return (printer); 281 } 282 283 /* 284 * FUNCTION: 285 * int ns_bsd_addr_cmp(ns_bsd_addr_t *at, ns_bsd_addr_t *a2) 286 * INPUTS: 287 * ns_bsd_addr_t *a1 - a bsd addr 288 * ns_bsd_addr_t *21 - another bsd addr 289 * DESCRIPTION: 290 * This functions compare 2 bsd_addr structures to determine if the 291 * information in them is the same. 292 */ 293 static int 294 ns_bsd_addr_cmp(ns_bsd_addr_t *a1, ns_bsd_addr_t *a2) 295 { 296 int rc; 297 298 if ((a1 == NULL) || (a2 == NULL)) 299 return (1); 300 301 if ((rc = strcmp(a1->server, a2->server)) != 0) 302 return (rc); 303 304 if ((a1->printer == NULL) || (a2->printer == NULL)) 305 return (a1->printer != a2->printer); 306 307 return (strcmp(a1->printer, a2->printer)); 308 } 309 310 311 312 313 /* 314 * FUNCTION: ns_bsd_addr_cmp_local() 315 * 316 * DESCRIPTION: This function compares 2 bsd_addr structures to determine if 317 * the information in them is the same. It destinquishes between 318 * real printer names and alias names while doing the compare. 319 * 320 * INPUTS: ns_bsd_addr_t *a1 - a bsd addr 321 * ns_bsd_addr_t *21 - another bsd addr 322 */ 323 324 static int 325 ns_bsd_addr_cmp_local(ns_bsd_addr_t *a1, ns_bsd_addr_t *a2) 326 327 { 328 int rc; 329 330 if ((a1 == NULL) || (a2 == NULL)) 331 { 332 return (1); 333 } 334 335 if ((rc = strcmp(a1->server, a2->server)) != 0) 336 { 337 return (rc); 338 } 339 340 if ((a1->printer == NULL) || (a2->printer == NULL)) 341 { 342 return (a1->printer != a2->printer); 343 } 344 345 rc = strcmp(a1->printer, a2->printer); 346 if (rc == 0) 347 { 348 /* 349 * The printer's real names are the same, but now check if 350 * their local names (alias) are the same. 351 */ 352 rc = strcmp(a1->pname, a2->pname); 353 } 354 355 return (rc); 356 } /* ns_bsd_addr_cmp_local */ 357 358 359 360 /* 361 * FUNCTION: 362 * ns_bsd_addr_t *ns_bsd_addr_get_name(char *name) 363 * INPUTS: 364 * char *name - name of printer to get address for 365 * OUTPUTS: 366 * ns_bsd_addr_t *(return) - the address of the printer 367 * DESCRIPTION: 368 * This function will get the BSD address of the printer specified. 369 * it fills in the printer name if none is specified in the "name service" 370 * as a convenience to calling functions. 371 */ 372 ns_bsd_addr_t * 373 ns_bsd_addr_get_name(char *name) 374 { 375 ns_printer_t *printer; 376 ns_bsd_addr_t *addr = NULL; 377 378 endprinterentry(); 379 if ((printer = ns_printer_get_name(name, NULL)) != NULL) { 380 addr = ns_get_value(NS_KEY_BSDADDR, printer); 381 382 if (addr != NULL && addr->printer == NULL) 383 addr->printer = strdup(printer->name); 384 if (addr != NULL) { 385 /* 386 * if the name given is not the same as that in the 387 * this is an alias/remote name so put that into the 388 * pname field otherwise duplicate the real printer 389 * name 390 */ 391 if (strcmp(name, printer->name) != 0) { 392 addr->pname = strdup(name); 393 } else { 394 addr->pname = strdup(printer->name); 395 } 396 } 397 } 398 399 return (addr); 400 } 401 402 403 /* 404 * FUNCTION: 405 * ns_bsd_addr_t **ns_bsd_addr_get_list() 406 * OUTPUT: 407 * ns_bsd_addr_t **(return) - a list of bsd addresses for all printers 408 * in all "name services" 409 * DESCRIPTION: 410 * This function will gather a list of all printer addresses in all 411 * of the "name services". All redundancy is removed. 412 */ 413 ns_bsd_addr_t ** 414 ns_bsd_addr_get_list(int unique) 415 416 { 417 ns_printer_t **printers; 418 ns_bsd_addr_t **list = NULL; 419 char **aliases = NULL; 420 421 for (printers = ns_printer_get_list(NULL); 422 printers != NULL && *printers != NULL; printers++) { 423 ns_bsd_addr_t *addr; 424 425 if (strcmp(NS_NAME_ALL, (*printers)->name) == 0) 426 continue; 427 428 if ((addr = ns_get_value(NS_KEY_BSDADDR, *printers)) != NULL) { 429 if (addr->printer == NULL) 430 addr->printer = strdup((*printers)->name); 431 addr->pname = strdup((*printers)->name); 432 } 433 434 if (unique == UNIQUE) 435 list = 436 (ns_bsd_addr_t **)list_append_unique((void **)list, 437 (void *)addr, (COMP_T)ns_bsd_addr_cmp); 438 else 439 if (unique == LOCAL_UNIQUE) 440 list = 441 (ns_bsd_addr_t **)list_append_unique((void **)list, 442 (void *)addr, (COMP_T)ns_bsd_addr_cmp_local); 443 else 444 list = (ns_bsd_addr_t **)list_append((void **)list, 445 (void *)addr); 446 447 for (aliases = (*printers)->aliases; 448 (aliases != NULL) && (*aliases != NULL); aliases++) 449 { 450 /* 451 * Include any alias names that belong to the printer 452 */ 453 454 if ((addr = 455 ns_get_value(NS_KEY_BSDADDR, *printers)) != NULL) 456 { 457 if (addr->printer == NULL) 458 { 459 addr->printer = strdup(*aliases); 460 } 461 addr->pname = strdup(*aliases); 462 } 463 464 if (unique == UNIQUE) 465 { 466 list = (ns_bsd_addr_t **) 467 list_append_unique((void **)list, 468 (void *)addr, (COMP_T)ns_bsd_addr_cmp); 469 } 470 else 471 if (unique == LOCAL_UNIQUE) 472 { 473 list = (ns_bsd_addr_t **) 474 list_append_unique((void **)list, 475 (void *)addr, 476 (COMP_T)ns_bsd_addr_cmp_local); 477 } 478 else 479 { 480 list = (ns_bsd_addr_t **) 481 list_append((void **)list, (void *)addr); 482 } 483 } 484 } 485 486 return (list); 487 } 488 489 490 491 492 /* 493 * FUNCTION: 494 * ns_bsd_addr_t **ns_bsd_addr_get_list() 495 * OUTPUT: 496 * ns_bsd_addr_t **(return) - a list of bsd addresses for "_all" printers 497 * in the "name service" 498 * DESCRIPTION: 499 * This function will use the "_all" entry to find a list of printers and 500 * addresses. The "default" printer is also added to the list. 501 * All redundancy is removed. 502 */ 503 ns_bsd_addr_t ** 504 ns_bsd_addr_get_all(int unique) 505 { 506 ns_printer_t *printer; 507 ns_bsd_addr_t **list = NULL; 508 char **printers; 509 char *def = NULL; 510 511 if (((def = (char *)getenv("PRINTER")) == NULL) && 512 ((def = (char *)getenv("LPDEST")) == NULL)) 513 def = NS_NAME_DEFAULT; 514 515 list = (ns_bsd_addr_t **)list_append((void **)list, 516 (void *)ns_bsd_addr_get_name(def)); 517 518 endprinterentry(); 519 if ((printer = ns_printer_get_name(NS_NAME_ALL, NULL)) == NULL) 520 return (ns_bsd_addr_get_list(unique)); 521 522 for (printers = (char **)ns_get_value(NS_KEY_ALL, printer); 523 printers != NULL && *printers != NULL; printers++) { 524 ns_bsd_addr_t *addr; 525 526 addr = ns_bsd_addr_get_name(*printers); 527 if (addr != NULL) 528 addr->pname = *printers; 529 if (unique == UNIQUE) 530 list = 531 (ns_bsd_addr_t **)list_append_unique((void **)list, 532 (void *)addr, (COMP_T)ns_bsd_addr_cmp); 533 else 534 list = (ns_bsd_addr_t **)list_append((void **)list, 535 (void *)addr); 536 } 537 538 return (list); 539 } 540 541 ns_bsd_addr_t * 542 ns_bsd_addr_get_default() 543 { 544 char *def = NULL; 545 ns_bsd_addr_t *addr; 546 547 if (((def = (char *)getenv("PRINTER")) == NULL) && 548 ((def = (char *)getenv("LPDEST")) == NULL)) { 549 def = NS_NAME_DEFAULT; 550 addr = ns_bsd_addr_get_name(def); 551 if (addr != NULL) { 552 addr->pname = def; 553 return (addr); 554 } 555 } 556 557 return (NULL); 558 } 559