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