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