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