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