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