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