4 * Printer routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 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 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * cupsdAddPrinter() - Add a printer to the system.
27 * cupsdAddPrinterFilter() - Add a MIME filter for a printer.
28 * cupsdAddPrinterHistory() - Add the current printer state to the history.
29 * cupsdAddPrinterUser() - Add a user to the ACL.
30 * cupsdDeleteAllPrinters() - Delete all printers from the system.
31 * cupsdDeletePrinter() - Delete a printer from the system.
32 * cupsdDeletePrinterFilters() - Delete all MIME filters for a printer.
33 * cupsdFindPrinter() - Find a printer in the list.
34 * cupsdFreePrinterUsers() - Free allow/deny users.
35 * cupsdLoadAllPrinters() - Load printers from the printers.conf file.
36 * cupsdSaveAllPrinters() - Save all printer definitions to the printers.conf
37 * cupsdSetPrinterAttrs() - Set printer attributes based upon the PPD file.
38 * cupsdSetPrinterReasons() - Set/update the reasons strings.
39 * cupsdSetPrinterState() - Update the current state of a printer.
40 * cupsdStopPrinter() - Stop a printer from printing any jobs...
41 * cupsdUpdatePrinters() - Update printers after a partial reload.
42 * cupsdValidateDest() - Validate a printer/class destination.
43 * cupsdWritePrintcap() - Write a pseudo-printcap file for older
44 * applications that need it...
45 * cupsdSanitizeURI() - Sanitize a device URI...
46 * compare_printers() - Compare two printers.
47 * write_irix_config() - Update the config files used by the IRIX
49 * write_irix_state() - Update the status files used by IRIX printing
54 * Include necessary headers...
64 static int compare_printers(void *first
, void *second
, void *data
);
66 static void write_irix_config(cupsd_printer_t
*p
);
67 static void write_irix_state(cupsd_printer_t
*p
);
72 * 'cupsdAddPrinter()' - Add a printer to the system.
75 cupsd_printer_t
* /* O - New printer */
76 cupsdAddPrinter(const char *name
) /* I - Name of printer */
78 cupsd_printer_t
*p
; /* New printer */
82 * Range check input...
85 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdAddPrinter(\"%s\")", name
);
88 * Create a new printer entity...
91 if ((p
= calloc(1, sizeof(cupsd_printer_t
))) == NULL
)
93 cupsdLogMessage(CUPSD_LOG_CRIT
, "Unable to allocate memory for printer - %s",
98 cupsdSetString(&p
->name
, name
);
99 cupsdSetString(&p
->info
, name
);
100 cupsdSetString(&p
->hostname
, ServerName
);
102 cupsdSetStringf(&p
->uri
, "ipp://%s:%d/printers/%s", ServerName
, LocalPort
, name
);
103 cupsdSetStringf(&p
->device_uri
, "file:/dev/null");
105 p
->state
= IPP_PRINTER_STOPPED
;
106 p
->state_time
= time(NULL
);
109 p
->filetype
= mimeAddType(MimeDatabase
, "printer", name
);
111 cupsdSetString(&p
->job_sheets
[0], "none");
112 cupsdSetString(&p
->job_sheets
[1], "none");
114 cupsdSetString(&p
->error_policy
, "stop-printer");
115 cupsdSetString(&p
->op_policy
, DefaultPolicy
);
117 p
->op_policy_ptr
= DefaultPolicyPtr
;
119 if (MaxPrinterHistory
)
120 p
->history
= calloc(MaxPrinterHistory
, sizeof(ipp_t
*));
123 * Insert the printer in the printer list alphabetically...
127 Printers
= cupsArrayNew(compare_printers
, NULL
);
129 cupsArrayAdd(Printers
, p
);
131 if (!ImplicitPrinters
)
132 ImplicitPrinters
= cupsArrayNew(compare_printers
, NULL
);
135 * Return the new printer...
143 * 'cupsdAddPrinterFilter()' - Add a MIME filter for a printer.
147 cupsdAddPrinterFilter(
148 cupsd_printer_t
*p
, /* I - Printer to add to */
149 const char *filter
) /* I - Filter to add */
151 int i
; /* Looping var */
152 char super
[MIME_MAX_SUPER
], /* Super-type for filter */
153 type
[MIME_MAX_TYPE
], /* Type for filter */
154 program
[1024]; /* Program/filter name */
155 int cost
; /* Cost of filter */
156 mime_type_t
**temptype
; /* MIME type looping var */
160 * Range check input...
163 if (p
== NULL
|| p
->filetype
== NULL
|| filter
== NULL
)
167 * Parse the filter string; it should be in the following format:
169 * super/type cost program
172 if (sscanf(filter
, "%15[^/]/%31s%d%1023s", super
, type
, &cost
, program
) != 4)
174 cupsdLogMessage(CUPSD_LOG_ERROR
,
175 "cupsdAddPrinterFilter: Invalid filter string \"%s\"!",
181 * Add the filter to the MIME database, supporting wildcards as needed...
184 for (temptype
= MimeDatabase
->types
, i
= MimeDatabase
->num_types
;
187 if (((super
[0] == '*' && strcasecmp((*temptype
)->super
, "printer") != 0) ||
188 !strcasecmp((*temptype
)->super
, super
)) &&
189 (type
[0] == '*' || !strcasecmp((*temptype
)->type
, type
)))
191 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "Adding filter %s/%s %s/%s %d %s",
192 (*temptype
)->super
, (*temptype
)->type
,
193 p
->filetype
->super
, p
->filetype
->type
,
195 mimeAddFilter(MimeDatabase
, *temptype
, p
->filetype
, cost
, program
);
201 * 'cupsdAddPrinterHistory()' - Add the current printer state to the history.
205 cupsdAddPrinterHistory(
206 cupsd_printer_t
*p
) /* I - Printer */
208 ipp_t
*history
; /* History collection */
212 * Stop early if we aren't keeping history data...
215 if (MaxPrinterHistory
<= 0)
219 * Retire old history data as needed...
222 p
->sequence_number
++;
224 if (p
->num_history
>= MaxPrinterHistory
)
227 ippDelete(p
->history
[0]);
228 memmove(p
->history
, p
->history
+ 1, p
->num_history
* sizeof(ipp_t
*));
232 * Create a collection containing the current printer-state, printer-up-time,
233 * printer-state-message, and printer-state-reasons attributes.
237 ippAddInteger(history
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-state",
239 ippAddBoolean(history
, IPP_TAG_PRINTER
, "printer-is-accepting-jobs",
241 ippAddString(history
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-state-message",
242 NULL
, p
->state_message
);
243 if (p
->num_reasons
== 0)
244 ippAddString(history
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
245 "printer-state-reasons", NULL
,
246 p
->state
== IPP_PRINTER_STOPPED
? "paused" : "none");
248 ippAddStrings(history
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
249 "printer-state-reasons", p
->num_reasons
, NULL
,
250 (const char * const *)p
->reasons
);
251 ippAddInteger(history
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
252 "printer-state-change-time", p
->state_time
);
253 ippAddInteger(history
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
254 "printer-state-sequence-number", p
->sequence_number
);
256 p
->history
[p
->num_history
] = history
;
262 * 'cupsdAddPrinterUser()' - Add a user to the ACL.
267 cupsd_printer_t
*p
, /* I - Printer */
268 const char *username
) /* I - User */
270 const char **temp
; /* Temporary array pointer */
276 if (p
->num_users
== 0)
277 temp
= malloc(sizeof(char **));
279 temp
= realloc(p
->users
, sizeof(char **) * (p
->num_users
+ 1));
285 temp
+= p
->num_users
;
287 if ((*temp
= strdup(username
)) != NULL
)
293 * 'cupsdCreateCommonData()' - Create the common printer data.
297 cupsdCreateCommonData(void)
299 int i
; /* Looping var */
300 ipp_attribute_t
*attr
; /* Attribute data */
301 static const int nups
[] = /* number-up-supported values */
302 { 1, 2, 4, 6, 9, 16 };
303 static const ipp_orient_t orients
[4] =/* orientation-requested-supported values */
307 IPP_REVERSE_LANDSCAPE
,
310 static const char * const holds
[] = /* job-hold-until-supported values */
321 static const char * const versions
[] =/* ipp-versions-supported values */
326 static const ipp_op_t ops
[] = /* operations-supported values */
333 IPP_GET_JOB_ATTRIBUTES
,
335 IPP_GET_PRINTER_ATTRIBUTES
,
341 IPP_SET_JOB_ATTRIBUTES
,
342 IPP_CREATE_PRINTER_SUBSCRIPTION
,
343 IPP_CREATE_JOB_SUBSCRIPTION
,
344 IPP_GET_SUBSCRIPTION_ATTRIBUTES
,
345 IPP_GET_SUBSCRIPTIONS
,
346 IPP_RENEW_SUBSCRIPTION
,
347 IPP_CANCEL_SUBSCRIPTION
,
348 IPP_GET_NOTIFICATIONS
,
364 CUPS_AUTHENTICATE_JOB
,
367 static const char * const charsets
[] =/* charset-supported values */
372 static const char * const compressions
[] =
373 { /* document-compression-supported values */
377 #endif /* HAVE_LIBZ */
379 static const char * const multiple_document_handling
[] =
380 { /* multiple-document-handling-supported values */
381 "separate-documents-uncollated-copies",
382 "separate-documents-collated-copies"
384 static const char * const errors
[] = /* printer-error-policy-supported values */
390 static const char * const notify_attrs
[] =
391 { /* notify-attributes-supported values */
392 "printer-state-change-time",
393 "notify-lease-expiration-time",
394 "notify-subscriber-user-name"
396 static const char * const notify_events
[] =
397 { /* notify-events-supported values */
399 "job-config-changed",
406 "printer-config-changed",
408 "printer-finishings-changed",
409 "printer-media-changed",
413 "printer-state-changed",
423 ippDelete(CommonData
);
425 CommonData
= ippNew();
428 * This list of attributes is sorted to improve performance when the
429 * client provides a requested-attributes attribute...
432 /* charset-configured */
433 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_CHARSET
,
434 "charset-configured", NULL
, DefaultCharset
);
436 /* charset-supported */
437 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_CHARSET
,
438 "charset-supported", sizeof(charsets
) / sizeof(charsets
[0]),
441 /* compression-supported */
442 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
443 "compression-supported",
444 sizeof(compressions
) / sizeof(compressions
[0]),
447 /* TODO: move to printer-specific section! */
449 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
450 "copies-default", 1);
452 /* copies-supported */
453 ippAddRange(CommonData
, IPP_TAG_PRINTER
, "copies-supported", 1, MaxCopies
);
455 /* TODO: move to printer-specific section! */
456 /* document-format-default */
457 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_MIMETYPE
,
458 "document-format-default", NULL
, "application/octet-stream");
460 /* document-format-supported */
461 ippAddStrings(CommonData
, IPP_TAG_PRINTER
,
462 (ipp_tag_t
)(IPP_TAG_MIMETYPE
| IPP_TAG_COPY
),
463 "document-format-supported", NumMimeTypes
, NULL
, MimeTypes
);
465 /* generated-natural-language-supported */
466 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_LANGUAGE
,
467 "generated-natural-language-supported", NULL
, DefaultLanguage
);
469 /* ipp-versions-supported */
470 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
471 "ipp-versions-supported", sizeof(versions
) / sizeof(versions
[0]),
474 /* TODO: move to printer-specific section! */
475 /* job-hold-until-default */
476 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
477 "job-hold-until-default", NULL
, "no-hold");
479 /* job-hold-until-supported */
480 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
481 "job-hold-until-supported", sizeof(holds
) / sizeof(holds
[0]),
484 /* TODO: move to printer-specific section! */
485 /* job-priority-default */
486 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
487 "job-priority-default", 50);
489 /* job-priority-supported */
490 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
491 "job-priority-supported", 100);
493 /* job-sheets-supported */
497 * Setup the job-sheets-supported attribute...
500 if (Classification
&& !ClassifyOverride
)
501 attr
= ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
502 "job-sheets-supported", NULL
, Classification
);
504 attr
= ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
505 "job-sheets-supported", NumBanners
+ 1, NULL
, NULL
);
508 cupsdLogMessage(CUPSD_LOG_EMERG
,
509 "cupsdSetPrinterAttrs: Unable to allocate memory for "
510 "job-sheets-supported attribute: %s!", strerror(errno
));
511 else if (!Classification
|| ClassifyOverride
)
513 attr
->values
[0].string
.text
= strdup("none");
515 for (i
= 0; i
< NumBanners
; i
++)
516 attr
->values
[i
+ 1].string
.text
= strdup(Banners
[i
].name
);
520 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
521 "job-sheets-supported", NULL
, "none");
523 /* multiple-document-handling-supported */
524 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
525 "multiple-document-handling-supported",
526 sizeof(multiple_document_handling
) /
527 sizeof(multiple_document_handling
[0]), NULL
,
528 multiple_document_handling
);
530 /* multiple-document-jobs-supported */
531 ippAddBoolean(CommonData
, IPP_TAG_PRINTER
,
532 "multiple-document-jobs-supported", 1);
534 /* multiple-operation-time-out */
535 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
536 "multiple-operation-time-out", 60);
538 /* natural-language-configured */
539 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_LANGUAGE
,
540 "natural-language-configured", NULL
, DefaultLanguage
);
542 /* notify-attributes-supported */
543 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
544 "notify-attributes-supported",
545 (int)(sizeof(notify_attrs
) / sizeof(notify_attrs
[0])),
548 /* TODO: move to printer-specific section! */
549 /* notify-lease-duration-default */
550 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
551 "notify-lease-duration-default", DefaultLeaseDuration
);
553 /* notify-lease-duration-supported */
554 ippAddRange(CommonData
, IPP_TAG_PRINTER
,
555 "notify-lease-duration-supported", 0,
556 MaxLeaseDuration
? MaxLeaseDuration
: 2147483647);
558 /* notify-max-events-supported */
559 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
560 "notify-max-events-supported", MaxEvents
);
562 /* notify-notify-events-default */
563 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
564 "notify-events-default", NULL
, "job-completed");
566 /* notify-notify-events-supported */
567 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
568 "notify-events-supported",
569 (int)(sizeof(notify_events
) / sizeof(notify_events
[0])),
570 NULL
, notify_events
);
572 /* notify-pull-method-supported */
573 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
574 "notify-pull-method-supported", NULL
, "ippget");
576 /* TODO: scan notifier directory */
577 /* notify-schemes-supported */
578 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
579 "notify-schemes-supported", NULL
, "mailto");
581 /* TODO: move to printer-specific section! */
582 /* number-up-default */
583 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
584 "number-up-default", 1);
586 /* number-up-supported */
587 ippAddIntegers(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
588 "number-up-supported", sizeof(nups
) / sizeof(nups
[0]), nups
);
590 /* operations-supported */
591 ippAddIntegers(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
592 "operations-supported",
593 sizeof(ops
) / sizeof(ops
[0]) + JobFiles
- 1, (int *)ops
);
595 /* TODO: move to printer-specific section! */
596 /* orientation-requested-default */
597 ippAddInteger(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
598 "orientation-requested-default", IPP_PORTRAIT
);
600 /* orientation-requested-supported */
601 ippAddIntegers(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
602 "orientation-requested-supported", 4, (int *)orients
);
604 /* page-ranges-supported */
605 ippAddBoolean(CommonData
, IPP_TAG_PRINTER
, "page-ranges-supported", 1);
607 /* pdf-override-supported */
608 ippAddString(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
609 "pdl-override-supported", NULL
, "not-attempted");
611 /* printer-error-policy-supported */
612 ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
613 "printer-error-policy-supported",
614 sizeof(errors
) / sizeof(errors
[0]), NULL
, errors
);
616 /* printer-op-policy-supported */
617 attr
= ippAddStrings(CommonData
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
618 "printer-op-policy-supported", NumPolicies
, NULL
, NULL
);
619 for (i
= 0; i
< NumPolicies
; i
++)
620 attr
->values
[i
].string
.text
= strdup(Policies
[i
]->name
);
625 * 'cupsdDeleteAllPrinters()' - Delete all printers from the system.
629 cupsdDeleteAllPrinters(void)
631 cupsd_printer_t
*p
; /* Pointer to current printer/class */
634 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
636 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
637 if (!(p
->type
& CUPS_PRINTER_CLASS
))
638 cupsdDeletePrinter(p
, 0);
643 * 'cupsdDeletePrinter()' - Delete a printer from the system.
648 cupsd_printer_t
*p
, /* I - Printer to delete */
649 int update
) /* I - Update printers.conf? */
651 int i
; /* Looping var */
653 char filename
[1024]; /* Interface script filename */
657 DEBUG_printf(("cupsdDeletePrinter(%08x): p->name = \"%s\"...\n", p
, p
->name
));
660 * Stop printing on this printer...
663 cupsdStopPrinter(p
, update
);
666 * If this printer is the next for browsing, point to the next one...
671 cupsArrayFind(Printers
, p
);
672 BrowseNext
= (cupsd_printer_t
*)cupsArrayNext(Printers
);
676 * Remove the printer from the list...
679 cupsArrayRemove(Printers
, p
);
682 * Remove the dummy interface/icon/option files under IRIX...
686 snprintf(filename
, sizeof(filename
), "/var/spool/lp/interface/%s", p
->name
);
689 snprintf(filename
, sizeof(filename
), "/var/spool/lp/gui_interface/ELF/%s.gui",
693 snprintf(filename
, sizeof(filename
), "/var/spool/lp/activeicons/%s", p
->name
);
696 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.config", p
->name
);
699 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.status", p
->name
);
702 snprintf(filename
, sizeof(filename
), "/var/spool/lp/member/%s", p
->name
);
707 * If p is the default printer, assign the next one...
710 if (p
== DefaultPrinter
)
711 DefaultPrinter
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
714 * Remove this printer from any classes and send a browse delete message...
717 if (!(p
->type
& CUPS_PRINTER_IMPLICIT
))
719 cupsdDeletePrinterFromClasses(p
);
720 cupsdSendBrowseDelete(p
);
724 * Free all memory used by the printer...
727 if (p
->printers
!= NULL
)
730 if (MaxPrinterHistory
)
732 for (i
= 0; i
< p
->num_history
; i
++)
733 ippDelete(p
->history
[i
]);
738 for (i
= 0; i
< p
->num_reasons
; i
++)
743 cupsdDeletePrinterFilters(p
);
745 cupsdFreePrinterUsers(p
);
748 cupsdClearString(&p
->uri
);
749 cupsdClearString(&p
->hostname
);
750 cupsdClearString(&p
->name
);
751 cupsdClearString(&p
->location
);
752 cupsdClearString(&p
->make_model
);
753 cupsdClearString(&p
->info
);
754 cupsdClearString(&p
->job_sheets
[0]);
755 cupsdClearString(&p
->job_sheets
[1]);
756 cupsdClearString(&p
->device_uri
);
757 cupsdClearString(&p
->port_monitor
);
758 cupsdClearString(&p
->op_policy
);
759 cupsdClearString(&p
->error_policy
);
766 * 'cupsdDeletePrinterFilters()' - Delete all MIME filters for a printer.
770 cupsdDeletePrinterFilters(
771 cupsd_printer_t
*p
) /* I - Printer to remove from */
773 int i
; /* Looping var */
774 mime_filter_t
*filter
; /* MIME filter looping var */
778 * Range check input...
785 * Remove all filters from the MIME database that have a destination
789 for (filter
= MimeDatabase
->filters
, i
= MimeDatabase
->num_filters
;
792 if (filter
->dst
== p
->filetype
)
795 * Delete the current filter...
798 MimeDatabase
->num_filters
--;
801 memmove(filter
, filter
+ 1, sizeof(mime_filter_t
) * (i
- 1));
809 * 'cupsdFindDest()' - Find a destination in the list.
812 cupsd_printer_t
* /* O - Destination in list */
813 cupsdFindDest(const char *name
) /* I - Name of printer or class to find */
815 cupsd_printer_t key
; /* Search key */
818 key
.name
= (char *)name
;
819 return ((cupsd_printer_t
*)cupsArrayFind(Printers
, &key
));
824 * 'cupsdFindPrinter()' - Find a printer in the list.
827 cupsd_printer_t
* /* O - Printer in list */
828 cupsdFindPrinter(const char *name
) /* I - Name of printer to find */
830 cupsd_printer_t
*p
; /* Printer in list */
833 if ((p
= cupsdFindDest(name
)) != NULL
&& (p
->type
& CUPS_PRINTER_CLASS
))
841 * 'cupsdFreePrinterUsers()' - Free allow/deny users.
845 cupsdFreePrinterUsers(
846 cupsd_printer_t
*p
) /* I - Printer */
848 int i
; /* Looping var */
851 if (!p
|| !p
->num_users
)
854 for (i
= 0; i
< p
->num_users
; i
++)
855 free((void *)p
->users
[i
]);
865 * 'cupsdLoadAllPrinters()' - Load printers from the printers.conf file.
869 cupsdLoadAllPrinters(void)
871 cups_file_t
*fp
; /* printers.conf file */
872 int linenum
; /* Current line number */
873 char line
[1024], /* Line from file */
874 *value
, /* Pointer to value */
875 *valueptr
; /* Pointer into value */
876 cupsd_printer_t
*p
; /* Current printer */
880 * Open the printers.conf file...
883 snprintf(line
, sizeof(line
), "%s/printers.conf", ServerRoot
);
884 if ((fp
= cupsFileOpen(line
, "r")) == NULL
)
886 cupsdLogMessage(CUPSD_LOG_ERROR
,
887 "cupsdLoadAllPrinters: Unable to open %s - %s", line
,
893 * Read printer configurations until we hit EOF...
899 while (cupsFileGetConf(fp
, line
, sizeof(line
), &value
, &linenum
))
902 * Decode the directive...
905 if (!strcasecmp(line
, "<Printer") ||
906 !strcasecmp(line
, "<DefaultPrinter"))
909 * <Printer name> or <DefaultPrinter name>
912 if (p
== NULL
&& value
)
915 * Add the printer and a base file type...
918 cupsdLogMessage(CUPSD_LOG_DEBUG
,
919 "cupsdLoadAllPrinters: Loading printer %s...", value
);
921 p
= cupsdAddPrinter(value
);
923 p
->state
= IPP_PRINTER_IDLE
;
926 * Set the default printer as needed...
929 if (!strcasecmp(line
, "<DefaultPrinter"))
934 cupsdLogMessage(CUPSD_LOG_ERROR
,
935 "Syntax error on line %d of printers.conf.", linenum
);
939 else if (!strcasecmp(line
, "</Printer>"))
944 * Close out the current printer...
947 cupsdSetPrinterAttrs(p
);
948 cupsdAddPrinterHistory(p
);
950 if (p
->device_uri
&& strncmp(p
->device_uri
, "file:", 5) &&
951 p
->state
!= IPP_PRINTER_STOPPED
)
954 * See if the backend exists...
957 snprintf(line
, sizeof(line
), "%s/backend/%s", ServerBin
,
960 if ((valueptr
= strchr(line
+ strlen(ServerBin
), ':')) != NULL
)
961 *valueptr
= '\0'; /* Chop everything but URI scheme */
966 * Backend does not exist, stop printer...
969 p
->state
= IPP_PRINTER_STOPPED
;
970 snprintf(p
->state_message
, sizeof(p
->state_message
),
971 "Backend %s does not exist!", line
);
979 cupsdLogMessage(CUPSD_LOG_ERROR
,
980 "Syntax error on line %d of printers.conf.", linenum
);
986 cupsdLogMessage(CUPSD_LOG_ERROR
,
987 "Syntax error on line %d of printers.conf.", linenum
);
990 else if (!strcasecmp(line
, "Info"))
993 cupsdSetString(&p
->info
, value
);
995 else if (!strcasecmp(line
, "Location"))
998 cupsdSetString(&p
->location
, value
);
1000 else if (!strcasecmp(line
, "DeviceURI"))
1003 cupsdSetString(&p
->device_uri
, value
);
1006 cupsdLogMessage(CUPSD_LOG_ERROR
,
1007 "Syntax error on line %d of printers.conf.", linenum
);
1011 else if (!strcasecmp(line
, "PortMonitor"))
1013 if (value
&& strcmp(value
, "none"))
1014 cupsdSetString(&p
->port_monitor
, value
);
1016 cupsdClearString(&p
->port_monitor
);
1019 cupsdLogMessage(CUPSD_LOG_ERROR
,
1020 "Syntax error on line %d of printers.conf.", linenum
);
1024 else if (!strcasecmp(line
, "State"))
1027 * Set the initial queue state...
1030 if (value
&& !strcasecmp(value
, "idle"))
1031 p
->state
= IPP_PRINTER_IDLE
;
1032 else if (value
&& !strcasecmp(value
, "stopped"))
1033 p
->state
= IPP_PRINTER_STOPPED
;
1036 cupsdLogMessage(CUPSD_LOG_ERROR
,
1037 "Syntax error on line %d of printers.conf.", linenum
);
1041 else if (!strcasecmp(line
, "StateMessage"))
1044 * Set the initial queue state message...
1048 strlcpy(p
->state_message
, value
, sizeof(p
->state_message
));
1050 else if (!strcasecmp(line
, "StateTime"))
1053 * Set the state time...
1057 p
->state_time
= atoi(value
);
1059 else if (!strcasecmp(line
, "Accepting"))
1062 * Set the initial accepting state...
1066 (!strcasecmp(value
, "yes") ||
1067 !strcasecmp(value
, "on") ||
1068 !strcasecmp(value
, "true")))
1071 (!strcasecmp(value
, "no") ||
1072 !strcasecmp(value
, "off") ||
1073 !strcasecmp(value
, "false")))
1077 cupsdLogMessage(CUPSD_LOG_ERROR
,
1078 "Syntax error on line %d of printers.conf.", linenum
);
1082 else if (!strcasecmp(line
, "Shared"))
1085 * Set the initial shared state...
1089 (!strcasecmp(value
, "yes") ||
1090 !strcasecmp(value
, "on") ||
1091 !strcasecmp(value
, "true")))
1094 (!strcasecmp(value
, "no") ||
1095 !strcasecmp(value
, "off") ||
1096 !strcasecmp(value
, "false")))
1100 cupsdLogMessage(CUPSD_LOG_ERROR
,
1101 "Syntax error on line %d of printers.conf.", linenum
);
1105 else if (!strcasecmp(line
, "JobSheets"))
1108 * Set the initial job sheets...
1113 for (valueptr
= value
; *valueptr
&& !isspace(*valueptr
& 255); valueptr
++);
1118 cupsdSetString(&p
->job_sheets
[0], value
);
1120 while (isspace(*valueptr
& 255))
1125 for (value
= valueptr
; *valueptr
&& !isspace(*valueptr
& 255); valueptr
++);
1130 cupsdSetString(&p
->job_sheets
[1], value
);
1135 cupsdLogMessage(CUPSD_LOG_ERROR
,
1136 "Syntax error on line %d of printers.conf.", linenum
);
1140 else if (!strcasecmp(line
, "AllowUser"))
1145 cupsdAddPrinterUser(p
, value
);
1149 cupsdLogMessage(CUPSD_LOG_ERROR
,
1150 "Syntax error on line %d of printers.conf.", linenum
);
1154 else if (!strcasecmp(line
, "DenyUser"))
1159 cupsdAddPrinterUser(p
, value
);
1163 cupsdLogMessage(CUPSD_LOG_ERROR
,
1164 "Syntax error on line %d of printers.conf.", linenum
);
1168 else if (!strcasecmp(line
, "QuotaPeriod"))
1171 p
->quota_period
= atoi(value
);
1174 cupsdLogMessage(CUPSD_LOG_ERROR
,
1175 "Syntax error on line %d of printers.conf.", linenum
);
1179 else if (!strcasecmp(line
, "PageLimit"))
1182 p
->page_limit
= atoi(value
);
1185 cupsdLogMessage(CUPSD_LOG_ERROR
,
1186 "Syntax error on line %d of printers.conf.", linenum
);
1190 else if (!strcasecmp(line
, "KLimit"))
1193 p
->k_limit
= atoi(value
);
1196 cupsdLogMessage(CUPSD_LOG_ERROR
,
1197 "Syntax error on line %d of printers.conf.", linenum
);
1201 else if (!strcasecmp(line
, "OpPolicy"))
1204 cupsdSetString(&p
->op_policy
, value
);
1207 cupsdLogMessage(CUPSD_LOG_ERROR
,
1208 "Syntax error on line %d of printers.conf.", linenum
);
1212 else if (!strcasecmp(line
, "ErrorPolicy"))
1215 cupsdSetString(&p
->error_policy
, value
);
1218 cupsdLogMessage(CUPSD_LOG_ERROR
,
1219 "Syntax error on line %d of printers.conf.", linenum
);
1226 * Something else we don't understand...
1229 cupsdLogMessage(CUPSD_LOG_ERROR
,
1230 "Unknown configuration directive %s on line %d of printers.conf.",
1240 * 'cupsdSaveAllPrinters()' - Save all printer definitions to the printers.conf
1245 cupsdSaveAllPrinters(void)
1247 int i
; /* Looping var */
1248 cups_file_t
*fp
; /* printers.conf file */
1249 char temp
[1024]; /* Temporary string */
1250 char backup
[1024]; /* printers.conf.O file */
1251 cupsd_printer_t
*printer
; /* Current printer class */
1252 time_t curtime
; /* Current time */
1253 struct tm
*curdate
; /* Current date */
1257 * Create the printers.conf file...
1260 snprintf(temp
, sizeof(temp
), "%s/printers.conf", ServerRoot
);
1261 snprintf(backup
, sizeof(backup
), "%s/printers.conf.O", ServerRoot
);
1263 if (rename(temp
, backup
))
1265 if (errno
!= ENOENT
)
1266 cupsdLogMessage(CUPSD_LOG_ERROR
,
1267 "Unable to backup printers.conf - %s", strerror(errno
));
1270 if ((fp
= cupsFileOpen(temp
, "w")) == NULL
)
1272 cupsdLogMessage(CUPSD_LOG_ERROR
,
1273 "Unable to save printers.conf - %s", strerror(errno
));
1275 if (rename(backup
, temp
))
1276 cupsdLogMessage(CUPSD_LOG_ERROR
,
1277 "Unable to restore printers.conf - %s", strerror(errno
));
1281 cupsdLogMessage(CUPSD_LOG_INFO
, "Saving printers.conf...");
1284 * Restrict access to the file...
1287 fchown(cupsFileNumber(fp
), getuid(), Group
);
1288 fchmod(cupsFileNumber(fp
), ConfigFilePerm
);
1291 * Write a small header to the file...
1294 curtime
= time(NULL
);
1295 curdate
= localtime(&curtime
);
1296 strftime(temp
, sizeof(temp
) - 1, "%Y-%m-%d %H:%M", curdate
);
1298 cupsFilePuts(fp
, "# Printer configuration file for " CUPS_SVERSION
"\n");
1299 cupsFilePrintf(fp
, "# Written by cupsd on %s\n", temp
);
1302 * Write each local printer known to the system...
1305 for (printer
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
1307 printer
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
1310 * Skip remote destinations and printer classes...
1313 if ((printer
->type
& CUPS_PRINTER_REMOTE
) ||
1314 (printer
->type
& CUPS_PRINTER_CLASS
) ||
1315 (printer
->type
& CUPS_PRINTER_IMPLICIT
))
1319 * Write printers as needed...
1322 if (printer
== DefaultPrinter
)
1323 cupsFilePrintf(fp
, "<DefaultPrinter %s>\n", printer
->name
);
1325 cupsFilePrintf(fp
, "<Printer %s>\n", printer
->name
);
1328 cupsFilePrintf(fp
, "Info %s\n", printer
->info
);
1330 if (printer
->location
)
1331 cupsFilePrintf(fp
, "Location %s\n", printer
->location
);
1333 if (printer
->device_uri
)
1334 cupsFilePrintf(fp
, "DeviceURI %s\n", printer
->device_uri
);
1336 if (printer
->port_monitor
)
1337 cupsFilePrintf(fp
, "PortMonitor %s\n", printer
->port_monitor
);
1339 if (printer
->state
== IPP_PRINTER_STOPPED
)
1341 cupsFilePuts(fp
, "State Stopped\n");
1342 cupsFilePrintf(fp
, "StateMessage %s\n", printer
->state_message
);
1345 cupsFilePuts(fp
, "State Idle\n");
1347 cupsFilePrintf(fp
, "StateTime %d\n", (int)printer
->state_time
);
1349 if (printer
->accepting
)
1350 cupsFilePuts(fp
, "Accepting Yes\n");
1352 cupsFilePuts(fp
, "Accepting No\n");
1354 if (printer
->shared
)
1355 cupsFilePuts(fp
, "Shared Yes\n");
1357 cupsFilePuts(fp
, "Shared No\n");
1359 cupsFilePrintf(fp
, "JobSheets %s %s\n", printer
->job_sheets
[0],
1360 printer
->job_sheets
[1]);
1362 cupsFilePrintf(fp
, "QuotaPeriod %d\n", printer
->quota_period
);
1363 cupsFilePrintf(fp
, "PageLimit %d\n", printer
->page_limit
);
1364 cupsFilePrintf(fp
, "KLimit %d\n", printer
->k_limit
);
1366 for (i
= 0; i
< printer
->num_users
; i
++)
1367 cupsFilePrintf(fp
, "%sUser %s\n", printer
->deny_users
? "Deny" : "Allow",
1370 if (printer
->op_policy
)
1371 cupsFilePrintf(fp
, "OpPolicy %s\n", printer
->op_policy
);
1372 if (printer
->error_policy
)
1373 cupsFilePrintf(fp
, "ErrorPolicy %s\n", printer
->error_policy
);
1375 cupsFilePuts(fp
, "</Printer>\n");
1379 * Make IRIX desktop & printer status happy
1382 write_irix_state(printer
);
1391 * 'cupsdSetPrinterAttrs()' - Set printer attributes based upon the PPD file.
1395 cupsdSetPrinterAttrs(cupsd_printer_t
*p
)/* I - Printer to setup */
1397 char uri
[HTTP_MAX_URI
];
1398 /* URI for printer */
1399 char resource
[HTTP_MAX_URI
];
1400 /* Resource portion of URI */
1401 int i
; /* Looping var */
1402 char filename
[1024]; /* Name of PPD file */
1403 int num_media
; /* Number of media options */
1404 cupsd_location_t
*auth
; /* Pointer to authentication element */
1405 const char *auth_supported
;/* Authentication supported */
1406 cups_ptype_t cupsd_printer_type
;
1407 /* Printer type data */
1408 ppd_file_t
*ppd
; /* PPD file data */
1409 ppd_option_t
*input_slot
, /* InputSlot options */
1410 *media_type
, /* MediaType options */
1411 *page_size
, /* PageSize options */
1412 *output_bin
, /* OutputBin options */
1413 *media_quality
; /* EFMediaQualityMode options */
1414 ppd_attr_t
*ppdattr
; /* PPD attribute */
1415 ipp_attribute_t
*attr
; /* Attribute data */
1416 ipp_value_t
*val
; /* Attribute value */
1417 int num_finishings
; /* Number of finishings */
1418 ipp_finish_t finishings
[5]; /* finishings-supported values */
1419 static const char * const sides
[3] = /* sides-supported values */
1427 DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p
->name
,
1431 * Make sure that we have the common attributes defined...
1435 cupsdCreateCommonData();
1438 * Clear out old filters, if any...
1441 cupsdDeletePrinterFilters(p
);
1444 * Figure out the authentication that is required for the printer.
1447 auth_supported
= "requesting-user-name";
1448 if (!(p
->type
& CUPS_PRINTER_REMOTE
))
1450 if (p
->type
& CUPS_PRINTER_CLASS
)
1451 snprintf(resource
, sizeof(resource
), "/classes/%s", p
->name
);
1453 snprintf(resource
, sizeof(resource
), "/printers/%s", p
->name
);
1455 if ((auth
= cupsdFindBest(resource
, HTTP_POST
)) == NULL
)
1456 auth
= cupsdFindPolicyOp(p
->op_policy_ptr
, IPP_PRINT_JOB
);
1460 if (auth
->type
== AUTH_BASIC
|| auth
->type
== AUTH_BASICDIGEST
)
1461 auth_supported
= "basic";
1462 else if (auth
->type
== AUTH_DIGEST
)
1463 auth_supported
= "digest";
1465 if (auth
->type
!= AUTH_NONE
)
1466 p
->type
|= CUPS_PRINTER_AUTHENTICATED
;
1468 p
->type
&= ~CUPS_PRINTER_AUTHENTICATED
;
1471 p
->type
&= ~CUPS_PRINTER_AUTHENTICATED
;
1475 * Create the required IPP attributes for a printer...
1479 ippDelete(p
->attrs
);
1481 p
->attrs
= ippNew();
1483 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1484 "uri-authentication-supported", NULL
, auth_supported
);
1485 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1486 "uri-security-supported", NULL
, "none");
1487 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "printer-name", NULL
,
1489 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location",
1490 NULL
, p
->location
? p
->location
: "");
1491 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info",
1492 NULL
, p
->info
? p
->info
: "");
1493 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "printer-more-info",
1499 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1500 "requesting-user-name-denied", p
->num_users
, NULL
,
1503 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1504 "requesting-user-name-allowed", p
->num_users
, NULL
,
1508 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1509 "job-quota-period", p
->quota_period
);
1510 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1511 "job-k-limit", p
->k_limit
);
1512 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1513 "job-page-limit", p
->page_limit
);
1515 if (NumBanners
> 0 && !(p
->type
& CUPS_PRINTER_REMOTE
))
1518 * Setup the job-sheets-default attribute...
1521 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1522 "job-sheets-default", 2, NULL
, NULL
);
1526 attr
->values
[0].string
.text
= strdup(Classification
?
1527 Classification
: p
->job_sheets
[0]);
1528 attr
->values
[1].string
.text
= strdup(Classification
?
1529 Classification
: p
->job_sheets
[1]);
1533 cupsd_printer_type
= p
->type
;
1537 if (p
->type
& CUPS_PRINTER_REMOTE
)
1540 * Tell the client this is a remote printer of some type...
1543 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1544 "printer-uri-supported", NULL
, p
->uri
);
1547 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1548 "printer-make-and-model", NULL
, p
->make_model
);
1555 * Assign additional attributes depending on whether this is a printer
1559 p
->type
&= ~CUPS_PRINTER_OPTIONS
;
1561 if (p
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1566 * Add class-specific attributes...
1569 if ((p
->type
& CUPS_PRINTER_IMPLICIT
) && p
->num_printers
> 0 &&
1570 p
->printers
[0]->make_model
)
1571 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1572 "printer-make-and-model", NULL
, p
->printers
[0]->make_model
);
1574 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1575 "printer-make-and-model", NULL
, "Local Printer Class");
1577 if (p
->num_printers
> 0)
1580 * Add a list of member URIs and names...
1583 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1584 "member-uris", p
->num_printers
, NULL
, NULL
);
1585 p
->type
|= CUPS_PRINTER_OPTIONS
;
1587 for (i
= 0; i
< p
->num_printers
; i
++)
1590 attr
->values
[i
].string
.text
= strdup(p
->printers
[i
]->uri
);
1592 p
->type
&= ~CUPS_PRINTER_OPTIONS
| p
->printers
[i
]->type
;
1595 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1596 "member-names", p
->num_printers
, NULL
, NULL
);
1600 for (i
= 0; i
< p
->num_printers
; i
++)
1601 attr
->values
[i
].string
.text
= strdup(p
->printers
[i
]->name
);
1608 * Add printer-specific attributes... Start by sanitizing the device
1609 * URI so it doesn't have a username or password in it...
1613 strcpy(uri
, "file:/dev/null");
1614 else if (strstr(p
->device_uri
, "://") != NULL
)
1617 * http://..., ipp://..., etc.
1620 cupsdSanitizeURI(p
->device_uri
, uri
, sizeof(uri
));
1625 * file:..., serial:..., etc.
1628 strlcpy(uri
, p
->device_uri
, sizeof(uri
));
1631 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1635 * Assign additional attributes from the PPD file (if any)...
1638 p
->type
|= CUPS_PRINTER_BW
;
1639 finishings
[0] = IPP_FINISHINGS_NONE
;
1642 snprintf(filename
, sizeof(filename
), "%s/ppd/%s.ppd", ServerRoot
,
1645 if ((ppd
= ppdOpenFile(filename
)) != NULL
)
1648 * Add make/model and other various attributes...
1651 if (ppd
->color_device
)
1652 p
->type
|= CUPS_PRINTER_COLOR
;
1653 if (ppd
->variable_sizes
)
1654 p
->type
|= CUPS_PRINTER_VARIABLE
;
1655 if (!ppd
->manual_copies
)
1656 p
->type
|= CUPS_PRINTER_COPIES
;
1657 if ((ppdattr
= ppdFindAttr(ppd
, "cupsFax", NULL
)) != NULL
)
1658 if (ppdattr
->value
&& !strcasecmp(ppdattr
->value
, "true"))
1659 p
->type
|= CUPS_PRINTER_FAX
;
1661 ippAddBoolean(p
->attrs
, IPP_TAG_PRINTER
, "color-supported",
1663 if (ppd
->throughput
)
1664 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1665 "pages-per-minute", ppd
->throughput
);
1668 cupsdSetString(&p
->make_model
, ppd
->nickname
);
1669 else if (ppd
->modelname
)
1670 cupsdSetString(&p
->make_model
, ppd
->modelname
);
1672 cupsdSetString(&p
->make_model
, "Bad PPD File");
1675 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1676 "printer-make-and-model", NULL
, p
->make_model
);
1679 * Add media options from the PPD file...
1682 if ((input_slot
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1683 num_media
= input_slot
->num_choices
;
1687 if ((media_type
= ppdFindOption(ppd
, "MediaType")) != NULL
)
1688 num_media
+= media_type
->num_choices
;
1690 if ((page_size
= ppdFindOption(ppd
, "PageSize")) != NULL
)
1691 num_media
+= page_size
->num_choices
;
1693 if ((media_quality
= ppdFindOption(ppd
, "EFMediaQualityMode")) != NULL
)
1694 num_media
+= media_quality
->num_choices
;
1698 cupsdLogMessage(CUPSD_LOG_CRIT
, "cupsdSetPrinterAttrs: The PPD file for printer %s "
1699 "contains no media options and is therefore "
1700 "invalid!", p
->name
);
1704 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1705 "media-supported", num_media
, NULL
, NULL
);
1710 if (input_slot
!= NULL
)
1711 for (i
= 0; i
< input_slot
->num_choices
; i
++, val
++)
1712 val
->string
.text
= strdup(input_slot
->choices
[i
].choice
);
1714 if (media_type
!= NULL
)
1715 for (i
= 0; i
< media_type
->num_choices
; i
++, val
++)
1716 val
->string
.text
= strdup(media_type
->choices
[i
].choice
);
1718 if (media_quality
!= NULL
)
1719 for (i
= 0; i
< media_quality
->num_choices
; i
++, val
++)
1720 val
->string
.text
= strdup(media_quality
->choices
[i
].choice
);
1722 if (page_size
!= NULL
)
1724 for (i
= 0; i
< page_size
->num_choices
; i
++, val
++)
1725 val
->string
.text
= strdup(page_size
->choices
[i
].choice
);
1727 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1728 NULL
, page_size
->defchoice
);
1730 else if (input_slot
!= NULL
)
1731 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1732 NULL
, input_slot
->defchoice
);
1733 else if (media_type
!= NULL
)
1734 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1735 NULL
, media_type
->defchoice
);
1736 else if (media_quality
!= NULL
)
1737 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1738 NULL
, media_quality
->defchoice
);
1740 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1749 if ((output_bin
= ppdFindOption(ppd
, "OutputBin")) != NULL
)
1751 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1752 "output-bin-supported", output_bin
->num_choices
,
1757 for (i
= 0, val
= attr
->values
;
1758 i
< output_bin
->num_choices
;
1760 val
->string
.text
= strdup(output_bin
->choices
[i
].choice
);
1768 if (ppdFindOption(ppd
, "Duplex") != NULL
)
1770 p
->type
|= CUPS_PRINTER_DUPLEX
;
1772 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "sides-supported",
1774 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "sides-default",
1778 if (ppdFindOption(ppd
, "Collate") != NULL
)
1779 p
->type
|= CUPS_PRINTER_COLLATE
;
1781 if (ppdFindOption(ppd
, "StapleLocation") != NULL
)
1783 p
->type
|= CUPS_PRINTER_STAPLE
;
1784 finishings
[num_finishings
++] = IPP_FINISHINGS_STAPLE
;
1787 if (ppdFindOption(ppd
, "BindEdge") != NULL
)
1789 p
->type
|= CUPS_PRINTER_BIND
;
1790 finishings
[num_finishings
++] = IPP_FINISHINGS_BIND
;
1793 for (i
= 0; i
< ppd
->num_sizes
; i
++)
1794 if (ppd
->sizes
[i
].length
> 1728)
1795 p
->type
|= CUPS_PRINTER_LARGE
;
1796 else if (ppd
->sizes
[i
].length
> 1008)
1797 p
->type
|= CUPS_PRINTER_MEDIUM
;
1799 p
->type
|= CUPS_PRINTER_SMALL
;
1802 * Add a filter from application/vnd.cups-raw to printer/name to
1803 * handle "raw" printing by users.
1806 cupsdAddPrinterFilter(p
, "application/vnd.cups-raw 0 -");
1809 * Add any filters in the PPD file...
1812 DEBUG_printf(("ppd->num_filters = %d\n", ppd
->num_filters
));
1813 for (i
= 0; i
< ppd
->num_filters
; i
++)
1815 DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i
, ppd
->filters
[i
]));
1816 cupsdAddPrinterFilter(p
, ppd
->filters
[i
]);
1819 if (ppd
->num_filters
== 0)
1822 * If there are no filters, add a PostScript printing filter.
1825 cupsdAddPrinterFilter(p
, "application/vnd.cups-postscript 0 -");
1829 * Show current and available port monitors for this printer...
1832 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "port-monitor",
1833 NULL
, p
->port_monitor
? p
->port_monitor
: "none");
1836 for (i
= 1, ppdattr
= ppdFindAttr(ppd
, "cupsPortMonitor", NULL
);
1838 i
++, ppdattr
= ppdFindNextAttr(ppd
, "cupsPortMonitor", NULL
));
1842 if (strstr(ppd
->protocols
, "TBCP"))
1844 else if (strstr(ppd
->protocols
, "BCP"))
1848 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1849 "port-monitor-supported", i
, NULL
, NULL
);
1851 attr
->values
[0].string
.text
= strdup("none");
1853 for (i
= 1, ppdattr
= ppdFindAttr(ppd
, "cupsPortMonitor", NULL
);
1855 i
++, ppdattr
= ppdFindNextAttr(ppd
, "cupsPortMonitor", NULL
))
1856 attr
->values
[i
].string
.text
= strdup(ppdattr
->value
);
1860 if (strstr(ppd
->protocols
, "TBCP"))
1861 attr
->values
[i
].string
.text
= strdup("tbcp");
1862 else if (strstr(ppd
->protocols
, "BCP"))
1863 attr
->values
[i
].string
.text
= strdup("bcp");
1867 * Close the PPD and set the type...
1872 cupsd_printer_type
= p
->type
;
1874 else if (!access(filename
, 0))
1876 int pline
; /* PPD line number */
1877 ppd_status_t pstatus
; /* PPD load status */
1880 pstatus
= ppdLastError(&pline
);
1882 cupsdLogMessage(CUPSD_LOG_ERROR
, "PPD file for %s cannot be loaded!", p
->name
);
1884 if (pstatus
<= PPD_ALLOC_ERROR
)
1885 cupsdLogMessage(CUPSD_LOG_ERROR
, "%s", strerror(errno
));
1887 cupsdLogMessage(CUPSD_LOG_ERROR
, "%s on line %d.", ppdErrorString(pstatus
),
1890 cupsdLogMessage(CUPSD_LOG_INFO
, "Hint: Run \"cupstestppd %s\" and fix any errors.",
1894 * Add a filter from application/vnd.cups-raw to printer/name to
1895 * handle "raw" printing by users.
1898 cupsdAddPrinterFilter(p
, "application/vnd.cups-raw 0 -");
1901 * Add a PostScript filter, since this is still possibly PS printer.
1904 cupsdAddPrinterFilter(p
, "application/vnd.cups-postscript 0 -");
1909 * If we have an interface script, add a filter entry for it...
1912 snprintf(filename
, sizeof(filename
), "%s/interfaces/%s", ServerRoot
,
1914 if (access(filename
, X_OK
) == 0)
1917 * Yes, we have a System V style interface script; use it!
1920 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1921 "printer-make-and-model", NULL
, "Local System V Printer");
1923 snprintf(filename
, sizeof(filename
), "*/* 0 %s/interfaces/%s",
1924 ServerRoot
, p
->name
);
1925 cupsdAddPrinterFilter(p
, filename
);
1927 else if (p
->device_uri
&&
1928 !strncmp(p
->device_uri
, "ipp://", 6) &&
1929 (strstr(p
->device_uri
, "/printers/") != NULL
||
1930 strstr(p
->device_uri
, "/classes/") != NULL
))
1933 * Tell the client this is really a hard-wired remote printer.
1936 cupsd_printer_type
|= CUPS_PRINTER_REMOTE
;
1939 * Point the printer-uri-supported attribute to the
1943 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1944 "printer-uri-supported", NULL
, p
->device_uri
);
1947 * Then set the make-and-model accordingly...
1950 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1951 "printer-make-and-model", NULL
, "Remote Printer");
1954 * Print all files directly...
1962 * Otherwise we have neither - treat this as a "dumb" printer
1963 * with no PPD file...
1966 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1967 "printer-make-and-model", NULL
, "Local Raw Printer");
1973 ippAddIntegers(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
1974 "finishings-supported", num_finishings
, (int *)finishings
);
1975 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
1976 "finishings-default", IPP_FINISHINGS_NONE
);
1981 * Add the CUPS-specific printer-type attribute...
1985 p
->type
|= CUPS_PRINTER_NOT_SHARED
;
1987 p
->type
&= ~CUPS_PRINTER_NOT_SHARED
;
1989 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-type",
1990 cupsd_printer_type
);
1992 DEBUG_printf(("cupsdSetPrinterAttrs: leaving name = %s, type = %x\n", p
->name
,
1997 * Write the IRIX printer config and status files...
2000 write_irix_config(p
);
2001 write_irix_state(p
);
2007 * 'cupsdSetPrinterReasons()' - Set/update the reasons strings.
2011 cupsdSetPrinterReasons(
2012 cupsd_printer_t
*p
, /* I - Printer */
2013 const char *s
) /* I - Reasons strings */
2015 int i
; /* Looping var */
2016 const char *sptr
; /* Pointer into reasons */
2017 char reason
[255], /* Reason string */
2018 *rptr
; /* Pointer into reason */
2021 if (s
[0] == '-' || s
[0] == '+')
2024 * Add/remove reasons...
2032 * Replace reasons...
2037 for (i
= 0; i
< p
->num_reasons
; i
++)
2038 free(p
->reasons
[i
]);
2044 * Loop through all of the reasons...
2050 * Skip leading whitespace and commas...
2053 while (isspace(*sptr
& 255) || *sptr
== ',')
2056 for (rptr
= reason
; *sptr
&& !isspace(*sptr
& 255) && *sptr
!= ','; sptr
++)
2057 if (rptr
< (reason
+ sizeof(reason
) - 1))
2071 for (i
= 0; i
< p
->num_reasons
; i
++)
2072 if (!strcasecmp(reason
, p
->reasons
[i
]))
2075 * Found a match, so remove it...
2079 free(p
->reasons
[i
]);
2081 if (i
< p
->num_reasons
)
2082 memmove(p
->reasons
+ i
, p
->reasons
+ i
+ 1,
2083 (p
->num_reasons
- i
) * sizeof(char *));
2088 else if (p
->num_reasons
< (int)(sizeof(p
->reasons
) / sizeof(p
->reasons
[0])))
2094 for (i
= 0; i
< p
->num_reasons
; i
++)
2095 if (!strcasecmp(reason
, p
->reasons
[i
]))
2098 if (i
>= p
->num_reasons
)
2100 p
->reasons
[i
] = strdup(reason
);
2109 * 'cupsdSetPrinterState()' - Update the current state of a printer.
2113 cupsdSetPrinterState(
2114 cupsd_printer_t
*p
, /* I - Printer to change */
2115 ipp_pstate_t s
, /* I - New state */
2116 int update
) /* I - Update printers.conf? */
2118 ipp_pstate_t old_state
; /* Old printer state */
2122 * Can't set status of remote printers...
2125 if (p
->type
& CUPS_PRINTER_REMOTE
)
2129 * Set the new state...
2132 old_state
= p
->state
;
2138 * Let the browse code know this needs to be updated...
2142 p
->state_time
= time(NULL
);
2146 write_irix_state(p
);
2150 cupsdAddPrinterHistory(p
);
2153 * Save the printer configuration if a printer goes from idle or processing
2154 * to stopped (or visa-versa)...
2157 if ((old_state
== IPP_PRINTER_STOPPED
) != (s
== IPP_PRINTER_STOPPED
) &&
2160 if (p
->type
& CUPS_PRINTER_CLASS
)
2161 cupsdSaveAllClasses();
2163 cupsdSaveAllPrinters();
2169 * 'cupsdStopPrinter()' - Stop a printer from printing any jobs...
2173 cupsdStopPrinter(cupsd_printer_t
*p
, /* I - Printer to stop */
2174 int update
)/* I - Update printers.conf? */
2176 cupsd_job_t
*job
; /* Active print job */
2180 * Set the printer state...
2183 cupsdSetPrinterState(p
, IPP_PRINTER_STOPPED
, update
);
2186 * See if we have a job printing on this printer...
2192 * Get pointer to job...
2195 job
= (cupsd_job_t
*)p
->job
;
2201 cupsdStopJob(job
, 0);
2204 * Reset the state to pending...
2207 job
->state
->values
[0].integer
= IPP_JOB_PENDING
;
2215 * 'cupsdUpdatePrinters()' - Update printers after a partial reload.
2219 cupsdUpdatePrinters(void)
2221 cupsd_printer_t
*p
; /* Current printer */
2225 * Loop through the printers and recreate the printer attributes
2226 * for any local printers since the policy and/or access control
2227 * stuff may have changed. Also, if browsing is disabled, remove
2228 * any remote printers...
2231 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
2233 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
2235 if (!Browsing
&& (p
->type
& (CUPS_PRINTER_IMPLICIT
| CUPS_PRINTER_REMOTE
)))
2237 if (p
->type
& CUPS_PRINTER_IMPLICIT
)
2238 cupsArrayRemove(ImplicitPrinters
, p
);
2240 cupsArraySave(Printers
);
2241 cupsdDeletePrinter(p
, 0);
2242 cupsArrayRestore(Printers
);
2245 else if (!(p
->type
& CUPS_PRINTER_REMOTE
))
2246 cupsdSetPrinterAttrs(p
);
2249 * Update the operation policy pointer...
2252 if ((p
->op_policy_ptr
= cupsdFindPolicy(p
->op_policy
)) == NULL
)
2253 p
->op_policy_ptr
= DefaultPolicyPtr
;
2259 * 'cupsdValidateDest()' - Validate a printer/class destination.
2262 const char * /* O - Printer or class name */
2264 const char *hostname
, /* I - Host name */
2265 const char *resource
, /* I - Resource name */
2266 cups_ptype_t
*dtype
, /* O - Type (printer or class) */
2267 cupsd_printer_t
**printer
) /* O - Printer pointer */
2269 cupsd_printer_t
*p
; /* Current printer */
2270 char localname
[1024],/* Localized hostname */
2271 *lptr
, /* Pointer into localized hostname */
2272 *sptr
; /* Pointer into server name */
2275 DEBUG_printf(("cupsdValidateDest(\"%s\", \"%s\", %p, %p)\n", hostname
, resource
,
2279 * Initialize return values...
2285 *dtype
= (cups_ptype_t
)0;
2288 * See if the resource is a class or printer...
2291 if (!strncmp(resource
, "/classes/", 9))
2299 else if (!strncmp(resource
, "/printers/", 10))
2310 * Bad resource name...
2317 * See if the printer or class name exists...
2320 p
= cupsdFindDest(resource
);
2322 if (p
== NULL
&& strchr(resource
, '@') == NULL
)
2329 *dtype
= p
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
|
2330 CUPS_PRINTER_REMOTE
);
2335 * Change localhost to the server name...
2338 if (!strcasecmp(hostname
, "localhost"))
2339 hostname
= ServerName
;
2341 strlcpy(localname
, hostname
, sizeof(localname
));
2343 if (!strcasecmp(hostname
, ServerName
))
2346 * Localize the hostname...
2349 lptr
= strchr(localname
, '.');
2350 sptr
= strchr(ServerName
, '.');
2352 if (sptr
!= NULL
&& lptr
!= NULL
)
2355 * Strip the common domain name components...
2358 while (lptr
!= NULL
)
2360 if (!strcasecmp(lptr
, sptr
))
2366 lptr
= strchr(lptr
+ 1, '.');
2371 DEBUG_printf(("localized hostname is \"%s\"...\n", localname
));
2374 * Find a matching printer or class...
2377 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
2379 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
2380 if (!strcasecmp(p
->hostname
, localname
) &&
2381 !strcasecmp(p
->name
, resource
))
2386 *dtype
= p
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
|
2387 CUPS_PRINTER_REMOTE
);
2396 * 'cupsdWritePrintcap()' - Write a pseudo-printcap file for older applications
2401 cupsdWritePrintcap(void)
2403 cups_file_t
*fp
; /* printcap file */
2404 cupsd_printer_t
*p
; /* Current printer */
2409 * Update the IRIX printer state for the default printer; if
2410 * no printers remain, then the default printer file will be
2414 write_irix_state(DefaultPrinter
);
2418 * See if we have a printcap file; if not, don't bother writing it.
2421 if (!Printcap
|| !*Printcap
)
2425 * Open the printcap file...
2428 if ((fp
= cupsFileOpen(Printcap
, "w")) == NULL
)
2432 * Put a comment header at the top so that users will know where the
2433 * data has come from...
2436 cupsFilePuts(fp
, "# This file was automatically generated by cupsd(8) from the\n");
2437 cupsFilePrintf(fp
, "# %s/printers.conf file. All changes to this file\n",
2439 cupsFilePuts(fp
, "# will be lost.\n");
2444 * Write a new printcap with the current list of printers.
2447 switch (PrintcapFormat
)
2451 * Each printer is put in the file as:
2461 cupsFilePrintf(fp
, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter
->name
,
2462 DefaultPrinter
->info
, ServerName
, DefaultPrinter
->name
);
2464 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
2466 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
2467 if (p
!= DefaultPrinter
)
2468 cupsFilePrintf(fp
, "%s|%s:rm=%s:rp=%s:\n", p
->name
, p
->info
,
2469 ServerName
, p
->name
);
2472 case PRINTCAP_SOLARIS
:
2474 * Each printer is put in the file as:
2476 * _all:all=Printer1,Printer2,Printer3,...,PrinterN
2477 * _default:use=DefaultPrinter
2479 * :bsdaddr=ServerName,Printer1:\
2480 * :description=Description:
2482 * :bsdaddr=ServerName,Printer2:\
2483 * :description=Description:
2485 * :bsdaddr=ServerName,Printer3:\
2486 * :description=Description:
2489 * :bsdaddr=ServerName,PrinterN:\
2490 * :description=Description:
2493 cupsFilePuts(fp
, "_all:all=");
2494 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
2496 p
= (cupsd_printer_t
*)cupsArrayCurrent(Printers
))
2497 cupsFilePrintf(fp
, "%s%c", p
->name
,
2498 cupsArrayNext(Printers
) ? ',' : '\n');
2501 cupsFilePrintf(fp
, "_default:use=%s\n", DefaultPrinter
->name
);
2503 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
2505 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
2506 cupsFilePrintf(fp
, "%s:\\\n"
2507 "\t:bsdaddr=%s,%s:\\\n"
2508 "\t:description=%s:\n",
2509 p
->name
, ServerName
, p
->name
, p
->info
? p
->info
: "");
2523 * 'cupsdSanitizeURI()' - Sanitize a device URI...
2526 char * /* O - New device URI */
2527 cupsdSanitizeURI(const char *uri
, /* I - Original device URI */
2528 char *buffer
, /* O - New device URI */
2529 int buflen
) /* I - Size of new device URI buffer */
2531 char *start
, /* Start of data after scheme */
2532 *slash
, /* First slash after scheme:// */
2533 *ptr
; /* Pointer into user@host:port part */
2537 * Range check input...
2540 if (!uri
|| !buffer
|| buflen
< 2)
2544 * Copy the device URI to the new buffer...
2547 strlcpy(buffer
, uri
, buflen
);
2550 * Find the end of the scheme:// part...
2553 if ((ptr
= strchr(buffer
, ':')) == NULL
)
2554 return (buffer
); /* No scheme: part... */
2556 for (start
= ptr
+ 1; *start
; start
++)
2561 * Find the next slash (/) in the URI...
2564 if ((slash
= strchr(start
, '/')) == NULL
)
2565 slash
= start
+ strlen(start
); /* No slash, point to the end */
2568 * Check for an @ sign before the slash...
2571 if ((ptr
= strchr(start
, '@')) != NULL
&& ptr
< slash
)
2574 * Found an @ sign and it is before the resource part, so we have
2575 * an authentication string. Copy the remaining URI over the
2576 * authentication string...
2579 _cups_strcpy(start
, ptr
+ 1);
2583 * Return the new device URI...
2591 * 'compare_printers()' - Compare two printers.
2594 static int /* O - Result of comparison */
2595 compare_printers(void *first
, /* I - First printer */
2596 void *second
, /* I - Second printer */
2597 void *data
) /* I - App data (not used) */
2599 return (strcasecmp(((cupsd_printer_t
*)first
)->name
,
2600 ((cupsd_printer_t
*)second
)->name
));
2606 * 'write_irix_config()' - Update the config files used by the IRIX
2611 write_irix_config(cupsd_printer_t
*p
) /* I - Printer to update */
2613 char filename
[1024]; /* Interface script filename */
2614 cups_file_t
*fp
; /* Interface script file */
2615 int tag
; /* Status tag value */
2620 * Add dummy interface and GUI scripts to fool SGI's "challenged" printing
2621 * tools. First the interface script that tells the tools what kind of
2622 * printer we have...
2625 snprintf(filename
, sizeof(filename
), "/var/spool/lp/interface/%s", p
->name
);
2627 if (p
->type
& CUPS_PRINTER_CLASS
)
2629 else if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
2631 cupsFilePuts(fp
, "#!/bin/sh\n");
2633 if ((attr
= ippFindAttribute(p
->attrs
, "printer-make-and-model",
2634 IPP_TAG_TEXT
)) != NULL
)
2635 cupsFilePrintf(fp
, "NAME=\"%s\"\n", attr
->values
[0].string
.text
);
2636 else if (p
->type
& CUPS_PRINTER_CLASS
)
2637 cupsFilePuts(fp
, "NAME=\"Printer Class\"\n");
2639 cupsFilePuts(fp
, "NAME=\"Remote Destination\"\n");
2641 if (p
->type
& CUPS_PRINTER_COLOR
)
2642 cupsFilePuts(fp
, "TYPE=ColorPostScript\n");
2644 cupsFilePuts(fp
, "TYPE=MonoPostScript\n");
2646 cupsFilePrintf(fp
, "HOSTNAME=%s\n", ServerName
);
2647 cupsFilePrintf(fp
, "HOSTPRINTER=%s\n", p
->name
);
2651 chmod(filename
, 0755);
2652 chown(filename
, User
, Group
);
2656 * Then the member file that tells which device file the queue is connected
2657 * to... Networked printers use "/dev/null" in this file, so that's what
2658 * we use (the actual device URI can confuse some apps...)
2661 snprintf(filename
, sizeof(filename
), "/var/spool/lp/member/%s", p
->name
);
2663 if (p
->type
& CUPS_PRINTER_CLASS
)
2665 else if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
2667 cupsFilePuts(fp
, "/dev/null\n");
2671 chmod(filename
, 0644);
2672 chown(filename
, User
, Group
);
2676 * The gui_interface file is a script or program that launches a GUI
2677 * option panel for the printer, using options specified on the
2678 * command-line in the third argument. The option panel must send
2679 * any printing options to stdout on a single line when the user
2680 * accepts them, or nothing if the user cancels the dialog.
2682 * The default options panel program is /usr/bin/glpoptions, from
2683 * the ESP Print Pro software. You can select another using the
2684 * PrintcapGUI option.
2687 snprintf(filename
, sizeof(filename
), "/var/spool/lp/gui_interface/ELF/%s.gui", p
->name
);
2689 if (p
->type
& CUPS_PRINTER_CLASS
)
2691 else if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
2693 cupsFilePuts(fp
, "#!/bin/sh\n");
2694 cupsFilePrintf(fp
, "%s -d %s -o \"$3\"\n", PrintcapGUI
, p
->name
);
2698 chmod(filename
, 0755);
2699 chown(filename
, User
, Group
);
2703 * The POD config file is needed by the printstatus command to show
2704 * the printer location and device.
2707 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.config", p
->name
);
2709 if (p
->type
& CUPS_PRINTER_CLASS
)
2711 else if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
2713 cupsFilePrintf(fp
, "Printer Class | %s\n",
2714 (p
->type
& CUPS_PRINTER_COLOR
) ? "ColorPostScript" : "MonoPostScript");
2715 cupsFilePrintf(fp
, "Printer Model | %s\n", p
->make_model
? p
->make_model
: "");
2716 cupsFilePrintf(fp
, "Location Code | %s\n", p
->location
? p
->location
: "");
2717 cupsFilePrintf(fp
, "Physical Location | %s\n", p
->info
? p
->info
: "");
2718 cupsFilePrintf(fp
, "Port Path | %s\n", p
->device_uri
? p
->device_uri
: "");
2719 cupsFilePrintf(fp
, "Config Path | /var/spool/lp/pod/%s.config\n", p
->name
);
2720 cupsFilePrintf(fp
, "Active Status Path | /var/spool/lp/pod/%s.status\n", p
->name
);
2721 cupsFilePuts(fp
, "Status Update Wait | 10 seconds\n");
2725 chmod(filename
, 0664);
2726 chown(filename
, User
, Group
);
2732 * 'write_irix_state()' - Update the status files used by IRIX printing
2737 write_irix_state(cupsd_printer_t
*p
) /* I - Printer to update */
2739 char filename
[1024]; /* Interface script filename */
2740 cups_file_t
*fp
; /* Interface script file */
2741 int tag
; /* Status tag value */
2747 * The POD status file is needed for the printstatus window to
2748 * provide the current status of the printer.
2751 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.status", p
->name
);
2753 if (p
->type
& CUPS_PRINTER_CLASS
)
2755 else if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
2757 cupsFilePrintf(fp
, "Operational Status | %s\n",
2758 (p
->state
== IPP_PRINTER_IDLE
) ? "Idle" :
2759 (p
->state
== IPP_PRINTER_PROCESSING
) ? "Busy" :
2761 cupsFilePrintf(fp
, "Information | 01 00 00 | %s\n", CUPS_SVERSION
);
2762 cupsFilePrintf(fp
, "Information | 02 00 00 | Device URI: %s\n",
2763 p
->device_uri
? p
->device_uri
: "");
2764 cupsFilePrintf(fp
, "Information | 03 00 00 | %s jobs\n",
2765 p
->accepting
? "Accepting" : "Not accepting");
2766 cupsFilePrintf(fp
, "Information | 04 00 00 | %s\n", p
->state_message
);
2770 chmod(filename
, 0664);
2771 chown(filename
, User
, Group
);
2775 * The activeicons file is needed to provide desktop icons for printers:
2777 * [ quoted from /usr/lib/print/tagit ]
2779 * --- Type of printer tags (base values)
2781 * Dumb=66048 # 0x10200
2782 * DumbColor=66080 # 0x10220
2783 * Raster=66112 # 0x10240
2784 * ColorRaster=66144 # 0x10260
2785 * Plotter=66176 # 0x10280
2786 * PostScript=66208 # 0x102A0
2787 * ColorPostScript=66240 # 0x102C0
2788 * MonoPostScript=66272 # 0x102E0
2790 * --- Printer state modifiers for local printers
2795 * Unknown=3 # 0x3 (Faulted due to unknown reason)
2797 * --- Printer state modifiers for network printers
2801 * NetFaulted=10 # 0xA
2802 * NetUnknown=11 # 0xB (Faulted due to unknown reason)
2805 snprintf(filename
, sizeof(filename
), "/var/spool/lp/activeicons/%s", p
->name
);
2807 if (p
->type
& CUPS_PRINTER_CLASS
)
2809 else if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
2811 if (p
->type
& CUPS_PRINTER_COLOR
)
2816 if (p
->type
& CUPS_PRINTER_REMOTE
)
2819 if (p
->state
== IPP_PRINTER_PROCESSING
)
2822 else if (p
->state
== IPP_PRINTER_STOPPED
)
2825 cupsFilePuts(fp
, "#!/bin/sh\n");
2826 cupsFilePrintf(fp
, "#Tag %d\n", tag
);
2830 chmod(filename
, 0755);
2831 chown(filename
, User
, Group
);
2836 * The default file is needed by the printers window to show
2837 * the default printer.
2840 snprintf(filename
, sizeof(filename
), "/var/spool/lp/default");
2842 if (DefaultPrinter
!= NULL
)
2844 if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
2846 cupsFilePrintf(fp
, "%s\n", DefaultPrinter
->name
);
2850 chmod(filename
, 0644);
2851 chown(filename
, User
, Group
);