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