]>
Commit | Line | Data |
---|---|---|
a129ddbd | 1 | /* |
b2e10895 | 2 | * "$Id$" |
a129ddbd | 3 | * |
cbbfcc63 | 4 | * Printer class routines for the Common UNIX Printing System (CUPS). |
a129ddbd | 5 | * |
c9d3f842 | 6 | * Copyright 1997-2005 by Easy Software Products, all rights reserved. |
a129ddbd | 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 | |
8784b6a6 | 17 | * 44141 Airport View Drive, Suite 204 |
8650fcf2 | 18 | * Hollywood, Maryland 20636 USA |
a129ddbd | 19 | * |
edfd3c3d | 20 | * Voice: (301) 373-9600 |
a129ddbd | 21 | * EMail: cups-info@cups.org |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
589eb420 | 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 | |
a4f3d51c | 36 | * classes. |
a129ddbd | 37 | */ |
38 | ||
39 | /* | |
40 | * Include necessary headers... | |
41 | */ | |
42 | ||
fd8b1cf8 | 43 | #include "cupsd.h" |
a129ddbd | 44 | |
45 | ||
cbbfcc63 | 46 | /* |
589eb420 | 47 | * 'cupsdAddClass()' - Add a class to the system. |
cbbfcc63 | 48 | */ |
49 | ||
589eb420 | 50 | cupsd_printer_t * /* O - New class */ |
51 | cupsdAddClass(const char *name) /* I - Name of class */ | |
a9de544f | 52 | { |
589eb420 | 53 | cupsd_printer_t *c; /* New class */ |
cbbfcc63 | 54 | |
55 | ||
56 | /* | |
57 | * Add the printer and set the type to "class"... | |
58 | */ | |
59 | ||
589eb420 | 60 | if ((c = cupsdAddPrinter(name)) != NULL) |
57c77867 | 61 | { |
d588a92e | 62 | /* |
63 | * Change from a printer to a class... | |
64 | */ | |
65 | ||
cbbfcc63 | 66 | c->type = CUPS_PRINTER_CLASS; |
d47f8ebe | 67 | |
589eb420 | 68 | cupsdSetStringf(&c->uri, "ipp://%s:%d/classes/%s", ServerName, LocalPort, name); |
69 | cupsdSetString(&c->error_policy, "retry-job"); | |
57c77867 | 70 | } |
cbbfcc63 | 71 | |
72 | return (c); | |
73 | } | |
74 | ||
75 | ||
76 | /* | |
589eb420 | 77 | * 'cupsdAddPrinterToClass()' - Add a printer to a class... |
cbbfcc63 | 78 | */ |
79 | ||
80 | void | |
589eb420 | 81 | cupsdAddPrinterToClass(cupsd_printer_t *c, /* I - Class to add to */ |
82 | cupsd_printer_t *p) /* I - Printer to add */ | |
cbbfcc63 | 83 | { |
b2e10895 | 84 | int i; /* Looping var */ |
589eb420 | 85 | cupsd_printer_t **temp; /* Pointer to printer array */ |
cbbfcc63 | 86 | |
87 | ||
b2e10895 | 88 | /* |
89 | * See if this printer is already a member of the class... | |
90 | */ | |
91 | ||
92 | for (i = 0; i < c->num_printers; i ++) | |
93 | if (c->printers[i] == p) | |
94 | return; | |
95 | ||
cbbfcc63 | 96 | /* |
97 | * Allocate memory as needed... | |
98 | */ | |
99 | ||
100 | if (c->num_printers == 0) | |
589eb420 | 101 | temp = malloc(sizeof(cupsd_printer_t *)); |
cbbfcc63 | 102 | else |
589eb420 | 103 | temp = realloc(c->printers, sizeof(cupsd_printer_t *) * (c->num_printers + 1)); |
cbbfcc63 | 104 | |
105 | if (temp == NULL) | |
106 | { | |
589eb420 | 107 | cupsdLogMessage(L_ERROR, "Unable to add printer %s to class %s!", |
cbbfcc63 | 108 | p->name, c->name); |
109 | return; | |
110 | } | |
111 | ||
112 | /* | |
113 | * Add the printer to the end of the array and update the number of printers. | |
114 | */ | |
115 | ||
116 | c->printers = temp; | |
117 | temp += c->num_printers; | |
118 | c->num_printers ++; | |
119 | ||
120 | *temp = p; | |
a9de544f | 121 | } |
122 | ||
123 | ||
cbbfcc63 | 124 | /* |
589eb420 | 125 | * 'cupsdDeletePrinterFromClass()' - Delete a printer from a class. |
cbbfcc63 | 126 | */ |
127 | ||
a9de544f | 128 | void |
589eb420 | 129 | cupsdDeletePrinterFromClass(cupsd_printer_t *c, /* I - Class to delete from */ |
130 | cupsd_printer_t *p) /* I - Printer to delete */ | |
a9de544f | 131 | { |
8d853fdf | 132 | int i; /* Looping var */ |
133 | cups_ptype_t type; /* Class type */ | |
cbbfcc63 | 134 | |
135 | ||
136 | /* | |
137 | * See if the printer is in the class... | |
138 | */ | |
139 | ||
140 | for (i = 0; i < c->num_printers; i ++) | |
141 | if (p == c->printers[i]) | |
142 | break; | |
143 | ||
144 | /* | |
145 | * If it is, remove it from the list... | |
146 | */ | |
147 | ||
148 | if (i < c->num_printers) | |
149 | { | |
150 | /* | |
151 | * Yes, remove the printer... | |
152 | */ | |
153 | ||
154 | c->num_printers --; | |
155 | if (i < c->num_printers) | |
217fb8a7 | 156 | memmove(c->printers + i, c->printers + i + 1, |
589eb420 | 157 | (c->num_printers - i) * sizeof(cupsd_printer_t *)); |
cbbfcc63 | 158 | } |
217fb8a7 | 159 | else |
160 | return; | |
cbbfcc63 | 161 | |
162 | /* | |
c1511ac0 | 163 | * Recompute the printer type mask as needed... |
cbbfcc63 | 164 | */ |
165 | ||
c1511ac0 | 166 | if (c->num_printers > 0) |
cbbfcc63 | 167 | { |
c1511ac0 | 168 | type = c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT); |
169 | c->type = ~CUPS_PRINTER_REMOTE; | |
cbbfcc63 | 170 | |
c1511ac0 | 171 | for (i = 0; i < c->num_printers; i ++) |
172 | c->type &= c->printers[i]->type; | |
cbbfcc63 | 173 | |
c1511ac0 | 174 | c->type |= type; |
cbbfcc63 | 175 | |
c1511ac0 | 176 | /* |
177 | * Update the IPP attributes... | |
178 | */ | |
cbbfcc63 | 179 | |
589eb420 | 180 | cupsdSetPrinterAttrs(c); |
c1511ac0 | 181 | } |
a9de544f | 182 | } |
183 | ||
184 | ||
cbbfcc63 | 185 | /* |
589eb420 | 186 | * 'cupsdDeletePrinterFromClasses()' - Delete a printer from all classes. |
cbbfcc63 | 187 | */ |
188 | ||
a9de544f | 189 | void |
589eb420 | 190 | cupsdDeletePrinterFromClasses(cupsd_printer_t *p) /* I - Printer to delete */ |
a9de544f | 191 | { |
589eb420 | 192 | cupsd_printer_t *c; /* Pointer to current class */ |
cbbfcc63 | 193 | |
194 | ||
195 | /* | |
196 | * Loop through the printer/class list and remove the printer | |
197 | * from each class listed... | |
198 | */ | |
199 | ||
589eb420 | 200 | for (c = (cupsd_printer_t *)cupsArrayFirst(Printers); |
90231631 | 201 | c; |
589eb420 | 202 | c = (cupsd_printer_t *)cupsArrayNext(Printers)) |
8d853fdf | 203 | if (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) |
589eb420 | 204 | cupsdDeletePrinterFromClass(c, p); |
c1511ac0 | 205 | |
206 | /* | |
90d20520 | 207 | * Then clean out any empty implicit classes... |
c1511ac0 | 208 | */ |
209 | ||
589eb420 | 210 | for (c = (cupsd_printer_t *)cupsArrayFirst(Printers); |
90231631 | 211 | c; |
589eb420 | 212 | c = (cupsd_printer_t *)cupsArrayNext(Printers)) |
90d20520 | 213 | if ((c->type & CUPS_PRINTER_IMPLICIT) && c->num_printers == 0) |
589eb420 | 214 | cupsdDeletePrinter(c, 0); |
a9de544f | 215 | } |
216 | ||
217 | ||
cbbfcc63 | 218 | /* |
589eb420 | 219 | * 'cupsdDeleteAllClasses()' - Remove all classes from the system. |
cbbfcc63 | 220 | */ |
221 | ||
a9de544f | 222 | void |
589eb420 | 223 | cupsdDeleteAllClasses(void) |
a9de544f | 224 | { |
589eb420 | 225 | cupsd_printer_t *c; /* Pointer to current printer/class */ |
cbbfcc63 | 226 | |
227 | ||
589eb420 | 228 | for (c = (cupsd_printer_t *)cupsArrayFirst(Printers); |
90231631 | 229 | c; |
589eb420 | 230 | c = (cupsd_printer_t *)cupsArrayNext(Printers)) |
cbbfcc63 | 231 | if (c->type & CUPS_PRINTER_CLASS) |
589eb420 | 232 | cupsdDeletePrinter(c, 0); |
a9de544f | 233 | } |
234 | ||
235 | ||
cbbfcc63 | 236 | /* |
589eb420 | 237 | * 'cupsdFindAvailablePrinter()' - Find an available printer in a class. |
cbbfcc63 | 238 | */ |
239 | ||
589eb420 | 240 | cupsd_printer_t * /* O - Available printer or NULL */ |
241 | cupsdFindAvailablePrinter(const char *name) /* I - Class to check */ | |
a9de544f | 242 | { |
cbbfcc63 | 243 | int i; /* Looping var */ |
589eb420 | 244 | cupsd_printer_t *c; /* Printer class */ |
cbbfcc63 | 245 | |
246 | ||
247 | /* | |
248 | * Find the class... | |
249 | */ | |
250 | ||
589eb420 | 251 | if ((c = cupsdFindClass(name)) == NULL) |
4f954c4e | 252 | { |
589eb420 | 253 | cupsdLogMessage(L_ERROR, "Unable to find class \"%s\"!", name); |
cbbfcc63 | 254 | return (NULL); |
4f954c4e | 255 | } |
cbbfcc63 | 256 | |
257 | /* | |
258 | * Loop through the printers in the class and return the first idle | |
21eb8c86 | 259 | * printer... We keep track of the last printer that we used so that |
260 | * a "round robin" type of scheduling is realized (otherwise the first | |
261 | * server might be saturated with print jobs...) | |
5c9f9fef | 262 | * |
263 | * Thanks to Joel Fredrikson for helping us get this right! | |
cbbfcc63 | 264 | */ |
265 | ||
5c9f9fef | 266 | for (i = c->last_printer + 1; ; i ++) |
21eb8c86 | 267 | { |
5c9f9fef | 268 | if (i >= c->num_printers) |
269 | i = 0; | |
270 | ||
9b13336b | 271 | if (c->printers[i]->accepting && |
272 | (c->printers[i]->state == IPP_PRINTER_IDLE || | |
273 | ((c->printers[i]->type & CUPS_PRINTER_REMOTE) && !c->printers[i]->job))) | |
21eb8c86 | 274 | { |
275 | c->last_printer = i; | |
cbbfcc63 | 276 | return (c->printers[i]); |
21eb8c86 | 277 | } |
35a2ba9d | 278 | |
5c9f9fef | 279 | if (i == c->last_printer) |
35a2ba9d | 280 | break; |
21eb8c86 | 281 | } |
cbbfcc63 | 282 | |
a9de544f | 283 | return (NULL); |
284 | } | |
285 | ||
286 | ||
cbbfcc63 | 287 | /* |
589eb420 | 288 | * 'cupsdFindClass()' - Find the named class. |
cbbfcc63 | 289 | */ |
290 | ||
589eb420 | 291 | cupsd_printer_t * /* O - Matching class or NULL */ |
292 | cupsdFindClass(const char *name) /* I - Name of class */ | |
a9de544f | 293 | { |
589eb420 | 294 | cupsd_printer_t *c; /* Current class/printer */ |
cbbfcc63 | 295 | |
cbbfcc63 | 296 | |
589eb420 | 297 | if ((c = cupsdFindDest(name)) != NULL && !(c->type & CUPS_PRINTER_CLASS)) |
90231631 | 298 | return (NULL); |
299 | else | |
300 | return (c); | |
a9de544f | 301 | } |
302 | ||
303 | ||
cbbfcc63 | 304 | /* |
589eb420 | 305 | * 'cupsdLoadAllClasses()' - Load classes from the classes.conf file. |
cbbfcc63 | 306 | */ |
307 | ||
a9de544f | 308 | void |
589eb420 | 309 | cupsdLoadAllClasses(void) |
a9de544f | 310 | { |
7b0fde61 | 311 | cups_file_t *fp; /* classes.conf file */ |
cbbfcc63 | 312 | int linenum; /* Current line number */ |
03081fd2 | 313 | char line[1024], /* Line from file */ |
aba2fa7e | 314 | *value, /* Pointer to value */ |
315 | *valueptr; /* Pointer into value */ | |
589eb420 | 316 | cupsd_printer_t *p, /* Current printer class */ |
cbbfcc63 | 317 | *temp; /* Temporary pointer to printer */ |
318 | ||
319 | ||
320 | /* | |
cc0561c6 | 321 | * Open the classes.conf file... |
cbbfcc63 | 322 | */ |
323 | ||
a6988fb1 | 324 | snprintf(line, sizeof(line), "%s/classes.conf", ServerRoot); |
7b0fde61 | 325 | if ((fp = cupsFileOpen(line, "r")) == NULL) |
d47f8ebe | 326 | { |
589eb420 | 327 | cupsdLogMessage(L_ERROR, "cupsdLoadAllClasses: Unable to open %s - %s", line, |
d47f8ebe | 328 | strerror(errno)); |
cbbfcc63 | 329 | return; |
d47f8ebe | 330 | } |
cbbfcc63 | 331 | |
332 | /* | |
cc0561c6 | 333 | * Read class configurations until we hit EOF... |
cbbfcc63 | 334 | */ |
335 | ||
336 | linenum = 0; | |
337 | p = NULL; | |
338 | ||
4a1c4581 | 339 | while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) |
cbbfcc63 | 340 | { |
cbbfcc63 | 341 | /* |
342 | * Decode the directive... | |
343 | */ | |
344 | ||
90d20520 | 345 | if (!strcasecmp(line, "<Class") || |
346 | !strcasecmp(line, "<DefaultClass")) | |
cbbfcc63 | 347 | { |
348 | /* | |
349 | * <Class name> or <DefaultClass name> | |
350 | */ | |
351 | ||
4a1c4581 | 352 | if (p == NULL && value) |
cbbfcc63 | 353 | { |
589eb420 | 354 | cupsdLogMessage(L_DEBUG, "cupsdLoadAllClasses: Loading class %s...", value); |
d47f8ebe | 355 | |
589eb420 | 356 | p = cupsdAddClass(value); |
4139b718 | 357 | p->accepting = 1; |
358 | p->state = IPP_PRINTER_IDLE; | |
cbbfcc63 | 359 | |
90d20520 | 360 | if (!strcasecmp(line, "<DefaultClass")) |
cbbfcc63 | 361 | DefaultPrinter = p; |
362 | } | |
363 | else | |
364 | { | |
589eb420 | 365 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
cbbfcc63 | 366 | linenum); |
367 | return; | |
368 | } | |
369 | } | |
90d20520 | 370 | else if (!strcasecmp(line, "</Class>")) |
cbbfcc63 | 371 | { |
372 | if (p != NULL) | |
373 | { | |
589eb420 | 374 | cupsdSetPrinterAttrs(p); |
cbbfcc63 | 375 | p = NULL; |
376 | } | |
377 | else | |
378 | { | |
589eb420 | 379 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
cbbfcc63 | 380 | linenum); |
381 | return; | |
382 | } | |
383 | } | |
a4b3db80 | 384 | else if (!p) |
cbbfcc63 | 385 | { |
589eb420 | 386 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
cbbfcc63 | 387 | linenum); |
388 | return; | |
389 | } | |
90d20520 | 390 | else if (!strcasecmp(line, "Info")) |
a4b3db80 | 391 | { |
392 | if (value) | |
589eb420 | 393 | cupsdSetString(&p->info, value); |
a4b3db80 | 394 | } |
90d20520 | 395 | else if (!strcasecmp(line, "Location")) |
a4b3db80 | 396 | { |
397 | if (value) | |
589eb420 | 398 | cupsdSetString(&p->location, value); |
a4b3db80 | 399 | } |
90d20520 | 400 | else if (!strcasecmp(line, "Printer")) |
cbbfcc63 | 401 | { |
a4b3db80 | 402 | if (!value) |
403 | { | |
589eb420 | 404 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 405 | linenum); |
406 | return; | |
407 | } | |
589eb420 | 408 | else if ((temp = cupsdFindPrinter(value)) == NULL) |
36992080 | 409 | { |
589eb420 | 410 | cupsdLogMessage(L_WARN, "Unknown printer %s on line %d of classes.conf.", |
cbbfcc63 | 411 | value, linenum); |
36992080 | 412 | |
413 | /* | |
414 | * Add the missing remote printer... | |
415 | */ | |
416 | ||
589eb420 | 417 | if ((temp = cupsdAddPrinter(value)) != NULL) |
36564e2c | 418 | { |
589eb420 | 419 | cupsdSetString(&temp->make_model, "Remote Printer on unknown"); |
36992080 | 420 | |
36564e2c | 421 | temp->state = IPP_PRINTER_STOPPED; |
422 | temp->type |= CUPS_PRINTER_REMOTE; | |
423 | temp->browse_time = 2147483647; | |
36992080 | 424 | |
589eb420 | 425 | cupsdSetString(&temp->location, "Location Unknown"); |
426 | cupsdSetString(&temp->info, "No Information Available"); | |
36564e2c | 427 | temp->hostname[0] = '\0'; |
36992080 | 428 | |
589eb420 | 429 | cupsdSetPrinterAttrs(temp); |
36564e2c | 430 | } |
36992080 | 431 | } |
432 | ||
433 | if (temp) | |
589eb420 | 434 | cupsdAddPrinterToClass(p, temp); |
cbbfcc63 | 435 | } |
90d20520 | 436 | else if (!strcasecmp(line, "State")) |
cbbfcc63 | 437 | { |
438 | /* | |
439 | * Set the initial queue state... | |
440 | */ | |
441 | ||
b2e10895 | 442 | if (!strcasecmp(value, "idle")) |
cbbfcc63 | 443 | p->state = IPP_PRINTER_IDLE; |
b2e10895 | 444 | else if (!strcasecmp(value, "stopped")) |
cbbfcc63 | 445 | p->state = IPP_PRINTER_STOPPED; |
a4b3db80 | 446 | else |
447 | { | |
589eb420 | 448 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 449 | linenum); |
450 | return; | |
451 | } | |
05e63c18 | 452 | } |
90d20520 | 453 | else if (!strcasecmp(line, "StateMessage")) |
03081fd2 | 454 | { |
455 | /* | |
456 | * Set the initial queue state message... | |
457 | */ | |
458 | ||
a4b3db80 | 459 | if (value) |
460 | strlcpy(p->state_message, value, sizeof(p->state_message)); | |
03081fd2 | 461 | } |
90d20520 | 462 | else if (!strcasecmp(line, "Accepting")) |
05e63c18 | 463 | { |
464 | /* | |
465 | * Set the initial accepting state... | |
466 | */ | |
467 | ||
a4b3db80 | 468 | if (value && |
469 | (!strcasecmp(value, "yes") || | |
470 | !strcasecmp(value, "on") || | |
471 | !strcasecmp(value, "true"))) | |
05e63c18 | 472 | p->accepting = 1; |
a4b3db80 | 473 | else if (value && |
474 | (!strcasecmp(value, "no") || | |
475 | !strcasecmp(value, "off") || | |
476 | !strcasecmp(value, "false"))) | |
05e63c18 | 477 | p->accepting = 0; |
a4b3db80 | 478 | else |
479 | { | |
589eb420 | 480 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 481 | linenum); |
482 | return; | |
483 | } | |
05e63c18 | 484 | } |
25392f52 | 485 | else if (!strcasecmp(line, "Shared")) |
486 | { | |
487 | /* | |
488 | * Set the initial shared state... | |
489 | */ | |
490 | ||
491 | if (value && | |
492 | (!strcasecmp(value, "yes") || | |
493 | !strcasecmp(value, "on") || | |
494 | !strcasecmp(value, "true"))) | |
495 | p->shared = 1; | |
496 | else if (value && | |
497 | (!strcasecmp(value, "no") || | |
498 | !strcasecmp(value, "off") || | |
499 | !strcasecmp(value, "false"))) | |
500 | p->shared = 0; | |
501 | else | |
502 | { | |
589eb420 | 503 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of printers.conf.", |
25392f52 | 504 | linenum); |
505 | return; | |
506 | } | |
507 | } | |
90d20520 | 508 | else if (!strcasecmp(line, "JobSheets")) |
aba2fa7e | 509 | { |
510 | /* | |
511 | * Set the initial job sheets... | |
512 | */ | |
513 | ||
a4b3db80 | 514 | if (value) |
515 | { | |
516 | for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++); | |
aba2fa7e | 517 | |
a4b3db80 | 518 | if (*valueptr) |
519 | *valueptr++ = '\0'; | |
aba2fa7e | 520 | |
589eb420 | 521 | cupsdSetString(&p->cupsd_job_sheets[0], value); |
aba2fa7e | 522 | |
a4b3db80 | 523 | while (isspace(*valueptr & 255)) |
524 | valueptr ++; | |
aba2fa7e | 525 | |
526 | if (*valueptr) | |
a4b3db80 | 527 | { |
528 | for (value = valueptr; *valueptr && !isspace(*valueptr & 255); valueptr ++); | |
529 | ||
530 | if (*valueptr) | |
531 | *valueptr++ = '\0'; | |
aba2fa7e | 532 | |
589eb420 | 533 | cupsdSetString(&p->cupsd_job_sheets[1], value); |
a4b3db80 | 534 | } |
535 | } | |
536 | else | |
537 | { | |
589eb420 | 538 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 539 | linenum); |
540 | return; | |
aba2fa7e | 541 | } |
542 | } | |
90d20520 | 543 | else if (!strcasecmp(line, "AllowUser")) |
d7845573 | 544 | { |
a4b3db80 | 545 | if (value) |
546 | { | |
547 | p->deny_users = 0; | |
589eb420 | 548 | cupsdAddPrinterUser(p, value); |
a4b3db80 | 549 | } |
550 | else | |
551 | { | |
589eb420 | 552 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 553 | linenum); |
554 | return; | |
555 | } | |
d7845573 | 556 | } |
90d20520 | 557 | else if (!strcasecmp(line, "DenyUser")) |
d7845573 | 558 | { |
a4b3db80 | 559 | if (value) |
560 | { | |
561 | p->deny_users = 1; | |
589eb420 | 562 | cupsdAddPrinterUser(p, value); |
a4b3db80 | 563 | } |
564 | else | |
565 | { | |
589eb420 | 566 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 567 | linenum); |
568 | return; | |
569 | } | |
d7845573 | 570 | } |
90d20520 | 571 | else if (!strcasecmp(line, "QuotaPeriod")) |
a4b3db80 | 572 | { |
573 | if (value) | |
574 | p->quota_period = atoi(value); | |
575 | else | |
576 | { | |
589eb420 | 577 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 578 | linenum); |
579 | return; | |
580 | } | |
581 | } | |
90d20520 | 582 | else if (!strcasecmp(line, "PageLimit")) |
a4b3db80 | 583 | { |
584 | if (value) | |
585 | p->page_limit = atoi(value); | |
586 | else | |
587 | { | |
589eb420 | 588 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 589 | linenum); |
590 | return; | |
591 | } | |
592 | } | |
90d20520 | 593 | else if (!strcasecmp(line, "KLimit")) |
a4b3db80 | 594 | { |
595 | if (value) | |
596 | p->k_limit = atoi(value); | |
597 | else | |
598 | { | |
589eb420 | 599 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 600 | linenum); |
601 | return; | |
602 | } | |
603 | } | |
90d20520 | 604 | else if (!strcasecmp(line, "OpPolicy")) |
a4b3db80 | 605 | { |
606 | if (value) | |
589eb420 | 607 | cupsdSetString(&p->op_policy, value); |
a4b3db80 | 608 | else |
609 | { | |
589eb420 | 610 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 611 | linenum); |
612 | return; | |
613 | } | |
614 | } | |
90d20520 | 615 | else if (!strcasecmp(line, "ErrorPolicy")) |
a4b3db80 | 616 | { |
617 | if (value) | |
589eb420 | 618 | cupsdSetString(&p->error_policy, value); |
a4b3db80 | 619 | else |
620 | { | |
589eb420 | 621 | cupsdLogMessage(L_ERROR, "Syntax error on line %d of classes.conf.", |
a4b3db80 | 622 | linenum); |
623 | return; | |
624 | } | |
625 | } | |
05e63c18 | 626 | else |
627 | { | |
628 | /* | |
629 | * Something else we don't understand... | |
630 | */ | |
4139b718 | 631 | |
589eb420 | 632 | cupsdLogMessage(L_ERROR, "Unknown configuration directive %s on line %d of classes.conf.", |
90d20520 | 633 | line, linenum); |
cbbfcc63 | 634 | } |
635 | } | |
636 | ||
7b0fde61 | 637 | cupsFileClose(fp); |
a9de544f | 638 | } |
639 | ||
640 | ||
cbbfcc63 | 641 | /* |
589eb420 | 642 | * 'cupsdSaveAllClasses()' - Save classes to the classes.conf file. |
cbbfcc63 | 643 | */ |
644 | ||
a9de544f | 645 | void |
589eb420 | 646 | cupsdSaveAllClasses(void) |
a9de544f | 647 | { |
7b0fde61 | 648 | cups_file_t *fp; /* classes.conf file */ |
cc0561c6 | 649 | char temp[1024]; /* Temporary string */ |
b2e10895 | 650 | char backup[1024]; /* classes.conf.O file */ |
589eb420 | 651 | cupsd_printer_t *pclass; /* Current printer class */ |
cc0561c6 | 652 | int i; /* Looping var */ |
653 | time_t curtime; /* Current time */ | |
654 | struct tm *curdate; /* Current date */ | |
655 | ||
656 | ||
657 | /* | |
658 | * Create the classes.conf file... | |
659 | */ | |
660 | ||
a6988fb1 | 661 | snprintf(temp, sizeof(temp), "%s/classes.conf", ServerRoot); |
b2e10895 | 662 | snprintf(backup, sizeof(backup), "%s/classes.conf.O", ServerRoot); |
663 | ||
664 | if (rename(temp, backup)) | |
589eb420 | 665 | cupsdLogMessage(L_ERROR, "Unable to backup classes.conf - %s", strerror(errno)); |
b2e10895 | 666 | |
7b0fde61 | 667 | if ((fp = cupsFileOpen(temp, "w")) == NULL) |
cc0561c6 | 668 | { |
589eb420 | 669 | cupsdLogMessage(L_ERROR, "Unable to save classes.conf - %s", strerror(errno)); |
b2e10895 | 670 | |
671 | if (rename(backup, temp)) | |
589eb420 | 672 | cupsdLogMessage(L_ERROR, "Unable to restore classes.conf - %s", strerror(errno)); |
cc0561c6 | 673 | return; |
674 | } | |
675 | else | |
589eb420 | 676 | cupsdLogMessage(L_INFO, "Saving classes.conf..."); |
cc0561c6 | 677 | |
35a2ba9d | 678 | /* |
679 | * Restrict access to the file... | |
680 | */ | |
681 | ||
48033118 | 682 | fchown(cupsFileNumber(fp), RunUser, Group); |
d59a189c | 683 | fchmod(cupsFileNumber(fp), ConfigFilePerm); |
35a2ba9d | 684 | |
cc0561c6 | 685 | /* |
686 | * Write a small header to the file... | |
687 | */ | |
688 | ||
689 | curtime = time(NULL); | |
aa3b74e1 | 690 | curdate = localtime(&curtime); |
03f61bf3 | 691 | strftime(temp, sizeof(temp) - 1, "%c", curdate); |
cc0561c6 | 692 | |
7b0fde61 | 693 | cupsFilePuts(fp, "# Class configuration file for " CUPS_SVERSION "\n"); |
694 | cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); | |
cc0561c6 | 695 | |
82306f04 | 696 | /* |
697 | * Write each local class known to the system... | |
698 | */ | |
699 | ||
589eb420 | 700 | for (pclass = (cupsd_printer_t *)cupsArrayFirst(Printers); |
82306f04 | 701 | pclass; |
589eb420 | 702 | pclass = (cupsd_printer_t *)cupsArrayNext(Printers)) |
cc0561c6 | 703 | { |
704 | /* | |
82306f04 | 705 | * Skip remote destinations and regular printers... |
cc0561c6 | 706 | */ |
707 | ||
82306f04 | 708 | if ((pclass->type & CUPS_PRINTER_REMOTE) || |
709 | (pclass->type & CUPS_PRINTER_IMPLICIT) || | |
710 | !(pclass->type & CUPS_PRINTER_CLASS)) | |
711 | continue; | |
cc0561c6 | 712 | |
82306f04 | 713 | /* |
714 | * Write printers as needed... | |
715 | */ | |
cc0561c6 | 716 | |
82306f04 | 717 | if (pclass == DefaultPrinter) |
718 | cupsFilePrintf(fp, "<DefaultClass %s>\n", pclass->name); | |
719 | else | |
720 | cupsFilePrintf(fp, "<Class %s>\n", pclass->name); | |
753453e4 | 721 | |
82306f04 | 722 | if (pclass->info) |
723 | cupsFilePrintf(fp, "Info %s\n", pclass->info); | |
753453e4 | 724 | |
82306f04 | 725 | if (pclass->location) |
726 | cupsFilePrintf(fp, "Location %s\n", pclass->location); | |
753453e4 | 727 | |
82306f04 | 728 | if (pclass->state == IPP_PRINTER_STOPPED) |
729 | { | |
730 | cupsFilePuts(fp, "State Stopped\n"); | |
731 | cupsFilePrintf(fp, "StateMessage %s\n", pclass->state_message); | |
732 | } | |
733 | else | |
734 | cupsFilePuts(fp, "State Idle\n"); | |
cc0561c6 | 735 | |
82306f04 | 736 | if (pclass->accepting) |
737 | cupsFilePuts(fp, "Accepting Yes\n"); | |
738 | else | |
739 | cupsFilePuts(fp, "Accepting No\n"); | |
90231631 | 740 | |
82306f04 | 741 | if (pclass->shared) |
742 | cupsFilePuts(fp, "Shared Yes\n"); | |
743 | else | |
744 | cupsFilePuts(fp, "Shared No\n"); | |
25392f52 | 745 | |
589eb420 | 746 | cupsFilePrintf(fp, "JobSheets %s %s\n", pclass->cupsd_job_sheets[0], |
747 | pclass->cupsd_job_sheets[1]); | |
b2e10895 | 748 | |
82306f04 | 749 | for (i = 0; i < pclass->num_printers; i ++) |
750 | cupsFilePrintf(fp, "Printer %s\n", pclass->printers[i]->name); | |
cc0561c6 | 751 | |
82306f04 | 752 | cupsFilePrintf(fp, "QuotaPeriod %d\n", pclass->quota_period); |
753 | cupsFilePrintf(fp, "PageLimit %d\n", pclass->page_limit); | |
754 | cupsFilePrintf(fp, "KLimit %d\n", pclass->k_limit); | |
d7845573 | 755 | |
82306f04 | 756 | for (i = 0; i < pclass->num_users; i ++) |
757 | cupsFilePrintf(fp, "%sUser %s\n", pclass->deny_users ? "Deny" : "Allow", | |
758 | pclass->users[i]); | |
d7845573 | 759 | |
82306f04 | 760 | if (pclass->op_policy) |
761 | cupsFilePrintf(fp, "OpPolicy %s\n", pclass->op_policy); | |
762 | if (pclass->error_policy) | |
763 | cupsFilePrintf(fp, "ErrorPolicy %s\n", pclass->error_policy); | |
e175d98d | 764 | |
82306f04 | 765 | cupsFilePuts(fp, "</Class>\n"); |
cc0561c6 | 766 | } |
767 | ||
7b0fde61 | 768 | cupsFileClose(fp); |
a9de544f | 769 | } |
770 | ||
771 | ||
a129ddbd | 772 | /* |
589eb420 | 773 | * 'cupsdUpdateImplicitClasses()' - Update the accepting state of implicit classes. |
a4f3d51c | 774 | */ |
775 | ||
776 | void | |
589eb420 | 777 | cupsdUpdateImplicitClasses(void) |
a4f3d51c | 778 | { |
779 | int i; /* Looping var */ | |
589eb420 | 780 | cupsd_printer_t *pclass; /* Current class */ |
a4f3d51c | 781 | int accepting; /* printer-is-accepting-jobs value */ |
782 | ||
783 | ||
589eb420 | 784 | for (pclass = (cupsd_printer_t *)cupsArrayFirst(Printers); |
90231631 | 785 | pclass; |
589eb420 | 786 | pclass = (cupsd_printer_t *)cupsArrayNext(Printers)) |
a4f3d51c | 787 | if (pclass->type & CUPS_PRINTER_IMPLICIT) |
788 | { | |
789 | /* | |
790 | * Implicit class, loop through the printers to come up with a | |
791 | * composite state... | |
792 | */ | |
793 | ||
794 | for (i = 0, accepting = 0; i < pclass->num_printers; i ++) | |
795 | if ((accepting |= pclass->printers[i]->accepting) != 0) | |
796 | break; | |
797 | ||
798 | pclass->accepting = accepting; | |
799 | } | |
800 | } | |
801 | ||
802 | ||
803 | /* | |
b2e10895 | 804 | * End of "$Id$". |
a129ddbd | 805 | */ |