Changeset 599 for trunk/server/source3/printing/print_cups.c
- Timestamp:
- Jul 6, 2011, 8:21:13 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server/source3/printing/print_cups.c
r480 r599 25 25 #include "includes.h" 26 26 #include "printing.h" 27 #include "librpc/gen_ndr/ndr_printcap.h" 27 28 28 29 #ifdef HAVE_CUPS … … 112 113 } 113 114 114 static void send_pcap_info(const char *name, const char *info, void *pd) 115 { 116 int fd = *(int *)pd; 117 size_t namelen = name ? strlen(name)+1 : 0; 118 size_t infolen = info ? strlen(info)+1 : 0; 119 120 DEBUG(11,("send_pcap_info: writing namelen %u\n", (unsigned int)namelen)); 121 if (sys_write(fd, &namelen, sizeof(namelen)) != sizeof(namelen)) { 122 DEBUG(10,("send_pcap_info: namelen write failed %s\n", 123 strerror(errno))); 124 return; 125 } 126 DEBUG(11,("send_pcap_info: writing infolen %u\n", (unsigned int)infolen)); 127 if (sys_write(fd, &infolen, sizeof(infolen)) != sizeof(infolen)) { 128 DEBUG(10,("send_pcap_info: infolen write failed %s\n", 129 strerror(errno))); 130 return; 131 } 132 if (namelen) { 133 DEBUG(11,("send_pcap_info: writing name %s\n", name)); 134 if (sys_write(fd, name, namelen) != namelen) { 135 DEBUG(10,("send_pcap_info: name write failed %s\n", 136 strerror(errno))); 137 return; 138 } 139 } 140 if (infolen) { 141 DEBUG(11,("send_pcap_info: writing info %s\n", info)); 142 if (sys_write(fd, info, infolen) != infolen) { 143 DEBUG(10,("send_pcap_info: info write failed %s\n", 144 strerror(errno))); 145 return; 146 } 147 } 115 static bool send_pcap_blob(DATA_BLOB *pcap_blob, int fd) 116 { 117 size_t ret; 118 119 ret = sys_write(fd, &pcap_blob->length, sizeof(pcap_blob->length)); 120 if (ret != sizeof(pcap_blob->length)) { 121 return false; 122 } 123 124 ret = sys_write(fd, pcap_blob->data, pcap_blob->length); 125 if (ret != pcap_blob->length) { 126 return false; 127 } 128 129 DEBUG(10, ("successfully sent blob of len %ld\n", (int64_t)ret)); 130 return true; 148 131 } 149 132 133 static bool recv_pcap_blob(TALLOC_CTX *mem_ctx, int fd, DATA_BLOB *pcap_blob) 134 { 135 size_t blob_len; 136 size_t ret; 137 138 ret = sys_read(fd, &blob_len, sizeof(blob_len)); 139 if (ret != sizeof(blob_len)) { 140 return false; 141 } 142 143 *pcap_blob = data_blob_talloc_named(mem_ctx, NULL, blob_len, 144 "cups pcap"); 145 if (pcap_blob->length != blob_len) { 146 return false; 147 } 148 ret = sys_read(fd, pcap_blob->data, blob_len); 149 if (ret != blob_len) { 150 talloc_free(pcap_blob->data); 151 return false; 152 } 153 154 DEBUG(10, ("successfully recvd blob of len %ld\n", (int64_t)ret)); 155 return true; 156 } 157 158 static bool process_cups_printers_response(TALLOC_CTX *mem_ctx, 159 ipp_t *response, 160 struct pcap_data *pcap_data) 161 { 162 ipp_attribute_t *attr; 163 char *name; 164 char *info; 165 struct pcap_printer *printer; 166 bool ret_ok = false; 167 168 for (attr = response->attrs; attr != NULL;) { 169 /* 170 * Skip leading attributes until we hit a printer... 171 */ 172 173 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) 174 attr = attr->next; 175 176 if (attr == NULL) 177 break; 178 179 /* 180 * Pull the needed attributes from this printer... 181 */ 182 183 name = NULL; 184 info = NULL; 185 186 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { 187 size_t size; 188 if (strcmp(attr->name, "printer-name") == 0 && 189 attr->value_tag == IPP_TAG_NAME) { 190 if (!pull_utf8_talloc(mem_ctx, 191 &name, 192 attr->values[0].string.text, 193 &size)) { 194 goto err_out; 195 } 196 } 197 198 if (strcmp(attr->name, "printer-info") == 0 && 199 attr->value_tag == IPP_TAG_TEXT) { 200 if (!pull_utf8_talloc(mem_ctx, 201 &info, 202 attr->values[0].string.text, 203 &size)) { 204 goto err_out; 205 } 206 } 207 208 attr = attr->next; 209 } 210 211 /* 212 * See if we have everything needed... 213 */ 214 215 if (name == NULL) 216 break; 217 218 if (pcap_data->count == 0) { 219 printer = talloc_array(mem_ctx, struct pcap_printer, 1); 220 } else { 221 printer = talloc_realloc(mem_ctx, pcap_data->printers, 222 struct pcap_printer, 223 pcap_data->count + 1); 224 } 225 if (printer == NULL) { 226 goto err_out; 227 } 228 pcap_data->printers = printer; 229 pcap_data->printers[pcap_data->count].name = name; 230 pcap_data->printers[pcap_data->count].info = info; 231 pcap_data->count++; 232 } 233 234 ret_ok = true; 235 err_out: 236 return ret_ok; 237 } 238 239 /* 240 * request printer list from cups, send result back to up parent via fd. 241 * returns true if the (possibly failed) result was successfuly sent to parent. 242 */ 150 243 static bool cups_cache_reload_async(int fd) 151 244 { 152 245 TALLOC_CTX *frame = talloc_stackframe(); 153 struct pcap_ cache *tmp_pcap_cache = NULL;246 struct pcap_data pcap_data; 154 247 http_t *http = NULL; /* HTTP connection to server */ 155 248 ipp_t *request = NULL, /* IPP Request */ 156 249 *response = NULL; /* IPP Response */ 157 ipp_attribute_t *attr; /* Current attribute */158 250 cups_lang_t *language = NULL; /* Default language */ 159 char *name, /* printer-name attribute */160 *info; /* printer-info attribute */161 251 static const char *requested[] =/* Requested attributes */ 162 252 { … … 165 255 }; 166 256 bool ret = False; 167 size_t size; 257 enum ndr_err_code ndr_ret; 258 DATA_BLOB pcap_blob; 259 260 ZERO_STRUCT(pcap_data); 261 pcap_data.status = NT_STATUS_UNSUCCESSFUL; 168 262 169 263 DEBUG(5, ("reloading cups printcap cache\n")); … … 174 268 175 269 cupsSetPasswordCB(cups_passwd_cb); 176 177 /*178 * Try to connect to the server...179 */180 270 181 271 if ((http = cups_connect(frame)) == NULL) { … … 210 300 NULL, requested); 211 301 212 /*213 * Do the request and get back a response...214 */215 216 302 if ((response = cupsDoRequest(http, request, "/")) == NULL) { 217 303 DEBUG(0,("Unable to get printer list - %s\n", … … 220 306 } 221 307 222 for (attr = response->attrs; attr != NULL;) { 223 /* 224 * Skip leading attributes until we hit a printer... 225 */ 226 227 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) 228 attr = attr->next; 229 230 if (attr == NULL) 231 break; 232 233 /* 234 * Pull the needed attributes from this printer... 235 */ 236 237 name = NULL; 238 info = NULL; 239 240 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { 241 if (strcmp(attr->name, "printer-name") == 0 && 242 attr->value_tag == IPP_TAG_NAME) { 243 if (!pull_utf8_talloc(frame, 244 &name, 245 attr->values[0].string.text, 246 &size)) { 247 goto out; 248 } 249 } 250 251 if (strcmp(attr->name, "printer-info") == 0 && 252 attr->value_tag == IPP_TAG_TEXT) { 253 if (!pull_utf8_talloc(frame, 254 &info, 255 attr->values[0].string.text, 256 &size)) { 257 goto out; 258 } 259 } 260 261 attr = attr->next; 262 } 263 264 /* 265 * See if we have everything needed... 266 */ 267 268 if (name == NULL) 269 break; 270 271 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) { 272 goto out; 273 } 308 ret = process_cups_printers_response(frame, response, &pcap_data); 309 if (!ret) { 310 DEBUG(0,("failed to process cups response\n")); 311 goto out; 274 312 } 275 313 … … 302 340 NULL, requested); 303 341 304 /*305 * Do the request and get back a response...306 */307 308 342 if ((response = cupsDoRequest(http, request, "/")) == NULL) { 309 343 DEBUG(0,("Unable to get printer list - %s\n", … … 312 346 } 313 347 314 for (attr = response->attrs; attr != NULL;) { 315 /* 316 * Skip leading attributes until we hit a printer... 317 */ 318 319 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) 320 attr = attr->next; 321 322 if (attr == NULL) 323 break; 324 325 /* 326 * Pull the needed attributes from this printer... 327 */ 328 329 name = NULL; 330 info = NULL; 331 332 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { 333 if (strcmp(attr->name, "printer-name") == 0 && 334 attr->value_tag == IPP_TAG_NAME) { 335 if (!pull_utf8_talloc(frame, 336 &name, 337 attr->values[0].string.text, 338 &size)) { 339 goto out; 340 } 341 } 342 343 if (strcmp(attr->name, "printer-info") == 0 && 344 attr->value_tag == IPP_TAG_TEXT) { 345 if (!pull_utf8_talloc(frame, 346 &info, 347 attr->values[0].string.text, 348 &size)) { 349 goto out; 350 } 351 } 352 353 attr = attr->next; 354 } 355 356 /* 357 * See if we have everything needed... 358 */ 359 360 if (name == NULL) 361 break; 362 363 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) { 364 goto out; 365 } 366 } 367 368 ret = True; 369 348 ret = process_cups_printers_response(frame, response, &pcap_data); 349 if (!ret) { 350 DEBUG(0,("failed to process cups response\n")); 351 goto out; 352 } 353 354 pcap_data.status = NT_STATUS_OK; 370 355 out: 371 356 if (response) … … 378 363 httpClose(http); 379 364 380 /* Send all the entries up the pipe. */ 381 if (tmp_pcap_cache) { 382 pcap_printer_fn_specific(tmp_pcap_cache, 383 send_pcap_info, 384 (void *)&fd); 385 386 pcap_cache_destroy_specific(&tmp_pcap_cache); 387 } 365 ret = false; 366 ndr_ret = ndr_push_struct_blob(&pcap_blob, frame, NULL, &pcap_data, 367 (ndr_push_flags_fn_t)ndr_push_pcap_data); 368 if (ndr_ret == NDR_ERR_SUCCESS) { 369 ret = send_pcap_blob(&pcap_blob, fd); 370 } 371 388 372 TALLOC_FREE(frame); 389 373 return ret; … … 450 434 } 451 435 436 struct cups_async_cb_args { 437 int pipe_fd; 438 void (*post_cache_fill_fn)(void); 439 }; 440 452 441 static void cups_async_callback(struct event_context *event_ctx, 453 442 struct fd_event *event, … … 456 445 { 457 446 TALLOC_CTX *frame = talloc_stackframe(); 458 int fd = *(int*)p;447 struct cups_async_cb_args *cb_args = (struct cups_async_cb_args *)p; 459 448 struct pcap_cache *tmp_pcap_cache = NULL; 449 bool ret_ok; 450 struct pcap_data pcap_data; 451 DATA_BLOB pcap_blob; 452 enum ndr_err_code ndr_ret; 453 int i; 460 454 461 455 DEBUG(5,("cups_async_callback: callback received for printer data. " 462 "fd = %d\n", fd)); 463 464 while (1) { 465 char *name = NULL, *info = NULL; 466 size_t namelen = 0, infolen = 0; 467 ssize_t ret = -1; 468 469 ret = sys_read(fd, &namelen, sizeof(namelen)); 470 if (ret == 0) { 471 /* EOF */ 456 "fd = %d\n", cb_args->pipe_fd)); 457 458 ret_ok = recv_pcap_blob(frame, cb_args->pipe_fd, &pcap_blob); 459 if (!ret_ok) { 460 DEBUG(0,("failed to recv pcap blob\n")); 461 goto err_out; 462 } 463 464 ndr_ret = ndr_pull_struct_blob(&pcap_blob, frame, NULL, &pcap_data, 465 (ndr_pull_flags_fn_t)ndr_pull_pcap_data); 466 if (ndr_ret != NDR_ERR_SUCCESS) { 467 goto err_out; 468 } 469 470 if (!NT_STATUS_IS_OK(pcap_data.status)) { 471 DEBUG(0,("failed to retrieve printer list: %s\n", 472 nt_errstr(pcap_data.status))); 473 goto err_out; 474 } 475 476 for (i = 0; i < pcap_data.count; i++) { 477 ret_ok = pcap_cache_add_specific(&tmp_pcap_cache, 478 pcap_data.printers[i].name, 479 pcap_data.printers[i].info); 480 if (!ret_ok) { 481 DEBUG(0, ("failed to add to tmp pcap cache\n")); 472 482 break; 473 483 } 474 if (ret != sizeof(namelen)) { 475 DEBUG(10,("cups_async_callback: namelen read failed %d %s\n", 476 errno, strerror(errno))); 477 break; 478 } 479 480 DEBUG(11,("cups_async_callback: read namelen %u\n", 481 (unsigned int)namelen)); 482 483 ret = sys_read(fd, &infolen, sizeof(infolen)); 484 if (ret == 0) { 485 /* EOF */ 486 break; 487 } 488 if (ret != sizeof(infolen)) { 489 DEBUG(10,("cups_async_callback: infolen read failed %s\n", 490 strerror(errno))); 491 break; 492 } 493 494 DEBUG(11,("cups_async_callback: read infolen %u\n", 495 (unsigned int)infolen)); 496 497 if (namelen) { 498 name = TALLOC_ARRAY(frame, char, namelen); 499 if (!name) { 500 break; 501 } 502 ret = sys_read(fd, name, namelen); 503 if (ret == 0) { 504 /* EOF */ 505 break; 506 } 507 if (ret != namelen) { 508 DEBUG(10,("cups_async_callback: name read failed %s\n", 509 strerror(errno))); 510 break; 511 } 512 DEBUG(11,("cups_async_callback: read name %s\n", 513 name)); 514 } else { 515 name = NULL; 516 } 517 if (infolen) { 518 info = TALLOC_ARRAY(frame, char, infolen); 519 if (!info) { 520 break; 521 } 522 ret = sys_read(fd, info, infolen); 523 if (ret == 0) { 524 /* EOF */ 525 break; 526 } 527 if (ret != infolen) { 528 DEBUG(10,("cups_async_callback: info read failed %s\n", 529 strerror(errno))); 530 break; 531 } 532 DEBUG(11,("cups_async_callback: read info %s\n", 533 info)); 534 } else { 535 info = NULL; 536 } 537 538 /* Add to our local pcap cache. */ 539 pcap_cache_add_specific(&tmp_pcap_cache, name, info); 540 TALLOC_FREE(name); 541 TALLOC_FREE(info); 542 } 543 544 TALLOC_FREE(frame); 545 if (tmp_pcap_cache) { 546 /* We got a namelist, replace our local cache. */ 484 } 485 486 if (!ret_ok) { 487 DEBUG(0,("failed to read a new printer list\n")); 488 pcap_cache_destroy_specific(&tmp_pcap_cache); 489 } else { 490 /* We got a possibly empty namelist, replace our local cache. */ 547 491 pcap_cache_destroy_specific(&local_pcap_copy); 548 492 local_pcap_copy = tmp_pcap_cache; … … 550 494 /* And the systemwide pcap cache. */ 551 495 pcap_cache_replace(local_pcap_copy); 552 } else { 553 DEBUG(2,("cups_async_callback: failed to read a new " 554 "printer list\n")); 555 } 556 close(fd); 557 TALLOC_FREE(p); 496 497 /* Caller may have requested post cache fill callback */ 498 if (cb_args->post_cache_fill_fn) { 499 cb_args->post_cache_fill_fn(); 500 } 501 } 502 err_out: 503 TALLOC_FREE(frame); 504 close(cb_args->pipe_fd); 505 TALLOC_FREE(cb_args); 558 506 TALLOC_FREE(cache_fd_event); 559 507 } 560 508 561 bool cups_cache_reload(void) 562 { 563 int *p_pipe_fd = TALLOC_P(NULL, int); 564 565 if (!p_pipe_fd) { 509 bool cups_cache_reload(void (*post_cache_fill_fn)(void)) 510 { 511 struct cups_async_cb_args *cb_args; 512 int *p_pipe_fd; 513 514 cb_args = TALLOC_P(NULL, struct cups_async_cb_args); 515 if (!cb_args) { 566 516 return false; 567 517 } 568 518 cb_args->post_cache_fill_fn = post_cache_fill_fn; 519 p_pipe_fd = &cb_args->pipe_fd; 569 520 *p_pipe_fd = -1; 570 521 571 522 /* Set up an async refresh. */ 572 523 if (!cups_pcap_load_async(p_pipe_fd)) { 524 talloc_free(cb_args); 573 525 return false; 574 526 } … … 583 535 NULL, 584 536 EVENT_FD_READ, 585 (void *) p_pipe_fd);537 (void *)cb_args); 586 538 if (!local_pcap_copy) { 587 539 return false; … … 600 552 EVENT_FD_READ, 601 553 cups_async_callback, 602 (void *) p_pipe_fd);554 (void *)cb_args); 603 555 if (!cache_fd_event) { 604 556 close(*p_pipe_fd); 605 TALLOC_FREE(p_pipe_fd);557 talloc_free(cb_args); 606 558 return false; 607 559 } … … 1645 1597 cups_lang_t *language = NULL; /* Default language */ 1646 1598 char uri[HTTP_MAX_URI]; 1647 char *server = NULL;1648 1599 char *sharename = NULL; 1649 1600 char *name = NULL; … … 1686 1637 "attributes-natural-language", NULL, language->language); 1687 1638 1688 if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {1689 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {1690 goto out;1691 }1692 } else {1693 server = talloc_strdup(frame,cupsServer());1694 }1695 if (server) {1696 goto out;1697 }1698 1639 if (!push_utf8_talloc(frame, &sharename, printer->sharename, &size)) { 1699 1640 goto out; 1700 1641 } 1701 slprintf(uri, sizeof(uri) - 1, "ipp:// %s/printers/%s",1702 s erver, sharename);1642 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", 1643 sharename); 1703 1644 1704 1645 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, … … 1801 1742 ippDelete(response); 1802 1743 1803 if (request) {1804 ippDelete(request);1805 }1806 1807 1744 if (language) 1808 1745 cupsLangFree(language);
Note:
See TracChangeset
for help on using the changeset viewer.