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