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