]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/classes.c
f0c27efd65652416c7e4cdbe0c55da184d3873c2
2 * "$Id: classes.c,v 1.41 2002/01/02 17:59:14 mike Exp $"
4 * Printer class routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2002 by Easy Software Products, all rights reserved.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * AddClass() - Add a class to the system.
27 * AddPrinterToClass() - Add a printer to a class...
28 * DeletePrinterFromClass() - Delete a printer from a class.
29 * DeletePrinterFromClasses() - Delete a printer from all classes.
30 * DeleteAllClasses() - Remove all classes from the system.
31 * FindAvailablePrinter() - Find an available printer in a class.
32 * FindClass() - Find the named class.
33 * LoadAllClasses() - Load classes from the classes.conf file.
34 * SaveAllClasses() - Save classes to the classes.conf file.
38 * Include necessary headers...
45 * 'AddClass()' - Add a class to the system.
48 printer_t
* /* O - New class */
49 AddClass(const char *name
) /* I - Name of class */
51 printer_t
*c
; /* New class */
55 * Add the printer and set the type to "class"...
58 if ((c
= AddPrinter(name
)) != NULL
)
61 * Change from a printer to a class...
64 c
->type
= CUPS_PRINTER_CLASS
;
65 snprintf(c
->uri
, sizeof(c
->uri
), "ipp://%s:%d/classes/%s", ServerName
,
66 ntohs(Listeners
[0].address
.sin_port
), name
);
69 * Set the printer attributes to make this a class.
80 * 'AddPrinterToClass()' - Add a printer to a class...
84 AddPrinterToClass(printer_t
*c
, /* I - Class to add to */
85 printer_t
*p
) /* I - Printer to add */
87 int i
; /* Looping var */
88 printer_t
**temp
; /* Pointer to printer array */
92 * See if this printer is already a member of the class...
95 for (i
= 0; i
< c
->num_printers
; i
++)
96 if (c
->printers
[i
] == p
)
100 * Allocate memory as needed...
103 if (c
->num_printers
== 0)
104 temp
= malloc(sizeof(printer_t
*));
106 temp
= realloc(c
->printers
, sizeof(printer_t
*) * (c
->num_printers
+ 1));
110 LogMessage(L_ERROR
, "Unable to add printer %s to class %s!",
116 * Add the printer to the end of the array and update the number of printers.
120 temp
+= c
->num_printers
;
126 * Update the IPP attributes...
134 * 'DeletePrinterFromClass()' - Delete a printer from a class.
138 DeletePrinterFromClass(printer_t
*c
, /* I - Class to delete from */
139 printer_t
*p
) /* I - Printer to delete */
141 int i
; /* Looping var */
142 cups_ptype_t type
; /* Class type */
146 * See if the printer is in the class...
149 for (i
= 0; i
< c
->num_printers
; i
++)
150 if (p
== c
->printers
[i
])
154 * If it is, remove it from the list...
157 if (i
< c
->num_printers
)
160 * Yes, remove the printer...
164 if (i
< c
->num_printers
)
165 memcpy(c
->printers
+ i
, c
->printers
+ i
+ 1,
166 (c
->num_printers
- i
) * sizeof(printer_t
*));
170 * Recompute the printer type mask as needed...
173 if (c
->num_printers
> 0)
175 type
= c
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
);
176 c
->type
= ~CUPS_PRINTER_REMOTE
;
178 for (i
= 0; i
< c
->num_printers
; i
++)
179 c
->type
&= c
->printers
[i
]->type
;
184 * Update the IPP attributes...
193 * 'DeletePrinterFromClasses()' - Delete a printer from all classes.
197 DeletePrinterFromClasses(printer_t
*p
) /* I - Printer to delete */
199 printer_t
*c
, /* Pointer to current class */
200 *next
; /* Pointer to next class */
204 * Loop through the printer/class list and remove the printer
205 * from each class listed...
208 for (c
= Printers
; c
!= NULL
; c
= next
)
212 if (c
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
213 DeletePrinterFromClass(c
, p
);
217 * Then clean out any empty classes...
220 for (c
= Printers
; c
!= NULL
; c
= next
)
224 if ((c
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
)) &&
225 c
->num_printers
== 0)
232 * 'DeleteAllClasses()' - Remove all classes from the system.
236 DeleteAllClasses(void)
238 printer_t
*c
, /* Pointer to current printer/class */
239 *next
; /* Pointer to next printer in list */
242 for (c
= Printers
; c
!= NULL
; c
= next
)
246 if (c
->type
& CUPS_PRINTER_CLASS
)
253 * 'FindAvailablePrinter()' - Find an available printer in a class.
256 printer_t
* /* O - Available printer or NULL */
257 FindAvailablePrinter(const char *name
) /* I - Class to check */
259 int i
; /* Looping var */
260 printer_t
*c
; /* Printer class */
267 if ((c
= FindClass(name
)) == NULL
)
269 LogMessage(L_ERROR
, "Unable to find class \"%s\"!", name
);
274 * Loop through the printers in the class and return the first idle
275 * printer... We keep track of the last printer that we used so that
276 * a "round robin" type of scheduling is realized (otherwise the first
277 * server might be saturated with print jobs...)
279 * Thanks to Joel Fredrikson for helping us get this right!
282 for (i
= c
->last_printer
+ 1; ; i
++)
284 if (i
>= c
->num_printers
)
287 if (c
->printers
[i
]->state
== IPP_PRINTER_IDLE
||
288 ((c
->printers
[i
]->type
& CUPS_PRINTER_REMOTE
) && !c
->printers
[i
]->job
))
291 return (c
->printers
[i
]);
294 if (i
== c
->last_printer
)
303 * 'FindClass()' - Find the named class.
306 printer_t
* /* O - Matching class or NULL */
307 FindClass(const char *name
) /* I - Name of class */
309 printer_t
*c
; /* Current class/printer */
312 for (c
= Printers
; c
!= NULL
; c
= c
->next
)
313 switch (strcasecmp(name
, c
->name
))
315 case 0 : /* name == c->name */
316 if (c
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
318 case 1 : /* name > c->name */
320 case -1 : /* name < c->name */
329 * 'LoadAllClasses()' - Load classes from the classes.conf file.
335 FILE *fp
; /* classes.conf file */
336 int linenum
; /* Current line number */
337 int len
; /* Length of line */
338 char line
[1024], /* Line from file */
339 name
[256], /* Parameter name */
340 *nameptr
, /* Pointer into name */
341 *value
, /* Pointer to value */
342 *valueptr
; /* Pointer into value */
343 printer_t
*p
, /* Current printer class */
344 *temp
; /* Temporary pointer to printer */
348 * Open the classes.conf file...
351 snprintf(line
, sizeof(line
), "%s/classes.conf", ServerRoot
);
352 if ((fp
= fopen(line
, "r")) == NULL
)
356 * Read class configurations until we hit EOF...
362 while (fgets(line
, sizeof(line
), fp
) != NULL
)
367 * Skip comment lines...
374 * Strip trailing whitespace, if any...
379 while (len
> 0 && isspace(line
[len
- 1]))
386 * Extract the name from the beginning of the line...
389 for (value
= line
; isspace(*value
); value
++);
391 for (nameptr
= name
; *value
!= '\0' && !isspace(*value
) &&
392 nameptr
< (name
+ sizeof(name
) - 1);)
393 *nameptr
++ = *value
++;
396 while (isspace(*value
))
403 * Decode the directive...
406 if (strcmp(name
, "<Class") == 0 ||
407 strcmp(name
, "<DefaultClass") == 0)
410 * <Class name> or <DefaultClass name>
413 if (line
[len
- 1] == '>' && p
== NULL
)
415 line
[len
- 1] = '\0';
419 p
->state
= IPP_PRINTER_IDLE
;
421 if (strcmp(name
, "<DefaultClass") == 0)
426 LogMessage(L_ERROR
, "Syntax error on line %d of classes.conf.",
431 else if (strcmp(name
, "</Class>") == 0)
440 LogMessage(L_ERROR
, "Syntax error on line %d of classes.conf.",
447 LogMessage(L_ERROR
, "Syntax error on line %d of classes.conf.",
452 else if (strcmp(name
, "Info") == 0)
453 strncpy(p
->info
, value
, sizeof(p
->info
) - 1);
454 else if (strcmp(name
, "Location") == 0)
455 strncpy(p
->location
, value
, sizeof(p
->location
) - 1);
456 else if (strcmp(name
, "Printer") == 0)
458 if ((temp
= FindPrinter(value
)) == NULL
)
460 LogMessage(L_WARN
, "Unknown printer %s on line %d of classes.conf.",
464 * Add the missing remote printer...
467 temp
= AddPrinter(value
);
468 strcpy(temp
->make_model
, "Remote Printer on unknown");
470 temp
->state
= IPP_PRINTER_STOPPED
;
471 temp
->type
|= CUPS_PRINTER_REMOTE
;
472 temp
->browse_time
= 2147483647;
474 strcpy(temp
->location
, "Location Unknown");
475 strcpy(temp
->info
, "No Information Available");
476 temp
->hostname
[0] = '\0';
478 SetPrinterAttrs(temp
);
482 AddPrinterToClass(p
, temp
);
484 else if (strcmp(name
, "State") == 0)
487 * Set the initial queue state...
490 if (strcasecmp(value
, "idle") == 0)
491 p
->state
= IPP_PRINTER_IDLE
;
492 else if (strcasecmp(value
, "stopped") == 0)
493 p
->state
= IPP_PRINTER_STOPPED
;
495 else if (strcmp(name
, "StateMessage") == 0)
498 * Set the initial queue state message...
501 while (isspace(*value
))
504 strncpy(p
->state_message
, value
, sizeof(p
->state_message
) - 1);
506 else if (strcmp(name
, "Accepting") == 0)
509 * Set the initial accepting state...
512 if (strcasecmp(value
, "yes") == 0)
517 else if (strcmp(name
, "JobSheets") == 0)
520 * Set the initial job sheets...
523 for (valueptr
= value
; *valueptr
&& !isspace(*valueptr
); valueptr
++);
528 strncpy(p
->job_sheets
[0], value
, sizeof(p
->job_sheets
[0]) - 1);
530 while (isspace(*valueptr
))
535 for (value
= valueptr
; *valueptr
&& !isspace(*valueptr
); valueptr
++);
540 strncpy(p
->job_sheets
[1], value
, sizeof(p
->job_sheets
[1]) - 1);
543 else if (strcmp(name
, "AllowUser") == 0)
546 AddPrinterUser(p
, value
);
548 else if (strcmp(name
, "DenyUser") == 0)
551 AddPrinterUser(p
, value
);
553 else if (strcmp(name
, "QuotaPeriod") == 0)
554 p
->quota_period
= atoi(value
);
555 else if (strcmp(name
, "PageLimit") == 0)
556 p
->page_limit
= atoi(value
);
557 else if (strcmp(name
, "KLimit") == 0)
558 p
->k_limit
= atoi(value
);
562 * Something else we don't understand...
565 LogMessage(L_ERROR
, "Unknown configuration directive %s on line %d of classes.conf.",
575 * 'SaveAllClasses()' - Save classes to the classes.conf file.
581 FILE *fp
; /* classes.conf file */
582 char temp
[1024]; /* Temporary string */
583 char backup
[1024]; /* classes.conf.O file */
584 printer_t
*pclass
; /* Current printer class */
585 int i
; /* Looping var */
586 time_t curtime
; /* Current time */
587 struct tm
*curdate
; /* Current date */
591 * Create the classes.conf file...
594 snprintf(temp
, sizeof(temp
), "%s/classes.conf", ServerRoot
);
595 snprintf(backup
, sizeof(backup
), "%s/classes.conf.O", ServerRoot
);
597 if (rename(temp
, backup
))
598 LogMessage(L_ERROR
, "Unable to backup classes.conf - %s", strerror(errno
));
600 if ((fp
= fopen(temp
, "w")) == NULL
)
602 LogMessage(L_ERROR
, "Unable to save classes.conf - %s", strerror(errno
));
604 if (rename(backup
, temp
))
605 LogMessage(L_ERROR
, "Unable to restore classes.conf - %s", strerror(errno
));
609 LogMessage(L_INFO
, "Saving classes.conf...");
612 * Restrict access to the file...
615 fchown(fileno(fp
), User
, Group
);
616 fchmod(fileno(fp
), 0600);
619 * Write a small header to the file...
622 curtime
= time(NULL
);
623 curdate
= gmtime(&curtime
);
624 strftime(temp
, sizeof(temp
) - 1, CUPS_STRFTIME_FORMAT
, curdate
);
626 fputs("# Class configuration file for " CUPS_SVERSION
"\n", fp
);
627 fprintf(fp
, "# Written by cupsd on %s\n", temp
);
630 * Write each local class known to the system...
633 for (pclass
= Printers
; pclass
!= NULL
; pclass
= pclass
->next
)
636 * Skip remote destinations and regular printers...
639 if ((pclass
->type
& CUPS_PRINTER_REMOTE
) ||
640 (pclass
->type
& CUPS_PRINTER_IMPLICIT
) ||
641 !(pclass
->type
& CUPS_PRINTER_CLASS
))
645 * Write printers as needed...
648 if (pclass
== DefaultPrinter
)
649 fprintf(fp
, "<DefaultClass %s>\n", pclass
->name
);
651 fprintf(fp
, "<Class %s>\n", pclass
->name
);
654 fprintf(fp
, "Info %s\n", pclass
->info
);
656 if (pclass
->location
[0])
657 fprintf(fp
, "Location %s\n", pclass
->location
);
659 if (pclass
->state
== IPP_PRINTER_STOPPED
)
661 fputs("State Stopped\n", fp
);
662 fprintf(fp
, "StateMessage %s\n", pclass
->state_message
);
665 fputs("State Idle\n", fp
);
667 if (pclass
->accepting
)
668 fputs("Accepting Yes\n", fp
);
670 fputs("Accepting No\n", fp
);
672 fprintf(fp
, "JobSheets %s %s\n", pclass
->job_sheets
[0],
673 pclass
->job_sheets
[1]);
675 for (i
= 0; i
< pclass
->num_printers
; i
++)
676 fprintf(fp
, "Printer %s\n", pclass
->printers
[i
]->name
);
678 fprintf(fp
, "QuotaPeriod %d\n", pclass
->quota_period
);
679 fprintf(fp
, "PageLimit %d\n", pclass
->page_limit
);
680 fprintf(fp
, "KLimit %d\n", pclass
->k_limit
);
682 for (i
= 0; i
< pclass
->num_users
; i
++)
683 fprintf(fp
, "%sUser %s\n", pclass
->deny_users
? "Deny" : "Allow",
686 fputs("</Class>\n", fp
);
694 * End of "$Id: classes.c,v 1.41 2002/01/02 17:59:14 mike Exp $".