2 * "$Id: printers.c,v 1.93.2.8 2002/01/23 17:32:16 mike Exp $"
4 * Printer routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2002 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * AddPrinter() - Add a printer to the system.
27 * AddPrinterFilter() - Add a MIME filter for a printer.
28 * AddPrinterUser() - Add a user to the ACL.
29 * DeleteAllPrinters() - Delete all printers from the system.
30 * DeletePrinter() - Delete a printer from the system.
31 * DeletePrinterFilters() - Delete all MIME filters for a printer.
32 * FindPrinter() - Find a printer in the list.
33 * FreePrinterUsers() - Free allow/deny users.
34 * LoadAllPrinters() - Load printers from the printers.conf file.
35 * SaveAllPrinters() - Save all printer definitions to the printers.conf
36 * SetPrinterAttrs() - Set printer attributes based upon the PPD file.
37 * SetPrinterState() - Update the current state of a printer.
38 * SortPrinters() - Sort the printer list when a printer name is
40 * StopPrinter() - Stop a printer from printing any jobs...
41 * ValidateDest() - Validate a printer/class destination.
42 * write_irix_state() - Update the status files used by IRIX printing
44 * write_printcap() - Write a pseudo-printcap file for older
45 * applications that need it...
49 * Include necessary headers...
59 static void write_printcap(void);
61 static void write_irix_state(printer_t
*p
);
66 * 'AddPrinter()' - Add a printer to the system.
69 printer_t
* /* O - New printer */
70 AddPrinter(const char *name
) /* I - Name of printer */
72 printer_t
*p
, /* New printer */
73 *current
, /* Current printer in list */
74 *prev
; /* Previous printer in list */
77 DEBUG_printf(("AddPrinter(\"%s\")\n", name
));
80 * Range check input...
87 * Create a new printer entity...
90 if ((p
= calloc(1, sizeof(printer_t
))) == NULL
)
93 strncpy(p
->name
, name
, sizeof(p
->name
) - 1);
94 strncpy(p
->hostname
, ServerName
, sizeof(p
->hostname
) - 1);
97 if (Listeners
[0].address
.addr
.sa_family
== AF_INET6
)
98 snprintf(p
->uri
, sizeof(p
->uri
), "ipp://%s:%d/printers/%s", ServerName
,
99 ntohs(Listeners
[0].address
.ipv6
.sin6_port
), name
);
101 #endif /* AF_INET6 */
102 snprintf(p
->uri
, sizeof(p
->uri
), "ipp://%s:%d/printers/%s", ServerName
,
103 ntohs(Listeners
[0].address
.ipv4
.sin_port
), name
);
105 p
->state
= IPP_PRINTER_STOPPED
;
107 p
->filetype
= mimeAddType(MimeDatabase
, "printer", name
);
109 strcpy(p
->job_sheets
[0], "none");
110 strcpy(p
->job_sheets
[1], "none");
113 * Setup required filters and IPP attributes...
119 * Insert the printer in the printer list alphabetically...
122 for (prev
= NULL
, current
= Printers
;
124 prev
= current
, current
= current
->next
)
125 if (strcasecmp(p
->name
, current
->name
) < 0)
129 * Insert this printer before the current one...
140 * Write a new /etc/printcap or /var/spool/lp/pstatus file.
150 * 'AddPrinterFilter()' - Add a MIME filter for a printer.
154 AddPrinterFilter(printer_t
*p
, /* I - Printer to add to */
155 const char *filter
) /* I - Filter to add */
157 int i
; /* Looping var */
158 char super
[MIME_MAX_SUPER
], /* Super-type for filter */
159 type
[MIME_MAX_TYPE
], /* Type for filter */
160 program
[1024]; /* Program/filter name */
161 int cost
; /* Cost of filter */
162 mime_type_t
**temptype
; /* MIME type looping var */
166 * Range check input...
169 if (p
== NULL
|| filter
== NULL
)
173 * Parse the filter string; it should be in the following format:
175 * super/type cost program
178 if (sscanf(filter
, "%15[^/]/%31s%d%1023s", super
, type
, &cost
, program
) != 4)
180 LogMessage(L_ERROR
, "AddPrinterFilter: Invalid filter string \"%s\"!",
186 * Add the filter to the MIME database, supporting wildcards as needed...
189 for (temptype
= MimeDatabase
->types
, i
= MimeDatabase
->num_types
;
192 if (((super
[0] == '*' && strcmp((*temptype
)->super
, "printer") != 0) ||
193 strcmp((*temptype
)->super
, super
) == 0) &&
194 (type
[0] == '*' || strcmp((*temptype
)->type
, type
) == 0))
196 LogMessage(L_DEBUG2
, "Adding filter %s/%s %s/%s %d %s",
197 (*temptype
)->super
, (*temptype
)->type
,
198 p
->filetype
->super
, p
->filetype
->type
,
200 mimeAddFilter(MimeDatabase
, *temptype
, p
->filetype
, cost
, program
);
206 * 'AddPrinterUser()' - Add a user to the ACL.
210 AddPrinterUser(printer_t
*p
, /* I - Printer */
211 const char *username
) /* I - User */
213 const char **temp
; /* Temporary array pointer */
219 if (p
->num_users
== 0)
220 temp
= malloc(sizeof(char **));
222 temp
= realloc(p
->users
, sizeof(char **) * (p
->num_users
+ 1));
228 temp
+= p
->num_users
;
230 if ((*temp
= strdup(username
)) != NULL
)
236 * 'DeleteAllPrinters()' - Delete all printers from the system.
240 DeleteAllPrinters(void)
242 printer_t
*p
, /* Pointer to current printer/class */
243 *next
; /* Pointer to next printer in list */
246 for (p
= Printers
; p
!= NULL
; p
= next
)
250 if (!(p
->type
& CUPS_PRINTER_CLASS
))
257 * 'DeletePrinter()' - Delete a printer from the system.
261 DeletePrinter(printer_t
*p
) /* I - Printer to delete */
263 printer_t
*current
, /* Current printer in list */
264 *prev
; /* Previous printer in list */
266 char filename
[1024]; /* Interface script filename */
270 DEBUG_printf(("DeletePrinter(%08x): p->name = \"%s\"...\n", p
, p
->name
));
273 * Range check input...
280 * Remove the printer from the list...
283 for (prev
= NULL
, current
= Printers
;
285 prev
= current
, current
= current
->next
)
291 LogMessage(L_ERROR
, "Tried to delete a non-existent printer %s!\n",
299 prev
->next
= p
->next
;
302 * Stop printing on this printer...
308 * Remove the dummy interface/icon/option files under IRIX...
312 snprintf(filename
, sizeof(filename
), "/var/spool/lp/interface/%s", p
->name
);
315 snprintf(filename
, sizeof(filename
), "/var/spool/lp/gui_interface/ELF/%s.gui",
319 snprintf(filename
, sizeof(filename
), "/var/spool/lp/activeicons/%s", p
->name
);
322 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.config", p
->name
);
325 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.status", p
->name
);
330 * If p is the default printer, assign the next one...
333 if (p
== DefaultPrinter
)
335 DefaultPrinter
= Printers
;
338 write_irix_state(DefaultPrinter
);
343 * Remove this printer from any classes...
346 if (!(p
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
)))
347 DeletePrinterFromClasses(p
);
350 * Free all memory used by the printer...
353 if (p
->printers
!= NULL
)
358 DeletePrinterFilters(p
);
366 * Write a new /etc/printcap file...
374 * 'DeletePrinterFilters()' - Delete all MIME filters for a printer.
378 DeletePrinterFilters(printer_t
*p
) /* I - Printer to remove from */
380 int i
; /* Looping var */
381 mime_filter_t
*filter
; /* MIME filter looping var */
385 * Range check input...
392 * Remove all filters from the MIME database that have a destination
396 for (filter
= MimeDatabase
->filters
, i
= MimeDatabase
->num_filters
;
399 if (filter
->dst
== p
->filetype
)
402 * Delete the current filter...
405 MimeDatabase
->num_filters
--;
408 memcpy(filter
, filter
+ 1, sizeof(mime_filter_t
) * (i
- 1));
416 * 'FindPrinter()' - Find a printer in the list.
419 printer_t
* /* O - Printer in list */
420 FindPrinter(const char *name
) /* I - Name of printer to find */
422 printer_t
*p
; /* Current printer */
425 for (p
= Printers
; p
!= NULL
; p
= p
->next
)
426 switch (strcasecmp(name
, p
->name
))
428 case 0 : /* name == p->name */
429 if (!(p
->type
& CUPS_PRINTER_CLASS
))
431 case 1 : /* name > p->name */
433 case -1 : /* name < p->name */
442 * 'FreePrinterUsers()' - Free allow/deny users.
446 FreePrinterUsers(printer_t
*p
) /* I - Printer */
448 int i
; /* Looping var */
451 if (!p
|| !p
->num_users
)
454 for (i
= 0; i
< p
->num_users
; i
++)
455 free((void *)p
->users
[i
]);
465 * 'LoadAllPrinters()' - Load printers from the printers.conf file.
469 LoadAllPrinters(void)
471 FILE *fp
; /* printers.conf file */
472 int linenum
; /* Current line number */
473 int len
; /* Length of line */
474 char line
[1024], /* Line from file */
475 name
[256], /* Parameter name */
476 *nameptr
, /* Pointer into name */
477 *value
, /* Pointer to value */
478 *valueptr
; /* Pointer into value */
479 printer_t
*p
; /* Current printer */
483 * Open the printers.conf file...
486 snprintf(line
, sizeof(line
), "%s/printers.conf", ServerRoot
);
487 if ((fp
= fopen(line
, "r")) == NULL
)
491 * Read printer configurations until we hit EOF...
497 while (fgets(line
, sizeof(line
), fp
) != NULL
)
502 * Skip comment lines...
509 * Strip trailing whitespace, if any...
514 while (len
> 0 && isspace(line
[len
- 1]))
521 * Extract the name from the beginning of the line...
524 for (value
= line
; isspace(*value
); value
++);
526 for (nameptr
= name
; *value
!= '\0' && !isspace(*value
) &&
527 nameptr
< (name
+ sizeof(name
) - 1);)
528 *nameptr
++ = *value
++;
531 while (isspace(*value
))
538 * Decode the directive...
541 if (strcmp(name
, "<Printer") == 0 ||
542 strcmp(name
, "<DefaultPrinter") == 0)
545 * <Printer name> or <DefaultPrinter name>
548 if (line
[len
- 1] == '>' && p
== NULL
)
551 * Add the printer and a base file type...
554 line
[len
- 1] = '\0';
556 p
= AddPrinter(value
);
558 p
->state
= IPP_PRINTER_IDLE
;
561 * Set the default printer as needed...
564 if (strcmp(name
, "<DefaultPrinter") == 0)
569 LogMessage(L_ERROR
, "Syntax error on line %d of printers.conf.",
574 else if (strcmp(name
, "</Printer>") == 0)
583 LogMessage(L_ERROR
, "Syntax error on line %d of printers.conf.",
590 LogMessage(L_ERROR
, "Syntax error on line %d of printers.conf.",
594 else if (strcmp(name
, "Info") == 0)
595 strncpy(p
->info
, value
, sizeof(p
->info
) - 1);
596 else if (strcmp(name
, "Location") == 0)
597 strncpy(p
->location
, value
, sizeof(p
->location
) - 1);
598 else if (strcmp(name
, "DeviceURI") == 0)
599 strncpy(p
->device_uri
, value
, sizeof(p
->device_uri
) - 1);
600 else if (strcmp(name
, "State") == 0)
603 * Set the initial queue state...
606 if (strcasecmp(value
, "idle") == 0)
607 p
->state
= IPP_PRINTER_IDLE
;
608 else if (strcasecmp(value
, "stopped") == 0)
609 p
->state
= IPP_PRINTER_STOPPED
;
611 else if (strcmp(name
, "StateMessage") == 0)
614 * Set the initial queue state message...
617 while (isspace(*value
))
620 strncpy(p
->state_message
, value
, sizeof(p
->state_message
) - 1);
622 else if (strcmp(name
, "Accepting") == 0)
625 * Set the initial accepting state...
628 if (strcasecmp(value
, "yes") == 0)
633 else if (strcmp(name
, "JobSheets") == 0)
636 * Set the initial job sheets...
639 for (valueptr
= value
; *valueptr
&& !isspace(*valueptr
); valueptr
++);
644 strncpy(p
->job_sheets
[0], value
, sizeof(p
->job_sheets
[0]) - 1);
646 while (isspace(*valueptr
))
651 for (value
= valueptr
; *valueptr
&& !isspace(*valueptr
); valueptr
++);
656 strncpy(p
->job_sheets
[1], value
, sizeof(p
->job_sheets
[1]) - 1);
659 else if (strcmp(name
, "AllowUser") == 0)
662 AddPrinterUser(p
, value
);
664 else if (strcmp(name
, "DenyUser") == 0)
667 AddPrinterUser(p
, value
);
669 else if (strcmp(name
, "QuotaPeriod") == 0)
670 p
->quota_period
= atoi(value
);
671 else if (strcmp(name
, "PageLimit") == 0)
672 p
->page_limit
= atoi(value
);
673 else if (strcmp(name
, "KLimit") == 0)
674 p
->k_limit
= atoi(value
);
678 * Something else we don't understand...
681 LogMessage(L_ERROR
, "Unknown configuration directive %s on line %d of printers.conf.",
691 * 'SaveAllPrinters()' - Save all printer definitions to the printers.conf
696 SaveAllPrinters(void)
698 int i
; /* Looping var */
699 FILE *fp
; /* printers.conf file */
700 char temp
[1024]; /* Temporary string */
701 char backup
[1024]; /* printers.conf.O file */
702 printer_t
*printer
; /* Current printer class */
703 time_t curtime
; /* Current time */
704 struct tm
*curdate
; /* Current date */
708 * Create the printers.conf file...
711 snprintf(temp
, sizeof(temp
), "%s/printers.conf", ServerRoot
);
712 snprintf(backup
, sizeof(backup
), "%s/printers.conf.O", ServerRoot
);
714 if (rename(temp
, backup
))
715 LogMessage(L_ERROR
, "Unable to backup printers.conf - %s", strerror(errno
));
717 if ((fp
= fopen(temp
, "w")) == NULL
)
719 LogMessage(L_ERROR
, "Unable to save printers.conf - %s", strerror(errno
));
721 if (rename(backup
, temp
))
722 LogMessage(L_ERROR
, "Unable to restore printers.conf - %s", strerror(errno
));
726 LogMessage(L_INFO
, "Saving printers.conf...");
729 * Restrict access to the file...
732 fchown(fileno(fp
), User
, Group
);
733 fchmod(fileno(fp
), 0600);
736 * Write a small header to the file...
739 curtime
= time(NULL
);
740 curdate
= gmtime(&curtime
);
741 strftime(temp
, sizeof(temp
) - 1, CUPS_STRFTIME_FORMAT
, curdate
);
743 fputs("# Printer configuration file for " CUPS_SVERSION
"\n", fp
);
744 fprintf(fp
, "# Written by cupsd on %s\n", temp
);
747 * Write each local printer known to the system...
750 for (printer
= Printers
; printer
!= NULL
; printer
= printer
->next
)
753 * Skip remote destinations and printer classes...
756 if ((printer
->type
& CUPS_PRINTER_REMOTE
) ||
757 (printer
->type
& CUPS_PRINTER_CLASS
) ||
758 (printer
->type
& CUPS_PRINTER_IMPLICIT
))
762 * Write printers as needed...
765 if (printer
== DefaultPrinter
)
766 fprintf(fp
, "<DefaultPrinter %s>\n", printer
->name
);
768 fprintf(fp
, "<Printer %s>\n", printer
->name
);
770 if (printer
->info
[0])
771 fprintf(fp
, "Info %s\n", printer
->info
);
773 if (printer
->location
[0])
774 fprintf(fp
, "Location %s\n", printer
->location
);
776 if (printer
->device_uri
[0])
777 fprintf(fp
, "DeviceURI %s\n", printer
->device_uri
);
779 if (printer
->state
== IPP_PRINTER_STOPPED
)
781 fputs("State Stopped\n", fp
);
782 fprintf(fp
, "StateMessage %s\n", printer
->state_message
);
785 fputs("State Idle\n", fp
);
787 if (printer
->accepting
)
788 fputs("Accepting Yes\n", fp
);
790 fputs("Accepting No\n", fp
);
792 fprintf(fp
, "JobSheets %s %s\n", printer
->job_sheets
[0],
793 printer
->job_sheets
[1]);
795 fprintf(fp
, "QuotaPeriod %d\n", printer
->quota_period
);
796 fprintf(fp
, "PageLimit %d\n", printer
->page_limit
);
797 fprintf(fp
, "KLimit %d\n", printer
->k_limit
);
799 for (i
= 0; i
< printer
->num_users
; i
++)
800 fprintf(fp
, "%sUser %s\n", printer
->deny_users
? "Deny" : "Allow",
803 fputs("</Printer>\n", fp
);
806 * Make IRIX desktop & printer status happy
809 write_irix_state(printer
);
819 * 'SetPrinterAttrs()' - Set printer attributes based upon the PPD file.
823 SetPrinterAttrs(printer_t
*p
) /* I - Printer to setup */
825 char uri
[HTTP_MAX_URI
]; /* URI for printer */
826 char method
[HTTP_MAX_URI
], /* Method portion of URI */
827 username
[HTTP_MAX_URI
], /* Username portion of URI */
828 host
[HTTP_MAX_URI
], /* Host portion of URI */
829 resource
[HTTP_MAX_URI
]; /* Resource portion of URI */
830 int port
; /* Port portion of URI */
831 int i
; /* Looping var */
832 char filename
[1024]; /* Name of PPD file */
833 int num_media
; /* Number of media options */
834 location_t
*auth
; /* Pointer to authentication element */
835 const char *auth_supported
; /* Authentication supported */
836 cups_ptype_t printer_type
; /* Printer type data */
837 ppd_file_t
*ppd
; /* PPD file data */
838 ppd_option_t
*input_slot
, /* InputSlot options */
839 *media_type
, /* MediaType options */
840 *page_size
, /* PageSize options */
841 *output_bin
; /* OutputBin options */
842 ipp_attribute_t
*attr
; /* Attribute data */
843 ipp_value_t
*val
; /* Attribute value */
844 int nups
[3] = /* number-up-supported values */
846 ipp_orient_t orients
[4] = /* orientation-requested-supported values */
850 IPP_REVERSE_LANDSCAPE
,
853 const char *sides
[3] = /* sides-supported values */
859 const char *versions
[] = /* ipp-versions-supported values */
864 ipp_op_t ops
[] = /* operations-supported values */
871 IPP_GET_JOB_ATTRIBUTES
,
873 IPP_GET_PRINTER_ATTRIBUTES
,
879 IPP_SET_JOB_ATTRIBUTES
,
895 const char *charsets
[] = /* charset-supported values */
924 ipp_finish_t finishings
[5];
925 const char *multiple_document_handling
[] =
927 "separate-documents-uncollated-copies",
928 "separate-documents-collated-copies"
931 FILE *fp
; /* Interface script file */
935 DEBUG_printf(("SetPrinterAttrs: entering name = %s, type = %x\n", p
->name
,
939 * Clear out old filters and add a filter from application/vnd.cups-raw to
940 * printer/name to handle "raw" printing by users.
943 DeletePrinterFilters(p
);
944 AddPrinterFilter(p
, "application/vnd.cups-raw 0 -");
947 * Figure out the authentication that is required for the printer.
950 auth_supported
= "requesting-user-name";
951 if (!(p
->type
& CUPS_PRINTER_REMOTE
))
953 if (p
->type
& CUPS_PRINTER_CLASS
)
954 snprintf(resource
, sizeof(resource
), "/classes/%s", p
->name
);
956 snprintf(resource
, sizeof(resource
), "/printers/%s", p
->name
);
958 if ((auth
= FindBest(resource
, HTTP_POST
)) != NULL
)
960 if (auth
->type
== AUTH_BASIC
|| auth
->type
== AUTH_BASICDIGEST
)
961 auth_supported
= "basic";
962 else if (auth
->type
== AUTH_DIGEST
)
963 auth_supported
= "digest";
968 * Create the required IPP attributes for a printer...
976 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "printer-uri-supported",
978 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
979 "uri-authentication-supported", NULL
, auth_supported
);
980 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
981 "uri-security-supported", NULL
, "none");
982 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
, "printer-name", NULL
,
984 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-location",
986 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
, "printer-info",
988 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "printer-more-info",
990 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
991 "pdl-override-supported", NULL
, "not-attempted");
992 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
993 "ipp-versions-supported", sizeof(versions
) / sizeof(versions
[0]),
995 ippAddIntegers(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "operations-supported",
996 sizeof(ops
) / sizeof(ops
[0]) + JobFiles
- 1, (int *)ops
);
997 ippAddBoolean(p
->attrs
, IPP_TAG_PRINTER
, "multiple-document-jobs-supported", 1);
998 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
999 "multiple-operation-time-out", 60);
1000 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1001 "multiple-document-handling-supported",
1002 sizeof(multiple_document_handling
) /
1003 sizeof(multiple_document_handling
[0]), NULL
,
1004 multiple_document_handling
);
1005 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_CHARSET
, "charset-configured",
1006 NULL
, DefaultCharset
);
1007 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_CHARSET
, "charset-supported",
1008 sizeof(charsets
) / sizeof(charsets
[0]), NULL
, charsets
);
1009 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_LANGUAGE
,
1010 "natural-language-configured", NULL
, DefaultLanguage
);
1011 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_LANGUAGE
,
1012 "generated-natural-language-supported", NULL
, DefaultLanguage
);
1013 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_MIMETYPE
,
1014 "document-format-default", NULL
, "application/octet-stream");
1015 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
,
1016 (ipp_tag_t
)(IPP_TAG_MIMETYPE
| IPP_TAG_COPY
),
1017 "document-format-supported", NumMimeTypes
, NULL
, MimeTypes
);
1018 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1019 "compression-supported", NULL
, "none");
1020 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1021 "job-priority-supported", 100);
1022 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1023 "job-priority-default", 50);
1024 ippAddRange(p
->attrs
, IPP_TAG_PRINTER
, "copies-supported", 1, 65535);
1025 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1026 "copies-default", 1);
1027 ippAddBoolean(p
->attrs
, IPP_TAG_PRINTER
, "page-ranges-supported", 1);
1028 ippAddIntegers(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1029 "number-up-supported", 3, nups
);
1030 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1031 "number-up-default", 1);
1032 ippAddIntegers(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
1033 "orientation-requested-supported", 4, (int *)orients
);
1034 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
1035 "orientation-requested-default", IPP_PORTRAIT
);
1040 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1041 "requesting-user-name-denied", p
->num_users
, NULL
,
1044 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1045 "requesting-user-name-allowed", p
->num_users
, NULL
,
1049 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1050 "job-quota-period", p
->quota_period
);
1051 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1052 "job-k-limit", p
->k_limit
);
1053 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1054 "job-page-limit", p
->page_limit
);
1059 * Setup the job-sheets-supported and job-sheets-default attributes...
1062 if (Classification
[0] && !ClassifyOverride
)
1063 attr
= ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1064 "job-sheets-supported", NULL
, Classification
);
1066 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1067 "job-sheets-supported", NumBanners
+ 1, NULL
, NULL
);
1070 LogMessage(L_EMERG
, "SetPrinterAttrs: Unable to allocate memory for "
1071 "job-sheets-supported attribute: %s!",
1073 else if (!Classification
[0] || ClassifyOverride
)
1075 attr
->values
[0].string
.text
= strdup("none");
1077 for (i
= 0; i
< NumBanners
; i
++)
1078 attr
->values
[i
+ 1].string
.text
= strdup(Banners
[i
].name
);
1081 if (!(p
->type
& CUPS_PRINTER_REMOTE
))
1083 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1084 "job-sheets-default", 2, NULL
, NULL
);
1088 attr
->values
[0].string
.text
= strdup(Classification
[0] ?
1089 Classification
: p
->job_sheets
[0]);
1090 attr
->values
[1].string
.text
= strdup(Classification
[0] ?
1091 Classification
: p
->job_sheets
[1]);
1096 printer_type
= p
->type
;
1098 if (p
->type
& CUPS_PRINTER_REMOTE
)
1101 * Tell the client this is a remote printer of some type...
1104 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1105 "printer-make-and-model", NULL
, p
->make_model
);
1110 * Assign additional attributes depending on whether this is a printer
1114 p
->type
&= ~CUPS_PRINTER_OPTIONS
;
1116 if (p
->type
& (CUPS_PRINTER_CLASS
| CUPS_PRINTER_IMPLICIT
))
1119 * Add class-specific attributes...
1122 if ((p
->type
& CUPS_PRINTER_IMPLICIT
) && p
->num_printers
> 0)
1123 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1124 "printer-make-and-model", NULL
, p
->printers
[0]->make_model
);
1126 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1127 "printer-make-and-model", NULL
, "Local Printer Class");
1129 if (p
->num_printers
> 0)
1132 * Add a list of member URIs and names...
1135 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
,
1136 "member-uris", p
->num_printers
, NULL
, NULL
);
1137 p
->type
|= CUPS_PRINTER_OPTIONS
;
1139 for (i
= 0; i
< p
->num_printers
; i
++)
1142 attr
->values
[i
].string
.text
= strdup(p
->printers
[i
]->uri
);
1144 p
->type
&= ~CUPS_PRINTER_OPTIONS
| p
->printers
[i
]->type
;
1147 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
1148 "member-names", p
->num_printers
, NULL
, NULL
);
1152 for (i
= 0; i
< p
->num_printers
; i
++)
1153 attr
->values
[i
].string
.text
= strdup(p
->printers
[i
]->name
);
1160 * Add printer-specific attributes... Start by sanitizing the device
1161 * URI so it doesn't have a username or password in it...
1164 if (strstr(p
->device_uri
, "://") != NULL
)
1167 * http://..., ipp://..., etc.
1170 httpSeparate(p
->device_uri
, method
, username
, host
, &port
, resource
);
1172 snprintf(uri
, sizeof(uri
), "%s://%s:%d%s", method
, host
, port
,
1175 snprintf(uri
, sizeof(uri
), "%s://%s%s", method
, host
, resource
);
1180 * file:..., serial:..., etc.
1183 strcpy(uri
, p
->device_uri
);
1186 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_URI
, "device-uri", NULL
,
1190 * Assign additional attributes from the PPD file (if any)...
1193 p
->type
|= CUPS_PRINTER_BW
;
1194 finishings
[0] = IPP_FINISHINGS_NONE
;
1197 snprintf(filename
, sizeof(filename
), "%s/ppd/%s.ppd", ServerRoot
,
1200 if ((ppd
= ppdOpenFile(filename
)) != NULL
)
1203 * Add make/model and other various attributes...
1206 if (ppd
->color_device
)
1207 p
->type
|= CUPS_PRINTER_COLOR
;
1208 if (ppd
->variable_sizes
)
1209 p
->type
|= CUPS_PRINTER_VARIABLE
;
1210 if (!ppd
->manual_copies
)
1211 p
->type
|= CUPS_PRINTER_COPIES
;
1213 ippAddBoolean(p
->attrs
, IPP_TAG_PRINTER
, "color-supported",
1215 if (ppd
->throughput
)
1216 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_INTEGER
,
1217 "pages-per-minute", ppd
->throughput
);
1218 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1219 "printer-make-and-model", NULL
, ppd
->nickname
);
1222 strncpy(p
->make_model
, ppd
->nickname
, sizeof(p
->make_model
) - 1);
1223 else if (ppd
->modelname
)
1224 strncpy(p
->make_model
, ppd
->modelname
, sizeof(p
->make_model
) - 1);
1226 strcpy(p
->make_model
, "Bad PPD File");
1229 * Add media options from the PPD file...
1232 if ((input_slot
= ppdFindOption(ppd
, "InputSlot")) != NULL
)
1233 num_media
= input_slot
->num_choices
;
1237 if ((media_type
= ppdFindOption(ppd
, "MediaType")) != NULL
)
1238 num_media
+= media_type
->num_choices
;
1240 if ((page_size
= ppdFindOption(ppd
, "PageSize")) != NULL
)
1241 num_media
+= page_size
->num_choices
;
1243 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1244 "media-supported", num_media
, NULL
, NULL
);
1249 if (input_slot
!= NULL
)
1250 for (i
= 0; i
< input_slot
->num_choices
; i
++, val
++)
1251 val
->string
.text
= strdup(input_slot
->choices
[i
].choice
);
1253 if (media_type
!= NULL
)
1254 for (i
= 0; i
< media_type
->num_choices
; i
++, val
++)
1255 val
->string
.text
= strdup(media_type
->choices
[i
].choice
);
1257 if (page_size
!= NULL
)
1259 for (i
= 0; i
< page_size
->num_choices
; i
++, val
++)
1260 val
->string
.text
= strdup(page_size
->choices
[i
].choice
);
1262 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1263 NULL
, page_size
->defchoice
);
1265 else if (input_slot
!= NULL
)
1266 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1267 NULL
, input_slot
->defchoice
);
1268 else if (media_type
!= NULL
)
1269 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1270 NULL
, media_type
->defchoice
);
1272 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "media-default",
1280 if ((output_bin
= ppdFindOption(ppd
, "OutputBin")) != NULL
)
1282 attr
= ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
,
1283 "output-bin-supported", output_bin
->num_choices
,
1288 for (i
= 0, val
= attr
->values
;
1289 i
< output_bin
->num_choices
;
1291 val
->string
.text
= strdup(output_bin
->choices
[i
].choice
);
1299 if (ppdFindOption(ppd
, "Duplex") != NULL
)
1301 p
->type
|= CUPS_PRINTER_DUPLEX
;
1303 ippAddStrings(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "sides-supported",
1305 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_KEYWORD
, "sides-default",
1309 if (ppdFindOption(ppd
, "Collate") != NULL
)
1310 p
->type
|= CUPS_PRINTER_COLLATE
;
1312 if (ppdFindOption(ppd
, "StapleLocation") != NULL
)
1314 p
->type
|= CUPS_PRINTER_STAPLE
;
1315 finishings
[num_finishings
++] = IPP_FINISHINGS_STAPLE
;
1318 if (ppdFindOption(ppd
, "BindEdge") != NULL
)
1320 p
->type
|= CUPS_PRINTER_BIND
;
1321 finishings
[num_finishings
++] = IPP_FINISHINGS_BIND
;
1324 for (i
= 0; i
< ppd
->num_sizes
; i
++)
1325 if (ppd
->sizes
[i
].length
> 1728)
1326 p
->type
|= CUPS_PRINTER_LARGE
;
1327 else if (ppd
->sizes
[i
].length
> 1008)
1328 p
->type
|= CUPS_PRINTER_MEDIUM
;
1330 p
->type
|= CUPS_PRINTER_SMALL
;
1333 * Add any filters in the PPD file...
1336 DEBUG_printf(("ppd->num_filters = %d\n", ppd
->num_filters
));
1337 for (i
= 0; i
< ppd
->num_filters
; i
++)
1339 DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i
, ppd
->filters
[i
]));
1340 AddPrinterFilter(p
, ppd
->filters
[i
]);
1343 if (ppd
->num_filters
== 0)
1344 AddPrinterFilter(p
, "application/vnd.cups-postscript 0 -");
1348 printer_type
= p
->type
;
1350 else if (access(filename
, 0) == 0)
1352 LogMessage(L_ERROR
, "PPD file for %s cannot be loaded!", p
->name
);
1354 AddPrinterFilter(p
, "application/vnd.cups-postscript 0 -");
1359 * If we have an interface script, add a filter entry for it...
1362 snprintf(filename
, sizeof(filename
), "%s/interfaces/%s", ServerRoot
,
1364 if (access(filename
, X_OK
) == 0)
1367 * Yes, we have a System V style interface script; use it!
1370 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1371 "printer-make-and-model", NULL
, "Local System V Printer");
1373 snprintf(filename
, sizeof(filename
), "*/* 0 %s/interfaces/%s",
1374 ServerRoot
, p
->name
);
1375 AddPrinterFilter(p
, filename
);
1377 else if (strncmp(p
->device_uri
, "ipp://", 6) == 0 &&
1378 (strstr(p
->device_uri
, "/printers/") != NULL
||
1379 strstr(p
->device_uri
, "/classes/") != NULL
))
1382 * Tell the client this is really a hard-wired remote printer.
1385 printer_type
|= CUPS_PRINTER_REMOTE
;
1388 * Reset the printer-uri-supported attribute to point at the
1392 attr
= ippFindAttribute(p
->attrs
, "printer-uri-supported", IPP_TAG_URI
);
1393 free(attr
->values
[0].string
.text
);
1394 attr
->values
[0].string
.text
= strdup(p
->device_uri
);
1397 * Then set the make-and-model accordingly...
1400 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1401 "printer-make-and-model", NULL
, "Remote Printer");
1404 * Print all files directly...
1407 AddPrinterFilter(p
, "*/* 0 -");
1412 * Otherwise we have neither - treat this as a "dumb" printer
1413 * with no PPD file...
1416 ippAddString(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
1417 "printer-make-and-model", NULL
, "Local Raw Printer");
1419 AddPrinterFilter(p
, "*/* 0 -");
1423 ippAddIntegers(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
1424 "finishings-supported", num_finishings
, (int *)finishings
);
1425 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
,
1426 "finishings-default", IPP_FINISHINGS_NONE
);
1431 * Add the CUPS-specific printer-type attribute...
1434 ippAddInteger(p
->attrs
, IPP_TAG_PRINTER
, IPP_TAG_ENUM
, "printer-type",
1437 DEBUG_printf(("SetPrinterAttrs: leaving name = %s, type = %x\n", p
->name
,
1442 * Add dummy interface and GUI scripts to fool SGI's "challenged" printing
1443 * tools. First the interface script that tells the tools what kind of
1444 * printer we have...
1447 snprintf(filename
, sizeof(filename
), "/var/spool/lp/interface/%s", p
->name
);
1449 if ((fp
= fopen(filename
, "w")) != NULL
)
1451 fputs("#!/bin/sh\n", fp
);
1453 if ((attr
= ippFindAttribute(p
->attrs
, "printer-make-and-model",
1454 IPP_TAG_TEXT
)) != NULL
)
1455 fprintf(fp
, "NAME=\"%s\"\n", attr
->values
[0].string
.text
);
1456 else if (p
->type
& CUPS_PRINTER_CLASS
)
1457 fputs("NAME=\"Printer Class\"\n", fp
);
1459 fputs("NAME=\"Remote Destination\"\n", fp
);
1461 if (p
->type
& CUPS_PRINTER_COLOR
)
1462 fputs("TYPE=ColorPostScript\n", fp
);
1464 fputs("TYPE=PostScript\n", fp
);
1468 chmod(filename
, 0755);
1469 chown(filename
, User
, Group
);
1473 * Then the member file that tells which device file the queue is connected
1474 * to... Networked printers use "/dev/null" in this file, so that's what
1475 * we use (the actual device URI can confuse some apps...)
1478 snprintf(filename
, sizeof(filename
), "/var/spool/lp/member/%s", p
->name
);
1479 if ((fp
= fopen(filename
, "w")) != NULL
)
1481 fputs("/dev/null\n", fp
);
1485 chmod(filename
, 0644);
1486 chown(filename
, User
, Group
);
1490 * The gui_interface file is a script or program that launches a GUI
1491 * option panel for the printer, using options specified on the
1492 * command-line in the third argument. The option panel must send
1493 * any printing options to stdout on a single line when the user
1494 * accepts them, or nothing if the user cancels the dialog.
1496 * The default options panel program is /usr/bin/glpoptions, from
1497 * the ESP Print Pro software. You can select another using the
1498 * PrintcapGUI option.
1501 snprintf(filename
, sizeof(filename
), "/var/spool/lp/gui_interface/ELF/%s.gui", p
->name
);
1503 if ((fp
= fopen(filename
, "w")) != NULL
)
1505 fputs("#!/bin/sh\n", fp
);
1506 fprintf(fp
, "%s -d %s -o \"$3\"\n", PrintcapGUI
, p
->name
);
1510 chmod(filename
, 0755);
1511 chown(filename
, User
, Group
);
1515 * The POD config file is needed by the printstatus command to show
1516 * the printer location and device.
1519 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.config", p
->name
);
1520 if ((fp
= fopen(filename
, "w")) != NULL
)
1522 fprintf(fp
, "Printer Class | %s\n",
1523 (p
->type
& CUPS_PRINTER_COLOR
) ? "ColorPostScript" : "PostScript");
1524 fprintf(fp
, "Printer Model | %s\n", p
->make_model
);
1525 fprintf(fp
, "Location Code | %s\n", p
->uri
);
1526 fprintf(fp
, "Physical Location | %s\n", p
->location
);
1527 fprintf(fp
, "Port Path | %s\n", p
->device_uri
);
1528 fprintf(fp
, "Config Path | /var/spool/lp/pod/%s.config\n", p
->name
);
1529 fprintf(fp
, "Active Status Path | /var/spool/lp/pod/%s.status\n", p
->name
);
1530 fputs("Status Update Wait | 10 seconds\n", fp
);
1534 chmod(filename
, 0664);
1535 chown(filename
, User
, Group
);
1539 * Write the IRIX printer status files...
1542 write_irix_state(p
);
1548 * 'SetPrinterState()' - Update the current state of a printer.
1552 SetPrinterState(printer_t
*p
, /* I - Printer to change */
1553 ipp_pstate_t s
) /* I - New state */
1555 ipp_pstate_t old_state
; /* Old printer state */
1559 * Can't set status of remote printers...
1562 if (p
->type
& CUPS_PRINTER_REMOTE
)
1566 * Set the new state...
1569 old_state
= p
->state
;
1571 p
->state_time
= time(NULL
);
1577 * Save the printer configuration if a printer goes from idle or processing
1578 * to stopped (or visa-versa)...
1581 if ((old_state
== IPP_PRINTER_STOPPED
) != (s
== IPP_PRINTER_STOPPED
))
1585 * Check to see if any pending jobs can now be printed...
1593 * 'SortPrinters()' - Sort the printer list when a printer name is changed.
1599 printer_t
*current
, /* Current printer */
1600 *prev
, /* Previous printer */
1601 *next
; /* Next printer */
1602 int did_swap
; /* Non-zero if we did a swap */
1607 for (did_swap
= 0, current
= Printers
, prev
= NULL
; current
!= NULL
;)
1608 if (current
->next
== NULL
)
1610 else if (strcasecmp(current
->name
, current
->next
->name
) > 0)
1612 DEBUG_printf(("Swapping %s and %s...\n", current
->name
,
1613 current
->next
->name
));
1616 * Need to swap these two printers...
1622 Printers
= current
->next
;
1624 prev
->next
= current
->next
;
1627 * Yes, we can all get a headache from the next bunch of pointer
1631 next
= current
->next
;
1632 current
->next
= next
->next
;
1633 next
->next
= current
;
1639 current
= current
->next
;
1647 * 'StopPrinter()' - Stop a printer from printing any jobs...
1651 StopPrinter(printer_t
*p
) /* I - Printer to stop */
1653 job_t
*job
; /* Active print job */
1657 * See if we have a job printing on this printer...
1663 * Get pointer to job...
1666 job
= (job_t
*)p
->job
;
1675 * Reset the state to pending...
1678 job
->state
->values
[0].integer
= IPP_JOB_PENDING
;
1683 p
->state
= IPP_PRINTER_STOPPED
;
1688 * 'ValidateDest()' - Validate a printer/class destination.
1691 const char * /* O - Printer or class name */
1692 ValidateDest(const char *hostname
, /* I - Host name */
1693 const char *resource
, /* I - Resource name */
1694 cups_ptype_t
*dtype
) /* O - Type (printer or class) */
1696 printer_t
*p
; /* Current printer */
1697 char localname
[1024], /* Localized hostname */
1698 *lptr
, /* Pointer into localized hostname */
1699 *sptr
; /* Pointer into server name */
1702 DEBUG_printf(("ValidateDest(\"%s\", \"%s\", %p)\n", hostname
, resource
, dtype
));
1705 * See if the resource is a class or printer...
1708 if (strncmp(resource
, "/classes/", 9) == 0)
1716 else if (strncmp(resource
, "/printers/", 10) == 0)
1727 * Bad resource name...
1734 * See if the printer or class name exists...
1737 if ((p
= FindPrinter(resource
)) == NULL
)
1738 p
= FindClass(resource
);
1740 if (p
== NULL
&& strchr(resource
, '@') == NULL
)
1744 *dtype
= p
->type
& CUPS_PRINTER_CLASS
;
1749 * Change localhost to the server name...
1752 if (strcasecmp(hostname
, "localhost") == 0)
1753 hostname
= ServerName
;
1755 strncpy(localname
, hostname
, sizeof(localname
) - 1);
1756 localname
[sizeof(localname
) - 1] = '\0';
1758 if (strcasecmp(hostname
, ServerName
) != 0)
1761 * Localize the hostname...
1764 lptr
= strchr(localname
, '.');
1765 sptr
= strchr(ServerName
, '.');
1767 if (sptr
!= NULL
&& lptr
!= NULL
)
1770 * Strip the common domain name components...
1773 while (lptr
!= NULL
)
1775 if (strcasecmp(lptr
, sptr
) == 0)
1781 lptr
= strchr(lptr
+ 1, '.');
1786 DEBUG_printf(("localized hostname is \"%s\"...\n", localname
));
1789 * Find a matching printer or class...
1792 for (p
= Printers
; p
!= NULL
; p
= p
->next
)
1793 if (strcasecmp(p
->hostname
, localname
) == 0 &&
1794 strcasecmp(p
->name
, resource
) == 0)
1796 *dtype
= p
->type
& CUPS_PRINTER_CLASS
;
1805 * 'write_printcap()' - Write a pseudo-printcap file for older applications
1810 write_printcap(void)
1812 FILE *fp
; /* printcap file */
1813 printer_t
*p
; /* Current printer */
1817 * See if we have a printcap file; if not, don't bother writing it.
1824 * Open the printcap file...
1827 if ((fp
= fopen(Printcap
, "w")) == NULL
)
1831 * Write a new printcap with the current list of printers.
1834 switch (PrintcapFormat
)
1838 * Each printer is put in the file as:
1847 for (p
= Printers
; p
!= NULL
; p
= p
->next
)
1848 fprintf(fp
, "%s:\n", p
->name
);
1851 case PRINTCAP_SOLARIS
:
1853 * Each printer is put in the file as:
1855 * _all:all=Printer1,Printer2,Printer3,...,PrinterN
1856 * _default:use=DefaultPrinter
1864 fputs("_all:all=", fp
);
1865 for (p
= Printers
; p
!= NULL
; p
= p
->next
)
1866 fprintf(fp
, "%s%c", p
->name
, p
->next
? ',' : '\n');
1869 fprintf(fp
, "_default:use=%s\n", DefaultPrinter
->name
);
1871 for (p
= Printers
; p
!= NULL
; p
= p
->next
)
1872 fprintf(fp
, "%s:\n", p
->name
);
1886 * 'write_irix_state()' - Update the status files used by IRIX printing
1891 write_irix_state(printer_t
*p
) /* I - Printer to update */
1893 char filename
[1024]; /* Interface script filename */
1894 FILE *fp
; /* Interface script file */
1895 int tag
; /* Status tag value */
1899 * The POD status file is needed for the printstatus window to
1900 * provide the current status of the printer.
1903 snprintf(filename
, sizeof(filename
), "/var/spool/lp/pod/%s.status", p
->name
);
1905 if ((fp
= fopen(filename
, "w")) != NULL
)
1907 fprintf(fp
, "Operational Status | %s\n",
1908 (p
->state
== IPP_PRINTER_IDLE
) ? "Idle" :
1909 (p
->state
== IPP_PRINTER_PROCESSING
) ? "Busy" :
1911 fprintf(fp
, "Information | 01 00 00 | %s\n", CUPS_SVERSION
);
1912 fprintf(fp
, "Information | 02 00 00 | %s jobs\n",
1913 p
->accepting
? "Accepting" : "Not accepting");
1914 fprintf(fp
, "Information | 03 00 00 | %s\n", p
->state_message
);
1918 chmod(filename
, 0664);
1919 chown(filename
, User
, Group
);
1923 * The activeicons file is needed to provide desktop icons for printers:
1925 * [ quoted from /usr/lib/print/tagit ]
1927 * --- Type of printer tags (base values)
1929 * Dumb=66048 # 0x10200
1930 * DumbColor=66080 # 0x10220
1931 * Raster=66112 # 0x10240
1932 * ColorRaster=66144 # 0x10260
1933 * Plotter=66176 # 0x10280
1934 * PostScript=66208 # 0x102A0
1935 * ColorPostScript=66240 # 0x102C0
1936 * MonoPostScript=66272 # 0x102E0
1938 * --- Printer state modifiers for local printers
1943 * Unknown=3 # 0x3 (Faulted due to unknown reason)
1945 * --- Printer state modifiers for network printers
1949 * NetFaulted=10 # 0xA
1950 * NetUnknown=11 # 0xB (Faulted due to unknown reason)
1953 snprintf(filename
, sizeof(filename
), "/var/spool/lp/activeicons/%s", p
->name
);
1955 if ((fp
= fopen(filename
, "w")) != NULL
)
1957 if (p
->type
& CUPS_PRINTER_COLOR
)
1962 if (p
->type
& CUPS_PRINTER_REMOTE
)
1965 if (p
->state
== IPP_PRINTER_PROCESSING
)
1968 else if (p
->state
== IPP_PRINTER_STOPPED
)
1971 fputs("#!/bin/sh\n", fp
);
1972 fprintf(fp
, "#Tag %d\n", tag
);
1976 chmod(filename
, 0755);
1977 chown(filename
, User
, Group
);
1981 * The default file is needed by the printers window to show
1982 * the default printer.
1985 snprintf(filename
, sizeof(filename
), "/var/spool/lp/default");
1987 if (DefaultPrinter
!= NULL
)
1989 if ((fp
= fopen(filename
, "w")) != NULL
)
1991 fprintf(fp
, "%s\n", DefaultPrinter
->name
);
1995 chmod(filename
, 0644);
1996 chown(filename
, User
, Group
);
2006 * End of "$Id: printers.c,v 1.93.2.8 2002/01/23 17:32:16 mike Exp $".