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