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