]>
Commit | Line | Data |
---|---|---|
a129ddbd | 1 | /* |
8784b6a6 | 2 | * "$Id: printers.c,v 1.20 1999/06/18 18:36:49 mike Exp $" |
a129ddbd | 3 | * |
cbbfcc63 | 4 | * Printer routines for the Common UNIX Printing System (CUPS). |
a129ddbd | 5 | * |
a9de544f | 6 | * Copyright 1997-1999 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 |
a129ddbd | 18 | * Hollywood, Maryland 20636-3111 USA |
19 | * | |
20 | * Voice: (301) 373-9603 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
6abc7437 | 26 | * AddPrinter() - Add a printer to the system. |
27 | * DeleteAllPrinters() - Delete all printers from the system. | |
28 | * DeletePrinter() - Delete a printer from the system. | |
29 | * FindPrinter() - Find a printer in the list. | |
30 | * LoadAllPrinters() - Load printers from the printers.conf file. | |
cbbfcc63 | 31 | * SaveAllPrinters() - Save all printer definitions to the printers.conf |
32 | * SetPrinterAttrs() - Set printer attributes based upon the PPD file. | |
33 | * SetPrinterState() - Update the current state of a printer. | |
34 | * StopPrinter() - Stop a printer from printing any jobs... | |
a129ddbd | 35 | */ |
36 | ||
37 | /* | |
38 | * Include necessary headers... | |
39 | */ | |
40 | ||
fd8b1cf8 | 41 | #include "cupsd.h" |
a129ddbd | 42 | |
43 | ||
44 | /* | |
a9de544f | 45 | * 'AddPrinter()' - Add a printer to the system. |
46 | */ | |
47 | ||
48 | printer_t * /* O - New printer */ | |
49 | AddPrinter(char *name) /* I - Name of printer */ | |
50 | { | |
51 | printer_t *p, /* New printer */ | |
52 | *current, /* Current printer in list */ | |
53 | *prev; /* Previous printer in list */ | |
54 | ||
55 | ||
56 | /* | |
57 | * Range check input... | |
58 | */ | |
59 | ||
60 | if (name == NULL) | |
61 | return (NULL); | |
62 | ||
63 | /* | |
64 | * Create a new printer entity... | |
65 | */ | |
66 | ||
67 | if ((p = calloc(sizeof(printer_t), 1)) == NULL) | |
68 | return (NULL); | |
69 | ||
f3d580b9 | 70 | strcpy(p->name, name); |
71 | p->state = IPP_PRINTER_STOPPED; | |
c7fa9d06 | 72 | p->accepting = 0; |
73 | p->filetype = mimeAddType(MimeDatabase, "printer", name); | |
74 | ||
75 | /* | |
76 | * Setup required filters and IPP attributes... | |
77 | */ | |
78 | ||
cbbfcc63 | 79 | SetPrinterAttrs(p); |
a9de544f | 80 | |
81 | /* | |
82 | * Insert the printer in the printer list alphabetically... | |
83 | */ | |
84 | ||
85 | for (prev = NULL, current = Printers; | |
86 | current != NULL; | |
87 | prev = current, current = current->next) | |
f3d580b9 | 88 | if (strcasecmp(p->name, current->name) < 0) |
a9de544f | 89 | break; |
90 | ||
91 | /* | |
92 | * Insert this printer before the current one... | |
93 | */ | |
94 | ||
95 | if (prev == NULL) | |
96 | Printers = p; | |
97 | else | |
98 | prev->next = p; | |
99 | ||
100 | p->next = current; | |
101 | ||
102 | return (p); | |
103 | } | |
104 | ||
105 | ||
c7fa9d06 | 106 | /* |
107 | * 'AddPrinterFilter()' - Add a MIME filter for a printer. | |
108 | */ | |
109 | ||
110 | void | |
111 | AddPrinterFilter(printer_t *p, /* I - Printer to add to */ | |
112 | char *filter) /* I - Filter to add */ | |
113 | { | |
114 | int i; /* Looping var */ | |
115 | char super[MIME_MAX_SUPER], /* Super-type for filter */ | |
116 | type[MIME_MAX_TYPE], /* Type for filter */ | |
117 | program[1024]; /* Program/filter name */ | |
118 | int cost; /* Cost of filter */ | |
119 | mime_type_t **temptype; /* MIME type looping var */ | |
120 | ||
121 | ||
122 | /* | |
123 | * Range check input... | |
124 | */ | |
125 | ||
126 | if (p == NULL || filter == NULL) | |
127 | return; | |
128 | ||
129 | /* | |
130 | * Parse the filter string; it should be in the following format: | |
131 | * | |
132 | * super/type cost program | |
133 | */ | |
134 | ||
135 | if (sscanf(filter, "%[^/]/%s%d%s", super, type, &cost, program) != 4) | |
136 | { | |
137 | LogMessage(LOG_ERROR, "AddPrinterFilter: Invalid filter string \"%s\"!", | |
138 | filter); | |
139 | return; | |
140 | } | |
141 | ||
142 | /* | |
143 | * Add the filter to the MIME database, supporting wildcards as needed... | |
144 | */ | |
145 | ||
146 | for (temptype = MimeDatabase->types, i = MimeDatabase->num_types; | |
147 | i > 0; | |
148 | i --, temptype ++) | |
149 | if ((super[0] == '*' || strcmp((*temptype)->super, super) == 0) && | |
150 | (type[0] == '*' || strcmp((*temptype)->type, type) == 0)) | |
151 | mimeAddFilter(MimeDatabase, *temptype, p->filetype, cost, program); | |
152 | } | |
153 | ||
154 | ||
a9de544f | 155 | /* |
156 | * 'DeleteAllPrinters()' - Delete all printers from the system. | |
157 | */ | |
158 | ||
159 | void | |
160 | DeleteAllPrinters(void) | |
161 | { | |
cbbfcc63 | 162 | printer_t *p, /* Pointer to current printer/class */ |
163 | *next; /* Pointer to next printer in list */ | |
164 | ||
165 | ||
166 | for (p = Printers; p != NULL; p = next) | |
167 | { | |
168 | next = p->next; | |
169 | ||
170 | if (!(p->type & CUPS_PRINTER_CLASS)) | |
171 | DeletePrinter(p); | |
172 | } | |
a9de544f | 173 | } |
174 | ||
175 | ||
176 | /* | |
177 | * 'DeletePrinter()' - Delete a printer from the system. | |
178 | */ | |
179 | ||
180 | void | |
181 | DeletePrinter(printer_t *p) /* I - Printer to delete */ | |
182 | { | |
3270670b | 183 | int i; /* Looping var */ |
a9de544f | 184 | printer_t *current, /* Current printer in list */ |
185 | *prev; /* Previous printer in list */ | |
186 | ||
187 | ||
188 | /* | |
189 | * Range check input... | |
190 | */ | |
191 | ||
192 | if (p == NULL) | |
193 | return; | |
194 | ||
195 | /* | |
196 | * Stop printing on this printer... | |
197 | */ | |
198 | ||
199 | StopPrinter(p); | |
200 | ||
201 | /* | |
202 | * Remove the printer from the list... | |
203 | */ | |
204 | ||
205 | for (prev = NULL, current = Printers; | |
206 | current != NULL; | |
207 | prev = current, current = current->next) | |
208 | if (p == current) | |
209 | break; | |
210 | ||
211 | if (current == NULL) | |
212 | { | |
213 | fputs("cupsd: WARNING - tried to delete a non-existent printer!\n", stderr); | |
214 | return; | |
215 | } | |
216 | ||
217 | if (prev == NULL) | |
218 | Printers = p->next; | |
219 | else | |
220 | prev->next = p->next; | |
221 | ||
3270670b | 222 | if (p->printers != NULL) |
223 | free(p->printers); | |
224 | ||
225 | ippDelete(p->attrs); | |
226 | ||
a9de544f | 227 | free(p); |
3270670b | 228 | |
229 | /* | |
230 | * If p is the default printer, assign the next one... | |
231 | */ | |
232 | ||
233 | if (p == DefaultPrinter) | |
234 | DefaultPrinter = Printers; | |
a9de544f | 235 | } |
236 | ||
237 | ||
c7fa9d06 | 238 | /* |
239 | * 'AddPrinterFilter()' - Add a MIME filter for a printer. | |
240 | */ | |
241 | ||
242 | void | |
243 | DeletePrinterFilters(printer_t *p) /* I - Printer to remove from */ | |
244 | { | |
245 | int i; /* Looping var */ | |
246 | mime_filter_t *filter; /* MIME filter looping var */ | |
247 | ||
248 | ||
249 | /* | |
250 | * Range check input... | |
251 | */ | |
252 | ||
253 | if (p == NULL) | |
254 | return; | |
255 | ||
256 | /* | |
257 | * Remove all filters from the MIME database that have a destination | |
258 | * type == printer... | |
259 | */ | |
260 | ||
261 | for (filter = MimeDatabase->filters, i = MimeDatabase->num_filters; | |
262 | i > 0; | |
263 | i --, filter ++) | |
264 | if (filter->dst == p->filetype) | |
265 | { | |
266 | /* | |
267 | * Delete the current filter... | |
268 | */ | |
269 | ||
270 | MimeDatabase->num_filters --; | |
271 | ||
272 | if (i > 1) | |
273 | memcpy(filter, filter + 1, sizeof(mime_filter_t) * (i - 1)); | |
274 | ||
275 | filter --; | |
276 | } | |
277 | } | |
278 | ||
279 | ||
a9de544f | 280 | /* |
281 | * 'FindPrinter()' - Find a printer in the list. | |
282 | */ | |
283 | ||
284 | printer_t * /* O - Printer in list */ | |
285 | FindPrinter(char *name) /* I - Name of printer to find */ | |
286 | { | |
287 | printer_t *p; /* Current printer */ | |
288 | ||
289 | ||
290 | for (p = Printers; p != NULL; p = p->next) | |
f3d580b9 | 291 | switch (strcasecmp(name, p->name)) |
a9de544f | 292 | { |
cbbfcc63 | 293 | case 0 : /* name == p->name */ |
294 | if (!(p->type & CUPS_PRINTER_CLASS)) | |
295 | return (p); | |
a9de544f | 296 | case 1 : /* name > p->name */ |
297 | break; | |
a9de544f | 298 | case -1 : /* name < p->name */ |
299 | return (NULL); | |
300 | } | |
301 | ||
302 | return (NULL); | |
303 | } | |
304 | ||
305 | ||
306 | /* | |
307 | * 'LoadAllPrinters()' - Load printers from the printers.conf file. | |
308 | */ | |
309 | ||
310 | void | |
311 | LoadAllPrinters(void) | |
312 | { | |
a9de544f | 313 | FILE *fp; /* printers.conf file */ |
6abc7437 | 314 | int i; /* Looping var */ |
a9de544f | 315 | int linenum; /* Current line number */ |
316 | int len; /* Length of line */ | |
a74b005d | 317 | char line[HTTP_MAX_BUFFER], /* Line from file */ |
a9de544f | 318 | name[256], /* Parameter name */ |
319 | *nameptr, /* Pointer into name */ | |
6abc7437 | 320 | *value, /* Pointer to value */ |
321 | *lineptr, /* Pointer in line */ | |
c7fa9d06 | 322 | *temp; /* Temporary pointer */ |
a9de544f | 323 | printer_t *p; /* Current printer */ |
324 | ||
325 | ||
326 | /* | |
327 | * Open the printer.conf file... | |
328 | */ | |
329 | ||
a74b005d | 330 | sprintf(line, "%s/conf/printers.conf", ServerRoot); |
a9de544f | 331 | if ((fp = fopen(line, "r")) == NULL) |
332 | return; | |
333 | ||
334 | /* | |
335 | * Read printer configurations until we hit EOF... | |
336 | */ | |
337 | ||
338 | linenum = 0; | |
339 | p = NULL; | |
340 | ||
341 | while (fgets(line, sizeof(line), fp) != NULL) | |
342 | { | |
343 | linenum ++; | |
344 | ||
345 | /* | |
346 | * Skip comment lines... | |
347 | */ | |
348 | ||
349 | if (line[0] == '#') | |
350 | continue; | |
351 | ||
352 | /* | |
353 | * Strip trailing newline, if any... | |
354 | */ | |
355 | ||
356 | len = strlen(line); | |
357 | ||
358 | if (line[len - 1] == '\n') | |
359 | { | |
360 | len --; | |
361 | line[len] = '\0'; | |
362 | } | |
363 | ||
364 | /* | |
365 | * Extract the name from the beginning of the line... | |
366 | */ | |
367 | ||
368 | for (value = line; isspace(*value); value ++); | |
369 | ||
370 | for (nameptr = name; *value != '\0' && !isspace(*value);) | |
371 | *nameptr++ = *value++; | |
372 | *nameptr = '\0'; | |
373 | ||
374 | while (isspace(*value)) | |
375 | value ++; | |
376 | ||
377 | if (name[0] == '\0') | |
378 | continue; | |
379 | ||
380 | /* | |
381 | * Decode the directive... | |
382 | */ | |
383 | ||
1d2c70a6 | 384 | if (strcmp(name, "<Printer") == 0 || |
385 | strcmp(name, "<DefaultPrinter") == 0) | |
a9de544f | 386 | { |
387 | /* | |
1d2c70a6 | 388 | * <Printer name> or <DefaultPrinter name> |
a9de544f | 389 | */ |
390 | ||
391 | if (line[len - 1] == '>' && p == NULL) | |
392 | { | |
cbbfcc63 | 393 | /* |
394 | * Add the printer and a base file type... | |
395 | */ | |
396 | ||
a9de544f | 397 | line[len - 1] = '\0'; |
398 | ||
c7fa9d06 | 399 | p = AddPrinter(value); |
cbbfcc63 | 400 | |
401 | /* | |
402 | * Set the default printer as needed... | |
403 | */ | |
404 | ||
1d2c70a6 | 405 | if (strcmp(name, "<DefaultPrinter") == 0) |
cbbfcc63 | 406 | DefaultPrinter = p; |
a9de544f | 407 | } |
408 | else | |
409 | { | |
410 | LogMessage(LOG_ERROR, "Syntax error on line %d of printers.conf.", | |
411 | linenum); | |
412 | return; | |
413 | } | |
414 | } | |
415 | else if (strcmp(name, "</Printer>") == 0) | |
416 | { | |
417 | if (p != NULL) | |
e5cf24b2 | 418 | { |
cbbfcc63 | 419 | SetPrinterAttrs(p); |
a9de544f | 420 | p = NULL; |
e5cf24b2 | 421 | } |
a9de544f | 422 | else |
423 | { | |
424 | LogMessage(LOG_ERROR, "Syntax error on line %d of printers.conf.", | |
425 | linenum); | |
426 | return; | |
427 | } | |
428 | } | |
429 | else if (p == NULL) | |
430 | { | |
431 | LogMessage(LOG_ERROR, "Syntax error on line %d of printers.conf.", | |
432 | linenum); | |
433 | return; | |
434 | } | |
435 | ||
436 | else if (strcmp(name, "Info") == 0) | |
f3d580b9 | 437 | strncpy(p->info, value, sizeof(p->info) - 1); |
a9de544f | 438 | else if (strcmp(name, "MoreInfo") == 0) |
f3d580b9 | 439 | strncpy(p->more_info, value, sizeof(p->more_info) - 1); |
a74b005d | 440 | else if (strcmp(name, "Location") == 0) |
f3d580b9 | 441 | strncpy(p->location, value, sizeof(p->location) - 1); |
a74b005d | 442 | else if (strcmp(name, "DeviceURI") == 0) |
a9de544f | 443 | strncpy(p->device_uri, value, sizeof(p->device_uri) - 1); |
c7fa9d06 | 444 | else if (strcmp(name, "State") == 0) |
a9de544f | 445 | { |
446 | /* | |
c7fa9d06 | 447 | * Set the initial queue state... |
6abc7437 | 448 | */ |
449 | ||
c7fa9d06 | 450 | if (strcasecmp(value, "idle") == 0) |
451 | { | |
452 | p->state = IPP_PRINTER_IDLE; | |
453 | p->accepting = 1; | |
454 | } | |
455 | else if (strcasecmp(value, "stopped") == 0) | |
456 | { | |
457 | p->state = IPP_PRINTER_STOPPED; | |
458 | p->accepting = 0; | |
459 | } | |
a9de544f | 460 | } |
c7fa9d06 | 461 | else |
a9de544f | 462 | { |
463 | /* | |
c7fa9d06 | 464 | * Something else we don't understand... |
a9de544f | 465 | */ |
466 | ||
c7fa9d06 | 467 | LogMessage(LOG_ERROR, "Unknown configuration directive %s on line %d of printers.conf.", |
468 | name, linenum); | |
a9de544f | 469 | } |
a9de544f | 470 | } |
471 | ||
472 | fclose(fp); | |
473 | } | |
474 | ||
475 | ||
d6de4648 | 476 | /* |
477 | * 'SaveAllPrinters()' - Save all printer definitions to the printers.conf | |
478 | * file. | |
479 | */ | |
480 | ||
a9de544f | 481 | void |
482 | SaveAllPrinters(void) | |
483 | { | |
cc0561c6 | 484 | FILE *fp; /* printers.conf file */ |
485 | char temp[1024]; /* Temporary string */ | |
486 | printer_t *printer; /* Current printer class */ | |
487 | int i; /* Looping var */ | |
488 | time_t curtime; /* Current time */ | |
489 | struct tm *curdate; /* Current date */ | |
490 | ||
491 | ||
492 | /* | |
493 | * Create the printers.conf file... | |
494 | */ | |
495 | ||
496 | sprintf(temp, "%s/conf/printers.conf", ServerRoot); | |
497 | if ((fp = fopen(temp, "w")) == NULL) | |
498 | { | |
499 | LogMessage(LOG_ERROR, "Unable to save printers.conf - %s", strerror(errno)); | |
500 | return; | |
501 | } | |
502 | else | |
503 | LogMessage(LOG_INFO, "Saving printers.conf..."); | |
504 | ||
505 | /* | |
506 | * Write a small header to the file... | |
507 | */ | |
508 | ||
509 | curtime = time(NULL); | |
510 | curdate = gmtime(&curtime); | |
511 | strftime(temp, sizeof(temp) - 1, "# Written by cupsd on %c\n", curdate); | |
512 | ||
513 | fputs("# Class configuration file for " CUPS_SVERSION "\n", fp); | |
514 | fputs(temp, fp); | |
515 | ||
516 | /* | |
517 | * Write each local printer known to the system... | |
518 | */ | |
519 | ||
520 | for (printer = Printers; printer != NULL; printer = printer->next) | |
521 | { | |
522 | /* | |
523 | * Skip remote destinations and printer classes... | |
524 | */ | |
525 | ||
526 | if ((printer->type & CUPS_PRINTER_REMOTE) || | |
527 | (printer->type & CUPS_PRINTER_CLASS)) | |
528 | continue; | |
529 | ||
530 | /* | |
531 | * Write printers as needed... | |
532 | */ | |
533 | ||
534 | if (printer == DefaultPrinter) | |
535 | fprintf(fp, "<DefaultPrinter %s>\n", printer->name); | |
536 | else | |
537 | fprintf(fp, "<Printer %s>\n", printer->name); | |
538 | ||
539 | if (printer->info[0]) | |
540 | fprintf(fp, "Info %s\n", printer->info); | |
541 | if (printer->more_info[0]) | |
542 | fprintf(fp, "MoreInfo %s\n", printer->more_info); | |
543 | if (printer->location[0]) | |
544 | fprintf(fp, "Location %s\n", printer->location); | |
545 | if (printer->device_uri[0]) | |
546 | fprintf(fp, "DeviceURI %s\n", printer->device_uri); | |
547 | if (printer->state == IPP_PRINTER_STOPPED) | |
548 | fputs("State Stopped\n", fp); | |
549 | else | |
550 | fputs("State Idle\n", fp); | |
551 | ||
552 | fputs("</Printer>\n", fp); | |
553 | } | |
554 | ||
555 | fclose(fp); | |
a9de544f | 556 | } |
557 | ||
558 | ||
f3d580b9 | 559 | /* |
cbbfcc63 | 560 | * 'SetPrinterAttrs()' - Set printer attributes based upon the PPD file. |
f3d580b9 | 561 | */ |
562 | ||
a9de544f | 563 | void |
cbbfcc63 | 564 | SetPrinterAttrs(printer_t *p) /* I - Printer to setup */ |
f3d580b9 | 565 | { |
566 | char uri[HTTP_MAX_URI];/* URI for printer */ | |
567 | int i; /* Looping var */ | |
568 | char filename[1024]; /* Name of PPD file */ | |
569 | int num_media; /* Number of media options */ | |
570 | ppd_file_t *ppd; /* PPD file data */ | |
571 | ppd_option_t *input_slot, /* InputSlot options */ | |
572 | *media_type, /* MediaType options */ | |
573 | *page_size; /* PageSize options */ | |
574 | ipp_attribute_t *attr; /* Attribute data */ | |
575 | ipp_value_t *val; /* Attribute value */ | |
576 | int nups[3] = /* number-up-supported values */ | |
577 | { 1, 2, 4 }; | |
578 | ipp_orient_t orients[4] = /* orientation-requested-supported values */ | |
579 | { | |
580 | IPP_PORTRAIT, | |
581 | IPP_LANDSCAPE, | |
582 | IPP_REVERSE_LANDSCAPE, | |
583 | IPP_REVERSE_PORTRAIT | |
584 | }; | |
585 | char *sides[3] = /* sides-supported values */ | |
586 | { | |
587 | "one", | |
588 | "two-long-edge", | |
589 | "two-short-edge" | |
590 | }; | |
591 | ipp_op_t ops[] = /* operations-supported values */ | |
592 | { | |
593 | IPP_PRINT_JOB, | |
594 | IPP_VALIDATE_JOB, | |
595 | IPP_CANCEL_JOB, | |
596 | IPP_GET_JOB_ATTRIBUTES, | |
597 | IPP_GET_JOBS, | |
598 | IPP_GET_PRINTER_ATTRIBUTES, | |
599 | IPP_PAUSE_PRINTER, | |
600 | IPP_RESUME_PRINTER, | |
601 | IPP_PURGE_JOBS, | |
602 | CUPS_GET_DEFAULT, | |
603 | CUPS_GET_PRINTERS, | |
604 | CUPS_ADD_PRINTER, | |
605 | CUPS_DELETE_PRINTER, | |
606 | CUPS_GET_CLASSES, | |
607 | CUPS_ADD_CLASS, | |
608 | CUPS_DELETE_CLASS, | |
609 | CUPS_ACCEPT_JOBS, | |
610 | CUPS_REJECT_JOBS | |
611 | }; | |
612 | char *charsets[] = /* charset-supported values */ | |
613 | { | |
614 | "us-ascii", | |
615 | "iso-8859-1", | |
616 | "iso-8859-2", | |
617 | "iso-8859-3", | |
618 | "iso-8859-4", | |
619 | "iso-8859-5", | |
620 | "iso-8859-6", | |
621 | "iso-8859-7", | |
622 | "iso-8859-8", | |
623 | "iso-8859-9", | |
624 | "iso-8859-10", | |
625 | "utf-8" | |
626 | }; | |
d6de4648 | 627 | int num_finishings; |
628 | ipp_finish_t finishings[5]; | |
f3d580b9 | 629 | |
630 | ||
c7fa9d06 | 631 | /* |
632 | * Clear out old filters and add a filter from application/vnd.cups-raw to | |
633 | * printer/name to handle "raw" printing by users. | |
634 | */ | |
635 | ||
636 | DeletePrinterFilters(p); | |
637 | AddPrinterFilter(p, "application/vnd.cups-raw 0 -"); | |
638 | ||
f3d580b9 | 639 | /* |
640 | * Create the required IPP attributes for a printer... | |
641 | */ | |
642 | ||
643 | if (p->attrs) | |
644 | ippDelete(p->attrs); | |
645 | ||
646 | p->attrs = ippNew(); | |
647 | ||
cbbfcc63 | 648 | if (p->type & CUPS_PRINTER_CLASS) |
649 | sprintf(p->uri, "ipp://%s:%d/classes/%s", ServerName, | |
650 | ntohs(Listeners[0].address.sin_port), p->name); | |
651 | else | |
652 | sprintf(p->uri, "ipp://%s:%d/printers/%s", ServerName, | |
653 | ntohs(Listeners[0].address.sin_port), p->name); | |
f3d580b9 | 654 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", |
d6de4648 | 655 | NULL, p->uri); |
f3d580b9 | 656 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, |
657 | "uri-security-supported", NULL, "none"); | |
658 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL, | |
659 | p->name); | |
660 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", | |
661 | NULL, p->location); | |
662 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", | |
663 | NULL, p->info); | |
664 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", | |
665 | NULL, p->more_info); | |
666 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
667 | "pdl-override-supported", NULL, "not-attempted"); | |
668 | ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "operations-supported", | |
42d48bd2 | 669 | sizeof(ops) / sizeof(ops[0]), (int *)ops); |
f3d580b9 | 670 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-configured", |
671 | NULL, DefaultCharset); | |
672 | ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-supported", | |
673 | sizeof(charsets) / sizeof(charsets[0]), NULL, charsets); | |
674 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, | |
675 | "natural-language-configured", NULL, DefaultLanguage); | |
676 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, | |
677 | "generated-natural-language-supported", NULL, DefaultLanguage); | |
678 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, | |
679 | "document-format-default", NULL, "application/octet-stream"); | |
680 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, | |
681 | "document-format-supported", NULL, "application/octet-stream"); | |
682 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
683 | "job-priority-supported", 100); | |
684 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
685 | "job-priority-default", 50); | |
686 | ippAddRange(p->attrs, IPP_TAG_PRINTER, "copies-supported", 1, 100); | |
687 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
688 | "copies-default", 1); | |
689 | ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "page-ranges-supported", 1); | |
690 | ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
691 | "number-up-supported", 3, nups); | |
692 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
693 | "number-up-default", 1); | |
694 | ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
42d48bd2 | 695 | "orientation-requested-supported", 4, (int *)orients); |
f3d580b9 | 696 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, |
697 | "orientation-requested-default", IPP_PORTRAIT); | |
698 | ||
699 | /* | |
cbbfcc63 | 700 | * Assign additional attributes depending on whether this is a printer |
701 | * or class... | |
f3d580b9 | 702 | */ |
703 | ||
cbbfcc63 | 704 | if (p->type & CUPS_PRINTER_CLASS) |
f3d580b9 | 705 | { |
706 | /* | |
cbbfcc63 | 707 | * Add class-specific attributes... |
f3d580b9 | 708 | */ |
709 | ||
cbbfcc63 | 710 | if (p->num_printers > 0) |
711 | { | |
712 | /* | |
713 | * Add a list of member URIs and names... | |
714 | */ | |
715 | ||
716 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, | |
717 | "member-uris", p->num_printers, NULL, NULL); | |
718 | ||
719 | for (i = 0; i < p->num_printers; i ++) | |
720 | attr->values[i].string.text = strdup(p->printers[i]->uri); | |
d6de4648 | 721 | |
cbbfcc63 | 722 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, |
723 | "member-names", p->num_printers, NULL, NULL); | |
f3d580b9 | 724 | |
cbbfcc63 | 725 | for (i = 0; i < p->num_printers; i ++) |
726 | attr->values[i].string.text = strdup(p->printers[i]->name); | |
727 | } | |
728 | } | |
729 | else | |
730 | { | |
f3d580b9 | 731 | /* |
cbbfcc63 | 732 | * Add printer-specific attributes... |
f3d580b9 | 733 | */ |
734 | ||
cbbfcc63 | 735 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, |
736 | p->device_uri); | |
f3d580b9 | 737 | |
cbbfcc63 | 738 | /* |
739 | * Assign additional attributes from the PPD file (if any)... | |
740 | */ | |
f3d580b9 | 741 | |
cbbfcc63 | 742 | p->type = CUPS_PRINTER_LOCAL + CUPS_PRINTER_BW + CUPS_PRINTER_SMALL; |
743 | finishings[0] = IPP_FINISH_NONE; | |
744 | num_finishings = 1; | |
f3d580b9 | 745 | |
cbbfcc63 | 746 | sprintf(filename, "%s/ppd/%s.ppd", ServerRoot, p->name); |
747 | if ((ppd = ppdOpenFile(filename)) != NULL) | |
748 | { | |
749 | /* | |
750 | * Add make/model and other various attributes... | |
751 | */ | |
f3d580b9 | 752 | |
cbbfcc63 | 753 | if (ppd->color_device) |
754 | p->type += CUPS_PRINTER_COLOR; | |
755 | if (ppd->variable_sizes) | |
756 | p->type += CUPS_PRINTER_VARIABLE; | |
757 | if (!ppd->manual_copies) | |
758 | p->type += CUPS_PRINTER_COPIES; | |
f3d580b9 | 759 | |
cbbfcc63 | 760 | ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "color-supported", |
761 | ppd->color_device); | |
762 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, | |
763 | "printer-make-and-model", NULL, ppd->nickname); | |
f3d580b9 | 764 | |
cbbfcc63 | 765 | /* |
766 | * Add media options from the PPD file... | |
767 | */ | |
f3d580b9 | 768 | |
cbbfcc63 | 769 | if ((input_slot = ppdFindOption(ppd, "InputSlot")) != NULL) |
770 | num_media = input_slot->num_choices; | |
771 | else | |
772 | num_media = 0; | |
f3d580b9 | 773 | |
cbbfcc63 | 774 | if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL) |
775 | num_media += media_type->num_choices; | |
d6de4648 | 776 | |
cbbfcc63 | 777 | if ((page_size = ppdFindOption(ppd, "PageSize")) != NULL) |
778 | num_media += page_size->num_choices; | |
f3d580b9 | 779 | |
cbbfcc63 | 780 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, |
781 | "media-supported", num_media, NULL, NULL); | |
782 | val = attr->values; | |
d6de4648 | 783 | |
cbbfcc63 | 784 | if (input_slot != NULL) |
785 | for (i = 0; i < input_slot->num_choices; i ++, val ++) | |
786 | val->string.text = strdup(input_slot->choices[i].choice); | |
d6de4648 | 787 | |
cbbfcc63 | 788 | if (media_type != NULL) |
789 | for (i = 0; i < media_type->num_choices; i ++, val ++) | |
790 | val->string.text = strdup(media_type->choices[i].choice); | |
d6de4648 | 791 | |
cbbfcc63 | 792 | if (page_size != NULL) |
793 | for (i = 0; i < page_size->num_choices; i ++, val ++) | |
794 | val->string.text = strdup(page_size->choices[i].choice); | |
d6de4648 | 795 | |
cbbfcc63 | 796 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", |
797 | NULL, page_size->defchoice); | |
d6de4648 | 798 | |
cbbfcc63 | 799 | if (ppdFindOption(ppd, "Duplex") != NULL) |
800 | { | |
801 | p->type += CUPS_PRINTER_DUPLEX; | |
d6de4648 | 802 | |
cbbfcc63 | 803 | ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-supported", |
804 | 3, NULL, sides); | |
805 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-default", | |
806 | NULL, "one"); | |
807 | } | |
808 | ||
809 | if (ppdFindOption(ppd, "Collate") != NULL) | |
810 | p->type += CUPS_PRINTER_COLLATE; | |
811 | ||
812 | if (ppdFindOption(ppd, "StapleLocation") != NULL) | |
813 | { | |
814 | p->type += CUPS_PRINTER_STAPLE; | |
815 | finishings[num_finishings++] = IPP_FINISH_STAPLE; | |
816 | } | |
817 | ||
818 | if (ppdFindOption(ppd, "BindEdge") != NULL) | |
819 | { | |
820 | p->type += CUPS_PRINTER_BIND; | |
821 | finishings[num_finishings++] = IPP_FINISH_BIND; | |
822 | } | |
823 | ||
824 | p->type -= CUPS_PRINTER_SMALL; | |
825 | ||
826 | for (i = 0; i < ppd->num_sizes; i ++) | |
827 | if (ppd->sizes[i].length > 1728) | |
828 | p->type += CUPS_PRINTER_LARGE; | |
829 | else if (ppd->sizes[i].length > 1008) | |
830 | p->type += CUPS_PRINTER_MEDIUM; | |
831 | else | |
832 | p->type += CUPS_PRINTER_SMALL; | |
833 | ||
c7fa9d06 | 834 | /* |
835 | * Add any filters in the PPD file... | |
836 | */ | |
837 | ||
838 | for (i = 0; i < ppd->num_filters; i ++) | |
839 | AddPrinterFilter(p, ppd->filters[i]); | |
840 | ||
841 | if (ppd->num_filters == 0) | |
842 | AddPrinterFilter(p, "application/vnd.cups-postscript 0 -"); | |
843 | ||
cbbfcc63 | 844 | ppdClose(ppd); |
845 | } | |
5b88701c | 846 | else if (access(filename, 0) == 0) |
847 | { | |
848 | LogMessage(LOG_ERROR, "PPD file for %s cannot be loaded!", p->name); | |
849 | ||
850 | AddPrinterFilter(p, "application/vnd.cups-postscript 0 -"); | |
851 | } | |
cbbfcc63 | 852 | |
853 | ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
854 | "finishings-supported", num_finishings, (int *)finishings); | |
855 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
856 | "finishings-default", IPP_FINISH_NONE); | |
857 | } | |
d6de4648 | 858 | |
c7fa9d06 | 859 | /* |
860 | * Add the CUPS-specific printer-type attribute... | |
861 | */ | |
862 | ||
d6de4648 | 863 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", p->type); |
c7fa9d06 | 864 | |
865 | /* | |
866 | * If we have an interface script, add a filter entry for it... | |
867 | */ | |
868 | ||
869 | sprintf(filename, "%s/interfaces/%s", ServerRoot, p->name); | |
870 | if (access(filename, X_OK) == 0) | |
871 | { | |
872 | /* | |
873 | * Yes, we have a System V style interface script; use it! | |
874 | */ | |
875 | ||
876 | sprintf(filename, "*/* 0 %s/interfaces/%s", ServerRoot, p->name); | |
877 | AddPrinterFilter(p, filename); | |
878 | } | |
879 | ||
880 | /* | |
881 | * Remote printers go directly to the remote destination... | |
882 | */ | |
883 | ||
884 | if (p->type & CUPS_PRINTER_REMOTE) | |
885 | AddPrinterFilter(p, "*/* 0 -"); | |
f3d580b9 | 886 | } |
887 | ||
888 | ||
889 | /* | |
cbbfcc63 | 890 | * 'SetPrinterState()' - Update the current state of a printer. |
891 | */ | |
892 | ||
893 | void | |
894 | SetPrinterState(printer_t *p, /* I - Printer to change */ | |
895 | ipp_pstate_t s) /* I - New state */ | |
896 | { | |
897 | ipp_pstate_t old_state; /* Old printer state */ | |
898 | ||
899 | ||
900 | /* | |
901 | * Set the new state... | |
902 | */ | |
903 | ||
904 | old_state = p->state; | |
905 | p->state = s; | |
906 | p->state_time = time(NULL); | |
907 | ||
908 | if (old_state != s) | |
909 | p->browse_time = 0; | |
910 | ||
911 | /* | |
912 | * Save the printer configuration if a printer goes from idle or processing | |
913 | * to stopped (or visa-versa)... | |
914 | */ | |
915 | ||
916 | if ((old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED)) | |
917 | SaveAllPrinters(); | |
918 | ||
919 | /* | |
920 | * Check to see if any pending jobs can now be printed... | |
921 | */ | |
922 | ||
923 | CheckJobs(); | |
924 | } | |
925 | ||
926 | ||
927 | /* | |
928 | * 'StopPrinter()' - Stop a printer from printing any jobs... | |
929 | */ | |
930 | ||
931 | void | |
932 | StopPrinter(printer_t *p) /* I - Printer to stop */ | |
933 | { | |
934 | if (p->job) | |
935 | StopJob(((job_t *)p->job)->id); | |
936 | ||
937 | p->state = IPP_PRINTER_STOPPED; | |
938 | } | |
939 | ||
940 | ||
941 | /* | |
8784b6a6 | 942 | * End of "$Id: printers.c,v 1.20 1999/06/18 18:36:49 mike Exp $". |
a129ddbd | 943 | */ |