1/* 2 * "$Id: adminutil.c 11093 2013-07-03 20:48:42Z msweet $" 3 * 4 * Administration utility API definitions for CUPS. 5 * 6 * Copyright 2007-2013 by Apple Inc. 7 * Copyright 2001-2007 by Easy Software Products. 8 * 9 * These coded instructions, statements, and computer programs are the 10 * property of Apple Inc. and are protected by Federal copyright 11 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 12 * which should have been included with this file. If this file is 13 * file is missing or damaged, see the license at "http://www.cups.org/". 14 * 15 * This file is subject to the Apple OS-Developed Software exception. 16 * 17 * Contents: 18 * 19 * cupsAdminCreateWindowsPPD() - Create the Windows PPD file for a printer. 20 * cupsAdminExportSamba() - Export a printer to Samba. 21 * cupsAdminGetServerSettings() - Get settings from the server. 22 * cupsAdminSetServerSettings() - Set settings on the server. 23 * do_samba_command() - Do a SAMBA command. 24 * get_cupsd_conf() - Get the current cupsd.conf file. 25 * invalidate_cupsd_cache() - Invalidate the cached cupsd.conf settings. 26 * write_option() - Write a CUPS option to a PPD file. 27 */ 28 29/* 30 * Include necessary headers... 31 */ 32 33#include "cups-private.h" 34#include "adminutil.h" 35#include <fcntl.h> 36#include <sys/stat.h> 37#ifdef WIN32 38#else 39# include <unistd.h> 40# include <sys/wait.h> 41#endif /* WIN32 */ 42 43 44/* 45 * Local functions... 46 */ 47 48static int do_samba_command(const char *command, 49 const char *address, 50 const char *subcommand, 51 const char *authfile, 52 FILE *logfile); 53static http_status_t get_cupsd_conf(http_t *http, _cups_globals_t *cg, 54 time_t last_update, char *name, 55 int namelen, int *remote); 56static void invalidate_cupsd_cache(_cups_globals_t *cg); 57static void write_option(cups_file_t *dstfp, int order, 58 const char *name, const char *text, 59 const char *attrname, 60 ipp_attribute_t *suppattr, 61 ipp_attribute_t *defattr, int defval, 62 int valcount); 63 64 65/* 66 * 'cupsAdminCreateWindowsPPD()' - Create the Windows PPD file for a printer. 67 * 68 * @deprecated@ 69 */ 70 71char * /* O - PPD file or NULL */ 72cupsAdminCreateWindowsPPD( 73 http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ 74 const char *dest, /* I - Printer or class */ 75 char *buffer, /* I - Filename buffer */ 76 int bufsize) /* I - Size of filename buffer */ 77{ 78 const char *src; /* Source PPD filename */ 79 cups_file_t *srcfp, /* Source PPD file */ 80 *dstfp; /* Destination PPD file */ 81 ipp_t *request, /* IPP request */ 82 *response; /* IPP response */ 83 ipp_attribute_t *suppattr, /* IPP -supported attribute */ 84 *defattr; /* IPP -default attribute */ 85 cups_lang_t *language; /* Current language */ 86 char line[256], /* Line from PPD file */ 87 junk[256], /* Extra junk to throw away */ 88 *ptr, /* Pointer into line */ 89 uri[1024], /* Printer URI */ 90 option[41], /* Option */ 91 choice[41]; /* Choice */ 92 int jcloption, /* In a JCL option? */ 93 jclorder, /* Next JCL order dependency */ 94 linenum; /* Current line number */ 95 time_t curtime; /* Current time */ 96 struct tm *curdate; /* Current date */ 97 static const char * const pattrs[] = /* Printer attributes we want */ 98 { 99 "job-hold-until-supported", 100 "job-hold-until-default", 101 "job-sheets-supported", 102 "job-sheets-default", 103 "job-priority-supported", 104 "job-priority-default" 105 }; 106 107 108 /* 109 * Range check the input... 110 */ 111 112 if (buffer) 113 *buffer = '\0'; 114 115 if (!http) 116 http = _cupsConnect(); 117 118 if (!http || !dest || !buffer || bufsize < 2) 119 return (NULL); 120 121 /* 122 * Get the PPD file... 123 */ 124 125 if ((src = cupsGetPPD2(http, dest)) == NULL) 126 return (NULL); 127 128 /* 129 * Get the supported banner pages, etc. for the printer... 130 */ 131 132 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); 133 134 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, 135 "localhost", 0, "/printers/%s", dest); 136 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, 137 "printer-uri", NULL, uri); 138 139 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, 140 "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), 141 NULL, pattrs); 142 143 /* 144 * Do the request and get back a response... 145 */ 146 147 response = cupsDoRequest(http, request, "/"); 148 if (!response || cupsLastError() > IPP_STATUS_OK_CONFLICTING) 149 { 150 unlink(src); 151 return (NULL); 152 } 153 154 /* 155 * Open the original PPD file... 156 */ 157 158 if ((srcfp = cupsFileOpen(src, "rb")) == NULL) 159 return (NULL); 160 161 /* 162 * Create a temporary output file using the destination buffer... 163 */ 164 165 if ((dstfp = cupsTempFile2(buffer, bufsize)) == NULL) 166 { 167 cupsFileClose(srcfp); 168 169 unlink(src); 170 171 return (NULL); 172 } 173 174 /* 175 * Write a new header explaining that this isn't the original PPD... 176 */ 177 178 cupsFilePuts(dstfp, "*PPD-Adobe: \"4.3\"\n"); 179 180 curtime = time(NULL); 181 curdate = gmtime(&curtime); 182 183 cupsFilePrintf(dstfp, "*%% Modified on %04d%02d%02d%02d%02d%02d+0000 " 184 "for CUPS Windows Driver\n", 185 curdate->tm_year + 1900, curdate->tm_mon + 1, curdate->tm_mday, 186 curdate->tm_hour, curdate->tm_min, curdate->tm_sec); 187 188 /* 189 * Read the existing PPD file, converting all PJL commands to CUPS 190 * job ticket comments... 191 */ 192 193 jcloption = 0; 194 jclorder = 0; 195 linenum = 0; 196 language = cupsLangDefault(); 197 198 while (cupsFileGets(srcfp, line, sizeof(line))) 199 { 200 linenum ++; 201 202 if (!strncmp(line, "*PPD-Adobe:", 11)) 203 { 204 /* 205 * Already wrote the PPD header... 206 */ 207 208 continue; 209 } 210 else if (!strncmp(line, "*JCLBegin:", 10) || 211 !strncmp(line, "*JCLToPSInterpreter:", 20) || 212 !strncmp(line, "*JCLEnd:", 8) || 213 !strncmp(line, "*Protocols:", 11)) 214 { 215 /* 216 * Don't use existing JCL keywords; we'll create our own, below... 217 */ 218 219 cupsFilePrintf(dstfp, "*%% Commented out for CUPS Windows Driver...\n" 220 "*%%%s\n", line + 1); 221 continue; 222 } 223 else if (!strncmp(line, "*JCLOpenUI", 10)) 224 { 225 jcloption = 1; 226 cupsFilePrintf(dstfp, "%s\n", line); 227 } 228 else if (!strncmp(line, "*JCLCloseUI", 11)) 229 { 230 jcloption = 0; 231 cupsFilePrintf(dstfp, "%s\n", line); 232 } 233 else if (jcloption && !strncmp(line, "*OrderDependency:", 17)) 234 { 235 for (ptr = line + 17; _cups_isspace(*ptr); ptr ++); 236 237 ptr = strchr(ptr, ' '); 238 239 if (ptr) 240 { 241 cupsFilePrintf(dstfp, "*OrderDependency: %d%s\n", jclorder, ptr); 242 jclorder ++; 243 } 244 else 245 cupsFilePrintf(dstfp, "%s\n", line); 246 } 247 else if (jcloption && 248 strncmp(line, "*End", 4) && 249 strncmp(line, "*Default", 8)) 250 { 251 if ((ptr = strchr(line, ':')) == NULL) 252 { 253 snprintf(line, sizeof(line), 254 _cupsLangString(language, _("Missing value on line %d.")), 255 linenum); 256 _cupsSetError(IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR, line, 0); 257 258 cupsFileClose(srcfp); 259 cupsFileClose(dstfp); 260 261 unlink(src); 262 unlink(buffer); 263 264 *buffer = '\0'; 265 266 return (NULL); 267 } 268 269 if ((ptr = strchr(ptr, '\"')) == NULL) 270 { 271 snprintf(line, sizeof(line), 272 _cupsLangString(language, 273 _("Missing double quote on line %d.")), 274 linenum); 275 _cupsSetError(IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR, line, 0); 276 277 cupsFileClose(srcfp); 278 cupsFileClose(dstfp); 279 280 unlink(src); 281 unlink(buffer); 282 283 *buffer = '\0'; 284 285 return (NULL); 286 } 287 288 if (sscanf(line, "*%40s%*[ \t]%40[^:/]", option, choice) != 2) 289 { 290 snprintf(line, sizeof(line), 291 _cupsLangString(language, 292 _("Bad option + choice on line %d.")), 293 linenum); 294 _cupsSetError(IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR, line, 0); 295 296 cupsFileClose(srcfp); 297 cupsFileClose(dstfp); 298 299 unlink(src); 300 unlink(buffer); 301 302 *buffer = '\0'; 303 304 return (NULL); 305 } 306 307 if (strchr(ptr + 1, '\"') == NULL) 308 { 309 /* 310 * Skip remaining... 311 */ 312 313 while (cupsFileGets(srcfp, junk, sizeof(junk)) != NULL) 314 { 315 linenum ++; 316 317 if (!strncmp(junk, "*End", 4)) 318 break; 319 } 320 } 321 322 snprintf(ptr + 1, sizeof(line) - (ptr - line + 1), 323 "%%cupsJobTicket: %s=%s\n\"\n*End", option, choice); 324 325 cupsFilePrintf(dstfp, "*%% Changed for CUPS Windows Driver...\n%s\n", 326 line); 327 } 328 else 329 cupsFilePrintf(dstfp, "%s\n", line); 330 } 331 332 cupsFileClose(srcfp); 333 unlink(src); 334 335 if (linenum == 0) 336 { 337 _cupsSetError(IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR, _("Empty PPD file."), 1); 338 339 cupsFileClose(dstfp); 340 unlink(buffer); 341 342 *buffer = '\0'; 343 344 return (NULL); 345 } 346 347 /* 348 * Now add the CUPS-specific attributes and options... 349 */ 350 351 cupsFilePuts(dstfp, "\n*% CUPS Job Ticket support and options...\n"); 352 cupsFilePuts(dstfp, "*Protocols: PJL\n"); 353 cupsFilePuts(dstfp, "*JCLBegin: \"%!PS-Adobe-3.0<0A>\"\n"); 354 cupsFilePuts(dstfp, "*JCLToPSInterpreter: \"\"\n"); 355 cupsFilePuts(dstfp, "*JCLEnd: \"\"\n"); 356 357 cupsFilePuts(dstfp, "\n*OpenGroup: CUPS/CUPS Options\n\n"); 358 359 if ((defattr = ippFindAttribute(response, "job-hold-until-default", 360 IPP_TAG_ZERO)) != NULL && 361 (suppattr = ippFindAttribute(response, "job-hold-until-supported", 362 IPP_TAG_ZERO)) != NULL) 363 write_option(dstfp, jclorder ++, "cupsJobHoldUntil", "Hold Until", 364 "job-hold-until", suppattr, defattr, 0, 1); 365 366 if ((defattr = ippFindAttribute(response, "job-priority-default", 367 IPP_TAG_INTEGER)) != NULL && 368 (suppattr = ippFindAttribute(response, "job-priority-supported", 369 IPP_TAG_RANGE)) != NULL) 370 write_option(dstfp, jclorder ++, "cupsJobPriority", "Priority", 371 "job-priority", suppattr, defattr, 0, 1); 372 373 if ((defattr = ippFindAttribute(response, "job-sheets-default", 374 IPP_TAG_ZERO)) != NULL && 375 (suppattr = ippFindAttribute(response, "job-sheets-supported", 376 IPP_TAG_ZERO)) != NULL) 377 { 378 write_option(dstfp, jclorder ++, "cupsJobSheetsStart", "Start Banner", 379 "job-sheets", suppattr, defattr, 0, 2); 380 write_option(dstfp, jclorder, "cupsJobSheetsEnd", "End Banner", 381 "job-sheets", suppattr, defattr, 1, 2); 382 } 383 384 cupsFilePuts(dstfp, "*CloseGroup: CUPS\n"); 385 cupsFileClose(dstfp); 386 387 ippDelete(response); 388 389 return (buffer); 390} 391 392 393/* 394 * 'cupsAdminExportSamba()' - Export a printer to Samba. 395 * 396 * @deprecated@ 397 */ 398 399int /* O - 1 on success, 0 on failure */ 400cupsAdminExportSamba( 401 const char *dest, /* I - Destination to export */ 402 const char *ppd, /* I - PPD file */ 403 const char *samba_server, /* I - Samba server */ 404 const char *samba_user, /* I - Samba username */ 405 const char *samba_password, /* I - Samba password */ 406 FILE *logfile) /* I - Log file, if any */ 407{ 408 int status; /* Status of Samba commands */ 409 int have_drivers; /* Have drivers? */ 410 char file[1024], /* File to test for */ 411 authfile[1024], /* Temporary authentication file */ 412 address[1024], /* Address for command */ 413 subcmd[1024], /* Sub-command */ 414 message[1024]; /* Error message */ 415 cups_file_t *fp; /* Authentication file */ 416 cups_lang_t *language; /* Current language */ 417 _cups_globals_t *cg = _cupsGlobals(); 418 /* Global data */ 419 420 421 /* 422 * Range check input... 423 */ 424 425 if (!dest || !ppd || !samba_server || !samba_user || !samba_password) 426 { 427 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); 428 return (0); 429 } 430 431 /* 432 * Create a temporary authentication file for Samba... 433 */ 434 435 if ((fp = cupsTempFile2(authfile, sizeof(authfile))) == NULL) 436 { 437 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); 438 return (0); 439 } 440 441 cupsFilePrintf(fp, "username = %s\n", samba_user); 442 cupsFilePrintf(fp, "password = %s\n", samba_password); 443 cupsFileClose(fp); 444 445 /* 446 * See which drivers are available; the new CUPS v6 and Adobe drivers 447 * depend on the Windows 2k PS driver, so copy that driver first: 448 * 449 * Files: 450 * 451 * ps5ui.dll 452 * pscript.hlp 453 * pscript.ntf 454 * pscript5.dll 455 */ 456 457 have_drivers = 0; 458 language = cupsLangDefault(); 459 460 snprintf(file, sizeof(file), "%s/drivers/pscript5.dll", cg->cups_datadir); 461 if (!access(file, 0)) 462 { 463 have_drivers |= 1; 464 465 /* 466 * Windows 2k driver is installed; do the smbclient commands needed 467 * to copy the Win2k drivers over... 468 */ 469 470 snprintf(address, sizeof(address), "//%s/print$", samba_server); 471 472 snprintf(subcmd, sizeof(subcmd), 473 "mkdir W32X86;" 474 "put %s W32X86/%s.ppd;" 475 "put %s/drivers/ps5ui.dll W32X86/ps5ui.dll;" 476 "put %s/drivers/pscript.hlp W32X86/pscript.hlp;" 477 "put %s/drivers/pscript.ntf W32X86/pscript.ntf;" 478 "put %s/drivers/pscript5.dll W32X86/pscript5.dll", 479 ppd, dest, cg->cups_datadir, cg->cups_datadir, 480 cg->cups_datadir, cg->cups_datadir); 481 482 if ((status = do_samba_command("smbclient", address, subcmd, 483 authfile, logfile)) != 0) 484 { 485 snprintf(message, sizeof(message), 486 _cupsLangString(language, 487 _("Unable to copy Windows 2000 printer " 488 "driver files (%d).")), status); 489 490 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 491 492 if (logfile) 493 _cupsLangPuts(logfile, message); 494 495 unlink(authfile); 496 497 return (0); 498 } 499 500 /* 501 * See if we also have the CUPS driver files; if so, use them! 502 */ 503 504 snprintf(file, sizeof(file), "%s/drivers/cupsps6.dll", cg->cups_datadir); 505 if (!access(file, 0)) 506 { 507 /* 508 * Copy the CUPS driver files over... 509 */ 510 511 snprintf(subcmd, sizeof(subcmd), 512 "put %s/drivers/cups6.ini W32X86/cups6.ini;" 513 "put %s/drivers/cupsps6.dll W32X86/cupsps6.dll;" 514 "put %s/drivers/cupsui6.dll W32X86/cupsui6.dll", 515 cg->cups_datadir, cg->cups_datadir, cg->cups_datadir); 516 517 if ((status = do_samba_command("smbclient", address, subcmd, 518 authfile, logfile)) != 0) 519 { 520 snprintf(message, sizeof(message), 521 _cupsLangString(language, 522 _("Unable to copy CUPS printer driver " 523 "files (%d).")), status); 524 525 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 526 527 if (logfile) 528 _cupsLangPuts(logfile, message); 529 530 unlink(authfile); 531 532 return (0); 533 } 534 535 /* 536 * Do the rpcclient command needed for the CUPS drivers... 537 */ 538 539 snprintf(subcmd, sizeof(subcmd), 540 "adddriver \"Windows NT x86\" \"%s:" 541 "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:" 542 "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf," 543 "cups6.ini,cupsps6.dll,cupsui6.dll\"", 544 dest, dest, dest); 545 } 546 else 547 { 548 /* 549 * Don't have the CUPS drivers, so just use the standard Windows 550 * drivers... 551 */ 552 553 snprintf(subcmd, sizeof(subcmd), 554 "adddriver \"Windows NT x86\" \"%s:" 555 "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:" 556 "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf\"", 557 dest, dest, dest); 558 } 559 560 if ((status = do_samba_command("rpcclient", samba_server, subcmd, 561 authfile, logfile)) != 0) 562 { 563 snprintf(message, sizeof(message), 564 _cupsLangString(language, 565 _("Unable to install Windows 2000 printer " 566 "driver files (%d).")), status); 567 568 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 569 570 if (logfile) 571 _cupsLangPuts(logfile, message); 572 573 unlink(authfile); 574 575 return (0); 576 } 577 } 578 579 /* 580 * See if we have the Win9x PS driver... 581 */ 582 583 snprintf(file, sizeof(file), "%s/drivers/ADOBEPS4.DRV", cg->cups_datadir); 584 if (!access(file, 0)) 585 { 586 have_drivers |= 2; 587 588 /* 589 * Do the smbclient commands needed for the Adobe Win9x drivers... 590 */ 591 592 snprintf(address, sizeof(address), "//%s/print$", samba_server); 593 594 snprintf(subcmd, sizeof(subcmd), 595 "mkdir WIN40;" 596 "put %s WIN40/%s.PPD;" 597 "put %s/drivers/ADFONTS.MFM WIN40/ADFONTS.MFM;" 598 "put %s/drivers/ADOBEPS4.DRV WIN40/ADOBEPS4.DRV;" 599 "put %s/drivers/ADOBEPS4.HLP WIN40/ADOBEPS4.HLP;" 600 "put %s/drivers/ICONLIB.DLL WIN40/ICONLIB.DLL;" 601 "put %s/drivers/PSMON.DLL WIN40/PSMON.DLL;", 602 ppd, dest, cg->cups_datadir, cg->cups_datadir, 603 cg->cups_datadir, cg->cups_datadir, cg->cups_datadir); 604 605 if ((status = do_samba_command("smbclient", address, subcmd, 606 authfile, logfile)) != 0) 607 { 608 snprintf(message, sizeof(message), 609 _cupsLangString(language, 610 _("Unable to copy Windows 9x printer " 611 "driver files (%d).")), status); 612 613 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 614 615 if (logfile) 616 _cupsLangPuts(logfile, message); 617 618 unlink(authfile); 619 620 return (0); 621 } 622 623 /* 624 * Do the rpcclient commands needed for the Adobe Win9x drivers... 625 */ 626 627 snprintf(subcmd, sizeof(subcmd), 628 "adddriver \"Windows 4.0\" \"%s:ADOBEPS4.DRV:%s.PPD:NULL:" 629 "ADOBEPS4.HLP:PSMON.DLL:RAW:" 630 "ADOBEPS4.DRV,%s.PPD,ADOBEPS4.HLP,PSMON.DLL,ADFONTS.MFM," 631 "ICONLIB.DLL\"", 632 dest, dest, dest); 633 634 if ((status = do_samba_command("rpcclient", samba_server, subcmd, 635 authfile, logfile)) != 0) 636 { 637 snprintf(message, sizeof(message), 638 _cupsLangString(language, 639 _("Unable to install Windows 9x printer " 640 "driver files (%d).")), status); 641 642 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 643 644 if (logfile) 645 _cupsLangPuts(logfile, message); 646 647 unlink(authfile); 648 649 return (0); 650 } 651 } 652 653 /* 654 * See if we have the 64-bit Windows PS driver... 655 * 656 * Files: 657 * 658 * x64/ps5ui.dll 659 * x64/pscript.hlp 660 * x64/pscript.ntf 661 * x64/pscript5.dll 662 */ 663 664 snprintf(file, sizeof(file), "%s/drivers/x64/pscript5.dll", cg->cups_datadir); 665 if (!access(file, 0)) 666 { 667 have_drivers |= 4; 668 669 /* 670 * 64-bit Windows driver is installed; do the smbclient commands needed 671 * to copy the Win64 drivers over... 672 */ 673 674 snprintf(address, sizeof(address), "//%s/print$", samba_server); 675 676 snprintf(subcmd, sizeof(subcmd), 677 "mkdir x64;" 678 "put %s x64/%s.ppd;" 679 "put %s/drivers/x64/ps5ui.dll x64/ps5ui.dll;" 680 "put %s/drivers/x64/pscript.hlp x64/pscript.hlp;" 681 "put %s/drivers/x64/pscript.ntf x64/pscript.ntf;" 682 "put %s/drivers/x64/pscript5.dll x64/pscript5.dll", 683 ppd, dest, cg->cups_datadir, cg->cups_datadir, 684 cg->cups_datadir, cg->cups_datadir); 685 686 if ((status = do_samba_command("smbclient", address, subcmd, 687 authfile, logfile)) != 0) 688 { 689 snprintf(message, sizeof(message), 690 _cupsLangString(language, 691 _("Unable to copy 64-bit Windows printer " 692 "driver files (%d).")), status); 693 694 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 695 696 if (logfile) 697 _cupsLangPuts(logfile, message); 698 699 unlink(authfile); 700 701 return (0); 702 } 703 704 /* 705 * See if we also have the CUPS driver files; if so, use them! 706 */ 707 708 snprintf(file, sizeof(file), "%s/drivers/x64/cupsps6.dll", cg->cups_datadir); 709 if (!access(file, 0)) 710 { 711 /* 712 * Copy the CUPS driver files over... 713 */ 714 715 snprintf(subcmd, sizeof(subcmd), 716 "put %s/drivers/x64/cups6.ini x64/cups6.ini;" 717 "put %s/drivers/x64/cupsps6.dll x64/cupsps6.dll;" 718 "put %s/drivers/x64/cupsui6.dll x64/cupsui6.dll", 719 cg->cups_datadir, cg->cups_datadir, cg->cups_datadir); 720 721 if ((status = do_samba_command("smbclient", address, subcmd, 722 authfile, logfile)) != 0) 723 { 724 snprintf(message, sizeof(message), 725 _cupsLangString(language, 726 _("Unable to copy 64-bit CUPS printer driver " 727 "files (%d).")), status); 728 729 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 730 731 if (logfile) 732 _cupsLangPuts(logfile, message); 733 734 unlink(authfile); 735 736 return (0); 737 } 738 739 /* 740 * Do the rpcclient command needed for the CUPS drivers... 741 */ 742 743 snprintf(subcmd, sizeof(subcmd), 744 "adddriver \"Windows x64\" \"%s:" 745 "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:" 746 "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf," 747 "cups6.ini,cupsps6.dll,cupsui6.dll\"", 748 dest, dest, dest); 749 } 750 else 751 { 752 /* 753 * Don't have the CUPS drivers, so just use the standard Windows 754 * drivers... 755 */ 756 757 snprintf(subcmd, sizeof(subcmd), 758 "adddriver \"Windows x64\" \"%s:" 759 "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:" 760 "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf\"", 761 dest, dest, dest); 762 } 763 764 if ((status = do_samba_command("rpcclient", samba_server, subcmd, 765 authfile, logfile)) != 0) 766 { 767 snprintf(message, sizeof(message), 768 _cupsLangString(language, 769 _("Unable to install Windows 2000 printer " 770 "driver files (%d).")), status); 771 772 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 773 774 if (logfile) 775 _cupsLangPuts(logfile, message); 776 777 unlink(authfile); 778 779 return (0); 780 } 781 } 782 783 if (logfile && !(have_drivers & 1)) 784 { 785 if (!have_drivers) 786 strlcpy(message, 787 _cupsLangString(language, 788 _("No Windows printer drivers are installed.")), 789 sizeof(message)); 790 else 791 strlcpy(message, 792 _cupsLangString(language, 793 _("Warning, no Windows 2000 printer drivers " 794 "are installed.")), 795 sizeof(message)); 796 797 _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, message, 0); 798 _cupsLangPuts(logfile, message); 799 } 800 801 if (have_drivers == 0) 802 { 803 _cupsSetError(IPP_STATUS_ERROR_NOT_FOUND, message, 0); 804 805 unlink(authfile); 806 807 return (0); 808 } 809 810 /* 811 * Finally, associate the drivers we just added with the queue... 812 */ 813 814 snprintf(subcmd, sizeof(subcmd), "setdriver %s %s", dest, dest); 815 816 if ((status = do_samba_command("rpcclient", samba_server, subcmd, 817 authfile, logfile)) != 0) 818 { 819 snprintf(message, sizeof(message), 820 _cupsLangString(language, 821 _("Unable to set Windows printer driver (%d).")), 822 status); 823 824 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 825 826 if (logfile) 827 _cupsLangPuts(logfile, message); 828 829 unlink(authfile); 830 831 return (0); 832 } 833 834 unlink(authfile); 835 836 return (1); 837} 838 839 840/* 841 * 'cupsAdminGetServerSettings()' - Get settings from the server. 842 * 843 * The returned settings should be freed with cupsFreeOptions() when 844 * you are done with them. 845 * 846 * @since CUPS 1.3/OS X 10.5@ 847 */ 848 849int /* O - 1 on success, 0 on failure */ 850cupsAdminGetServerSettings( 851 http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ 852 int *num_settings, /* O - Number of settings */ 853 cups_option_t **settings) /* O - Settings */ 854{ 855 int i; /* Looping var */ 856 cups_file_t *cupsd; /* cupsd.conf file */ 857 char cupsdconf[1024]; /* cupsd.conf filename */ 858 int remote; /* Remote cupsd.conf file? */ 859 http_status_t status; /* Status of getting cupsd.conf */ 860 char line[1024], /* Line from cupsd.conf file */ 861 *value; /* Value on line */ 862 cups_option_t *setting; /* Current setting */ 863 _cups_globals_t *cg = _cupsGlobals(); /* Global data */ 864 865 866 /* 867 * Range check input... 868 */ 869 870 if (!http) 871 { 872 /* 873 * See if we are connected to the same server... 874 */ 875 876 if (cg->http) 877 { 878 /* 879 * Compare the connection hostname, port, and encryption settings to 880 * the cached defaults; these were initialized the first time we 881 * connected... 882 */ 883 884 if (strcmp(cg->http->hostname, cg->server) || 885 cg->ipp_port != httpAddrPort(cg->http->hostaddr) || 886 (cg->http->encryption != cg->encryption && 887 cg->http->encryption == HTTP_ENCRYPTION_NEVER)) 888 { 889 /* 890 * Need to close the current connection because something has changed... 891 */ 892 893 httpClose(cg->http); 894 cg->http = NULL; 895 } 896 } 897 898 /* 899 * (Re)connect as needed... 900 */ 901 902 if (!cg->http) 903 { 904 if ((cg->http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, 905 cupsEncryption(), 1, 0, NULL)) == NULL) 906 { 907 if (errno) 908 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, NULL, 0); 909 else 910 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, 911 _("Unable to connect to host."), 1); 912 913 if (num_settings) 914 *num_settings = 0; 915 916 if (settings) 917 *settings = NULL; 918 919 return (0); 920 } 921 } 922 923 http = cg->http; 924 } 925 926 if (!http || !num_settings || !settings) 927 { 928 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); 929 930 if (num_settings) 931 *num_settings = 0; 932 933 if (settings) 934 *settings = NULL; 935 936 return (0); 937 } 938 939 *num_settings = 0; 940 *settings = NULL; 941 942 /* 943 * Get the cupsd.conf file... 944 */ 945 946 if ((status = get_cupsd_conf(http, cg, cg->cupsd_update, cupsdconf, 947 sizeof(cupsdconf), &remote)) == HTTP_STATUS_OK) 948 { 949 if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL) 950 { 951 char message[1024]; /* Message string */ 952 953 954 snprintf(message, sizeof(message), 955 _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")), 956 cupsdconf, strerror(errno)); 957 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 958 } 959 } 960 else 961 cupsd = NULL; 962 963 if (cupsd) 964 { 965 /* 966 * Read the file, keeping track of what settings are enabled... 967 */ 968 969 int remote_access = 0, /* Remote access allowed? */ 970 remote_admin = 0, /* Remote administration allowed? */ 971 remote_any = 0, /* Remote access from anywhere allowed? */ 972 browsing = 1, /* Browsing enabled? */ 973 cancel_policy = 1, /* Cancel-job policy set? */ 974 debug_logging = 0; /* LogLevel debug set? */ 975 int linenum = 0, /* Line number in file */ 976 in_location = 0, /* In a location section? */ 977 in_policy = 0, /* In a policy section? */ 978 in_cancel_job = 0, /* In a cancel-job section? */ 979 in_admin_location = 0; /* In the /admin location? */ 980 981 982 invalidate_cupsd_cache(cg); 983 984 cg->cupsd_update = time(NULL); 985 httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname)); 986 987 while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum)) 988 { 989 if (!value && strncmp(line, "</", 2)) 990 value = line + strlen(line); 991 992 if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && value) 993 { 994 char *port; /* Pointer to port number, if any */ 995 996 997 if ((port = strrchr(value, ':')) != NULL) 998 *port = '\0'; 999 else if (isdigit(*value & 255)) 1000 { 1001 /* 1002 * Listen on a port number implies remote access... 1003 */ 1004 1005 remote_access = 1; 1006 continue; 1007 } 1008 1009 if (_cups_strcasecmp(value, "localhost") && strcmp(value, "127.0.0.1") 1010#ifdef AF_LOCAL 1011 && *value != '/' 1012#endif /* AF_LOCAL */ 1013#ifdef AF_INET6 1014 && strcmp(value, "[::1]") 1015#endif /* AF_INET6 */ 1016 ) 1017 remote_access = 1; 1018 } 1019 else if (!_cups_strcasecmp(line, "Browsing")) 1020 { 1021 browsing = !_cups_strcasecmp(value, "yes") || 1022 !_cups_strcasecmp(value, "on") || 1023 !_cups_strcasecmp(value, "true"); 1024 } 1025 else if (!_cups_strcasecmp(line, "LogLevel")) 1026 { 1027 debug_logging = !_cups_strncasecmp(value, "debug", 5); 1028 } 1029 else if (!_cups_strcasecmp(line, "<Policy") && 1030 !_cups_strcasecmp(value, "default")) 1031 { 1032 in_policy = 1; 1033 } 1034 else if (!_cups_strcasecmp(line, "</Policy>")) 1035 { 1036 in_policy = 0; 1037 } 1038 else if (!_cups_strcasecmp(line, "<Limit") && in_policy && value) 1039 { 1040 /* 1041 * See if the policy limit is for the Cancel-Job operation... 1042 */ 1043 1044 char *valptr; /* Pointer into value */ 1045 1046 1047 while (*value) 1048 { 1049 for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++); 1050 1051 if (*valptr) 1052 *valptr++ = '\0'; 1053 1054 if (!_cups_strcasecmp(value, "cancel-job") || 1055 !_cups_strcasecmp(value, "all")) 1056 { 1057 in_cancel_job = 1; 1058 break; 1059 } 1060 1061 for (value = valptr; _cups_isspace(*value); value ++); 1062 } 1063 } 1064 else if (!_cups_strcasecmp(line, "</Limit>")) 1065 { 1066 in_cancel_job = 0; 1067 } 1068 else if (!_cups_strcasecmp(line, "Require") && in_cancel_job) 1069 { 1070 cancel_policy = 0; 1071 } 1072 else if (!_cups_strcasecmp(line, "<Location") && value) 1073 { 1074 in_admin_location = !_cups_strcasecmp(value, "/admin"); 1075 in_location = 1; 1076 } 1077 else if (!_cups_strcasecmp(line, "</Location>")) 1078 { 1079 in_admin_location = 0; 1080 in_location = 0; 1081 } 1082 else if (!_cups_strcasecmp(line, "Allow") && value && 1083 _cups_strcasecmp(value, "localhost") && 1084 _cups_strcasecmp(value, "127.0.0.1") 1085#ifdef AF_LOCAL 1086 && *value != '/' 1087#endif /* AF_LOCAL */ 1088#ifdef AF_INET6 1089 && strcmp(value, "::1") 1090#endif /* AF_INET6 */ 1091 ) 1092 { 1093 if (in_admin_location) 1094 remote_admin = 1; 1095 else if (!_cups_strcasecmp(value, "all")) 1096 remote_any = 1; 1097 } 1098 else if (line[0] != '<' && !in_location && !in_policy && 1099 _cups_strcasecmp(line, "Allow") && 1100 _cups_strcasecmp(line, "AuthType") && 1101 _cups_strcasecmp(line, "Deny") && 1102 _cups_strcasecmp(line, "Order") && 1103 _cups_strcasecmp(line, "Require") && 1104 _cups_strcasecmp(line, "Satisfy")) 1105 cg->cupsd_num_settings = cupsAddOption(line, value, 1106 cg->cupsd_num_settings, 1107 &(cg->cupsd_settings)); 1108 } 1109 1110 cupsFileClose(cupsd); 1111 1112 cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, 1113 debug_logging ? "1" : "0", 1114 cg->cupsd_num_settings, 1115 &(cg->cupsd_settings)); 1116 1117 cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, 1118 (remote_access && remote_admin) ? 1119 "1" : "0", 1120 cg->cupsd_num_settings, 1121 &(cg->cupsd_settings)); 1122 1123 cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, 1124 remote_any ? "1" : "0", 1125 cg->cupsd_num_settings, 1126 &(cg->cupsd_settings)); 1127 1128 cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, 1129 (remote_access && browsing) ? "1" : 1130 "0", 1131 cg->cupsd_num_settings, 1132 &(cg->cupsd_settings)); 1133 1134 cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, 1135 cancel_policy ? "1" : "0", 1136 cg->cupsd_num_settings, 1137 &(cg->cupsd_settings)); 1138 } 1139 else if (status != HTTP_STATUS_NOT_MODIFIED) 1140 invalidate_cupsd_cache(cg); 1141 1142 /* 1143 * Remove any temporary files and copy the settings array... 1144 */ 1145 1146 if (remote) 1147 unlink(cupsdconf); 1148 1149 for (i = cg->cupsd_num_settings, setting = cg->cupsd_settings; 1150 i > 0; 1151 i --, setting ++) 1152 *num_settings = cupsAddOption(setting->name, setting->value, 1153 *num_settings, settings); 1154 1155 return (cg->cupsd_num_settings > 0); 1156} 1157 1158 1159/* 1160 * 'cupsAdminSetServerSettings()' - Set settings on the server. 1161 * 1162 * @since CUPS 1.3/OS X 10.5@ 1163 */ 1164 1165int /* O - 1 on success, 0 on failure */ 1166cupsAdminSetServerSettings( 1167 http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ 1168 int num_settings, /* I - Number of settings */ 1169 cups_option_t *settings) /* I - Settings */ 1170{ 1171 int i; /* Looping var */ 1172 http_status_t status; /* GET/PUT status */ 1173 const char *server_port_env; /* SERVER_PORT env var */ 1174 int server_port; /* IPP port for server */ 1175 cups_file_t *cupsd; /* cupsd.conf file */ 1176 char cupsdconf[1024]; /* cupsd.conf filename */ 1177 int remote; /* Remote cupsd.conf file? */ 1178 char tempfile[1024]; /* Temporary new cupsd.conf */ 1179 cups_file_t *temp; /* Temporary file */ 1180 char line[1024], /* Line from cupsd.conf file */ 1181 *value; /* Value on line */ 1182 int linenum, /* Line number in file */ 1183 in_location, /* In a location section? */ 1184 in_policy, /* In a policy section? */ 1185 in_default_policy, /* In the default policy section? */ 1186 in_cancel_job, /* In a cancel-job section? */ 1187 in_admin_location, /* In the /admin location? */ 1188 in_conf_location, /* In the /admin/conf location? */ 1189 in_root_location; /* In the / location? */ 1190 const char *val; /* Setting value */ 1191 int share_printers, /* Share local printers */ 1192 remote_admin, /* Remote administration allowed? */ 1193 remote_any, /* Remote access from anywhere? */ 1194 user_cancel_any, /* Cancel-job policy set? */ 1195 debug_logging; /* LogLevel debug set? */ 1196 int wrote_port_listen, /* Wrote the port/listen lines? */ 1197 wrote_browsing, /* Wrote the browsing lines? */ 1198 wrote_policy, /* Wrote the policy? */ 1199 wrote_loglevel, /* Wrote the LogLevel line? */ 1200 wrote_admin_location, /* Wrote the /admin location? */ 1201 wrote_conf_location, /* Wrote the /admin/conf location? */ 1202 wrote_root_location; /* Wrote the / location? */ 1203 int indent; /* Indentation */ 1204 int cupsd_num_settings; /* New number of settings */ 1205 int old_share_printers, /* Share local printers */ 1206 old_remote_admin, /* Remote administration allowed? */ 1207 old_user_cancel_any, /* Cancel-job policy set? */ 1208 old_debug_logging; /* LogLevel debug set? */ 1209 cups_option_t *cupsd_settings, /* New settings */ 1210 *setting; /* Current setting */ 1211 _cups_globals_t *cg = _cupsGlobals(); /* Global data */ 1212 1213 1214 /* 1215 * Range check input... 1216 */ 1217 1218 if (!http) 1219 http = _cupsConnect(); 1220 1221 if (!http || !num_settings || !settings) 1222 { 1223 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); 1224 1225 return (0); 1226 } 1227 1228 /* 1229 * Get the cupsd.conf file... 1230 */ 1231 1232 if (get_cupsd_conf(http, cg, 0, cupsdconf, sizeof(cupsdconf), 1233 &remote) == HTTP_STATUS_OK) 1234 { 1235 if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL) 1236 { 1237 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); 1238 return (0); 1239 } 1240 } 1241 else 1242 return (0); 1243 1244 /* 1245 * Get current settings... 1246 */ 1247 1248 if (!cupsAdminGetServerSettings(http, &cupsd_num_settings, 1249 &cupsd_settings)) 1250 return (0); 1251 1252 if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, cupsd_num_settings, 1253 cupsd_settings)) != NULL) 1254 old_debug_logging = atoi(val); 1255 else 1256 old_debug_logging = 0; 1257 1258 DEBUG_printf(("1cupsAdminSetServerSettings: old debug_logging=%d", 1259 old_debug_logging)); 1260 1261 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, cupsd_num_settings, 1262 cupsd_settings)) != NULL) 1263 old_remote_admin = atoi(val); 1264 else 1265 old_remote_admin = 0; 1266 1267 DEBUG_printf(("1cupsAdminSetServerSettings: old remote_admin=%d", 1268 old_remote_admin)); 1269 1270 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, cupsd_num_settings, 1271 cupsd_settings)) != NULL) 1272 remote_any = atoi(val); 1273 else 1274 remote_any = 0; 1275 1276 DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d", 1277 remote_any)); 1278 1279 if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, cupsd_num_settings, 1280 cupsd_settings)) != NULL) 1281 old_share_printers = atoi(val); 1282 else 1283 old_share_printers = 0; 1284 1285 DEBUG_printf(("1cupsAdminSetServerSettings: old share_printers=%d", 1286 old_share_printers)); 1287 1288 if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, cupsd_num_settings, 1289 cupsd_settings)) != NULL) 1290 old_user_cancel_any = atoi(val); 1291 else 1292 old_user_cancel_any = 0; 1293 1294 DEBUG_printf(("1cupsAdminSetServerSettings: old user_cancel_any=%d", 1295 old_user_cancel_any)); 1296 1297 cupsFreeOptions(cupsd_num_settings, cupsd_settings); 1298 1299 /* 1300 * Get basic settings... 1301 */ 1302 1303 if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings, 1304 settings)) != NULL) 1305 { 1306 debug_logging = atoi(val); 1307 1308 if (debug_logging == old_debug_logging) 1309 { 1310 /* 1311 * No change to this setting... 1312 */ 1313 1314 debug_logging = -1; 1315 } 1316 } 1317 else 1318 debug_logging = -1; 1319 1320 DEBUG_printf(("1cupsAdminSetServerSettings: debug_logging=%d", 1321 debug_logging)); 1322 1323 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings, 1324 settings)) != NULL) 1325 remote_any = atoi(val); 1326 1327 DEBUG_printf(("1cupsAdminSetServerSettings: remote_any=%d", 1328 remote_any)); 1329 1330 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings, 1331 settings)) != NULL) 1332 { 1333 remote_admin = atoi(val); 1334 1335 if (remote_admin == old_remote_admin) 1336 { 1337 /* 1338 * No change to this setting... 1339 */ 1340 1341 remote_admin = -1; 1342 } 1343 } 1344 else 1345 remote_admin = -1; 1346 1347 DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d", 1348 remote_admin)); 1349 1350 if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings, 1351 settings)) != NULL) 1352 { 1353 share_printers = atoi(val); 1354 1355 if (share_printers == old_share_printers) 1356 { 1357 /* 1358 * No change to this setting... 1359 */ 1360 1361 share_printers = -1; 1362 } 1363 } 1364 else 1365 share_printers = -1; 1366 1367 DEBUG_printf(("1cupsAdminSetServerSettings: share_printers=%d", 1368 share_printers)); 1369 1370 if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings, 1371 settings)) != NULL) 1372 { 1373 user_cancel_any = atoi(val); 1374 1375 if (user_cancel_any == old_user_cancel_any) 1376 { 1377 /* 1378 * No change to this setting... 1379 */ 1380 1381 user_cancel_any = -1; 1382 } 1383 } 1384 else 1385 user_cancel_any = -1; 1386 1387 DEBUG_printf(("1cupsAdminSetServerSettings: user_cancel_any=%d", 1388 user_cancel_any)); 1389 1390 /* 1391 * Create a temporary file for the new cupsd.conf file... 1392 */ 1393 1394 if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL) 1395 { 1396 cupsFileClose(cupsd); 1397 1398 if (remote) 1399 unlink(cupsdconf); 1400 1401 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); 1402 return (0); 1403 } 1404 1405 /* 1406 * Copy the old file to the new, making changes along the way... 1407 */ 1408 1409 cupsd_num_settings = 0; 1410 in_admin_location = 0; 1411 in_cancel_job = 0; 1412 in_conf_location = 0; 1413 in_default_policy = 0; 1414 in_location = 0; 1415 in_policy = 0; 1416 in_root_location = 0; 1417 linenum = 0; 1418 wrote_admin_location = 0; 1419 wrote_browsing = 0; 1420 wrote_conf_location = 0; 1421 wrote_loglevel = 0; 1422 wrote_policy = 0; 1423 wrote_port_listen = 0; 1424 wrote_root_location = 0; 1425 indent = 0; 1426 1427 if ((server_port_env = getenv("SERVER_PORT")) != NULL) 1428 { 1429 if ((server_port = atoi(server_port_env)) <= 0) 1430 server_port = ippPort(); 1431 } 1432 else 1433 server_port = ippPort(); 1434 1435 if (server_port <= 0) 1436 server_port = IPP_PORT; 1437 1438 while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum)) 1439 { 1440 if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && 1441 (remote_admin >= 0 || remote_any > 0 || share_printers >= 0)) 1442 { 1443 if (!wrote_port_listen) 1444 { 1445 wrote_port_listen = 1; 1446 1447 if (remote_admin > 0 || remote_any > 0 || share_printers > 0) 1448 { 1449 cupsFilePuts(temp, "# Allow remote access\n"); 1450 cupsFilePrintf(temp, "Port %d\n", server_port); 1451 } 1452 else 1453 { 1454 cupsFilePuts(temp, "# Only listen for connections from the local " 1455 "machine.\n"); 1456 cupsFilePrintf(temp, "Listen localhost:%d\n", server_port); 1457 } 1458 1459#ifdef CUPS_DEFAULT_DOMAINSOCKET 1460 if ((!value || strcmp(CUPS_DEFAULT_DOMAINSOCKET, value)) && 1461 !access(CUPS_DEFAULT_DOMAINSOCKET, 0)) 1462 cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n"); 1463#endif /* CUPS_DEFAULT_DOMAINSOCKET */ 1464 } 1465 else if (value && value[0] == '/' 1466#ifdef CUPS_DEFAULT_DOMAINSOCKET 1467 && strcmp(CUPS_DEFAULT_DOMAINSOCKET, value) 1468#endif /* CUPS_DEFAULT_DOMAINSOCKET */ 1469 ) 1470 cupsFilePrintf(temp, "Listen %s\n", value); 1471 } 1472 else if ((!_cups_strcasecmp(line, "Browsing") || 1473 !_cups_strcasecmp(line, "BrowseLocalProtocols")) && 1474 share_printers >= 0) 1475 { 1476 if (!wrote_browsing) 1477 { 1478 int new_share_printers = (share_printers > 0 || 1479 (share_printers == -1 && 1480 old_share_printers > 0)); 1481 1482 wrote_browsing = 1; 1483 1484 if (new_share_printers) 1485 { 1486 const char *localp = cupsGetOption("BrowseLocalProtocols", 1487 num_settings, settings); 1488 1489 if (!localp || !localp[0]) 1490 localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings, 1491 cupsd_settings); 1492 1493 cupsFilePuts(temp, "# Share local printers on the local network.\n"); 1494 cupsFilePuts(temp, "Browsing On\n"); 1495 1496 if (!localp) 1497 localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; 1498 1499 cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp); 1500 1501 cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp, 1502 cupsd_num_settings, 1503 &cupsd_settings); 1504 } 1505 else 1506 { 1507 cupsFilePuts(temp, "# Disable printer sharing.\n"); 1508 cupsFilePuts(temp, "Browsing Off\n"); 1509 } 1510 } 1511 } 1512 else if (!_cups_strcasecmp(line, "LogLevel") && debug_logging >= 0) 1513 { 1514 wrote_loglevel = 1; 1515 1516 if (debug_logging) 1517 { 1518 cupsFilePuts(temp, 1519 "# Show troubleshooting information in error_log.\n"); 1520 cupsFilePuts(temp, "LogLevel debug\n"); 1521 } 1522 else 1523 { 1524 cupsFilePuts(temp, "# Show general information in error_log.\n"); 1525 cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n"); 1526 } 1527 } 1528 else if (!_cups_strcasecmp(line, "<Policy")) 1529 { 1530 in_default_policy = !_cups_strcasecmp(value, "default"); 1531 in_policy = 1; 1532 1533 cupsFilePrintf(temp, "%s %s>\n", line, value); 1534 indent += 2; 1535 } 1536 else if (!_cups_strcasecmp(line, "</Policy>")) 1537 { 1538 indent -= 2; 1539 if (!wrote_policy && in_default_policy) 1540 { 1541 wrote_policy = 1; 1542 1543 if (!user_cancel_any) 1544 cupsFilePuts(temp, " # Only the owner or an administrator can " 1545 "cancel a job...\n" 1546 " <Limit Cancel-Job>\n" 1547 " Order deny,allow\n" 1548 " Require user @OWNER " 1549 CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" 1550 " </Limit>\n"); 1551 } 1552 1553 in_policy = 0; 1554 in_default_policy = 0; 1555 1556 cupsFilePuts(temp, "</Policy>\n"); 1557 } 1558 else if (!_cups_strcasecmp(line, "<Location")) 1559 { 1560 in_location = 1; 1561 indent += 2; 1562 if (!strcmp(value, "/admin")) 1563 in_admin_location = 1; 1564 if (!strcmp(value, "/admin/conf")) 1565 in_conf_location = 1; 1566 else if (!strcmp(value, "/")) 1567 in_root_location = 1; 1568 1569 cupsFilePrintf(temp, "%s %s>\n", line, value); 1570 } 1571 else if (!_cups_strcasecmp(line, "</Location>")) 1572 { 1573 in_location = 0; 1574 indent -= 2; 1575 if (in_admin_location && remote_admin >= 0) 1576 { 1577 wrote_admin_location = 1; 1578 1579 if (remote_admin) 1580 cupsFilePuts(temp, " # Allow remote administration...\n"); 1581 else if (remote_admin == 0) 1582 cupsFilePuts(temp, " # Restrict access to the admin pages...\n"); 1583 1584 cupsFilePuts(temp, " Order allow,deny\n"); 1585 1586 if (remote_admin) 1587 cupsFilePrintf(temp, " Allow %s\n", 1588 remote_any > 0 ? "all" : "@LOCAL"); 1589 } 1590 else if (in_conf_location && remote_admin >= 0) 1591 { 1592 wrote_conf_location = 1; 1593 1594 if (remote_admin) 1595 cupsFilePuts(temp, " # Allow remote access to the configuration " 1596 "files...\n"); 1597 else 1598 cupsFilePuts(temp, " # Restrict access to the configuration " 1599 "files...\n"); 1600 1601 cupsFilePuts(temp, " Order allow,deny\n"); 1602 1603 if (remote_admin) 1604 cupsFilePrintf(temp, " Allow %s\n", 1605 remote_any > 0 ? "all" : "@LOCAL"); 1606 } 1607 else if (in_root_location && 1608 (remote_admin >= 0 || remote_any > 0 || share_printers >= 0)) 1609 { 1610 wrote_root_location = 1; 1611 1612 if (remote_admin > 0 && share_printers > 0) 1613 cupsFilePuts(temp, " # Allow shared printing and remote " 1614 "administration...\n"); 1615 else if (remote_admin > 0) 1616 cupsFilePuts(temp, " # Allow remote administration...\n"); 1617 else if (share_printers > 0) 1618 cupsFilePuts(temp, " # Allow shared printing...\n"); 1619 else if (remote_any > 0) 1620 cupsFilePuts(temp, " # Allow remote access...\n"); 1621 else 1622 cupsFilePuts(temp, " # Restrict access to the server...\n"); 1623 1624 cupsFilePuts(temp, " Order allow,deny\n"); 1625 1626 if (remote_admin > 0 || remote_any > 0 || share_printers > 0) 1627 cupsFilePrintf(temp, " Allow %s\n", 1628 remote_any > 0 ? "all" : "@LOCAL"); 1629 } 1630 1631 in_admin_location = 0; 1632 in_conf_location = 0; 1633 in_root_location = 0; 1634 1635 cupsFilePuts(temp, "</Location>\n"); 1636 } 1637 else if (!_cups_strcasecmp(line, "<Limit")) 1638 { 1639 if (in_default_policy) 1640 { 1641 /* 1642 * See if the policy limit is for the Cancel-Job operation... 1643 */ 1644 1645 char *valptr; /* Pointer into value */ 1646 1647 1648 if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0) 1649 { 1650 /* 1651 * Don't write anything for this limit section... 1652 */ 1653 1654 in_cancel_job = 2; 1655 } 1656 else 1657 { 1658 cupsFilePrintf(temp, "%*s%s", indent, "", line); 1659 1660 while (*value) 1661 { 1662 for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++); 1663 1664 if (*valptr) 1665 *valptr++ = '\0'; 1666 1667 if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0) 1668 { 1669 /* 1670 * Write everything except for this definition... 1671 */ 1672 1673 in_cancel_job = 1; 1674 } 1675 else 1676 cupsFilePrintf(temp, " %s", value); 1677 1678 for (value = valptr; _cups_isspace(*value); value ++); 1679 } 1680 1681 cupsFilePuts(temp, ">\n"); 1682 } 1683 } 1684 else 1685 cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value); 1686 1687 indent += 2; 1688 } 1689 else if (!_cups_strcasecmp(line, "</Limit>") && in_cancel_job) 1690 { 1691 indent -= 2; 1692 1693 if (in_cancel_job == 1) 1694 cupsFilePuts(temp, " </Limit>\n"); 1695 1696 wrote_policy = 1; 1697 1698 if (!user_cancel_any) 1699 cupsFilePuts(temp, " # Only the owner or an administrator can cancel " 1700 "a job...\n" 1701 " <Limit Cancel-Job>\n" 1702 " Order deny,allow\n" 1703 " Require user @OWNER " 1704 CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" 1705 " </Limit>\n"); 1706 1707 in_cancel_job = 0; 1708 } 1709 else if ((((in_admin_location || in_conf_location || in_root_location) && 1710 (remote_admin >= 0 || remote_any > 0)) || 1711 (in_root_location && share_printers >= 0)) && 1712 (!_cups_strcasecmp(line, "Allow") || !_cups_strcasecmp(line, "Deny") || 1713 !_cups_strcasecmp(line, "Order"))) 1714 continue; 1715 else if (in_cancel_job == 2) 1716 continue; 1717 else if (line[0] == '<') 1718 { 1719 if (value) 1720 { 1721 cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value); 1722 indent += 2; 1723 } 1724 else 1725 { 1726 if (line[1] == '/') 1727 indent -= 2; 1728 1729 cupsFilePrintf(temp, "%*s%s\n", indent, "", line); 1730 } 1731 } 1732 else if (!in_policy && !in_location && 1733 (val = cupsGetOption(line, num_settings, settings)) != NULL) 1734 { 1735 /* 1736 * Replace this directive's value with the new one... 1737 */ 1738 1739 cupsd_num_settings = cupsAddOption(line, val, cupsd_num_settings, 1740 &cupsd_settings); 1741 1742 /* 1743 * Write the new value in its place, without indentation since we 1744 * only support setting root directives, not in sections... 1745 */ 1746 1747 cupsFilePrintf(temp, "%s %s\n", line, val); 1748 } 1749 else if (value) 1750 { 1751 if (!in_policy && !in_location) 1752 { 1753 /* 1754 * Record the non-policy, non-location directives that we find 1755 * in the server settings, since we cache this info and record it 1756 * in cupsAdminGetServerSettings()... 1757 */ 1758 1759 cupsd_num_settings = cupsAddOption(line, value, cupsd_num_settings, 1760 &cupsd_settings); 1761 } 1762 1763 cupsFilePrintf(temp, "%*s%s %s\n", indent, "", line, value); 1764 } 1765 else 1766 cupsFilePrintf(temp, "%*s%s\n", indent, "", line); 1767 } 1768 1769 /* 1770 * Write any missing info... 1771 */ 1772 1773 if (!wrote_browsing && share_printers >= 0) 1774 { 1775 if (share_printers > 0) 1776 { 1777 cupsFilePuts(temp, "# Share local printers on the local network.\n"); 1778 cupsFilePuts(temp, "Browsing On\n"); 1779 } 1780 else 1781 { 1782 cupsFilePuts(temp, "# Disable printer sharing and shared printers.\n"); 1783 cupsFilePuts(temp, "Browsing Off\n"); 1784 } 1785 } 1786 1787 if (!wrote_loglevel && debug_logging >= 0) 1788 { 1789 if (debug_logging) 1790 { 1791 cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n"); 1792 cupsFilePuts(temp, "LogLevel debug\n"); 1793 } 1794 else 1795 { 1796 cupsFilePuts(temp, "# Show general information in error_log.\n"); 1797 cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n"); 1798 } 1799 } 1800 1801 if (!wrote_port_listen && 1802 (remote_admin >= 0 || remote_any > 0 || share_printers >= 0)) 1803 { 1804 if (remote_admin > 0 || remote_any > 0 || share_printers > 0) 1805 { 1806 cupsFilePuts(temp, "# Allow remote access\n"); 1807 cupsFilePrintf(temp, "Port %d\n", ippPort()); 1808 } 1809 else 1810 { 1811 cupsFilePuts(temp, 1812 "# Only listen for connections from the local machine.\n"); 1813 cupsFilePrintf(temp, "Listen localhost:%d\n", ippPort()); 1814 } 1815 1816#ifdef CUPS_DEFAULT_DOMAINSOCKET 1817 if (!access(CUPS_DEFAULT_DOMAINSOCKET, 0)) 1818 cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n"); 1819#endif /* CUPS_DEFAULT_DOMAINSOCKET */ 1820 } 1821 1822 if (!wrote_root_location && 1823 (remote_admin >= 0 || remote_any > 0 || share_printers >= 0)) 1824 { 1825 if (remote_admin > 0 && share_printers > 0) 1826 cupsFilePuts(temp, 1827 "# Allow shared printing and remote administration...\n"); 1828 else if (remote_admin > 0) 1829 cupsFilePuts(temp, "# Allow remote administration...\n"); 1830 else if (share_printers > 0) 1831 cupsFilePuts(temp, "# Allow shared printing...\n"); 1832 else if (remote_any > 0) 1833 cupsFilePuts(temp, "# Allow remote access...\n"); 1834 else 1835 cupsFilePuts(temp, "# Restrict access to the server...\n"); 1836 1837 cupsFilePuts(temp, "<Location />\n" 1838 " Order allow,deny\n"); 1839 1840 if (remote_admin > 0 || remote_any > 0 || share_printers > 0) 1841 cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); 1842 1843 cupsFilePuts(temp, "</Location>\n"); 1844 } 1845 1846 if (!wrote_admin_location && remote_admin >= 0) 1847 { 1848 if (remote_admin) 1849 cupsFilePuts(temp, "# Allow remote administration...\n"); 1850 else 1851 cupsFilePuts(temp, "# Restrict access to the admin pages...\n"); 1852 1853 cupsFilePuts(temp, "<Location /admin>\n" 1854 " Order allow,deny\n"); 1855 1856 if (remote_admin) 1857 cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); 1858 1859 cupsFilePuts(temp, "</Location>\n"); 1860 } 1861 1862 if (!wrote_conf_location && remote_admin >= 0) 1863 { 1864 if (remote_admin) 1865 cupsFilePuts(temp, 1866 "# Allow remote access to the configuration files...\n"); 1867 else 1868 cupsFilePuts(temp, "# Restrict access to the configuration files...\n"); 1869 1870 cupsFilePuts(temp, "<Location /admin/conf>\n" 1871 " AuthType Default\n" 1872 " Require user @SYSTEM\n" 1873 " Order allow,deny\n"); 1874 1875 if (remote_admin) 1876 cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); 1877 1878 cupsFilePuts(temp, "</Location>\n"); 1879 } 1880 1881 if (!wrote_policy && user_cancel_any >= 0) 1882 { 1883 cupsFilePuts(temp, "<Policy default>\n" 1884 " # Job-related operations must be done by the owner " 1885 "or an administrator...\n" 1886 " <Limit Send-Document Send-URI Hold-Job Release-Job " 1887 "Restart-Job Purge-Jobs Set-Job-Attributes " 1888 "Create-Job-Subscription Renew-Subscription " 1889 "Cancel-Subscription Get-Notifications Reprocess-Job " 1890 "Cancel-Current-Job Suspend-Current-Job Resume-Job " 1891 "CUPS-Move-Job>\n" 1892 " Require user @OWNER @SYSTEM\n" 1893 " Order deny,allow\n" 1894 " </Limit>\n" 1895 " # All administration operations require an " 1896 "administrator to authenticate...\n" 1897 " <Limit Pause-Printer Resume-Printer " 1898 "Set-Printer-Attributes Enable-Printer " 1899 "Disable-Printer Pause-Printer-After-Current-Job " 1900 "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer " 1901 "Activate-Printer Restart-Printer Shutdown-Printer " 1902 "Startup-Printer Promote-Job Schedule-Job-After " 1903 "CUPS-Add-Printer CUPS-Delete-Printer " 1904 "CUPS-Add-Class CUPS-Delete-Class " 1905 "CUPS-Accept-Jobs CUPS-Reject-Jobs " 1906 "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n" 1907 " AuthType Default\n" 1908 " Require user @SYSTEM\n" 1909 " Order deny,allow\n" 1910 "</Limit>\n"); 1911 1912 if (!user_cancel_any) 1913 cupsFilePuts(temp, " # Only the owner or an administrator can cancel " 1914 "a job...\n" 1915 " <Limit Cancel-Job>\n" 1916 " Order deny,allow\n" 1917 " Require user @OWNER " 1918 CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" 1919 " </Limit>\n"); 1920 1921 cupsFilePuts(temp, " <Limit All>\n" 1922 " Order deny,allow\n" 1923 " </Limit>\n" 1924 "</Policy>\n"); 1925 } 1926 1927 for (i = num_settings, setting = settings; i > 0; i --, setting ++) 1928 if (setting->name[0] != '_' && 1929 _cups_strcasecmp(setting->name, "Listen") && 1930 _cups_strcasecmp(setting->name, "Port") && 1931 !cupsGetOption(setting->name, cupsd_num_settings, cupsd_settings)) 1932 { 1933 /* 1934 * Add this directive to the list of directives we have written... 1935 */ 1936 1937 cupsd_num_settings = cupsAddOption(setting->name, setting->value, 1938 cupsd_num_settings, &cupsd_settings); 1939 1940 /* 1941 * Write the new value, without indentation since we only support 1942 * setting root directives, not in sections... 1943 */ 1944 1945 cupsFilePrintf(temp, "%s %s\n", setting->name, setting->value); 1946 } 1947 1948 cupsFileClose(cupsd); 1949 cupsFileClose(temp); 1950 1951 /* 1952 * Upload the configuration file to the server... 1953 */ 1954 1955 status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile); 1956 1957 if (status == HTTP_STATUS_CREATED) 1958 { 1959 /* 1960 * Updated OK, add the basic settings... 1961 */ 1962 1963 if (debug_logging >= 0) 1964 cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, 1965 debug_logging ? "1" : "0", 1966 cupsd_num_settings, &cupsd_settings); 1967 else 1968 cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, 1969 old_debug_logging ? "1" : "0", 1970 cupsd_num_settings, &cupsd_settings); 1971 1972 if (remote_admin >= 0) 1973 cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, 1974 remote_admin ? "1" : "0", 1975 cupsd_num_settings, &cupsd_settings); 1976 else 1977 cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, 1978 old_remote_admin ? "1" : "0", 1979 cupsd_num_settings, &cupsd_settings); 1980 1981 cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, 1982 remote_any ? "1" : "0", 1983 cupsd_num_settings, &cupsd_settings); 1984 1985 if (share_printers >= 0) 1986 cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, 1987 share_printers ? "1" : "0", 1988 cupsd_num_settings, &cupsd_settings); 1989 else 1990 cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, 1991 old_share_printers ? "1" : "0", 1992 cupsd_num_settings, &cupsd_settings); 1993 1994 if (user_cancel_any >= 0) 1995 cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, 1996 user_cancel_any ? "1" : "0", 1997 cupsd_num_settings, &cupsd_settings); 1998 else 1999 cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, 2000 old_user_cancel_any ? "1" : "0", 2001 cupsd_num_settings, &cupsd_settings); 2002 2003 /* 2004 * Save the new values... 2005 */ 2006 2007 invalidate_cupsd_cache(cg); 2008 2009 cg->cupsd_num_settings = cupsd_num_settings; 2010 cg->cupsd_settings = cupsd_settings; 2011 cg->cupsd_update = time(NULL); 2012 2013 httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname)); 2014 } 2015 else 2016 cupsFreeOptions(cupsd_num_settings, cupsd_settings); 2017 2018 /* 2019 * Remote our temp files and return... 2020 */ 2021 2022 if (remote) 2023 unlink(cupsdconf); 2024 2025 unlink(tempfile); 2026 2027 return (status == HTTP_STATUS_CREATED); 2028} 2029 2030 2031/* 2032 * 'do_samba_command()' - Do a SAMBA command. 2033 */ 2034 2035static int /* O - Status of command */ 2036do_samba_command(const char *command, /* I - Command to run */ 2037 const char *address, /* I - Address for command */ 2038 const char *subcmd, /* I - Sub-command */ 2039 const char *authfile, /* I - Samba authentication file */ 2040 FILE *logfile) /* I - Optional log file */ 2041{ 2042#ifdef WIN32 2043 return (1); /* Always fail on Windows... */ 2044 2045#else 2046 int status; /* Status of command */ 2047 int pid; /* Process ID of child */ 2048 2049 2050 if (logfile) 2051 _cupsLangPrintf(logfile, 2052 _("Running command: %s %s -N -A %s -c \'%s\'"), 2053 command, address, authfile, subcmd); 2054 2055 if ((pid = fork()) == 0) 2056 { 2057 /* 2058 * Child goes here, redirect stdin/out/err and execute the command... 2059 */ 2060 2061 int fd = open("/dev/null", O_RDONLY); 2062 2063 if (fd > 0) 2064 { 2065 dup2(fd, 0); 2066 close(fd); 2067 } 2068 2069 if (logfile) 2070 dup2(fileno(logfile), 1); 2071 else if ((fd = open("/dev/null", O_WRONLY)) > 1) 2072 { 2073 dup2(fd, 1); 2074 close(fd); 2075 } 2076 2077 dup2(1, 2); 2078 2079 execlp(command, command, address, "-N", "-A", authfile, "-c", subcmd, 2080 (char *)0); 2081 exit(errno); 2082 } 2083 else if (pid < 0) 2084 { 2085 status = -1; 2086 2087 if (logfile) 2088 _cupsLangPrintf(logfile, _("Unable to run \"%s\": %s"), 2089 command, strerror(errno)); 2090 } 2091 else 2092 { 2093 /* 2094 * Wait for the process to complete... 2095 */ 2096 2097 while (wait(&status) != pid); 2098 } 2099 2100 if (logfile) 2101 _cupsLangPuts(logfile, ""); 2102 2103 DEBUG_printf(("9do_samba_command: status=%d", status)); 2104 2105 if (WIFEXITED(status)) 2106 return (WEXITSTATUS(status)); 2107 else 2108 return (-WTERMSIG(status)); 2109#endif /* WIN32 */ 2110} 2111 2112 2113/* 2114 * 'get_cupsd_conf()' - Get the current cupsd.conf file. 2115 */ 2116 2117static http_status_t /* O - Status of request */ 2118get_cupsd_conf( 2119 http_t *http, /* I - Connection to server */ 2120 _cups_globals_t *cg, /* I - Global data */ 2121 time_t last_update, /* I - Last update time for file */ 2122 char *name, /* I - Filename buffer */ 2123 int namesize, /* I - Size of filename buffer */ 2124 int *remote) /* O - Remote file? */ 2125{ 2126 int fd; /* Temporary file descriptor */ 2127#ifndef WIN32 2128 struct stat info; /* cupsd.conf file information */ 2129#endif /* WIN32 */ 2130 http_status_t status; /* Status of getting cupsd.conf */ 2131 char host[HTTP_MAX_HOST]; /* Hostname for connection */ 2132 2133 2134 /* 2135 * See if we already have the data we need... 2136 */ 2137 2138 httpGetHostname(http, host, sizeof(host)); 2139 2140 if (_cups_strcasecmp(cg->cupsd_hostname, host)) 2141 invalidate_cupsd_cache(cg); 2142 2143 snprintf(name, namesize, "%s/cupsd.conf", cg->cups_serverroot); 2144 *remote = 0; 2145 2146#ifndef WIN32 2147 if (!_cups_strcasecmp(host, "localhost") && !access(name, R_OK)) 2148 { 2149 /* 2150 * Read the local file rather than using HTTP... 2151 */ 2152 2153 if (stat(name, &info)) 2154 { 2155 char message[1024]; /* Message string */ 2156 2157 2158 snprintf(message, sizeof(message), 2159 _cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")), 2160 name, strerror(errno)); 2161 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); 2162 2163 *name = '\0'; 2164 2165 return (HTTP_STATUS_SERVER_ERROR); 2166 } 2167 else if (last_update && info.st_mtime <= last_update) 2168 status = HTTP_STATUS_NOT_MODIFIED; 2169 else 2170 status = HTTP_STATUS_OK; 2171 } 2172 else 2173#endif /* !WIN32 */ 2174 { 2175 /* 2176 * Read cupsd.conf via a HTTP GET request... 2177 */ 2178 2179 if ((fd = cupsTempFd(name, namesize)) < 0) 2180 { 2181 *name = '\0'; 2182 2183 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); 2184 2185 invalidate_cupsd_cache(cg); 2186 2187 return (HTTP_STATUS_SERVER_ERROR); 2188 } 2189 2190 *remote = 1; 2191 2192 httpClearFields(http); 2193 2194 if (last_update) 2195 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, 2196 httpGetDateString(last_update)); 2197 2198 status = cupsGetFd(http, "/admin/conf/cupsd.conf", fd); 2199 2200 close(fd); 2201 2202 if (status != HTTP_STATUS_OK) 2203 { 2204 unlink(name); 2205 *name = '\0'; 2206 } 2207 } 2208 2209 return (status); 2210} 2211 2212 2213/* 2214 * 'invalidate_cupsd_cache()' - Invalidate the cached cupsd.conf settings. 2215 */ 2216 2217static void 2218invalidate_cupsd_cache( 2219 _cups_globals_t *cg) /* I - Global data */ 2220{ 2221 cupsFreeOptions(cg->cupsd_num_settings, cg->cupsd_settings); 2222 2223 cg->cupsd_hostname[0] = '\0'; 2224 cg->cupsd_update = 0; 2225 cg->cupsd_num_settings = 0; 2226 cg->cupsd_settings = NULL; 2227} 2228 2229 2230/* 2231 * 'write_option()' - Write a CUPS option to a PPD file. 2232 */ 2233 2234static void 2235write_option(cups_file_t *dstfp, /* I - PPD file */ 2236 int order, /* I - Order dependency */ 2237 const char *name, /* I - Option name */ 2238 const char *text, /* I - Option text */ 2239 const char *attrname, /* I - Attribute name */ 2240 ipp_attribute_t *suppattr, /* I - IPP -supported attribute */ 2241 ipp_attribute_t *defattr, /* I - IPP -default attribute */ 2242 int defval, /* I - Default value number */ 2243 int valcount) /* I - Number of values */ 2244{ 2245 int i; /* Looping var */ 2246 2247 2248 cupsFilePrintf(dstfp, "*JCLOpenUI *%s/%s: PickOne\n" 2249 "*OrderDependency: %d JCLSetup *%s\n", 2250 name, text, order, name); 2251 2252 if (defattr->value_tag == IPP_TAG_INTEGER) 2253 { 2254 /* 2255 * Do numeric options with a range or list... 2256 */ 2257 2258 cupsFilePrintf(dstfp, "*Default%s: %d\n", name, 2259 defattr->values[defval].integer); 2260 2261 if (suppattr->value_tag == IPP_TAG_RANGE) 2262 { 2263 /* 2264 * List each number in the range... 2265 */ 2266 2267 for (i = suppattr->values[0].range.lower; 2268 i <= suppattr->values[0].range.upper; 2269 i ++) 2270 { 2271 cupsFilePrintf(dstfp, "*%s %d: \"", name, i); 2272 2273 if (valcount == 1) 2274 cupsFilePrintf(dstfp, "%%cupsJobTicket: %s=%d\n\"\n*End\n", 2275 attrname, i); 2276 else if (defval == 0) 2277 cupsFilePrintf(dstfp, "%%cupsJobTicket: %s=%d\"\n", attrname, i); 2278 else if (defval < (valcount - 1)) 2279 cupsFilePrintf(dstfp, ",%d\"\n", i); 2280 else 2281 cupsFilePrintf(dstfp, ",%d\n\"\n*End\n", i); 2282 } 2283 } 2284 else 2285 { 2286 /* 2287 * List explicit numbers... 2288 */ 2289 2290 for (i = 0; i < suppattr->num_values; i ++) 2291 { 2292 cupsFilePrintf(dstfp, "*%s %d: \"", name, suppattr->values[i].integer); 2293 2294 if (valcount == 1) 2295 cupsFilePrintf(dstfp, "%%cupsJobTicket: %s=%d\n\"\n*End\n", attrname, 2296 suppattr->values[i].integer); 2297 else if (defval == 0) 2298 cupsFilePrintf(dstfp, "%%cupsJobTicket: %s=%d\"\n", attrname, 2299 suppattr->values[i].integer); 2300 else if (defval < (valcount - 1)) 2301 cupsFilePrintf(dstfp, ",%d\"\n", suppattr->values[i].integer); 2302 else 2303 cupsFilePrintf(dstfp, ",%d\n\"\n*End\n", suppattr->values[i].integer); 2304 } 2305 } 2306 } 2307 else 2308 { 2309 /* 2310 * Do text options with a list... 2311 */ 2312 2313 cupsFilePrintf(dstfp, "*Default%s: %s\n", name, 2314 defattr->values[defval].string.text); 2315 2316 for (i = 0; i < suppattr->num_values; i ++) 2317 { 2318 cupsFilePrintf(dstfp, "*%s %s: \"", name, 2319 suppattr->values[i].string.text); 2320 2321 if (valcount == 1) 2322 cupsFilePrintf(dstfp, "%%cupsJobTicket: %s=%s\n\"\n*End\n", attrname, 2323 suppattr->values[i].string.text); 2324 else if (defval == 0) 2325 cupsFilePrintf(dstfp, "%%cupsJobTicket: %s=%s\"\n", attrname, 2326 suppattr->values[i].string.text); 2327 else if (defval < (valcount - 1)) 2328 cupsFilePrintf(dstfp, ",%s\"\n", suppattr->values[i].string.text); 2329 else 2330 cupsFilePrintf(dstfp, ",%s\n\"\n*End\n", 2331 suppattr->values[i].string.text); 2332 } 2333 } 2334 2335 cupsFilePrintf(dstfp, "*JCLCloseUI: *%s\n\n", name); 2336} 2337 2338 2339/* 2340 * End of "$Id: adminutil.c 11093 2013-07-03 20:48:42Z msweet $". 2341 */ 2342