]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/classes.c
Merge changes from CUPS 1.5svn-r9631.
[thirdparty/cups.git] / scheduler / classes.c
CommitLineData
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
40cupsd_printer_t * /* O - New class */
41cupsdAddClass(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
74void
75cupsdAddPrinterToClass(
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 123int /* O - 1 if class changed, 0 otherwise */
ef416fc2 124cupsdDeletePrinterFromClass(
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 171int /* O - 1 if class changed, 0 otherwise */
ef416fc2 172cupsdDeletePrinterFromClasses(
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
213cupsd_printer_t * /* O - Available printer or NULL */
214cupsdFindAvailablePrinter(
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
276cupsd_printer_t * /* O - Matching class or NULL */
277cupsdFindClass(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
294void
295cupsdLoadAllClasses(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
690void
691cupsdSaveAllClasses(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
869void
870cupsdUpdateImplicitClasses(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 */