]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
7e86f2f6 | 2 | * Printer class routines for the CUPS scheduler. |
ef416fc2 | 3 | * |
409f5497 | 4 | * Copyright 2007-2017 by Apple Inc. |
7e86f2f6 | 5 | * Copyright 1997-2007 by Easy Software Products, all rights reserved. |
ef416fc2 | 6 | * |
e3101897 | 7 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
ef416fc2 | 8 | */ |
9 | ||
10 | /* | |
11 | * Include necessary headers... | |
12 | */ | |
13 | ||
14 | #include "cupsd.h" | |
15 | ||
16 | ||
17 | /* | |
18 | * 'cupsdAddClass()' - Add a class to the system. | |
19 | */ | |
20 | ||
21 | cupsd_printer_t * /* O - New class */ | |
22 | cupsdAddClass(const char *name) /* I - Name of class */ | |
23 | { | |
24 | cupsd_printer_t *c; /* New class */ | |
7cf5915e | 25 | char uri[1024]; /* Class URI */ |
ef416fc2 | 26 | |
27 | ||
28 | /* | |
29 | * Add the printer and set the type to "class"... | |
30 | */ | |
31 | ||
32 | if ((c = cupsdAddPrinter(name)) != NULL) | |
33 | { | |
34 | /* | |
35 | * Change from a printer to a class... | |
36 | */ | |
37 | ||
38 | c->type = CUPS_PRINTER_CLASS; | |
39 | ||
7cf5915e MS |
40 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, |
41 | ServerName, RemotePort, "/classes/%s", name); | |
42 | cupsdSetString(&c->uri, uri); | |
43 | ||
f11a948a | 44 | cupsdSetString(&c->error_policy, "retry-current-job"); |
ef416fc2 | 45 | } |
46 | ||
47 | return (c); | |
48 | } | |
49 | ||
50 | ||
51 | /* | |
52 | * 'cupsdAddPrinterToClass()' - Add a printer to a class... | |
53 | */ | |
54 | ||
55 | void | |
56 | cupsdAddPrinterToClass( | |
57 | cupsd_printer_t *c, /* I - Class to add to */ | |
58 | cupsd_printer_t *p) /* I - Printer to add */ | |
59 | { | |
60 | int i; /* Looping var */ | |
61 | cupsd_printer_t **temp; /* Pointer to printer array */ | |
62 | ||
63 | ||
64 | /* | |
65 | * See if this printer is already a member of the class... | |
66 | */ | |
67 | ||
68 | for (i = 0; i < c->num_printers; i ++) | |
69 | if (c->printers[i] == p) | |
70 | return; | |
71 | ||
72 | /* | |
73 | * Allocate memory as needed... | |
74 | */ | |
75 | ||
76 | if (c->num_printers == 0) | |
77 | temp = malloc(sizeof(cupsd_printer_t *)); | |
78 | else | |
7e86f2f6 | 79 | temp = realloc(c->printers, sizeof(cupsd_printer_t *) * (size_t)(c->num_printers + 1)); |
ef416fc2 | 80 | |
81 | if (temp == NULL) | |
82 | { | |
83 | cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to add printer %s to class %s!", | |
84 | p->name, c->name); | |
85 | return; | |
86 | } | |
87 | ||
88 | /* | |
89 | * Add the printer to the end of the array and update the number of printers. | |
90 | */ | |
91 | ||
92 | c->printers = temp; | |
93 | temp += c->num_printers; | |
94 | c->num_printers ++; | |
95 | ||
96 | *temp = p; | |
97 | } | |
98 | ||
99 | ||
100 | /* | |
101 | * 'cupsdDeletePrinterFromClass()' - Delete a printer from a class. | |
102 | */ | |
103 | ||
f8b3a85b | 104 | int /* O - 1 if class changed, 0 otherwise */ |
ef416fc2 | 105 | cupsdDeletePrinterFromClass( |
106 | cupsd_printer_t *c, /* I - Class to delete from */ | |
107 | cupsd_printer_t *p) /* I - Printer to delete */ | |
108 | { | |
c168a833 | 109 | int i; /* Looping var */ |
ef416fc2 | 110 | |
111 | ||
112 | /* | |
113 | * See if the printer is in the class... | |
114 | */ | |
115 | ||
116 | for (i = 0; i < c->num_printers; i ++) | |
117 | if (p == c->printers[i]) | |
118 | break; | |
119 | ||
120 | /* | |
121 | * If it is, remove it from the list... | |
122 | */ | |
123 | ||
124 | if (i < c->num_printers) | |
125 | { | |
126 | /* | |
127 | * Yes, remove the printer... | |
128 | */ | |
129 | ||
130 | c->num_printers --; | |
131 | if (i < c->num_printers) | |
132 | memmove(c->printers + i, c->printers + i + 1, | |
7e86f2f6 | 133 | (size_t)(c->num_printers - i) * sizeof(cupsd_printer_t *)); |
ef416fc2 | 134 | } |
135 | else | |
f8b3a85b | 136 | return (0); |
ef416fc2 | 137 | |
138 | /* | |
c168a833 | 139 | * Update the IPP attributes (have to do this for member-names)... |
ef416fc2 | 140 | */ |
141 | ||
c168a833 | 142 | cupsdSetPrinterAttrs(c); |
f8b3a85b MS |
143 | |
144 | return (1); | |
ef416fc2 | 145 | } |
146 | ||
147 | ||
148 | /* | |
149 | * 'cupsdDeletePrinterFromClasses()' - Delete a printer from all classes. | |
150 | */ | |
151 | ||
f8b3a85b | 152 | int /* O - 1 if class changed, 0 otherwise */ |
ef416fc2 | 153 | cupsdDeletePrinterFromClasses( |
154 | cupsd_printer_t *p) /* I - Printer to delete */ | |
155 | { | |
f8b3a85b | 156 | int changed = 0; /* Any class changed? */ |
ef416fc2 | 157 | cupsd_printer_t *c; /* Pointer to current class */ |
158 | ||
159 | ||
160 | /* | |
161 | * Loop through the printer/class list and remove the printer | |
162 | * from each class listed... | |
163 | */ | |
164 | ||
165 | for (c = (cupsd_printer_t *)cupsArrayFirst(Printers); | |
166 | c; | |
167 | c = (cupsd_printer_t *)cupsArrayNext(Printers)) | |
a2326b5b | 168 | if (c->type & CUPS_PRINTER_CLASS) |
f8b3a85b | 169 | changed |= cupsdDeletePrinterFromClass(c, p); |
ef416fc2 | 170 | |
f8b3a85b | 171 | return (changed); |
ef416fc2 | 172 | } |
173 | ||
174 | ||
ef416fc2 | 175 | /* |
176 | * 'cupsdFindAvailablePrinter()' - Find an available printer in a class. | |
177 | */ | |
178 | ||
179 | cupsd_printer_t * /* O - Available printer or NULL */ | |
180 | cupsdFindAvailablePrinter( | |
181 | const char *name) /* I - Class to check */ | |
182 | { | |
183 | int i; /* Looping var */ | |
184 | cupsd_printer_t *c; /* Printer class */ | |
185 | ||
186 | ||
187 | /* | |
188 | * Find the class... | |
189 | */ | |
190 | ||
191 | if ((c = cupsdFindClass(name)) == NULL) | |
192 | { | |
193 | cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to find class \"%s\"!", name); | |
194 | return (NULL); | |
195 | } | |
196 | ||
0a682745 MS |
197 | if (c->num_printers == 0) |
198 | return (NULL); | |
199 | ||
c0e1af83 | 200 | /* |
201 | * Make sure that the last printer is also a valid index into the printer | |
202 | * array. If not, reset the last printer to 0... | |
203 | */ | |
204 | ||
205 | if (c->last_printer >= c->num_printers) | |
206 | c->last_printer = 0; | |
207 | ||
ef416fc2 | 208 | /* |
209 | * Loop through the printers in the class and return the first idle | |
210 | * printer... We keep track of the last printer that we used so that | |
211 | * a "round robin" type of scheduling is realized (otherwise the first | |
212 | * server might be saturated with print jobs...) | |
213 | * | |
214 | * Thanks to Joel Fredrikson for helping us get this right! | |
215 | */ | |
216 | ||
217 | for (i = c->last_printer + 1; ; i ++) | |
218 | { | |
219 | if (i >= c->num_printers) | |
220 | i = 0; | |
221 | ||
222 | if (c->printers[i]->accepting && | |
223 | (c->printers[i]->state == IPP_PRINTER_IDLE || | |
224 | ((c->printers[i]->type & CUPS_PRINTER_REMOTE) && !c->printers[i]->job))) | |
225 | { | |
226 | c->last_printer = i; | |
227 | return (c->printers[i]); | |
228 | } | |
229 | ||
230 | if (i == c->last_printer) | |
231 | break; | |
232 | } | |
233 | ||
234 | return (NULL); | |
235 | } | |
236 | ||
237 | ||
238 | /* | |
239 | * 'cupsdFindClass()' - Find the named class. | |
240 | */ | |
241 | ||
242 | cupsd_printer_t * /* O - Matching class or NULL */ | |
243 | cupsdFindClass(const char *name) /* I - Name of class */ | |
244 | { | |
245 | cupsd_printer_t *c; /* Current class/printer */ | |
246 | ||
247 | ||
a2326b5b | 248 | if ((c = cupsdFindDest(name)) != NULL && (c->type & CUPS_PRINTER_CLASS)) |
ef416fc2 | 249 | return (c); |
250 | else | |
251 | return (NULL); | |
252 | } | |
253 | ||
254 | ||
255 | /* | |
256 | * 'cupsdLoadAllClasses()' - Load classes from the classes.conf file. | |
257 | */ | |
258 | ||
259 | void | |
260 | cupsdLoadAllClasses(void) | |
261 | { | |
68b10830 | 262 | int i; /* Looping var */ |
ef416fc2 | 263 | cups_file_t *fp; /* classes.conf file */ |
264 | int linenum; /* Current line number */ | |
d1c13e16 | 265 | char line[4096], /* Line from file */ |
ef416fc2 | 266 | *value, /* Pointer to value */ |
267 | *valueptr; /* Pointer into value */ | |
268 | cupsd_printer_t *p, /* Current printer class */ | |
269 | *temp; /* Temporary pointer to printer */ | |
270 | ||
271 | ||
272 | /* | |
273 | * Open the classes.conf file... | |
274 | */ | |
275 | ||
276 | snprintf(line, sizeof(line), "%s/classes.conf", ServerRoot); | |
321d8d57 | 277 | if ((fp = cupsdOpenConfFile(line)) == NULL) |
ef416fc2 | 278 | return; |
ef416fc2 | 279 | |
280 | /* | |
281 | * Read class configurations until we hit EOF... | |
282 | */ | |
283 | ||
284 | linenum = 0; | |
285 | p = NULL; | |
286 | ||
287 | while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) | |
288 | { | |
289 | /* | |
290 | * Decode the directive... | |
291 | */ | |
292 | ||
88f9aafc MS |
293 | if (!_cups_strcasecmp(line, "<Class") || |
294 | !_cups_strcasecmp(line, "<DefaultClass")) | |
ef416fc2 | 295 | { |
296 | /* | |
297 | * <Class name> or <DefaultClass name> | |
298 | */ | |
299 | ||
300 | if (p == NULL && value) | |
301 | { | |
bd7854cb | 302 | cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading class %s...", value); |
ef416fc2 | 303 | |
f7deaa1a | 304 | /* |
305 | * Since prior classes may have implicitly defined this class, | |
306 | * see if it already exists... | |
307 | */ | |
308 | ||
309 | if ((p = cupsdFindDest(value)) != NULL) | |
310 | { | |
311 | p->type = CUPS_PRINTER_CLASS; | |
312 | cupsdSetStringf(&p->uri, "ipp://%s:%d/classes/%s", ServerName, | |
313 | LocalPort, value); | |
314 | cupsdSetString(&p->error_policy, "retry-job"); | |
315 | } | |
316 | else | |
317 | p = cupsdAddClass(value); | |
318 | ||
ef416fc2 | 319 | p->accepting = 1; |
320 | p->state = IPP_PRINTER_IDLE; | |
321 | ||
88f9aafc | 322 | if (!_cups_strcasecmp(line, "<DefaultClass")) |
ef416fc2 | 323 | DefaultPrinter = p; |
324 | } | |
325 | else | |
ef416fc2 | 326 | cupsdLogMessage(CUPSD_LOG_ERROR, |
327 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 328 | } |
1dd965f6 | 329 | else if (!_cups_strcasecmp(line, "</Class>") || !_cups_strcasecmp(line, "</DefaultClass>")) |
ef416fc2 | 330 | { |
331 | if (p != NULL) | |
332 | { | |
333 | cupsdSetPrinterAttrs(p); | |
334 | p = NULL; | |
335 | } | |
336 | else | |
ef416fc2 | 337 | cupsdLogMessage(CUPSD_LOG_ERROR, |
338 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 339 | } |
340 | else if (!p) | |
341 | { | |
342 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
343 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 344 | } |
409f5497 MS |
345 | else if (!_cups_strcasecmp(line, "PrinterId")) |
346 | { | |
347 | if (value && (i = atoi(value)) > 0) | |
348 | p->printer_id = i; | |
349 | else | |
350 | cupsdLogMessage(CUPSD_LOG_ERROR, "Bad PrinterId on line %d of classes.conf.", linenum); | |
351 | } | |
88f9aafc | 352 | else if (!_cups_strcasecmp(line, "UUID")) |
82f97232 MS |
353 | { |
354 | if (value && !strncmp(value, "urn:uuid:", 9)) | |
355 | cupsdSetString(&(p->uuid), value); | |
356 | else | |
357 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
358 | "Bad UUID on line %d of classes.conf.", linenum); | |
359 | } | |
88f9aafc | 360 | else if (!_cups_strcasecmp(line, "AuthInfoRequired")) |
f7deaa1a | 361 | { |
362 | if (!cupsdSetAuthInfoRequired(p, value, NULL)) | |
363 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
364 | "Bad AuthInfoRequired on line %d of classes.conf.", | |
365 | linenum); | |
366 | } | |
88f9aafc | 367 | else if (!_cups_strcasecmp(line, "Info")) |
ef416fc2 | 368 | { |
369 | if (value) | |
370 | cupsdSetString(&p->info, value); | |
371 | } | |
88f9aafc | 372 | else if (!_cups_strcasecmp(line, "Location")) |
ef416fc2 | 373 | { |
374 | if (value) | |
375 | cupsdSetString(&p->location, value); | |
376 | } | |
88f9aafc | 377 | else if (!_cups_strcasecmp(line, "Option") && value) |
b423cd4c | 378 | { |
379 | /* | |
380 | * Option name value | |
381 | */ | |
382 | ||
383 | for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++); | |
384 | ||
385 | if (!*valueptr) | |
386 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
387 | "Syntax error on line %d of classes.conf.", linenum); | |
388 | else | |
389 | { | |
390 | for (; *valueptr && isspace(*valueptr & 255); *valueptr++ = '\0'); | |
391 | ||
392 | p->num_options = cupsAddOption(value, valueptr, p->num_options, | |
393 | &(p->options)); | |
394 | } | |
395 | } | |
88f9aafc | 396 | else if (!_cups_strcasecmp(line, "Printer")) |
ef416fc2 | 397 | { |
398 | if (!value) | |
399 | { | |
400 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
401 | "Syntax error on line %d of classes.conf.", linenum); | |
0af14961 | 402 | continue; |
ef416fc2 | 403 | } |
404 | else if ((temp = cupsdFindPrinter(value)) == NULL) | |
405 | { | |
406 | cupsdLogMessage(CUPSD_LOG_WARN, | |
407 | "Unknown printer %s on line %d of classes.conf.", | |
408 | value, linenum); | |
409 | ||
410 | /* | |
411 | * Add the missing remote printer... | |
412 | */ | |
413 | ||
414 | if ((temp = cupsdAddPrinter(value)) != NULL) | |
415 | { | |
416 | cupsdSetString(&temp->make_model, "Remote Printer on unknown"); | |
417 | ||
a2326b5b MS |
418 | temp->state = IPP_PRINTER_STOPPED; |
419 | temp->type |= CUPS_PRINTER_REMOTE; | |
ef416fc2 | 420 | |
421 | cupsdSetString(&temp->location, "Location Unknown"); | |
422 | cupsdSetString(&temp->info, "No Information Available"); | |
423 | temp->hostname[0] = '\0'; | |
424 | ||
425 | cupsdSetPrinterAttrs(temp); | |
426 | } | |
427 | } | |
428 | ||
429 | if (temp) | |
430 | cupsdAddPrinterToClass(p, temp); | |
431 | } | |
88f9aafc | 432 | else if (!_cups_strcasecmp(line, "State")) |
ef416fc2 | 433 | { |
434 | /* | |
435 | * Set the initial queue state... | |
436 | */ | |
437 | ||
88f9aafc | 438 | if (!_cups_strcasecmp(value, "idle")) |
ef416fc2 | 439 | p->state = IPP_PRINTER_IDLE; |
88f9aafc | 440 | else if (!_cups_strcasecmp(value, "stopped")) |
745129be | 441 | { |
ef416fc2 | 442 | p->state = IPP_PRINTER_STOPPED; |
68b10830 MS |
443 | |
444 | for (i = 0 ; i < p->num_reasons; i ++) | |
445 | if (!strcmp("paused", p->reasons[i])) | |
446 | break; | |
447 | ||
448 | if (i >= p->num_reasons && | |
449 | p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) | |
450 | { | |
451 | p->reasons[p->num_reasons] = _cupsStrAlloc("paused"); | |
452 | p->num_reasons ++; | |
453 | } | |
745129be | 454 | } |
ef416fc2 | 455 | else |
ef416fc2 | 456 | cupsdLogMessage(CUPSD_LOG_ERROR, |
457 | "Syntax error on line %d of classes.conf.", | |
458 | linenum); | |
ef416fc2 | 459 | } |
88f9aafc | 460 | else if (!_cups_strcasecmp(line, "StateMessage")) |
ef416fc2 | 461 | { |
462 | /* | |
463 | * Set the initial queue state message... | |
464 | */ | |
465 | ||
466 | if (value) | |
467 | strlcpy(p->state_message, value, sizeof(p->state_message)); | |
468 | } | |
88f9aafc | 469 | else if (!_cups_strcasecmp(line, "StateTime")) |
ef416fc2 | 470 | { |
471 | /* | |
472 | * Set the state time... | |
473 | */ | |
474 | ||
475 | if (value) | |
476 | p->state_time = atoi(value); | |
477 | } | |
88f9aafc | 478 | else if (!_cups_strcasecmp(line, "Accepting")) |
ef416fc2 | 479 | { |
480 | /* | |
481 | * Set the initial accepting state... | |
482 | */ | |
483 | ||
484 | if (value && | |
88f9aafc MS |
485 | (!_cups_strcasecmp(value, "yes") || |
486 | !_cups_strcasecmp(value, "on") || | |
487 | !_cups_strcasecmp(value, "true"))) | |
ef416fc2 | 488 | p->accepting = 1; |
489 | else if (value && | |
88f9aafc MS |
490 | (!_cups_strcasecmp(value, "no") || |
491 | !_cups_strcasecmp(value, "off") || | |
492 | !_cups_strcasecmp(value, "false"))) | |
ef416fc2 | 493 | p->accepting = 0; |
494 | else | |
ef416fc2 | 495 | cupsdLogMessage(CUPSD_LOG_ERROR, |
496 | "Syntax error on line %d of classes.conf.", | |
497 | linenum); | |
ef416fc2 | 498 | } |
88f9aafc | 499 | else if (!_cups_strcasecmp(line, "Shared")) |
ef416fc2 | 500 | { |
501 | /* | |
502 | * Set the initial shared state... | |
503 | */ | |
504 | ||
505 | if (value && | |
88f9aafc MS |
506 | (!_cups_strcasecmp(value, "yes") || |
507 | !_cups_strcasecmp(value, "on") || | |
508 | !_cups_strcasecmp(value, "true"))) | |
ef416fc2 | 509 | p->shared = 1; |
510 | else if (value && | |
88f9aafc MS |
511 | (!_cups_strcasecmp(value, "no") || |
512 | !_cups_strcasecmp(value, "off") || | |
513 | !_cups_strcasecmp(value, "false"))) | |
ef416fc2 | 514 | p->shared = 0; |
515 | else | |
ef416fc2 | 516 | cupsdLogMessage(CUPSD_LOG_ERROR, |
91c84a35 | 517 | "Syntax error on line %d of classes.conf.", |
ef416fc2 | 518 | linenum); |
ef416fc2 | 519 | } |
88f9aafc | 520 | else if (!_cups_strcasecmp(line, "JobSheets")) |
ef416fc2 | 521 | { |
522 | /* | |
523 | * Set the initial job sheets... | |
524 | */ | |
525 | ||
526 | if (value) | |
527 | { | |
528 | for (valueptr = value; | |
529 | *valueptr && !isspace(*valueptr & 255); | |
530 | valueptr ++); | |
531 | ||
532 | if (*valueptr) | |
533 | *valueptr++ = '\0'; | |
534 | ||
535 | cupsdSetString(&p->job_sheets[0], value); | |
536 | ||
537 | while (isspace(*valueptr & 255)) | |
538 | valueptr ++; | |
539 | ||
540 | if (*valueptr) | |
541 | { | |
542 | for (value = valueptr; | |
543 | *valueptr && !isspace(*valueptr & 255); | |
544 | valueptr ++); | |
545 | ||
546 | if (*valueptr) | |
1f0275e3 | 547 | *valueptr = '\0'; |
ef416fc2 | 548 | |
549 | cupsdSetString(&p->job_sheets[1], value); | |
550 | } | |
551 | } | |
552 | else | |
ef416fc2 | 553 | cupsdLogMessage(CUPSD_LOG_ERROR, |
554 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 555 | } |
88f9aafc | 556 | else if (!_cups_strcasecmp(line, "AllowUser")) |
ef416fc2 | 557 | { |
558 | if (value) | |
559 | { | |
560 | p->deny_users = 0; | |
10d09e33 | 561 | cupsdAddString(&(p->users), value); |
ef416fc2 | 562 | } |
563 | else | |
ef416fc2 | 564 | cupsdLogMessage(CUPSD_LOG_ERROR, |
565 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 566 | } |
88f9aafc | 567 | else if (!_cups_strcasecmp(line, "DenyUser")) |
ef416fc2 | 568 | { |
569 | if (value) | |
570 | { | |
571 | p->deny_users = 1; | |
10d09e33 | 572 | cupsdAddString(&(p->users), value); |
ef416fc2 | 573 | } |
574 | else | |
ef416fc2 | 575 | cupsdLogMessage(CUPSD_LOG_ERROR, |
576 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 577 | } |
88f9aafc | 578 | else if (!_cups_strcasecmp(line, "QuotaPeriod")) |
ef416fc2 | 579 | { |
580 | if (value) | |
581 | p->quota_period = atoi(value); | |
582 | else | |
ef416fc2 | 583 | cupsdLogMessage(CUPSD_LOG_ERROR, |
584 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 585 | } |
88f9aafc | 586 | else if (!_cups_strcasecmp(line, "PageLimit")) |
ef416fc2 | 587 | { |
588 | if (value) | |
589 | p->page_limit = atoi(value); | |
590 | else | |
ef416fc2 | 591 | cupsdLogMessage(CUPSD_LOG_ERROR, |
592 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 593 | } |
88f9aafc | 594 | else if (!_cups_strcasecmp(line, "KLimit")) |
ef416fc2 | 595 | { |
596 | if (value) | |
597 | p->k_limit = atoi(value); | |
598 | else | |
ef416fc2 | 599 | cupsdLogMessage(CUPSD_LOG_ERROR, |
600 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 601 | } |
88f9aafc | 602 | else if (!_cups_strcasecmp(line, "OpPolicy")) |
ef416fc2 | 603 | { |
604 | if (value) | |
c0e1af83 | 605 | { |
606 | cupsd_policy_t *pol; /* Policy */ | |
607 | ||
608 | ||
609 | if ((pol = cupsdFindPolicy(value)) != NULL) | |
610 | { | |
611 | cupsdSetString(&p->op_policy, value); | |
612 | p->op_policy_ptr = pol; | |
613 | } | |
614 | else | |
615 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
616 | "Bad policy \"%s\" on line %d of classes.conf", | |
617 | value, linenum); | |
618 | } | |
ef416fc2 | 619 | else |
ef416fc2 | 620 | cupsdLogMessage(CUPSD_LOG_ERROR, |
621 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 622 | } |
88f9aafc | 623 | else if (!_cups_strcasecmp(line, "ErrorPolicy")) |
ef416fc2 | 624 | { |
625 | if (value) | |
f11a948a MS |
626 | { |
627 | if (strcmp(value, "retry-current-job") && strcmp(value, "retry-job")) | |
628 | cupsdLogMessage(CUPSD_LOG_WARN, | |
629 | "ErrorPolicy %s ignored on line %d of classes.conf", | |
630 | value, linenum); | |
631 | } | |
ef416fc2 | 632 | else |
ef416fc2 | 633 | cupsdLogMessage(CUPSD_LOG_ERROR, |
634 | "Syntax error on line %d of classes.conf.", linenum); | |
ef416fc2 | 635 | } |
636 | else | |
637 | { | |
638 | /* | |
639 | * Something else we don't understand... | |
640 | */ | |
641 | ||
642 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
643 | "Unknown configuration directive %s on line %d of classes.conf.", | |
644 | line, linenum); | |
645 | } | |
646 | } | |
647 | ||
648 | cupsFileClose(fp); | |
649 | } | |
650 | ||
651 | ||
652 | /* | |
653 | * 'cupsdSaveAllClasses()' - Save classes to the classes.conf file. | |
654 | */ | |
655 | ||
656 | void | |
657 | cupsdSaveAllClasses(void) | |
658 | { | |
659 | cups_file_t *fp; /* classes.conf file */ | |
321d8d57 MS |
660 | char filename[1024], /* classes.conf filename */ |
661 | temp[1024], /* Temporary string */ | |
10d09e33 MS |
662 | value[2048], /* Value string */ |
663 | *name; /* Current user name */ | |
ef416fc2 | 664 | cupsd_printer_t *pclass; /* Current printer class */ |
665 | int i; /* Looping var */ | |
666 | time_t curtime; /* Current time */ | |
667 | struct tm *curdate; /* Current date */ | |
b423cd4c | 668 | cups_option_t *option; /* Current option */ |
ef416fc2 | 669 | |
670 | ||
671 | /* | |
672 | * Create the classes.conf file... | |
673 | */ | |
674 | ||
321d8d57 | 675 | snprintf(filename, sizeof(filename), "%s/classes.conf", ServerRoot); |
ef416fc2 | 676 | |
321d8d57 | 677 | if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL) |
ef416fc2 | 678 | return; |
ef416fc2 | 679 | |
321d8d57 | 680 | cupsdLogMessage(CUPSD_LOG_INFO, "Saving classes.conf..."); |
ef416fc2 | 681 | |
682 | /* | |
683 | * Write a small header to the file... | |
684 | */ | |
685 | ||
686 | curtime = time(NULL); | |
687 | curdate = localtime(&curtime); | |
688 | strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate); | |
689 | ||
690 | cupsFilePuts(fp, "# Class configuration file for " CUPS_SVERSION "\n"); | |
691 | cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); | |
b226ab99 | 692 | cupsFilePuts(fp, "# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING\n"); |
ef416fc2 | 693 | |
694 | /* | |
695 | * Write each local class known to the system... | |
696 | */ | |
697 | ||
698 | for (pclass = (cupsd_printer_t *)cupsArrayFirst(Printers); | |
699 | pclass; | |
700 | pclass = (cupsd_printer_t *)cupsArrayNext(Printers)) | |
701 | { | |
702 | /* | |
703 | * Skip remote destinations and regular printers... | |
704 | */ | |
705 | ||
706 | if ((pclass->type & CUPS_PRINTER_REMOTE) || | |
ef416fc2 | 707 | !(pclass->type & CUPS_PRINTER_CLASS)) |
708 | continue; | |
709 | ||
710 | /* | |
711 | * Write printers as needed... | |
712 | */ | |
713 | ||
714 | if (pclass == DefaultPrinter) | |
715 | cupsFilePrintf(fp, "<DefaultClass %s>\n", pclass->name); | |
716 | else | |
717 | cupsFilePrintf(fp, "<Class %s>\n", pclass->name); | |
718 | ||
409f5497 MS |
719 | if (pclass->printer_id) |
720 | cupsFilePrintf(fp, "PrinterId %d\n", pclass->printer_id); | |
721 | ||
82f97232 MS |
722 | cupsFilePrintf(fp, "UUID %s\n", pclass->uuid); |
723 | ||
f7deaa1a | 724 | if (pclass->num_auth_info_required > 0) |
725 | { | |
58dc1933 | 726 | switch (pclass->num_auth_info_required) |
f7deaa1a | 727 | { |
58dc1933 MS |
728 | case 1 : |
729 | strlcpy(value, pclass->auth_info_required[0], sizeof(value)); | |
730 | break; | |
731 | ||
732 | case 2 : | |
733 | snprintf(value, sizeof(value), "%s,%s", | |
734 | pclass->auth_info_required[0], | |
735 | pclass->auth_info_required[1]); | |
736 | break; | |
737 | ||
738 | case 3 : | |
739 | default : | |
740 | snprintf(value, sizeof(value), "%s,%s,%s", | |
741 | pclass->auth_info_required[0], | |
742 | pclass->auth_info_required[1], | |
743 | pclass->auth_info_required[2]); | |
744 | break; | |
f7deaa1a | 745 | } |
58dc1933 MS |
746 | |
747 | cupsFilePutConf(fp, "AuthInfoRequired", value); | |
f7deaa1a | 748 | } |
ef416fc2 | 749 | |
58dc1933 MS |
750 | if (pclass->info) |
751 | cupsFilePutConf(fp, "Info", pclass->info); | |
f7deaa1a | 752 | |
58dc1933 MS |
753 | if (pclass->location) |
754 | cupsFilePutConf(fp, "Location", pclass->location); | |
ef416fc2 | 755 | |
756 | if (pclass->state == IPP_PRINTER_STOPPED) | |
ef416fc2 | 757 | cupsFilePuts(fp, "State Stopped\n"); |
ef416fc2 | 758 | else |
759 | cupsFilePuts(fp, "State Idle\n"); | |
760 | ||
761 | cupsFilePrintf(fp, "StateTime %d\n", (int)pclass->state_time); | |
762 | ||
763 | if (pclass->accepting) | |
764 | cupsFilePuts(fp, "Accepting Yes\n"); | |
765 | else | |
766 | cupsFilePuts(fp, "Accepting No\n"); | |
767 | ||
768 | if (pclass->shared) | |
769 | cupsFilePuts(fp, "Shared Yes\n"); | |
770 | else | |
771 | cupsFilePuts(fp, "Shared No\n"); | |
772 | ||
58dc1933 MS |
773 | snprintf(value, sizeof(value), "%s %s", pclass->job_sheets[0], |
774 | pclass->job_sheets[1]); | |
775 | cupsFilePutConf(fp, "JobSheets", value); | |
ef416fc2 | 776 | |
94da7e34 MS |
777 | for (i = 0; i < pclass->num_printers; i ++) |
778 | cupsFilePrintf(fp, "Printer %s\n", pclass->printers[i]->name); | |
779 | ||
ef416fc2 | 780 | cupsFilePrintf(fp, "QuotaPeriod %d\n", pclass->quota_period); |
781 | cupsFilePrintf(fp, "PageLimit %d\n", pclass->page_limit); | |
782 | cupsFilePrintf(fp, "KLimit %d\n", pclass->k_limit); | |
783 | ||
10d09e33 MS |
784 | for (name = (char *)cupsArrayFirst(pclass->users); |
785 | name; | |
786 | name = (char *)cupsArrayNext(pclass->users)) | |
787 | cupsFilePutConf(fp, pclass->deny_users ? "DenyUser" : "AllowUser", name); | |
ef416fc2 | 788 | |
58dc1933 MS |
789 | if (pclass->op_policy) |
790 | cupsFilePutConf(fp, "OpPolicy", pclass->op_policy); | |
ef416fc2 | 791 | if (pclass->error_policy) |
58dc1933 | 792 | cupsFilePutConf(fp, "ErrorPolicy", pclass->error_policy); |
ef416fc2 | 793 | |
b423cd4c | 794 | for (i = pclass->num_options, option = pclass->options; |
795 | i > 0; | |
796 | i --, option ++) | |
58dc1933 MS |
797 | { |
798 | snprintf(value, sizeof(value), "%s %s", option->name, option->value); | |
799 | cupsFilePutConf(fp, "Option", value); | |
800 | } | |
b423cd4c | 801 | |
1dd965f6 MS |
802 | if (pclass == DefaultPrinter) |
803 | cupsFilePuts(fp, "</DefaultClass>\n"); | |
804 | else | |
805 | cupsFilePuts(fp, "</Class>\n"); | |
ef416fc2 | 806 | } |
807 | ||
321d8d57 | 808 | cupsdCloseCreatedConfFile(fp, filename); |
ef416fc2 | 809 | } |