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