]>
Commit | Line | Data |
---|---|---|
a129ddbd | 1 | /* |
e673c4b4 | 2 | * "$Id: printers.c,v 1.93.2.55 2004/02/24 21:36:59 mike Exp $" |
a129ddbd | 3 | * |
cbbfcc63 | 4 | * Printer routines for the Common UNIX Printing System (CUPS). |
a129ddbd | 5 | * |
1d9595ab | 6 | * Copyright 1997-2003 by Easy Software Products, all rights reserved. |
a129ddbd | 7 | * |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
8784b6a6 | 17 | * 44141 Airport View Drive, Suite 204 |
a129ddbd | 18 | * Hollywood, Maryland 20636-3111 USA |
19 | * | |
20 | * Voice: (301) 373-9603 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
20b85438 | 26 | * AddPrinter() - Add a printer to the system. |
27 | * AddPrinterFilter() - Add a MIME filter for a printer. | |
62bcac22 | 28 | * AddPrinterHistory() - Add the current printer state to the history. |
d7845573 | 29 | * AddPrinterUser() - Add a user to the ACL. |
20b85438 | 30 | * DeleteAllPrinters() - Delete all printers from the system. |
31 | * DeletePrinter() - Delete a printer from the system. | |
32 | * DeletePrinterFilters() - Delete all MIME filters for a printer. | |
33 | * FindPrinter() - Find a printer in the list. | |
04d756fc | 34 | * FreePrinterUsers() - Free allow/deny users. |
20b85438 | 35 | * LoadAllPrinters() - Load printers from the printers.conf file. |
36 | * SaveAllPrinters() - Save all printer definitions to the printers.conf | |
37 | * SetPrinterAttrs() - Set printer attributes based upon the PPD file. | |
62bcac22 | 38 | * SetPrinterReasons() - Set/update the reasons strings. |
20b85438 | 39 | * SetPrinterState() - Update the current state of a printer. |
40 | * SortPrinters() - Sort the printer list when a printer name is | |
41 | * changed. | |
42 | * StopPrinter() - Stop a printer from printing any jobs... | |
43 | * ValidateDest() - Validate a printer/class destination. | |
3a74d6bf | 44 | * WritePrintcap() - Write a pseudo-printcap file for older |
45 | * applications that need it... | |
dd5cfc84 | 46 | * write_irix_config() - Update the config files used by the IRIX |
47 | * desktop tools. | |
9ae34eb7 | 48 | * write_irix_state() - Update the status files used by IRIX printing |
49 | * desktop tools. | |
a129ddbd | 50 | */ |
51 | ||
52 | /* | |
53 | * Include necessary headers... | |
54 | */ | |
55 | ||
fd8b1cf8 | 56 | #include "cupsd.h" |
a129ddbd | 57 | |
58 | ||
9cd605da | 59 | /* |
60 | * Local functions... | |
61 | */ | |
62 | ||
9ae34eb7 | 63 | #ifdef __sgi |
64 | static void write_irix_state(printer_t *p); | |
65 | #endif /* __sgi */ | |
9cd605da | 66 | |
67 | ||
a129ddbd | 68 | /* |
a9de544f | 69 | * 'AddPrinter()' - Add a printer to the system. |
70 | */ | |
71 | ||
72 | printer_t * /* O - New printer */ | |
1049abbe | 73 | AddPrinter(const char *name) /* I - Name of printer */ |
a9de544f | 74 | { |
75 | printer_t *p, /* New printer */ | |
76 | *current, /* Current printer in list */ | |
77 | *prev; /* Previous printer in list */ | |
78 | ||
79 | ||
80 | /* | |
81 | * Range check input... | |
82 | */ | |
83 | ||
36564e2c | 84 | LogMessage(L_DEBUG2, "AddPrinter(\"%s\")", name ? name : "(null)"); |
85 | ||
a9de544f | 86 | if (name == NULL) |
87 | return (NULL); | |
88 | ||
89 | /* | |
90 | * Create a new printer entity... | |
91 | */ | |
92 | ||
d588a92e | 93 | if ((p = calloc(1, sizeof(printer_t))) == NULL) |
36564e2c | 94 | { |
95 | LogMessage(L_ERROR, "Unable to allocate memory for printer - %s", | |
96 | strerror(errno)); | |
a9de544f | 97 | return (NULL); |
36564e2c | 98 | } |
a9de544f | 99 | |
36992080 | 100 | SetString(&p->name, name); |
101 | SetString(&p->info, name); | |
102 | SetString(&p->hostname, ServerName); | |
99de6da0 | 103 | |
e673c4b4 | 104 | if (NumListeners == 0) |
105 | SetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName, ippPort(), name); | |
99de6da0 | 106 | #ifdef AF_INET6 |
e673c4b4 | 107 | else if (Listeners[0].address.addr.sa_family == AF_INET6) |
36992080 | 108 | SetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName, |
109 | ntohs(Listeners[0].address.ipv6.sin6_port), name); | |
99de6da0 | 110 | #endif /* AF_INET6 */ |
e673c4b4 | 111 | else |
112 | SetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName, | |
113 | ntohs(Listeners[0].address.ipv4.sin_port), name); | |
0af867a8 | 114 | SetStringf(&p->device_uri, "file:/dev/null"); |
d588a92e | 115 | |
f3d580b9 | 116 | p->state = IPP_PRINTER_STOPPED; |
c7fa9d06 | 117 | p->accepting = 0; |
118 | p->filetype = mimeAddType(MimeDatabase, "printer", name); | |
119 | ||
36992080 | 120 | SetString(&p->job_sheets[0], "none"); |
121 | SetString(&p->job_sheets[1], "none"); | |
62bcac22 | 122 | |
123 | if (MaxPrinterHistory) | |
124 | p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *)); | |
a3e17a89 | 125 | |
a9de544f | 126 | /* |
127 | * Insert the printer in the printer list alphabetically... | |
128 | */ | |
129 | ||
130 | for (prev = NULL, current = Printers; | |
131 | current != NULL; | |
132 | prev = current, current = current->next) | |
f3d580b9 | 133 | if (strcasecmp(p->name, current->name) < 0) |
a9de544f | 134 | break; |
135 | ||
136 | /* | |
137 | * Insert this printer before the current one... | |
138 | */ | |
139 | ||
140 | if (prev == NULL) | |
141 | Printers = p; | |
142 | else | |
143 | prev->next = p; | |
144 | ||
145 | p->next = current; | |
146 | ||
9cd605da | 147 | /* |
957c6597 | 148 | * Write a new /etc/printcap or /var/spool/lp/pstatus file. |
9cd605da | 149 | */ |
150 | ||
3a74d6bf | 151 | WritePrintcap(); |
9cd605da | 152 | |
a9de544f | 153 | return (p); |
154 | } | |
155 | ||
156 | ||
c7fa9d06 | 157 | /* |
158 | * 'AddPrinterFilter()' - Add a MIME filter for a printer. | |
159 | */ | |
160 | ||
161 | void | |
d7845573 | 162 | AddPrinterFilter(printer_t *p, /* I - Printer to add to */ |
163 | const char *filter) /* I - Filter to add */ | |
c7fa9d06 | 164 | { |
165 | int i; /* Looping var */ | |
166 | char super[MIME_MAX_SUPER], /* Super-type for filter */ | |
167 | type[MIME_MAX_TYPE], /* Type for filter */ | |
168 | program[1024]; /* Program/filter name */ | |
169 | int cost; /* Cost of filter */ | |
170 | mime_type_t **temptype; /* MIME type looping var */ | |
171 | ||
172 | ||
173 | /* | |
174 | * Range check input... | |
175 | */ | |
176 | ||
d47f8ebe | 177 | if (p == NULL || p->filetype == NULL || filter == NULL) |
c7fa9d06 | 178 | return; |
179 | ||
180 | /* | |
181 | * Parse the filter string; it should be in the following format: | |
182 | * | |
183 | * super/type cost program | |
184 | */ | |
185 | ||
970017a4 | 186 | if (sscanf(filter, "%15[^/]/%31s%d%1023s", super, type, &cost, program) != 4) |
c7fa9d06 | 187 | { |
5ea8888e | 188 | LogMessage(L_ERROR, "AddPrinterFilter: Invalid filter string \"%s\"!", |
c7fa9d06 | 189 | filter); |
190 | return; | |
191 | } | |
192 | ||
193 | /* | |
194 | * Add the filter to the MIME database, supporting wildcards as needed... | |
195 | */ | |
196 | ||
197 | for (temptype = MimeDatabase->types, i = MimeDatabase->num_types; | |
198 | i > 0; | |
199 | i --, temptype ++) | |
da312e94 | 200 | if (((super[0] == '*' && strcasecmp((*temptype)->super, "printer") != 0) || |
201 | strcasecmp((*temptype)->super, super) == 0) && | |
202 | (type[0] == '*' || strcasecmp((*temptype)->type, type) == 0)) | |
882031b3 | 203 | { |
8c2f8763 | 204 | LogMessage(L_DEBUG2, "Adding filter %s/%s %s/%s %d %s", |
57c77867 | 205 | (*temptype)->super, (*temptype)->type, |
206 | p->filetype->super, p->filetype->type, | |
207 | cost, program); | |
c7fa9d06 | 208 | mimeAddFilter(MimeDatabase, *temptype, p->filetype, cost, program); |
882031b3 | 209 | } |
c7fa9d06 | 210 | } |
211 | ||
212 | ||
62bcac22 | 213 | /* |
214 | * 'AddPrinterHistory()' - Add the current printer state to the history. | |
215 | */ | |
216 | ||
217 | void | |
218 | AddPrinterHistory(printer_t *p) /* I - Printer */ | |
219 | { | |
220 | ipp_t *history; /* History collection */ | |
221 | ||
222 | ||
223 | /* | |
224 | * Stop early if we aren't keeping history data... | |
225 | */ | |
226 | ||
227 | if (MaxPrinterHistory <= 0) | |
228 | return; | |
229 | ||
230 | /* | |
231 | * Retire old history data as needed... | |
232 | */ | |
233 | ||
c8a55d2c | 234 | p->sequence_number ++; |
235 | ||
62bcac22 | 236 | if (p->num_history >= MaxPrinterHistory) |
237 | { | |
238 | p->num_history --; | |
239 | ippDelete(p->history[0]); | |
240 | memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *)); | |
241 | } | |
242 | ||
243 | /* | |
244 | * Create a collection containing the current printer-state, printer-up-time, | |
245 | * printer-state-message, and printer-state-reasons attributes. | |
246 | */ | |
247 | ||
248 | history = ippNew(); | |
249 | ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", | |
250 | p->state); | |
c8a55d2c | 251 | ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-accepting-jobs", |
252 | p->accepting); | |
62bcac22 | 253 | ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message", |
254 | NULL, p->state_message); | |
255 | if (p->num_reasons == 0) | |
256 | ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
257 | "printer-state-reasons", NULL, | |
258 | p->state == IPP_PRINTER_STOPPED ? "paused" : "none"); | |
259 | else | |
260 | ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
261 | "printer-state-reasons", p->num_reasons, NULL, | |
262 | (const char * const *)p->reasons); | |
c8a55d2c | 263 | ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER, |
264 | "printer-state-time", p->state_time); | |
265 | ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
266 | "printer-state-sequence-number", p->sequence_number); | |
62bcac22 | 267 | |
268 | p->history[p->num_history] = history; | |
269 | p->num_history ++; | |
270 | } | |
271 | ||
272 | ||
d7845573 | 273 | /* |
274 | * 'AddPrinterUser()' - Add a user to the ACL. | |
275 | */ | |
276 | ||
277 | void | |
278 | AddPrinterUser(printer_t *p, /* I - Printer */ | |
279 | const char *username) /* I - User */ | |
280 | { | |
281 | const char **temp; /* Temporary array pointer */ | |
282 | ||
283 | ||
284 | if (!p || !username) | |
285 | return; | |
286 | ||
287 | if (p->num_users == 0) | |
288 | temp = malloc(sizeof(char **)); | |
289 | else | |
290 | temp = realloc(p->users, sizeof(char **) * (p->num_users + 1)); | |
291 | ||
292 | if (!temp) | |
293 | return; | |
294 | ||
295 | p->users = temp; | |
296 | temp += p->num_users; | |
297 | ||
298 | if ((*temp = strdup(username)) != NULL) | |
299 | p->num_users ++; | |
300 | } | |
301 | ||
302 | ||
67c158fa | 303 | /* |
304 | * 'CreateCommonData()' - Create the common printer data. | |
305 | */ | |
306 | ||
307 | void | |
308 | CreateCommonData(void) | |
309 | { | |
310 | int i; /* Looping var */ | |
311 | ipp_attribute_t *attr; /* Attribute data */ | |
312 | static const int nups[] = /* number-up-supported values */ | |
313 | { 1, 2, 4, 6, 9, 16 }; | |
314 | static const ipp_orient_t orients[4] =/* orientation-requested-supported values */ | |
315 | { | |
316 | IPP_PORTRAIT, | |
317 | IPP_LANDSCAPE, | |
318 | IPP_REVERSE_LANDSCAPE, | |
319 | IPP_REVERSE_PORTRAIT | |
320 | }; | |
321 | static const char * const holds[] = /* job-hold-until-supported values */ | |
322 | { | |
323 | "no-hold", | |
324 | "indefinite", | |
325 | "day-time", | |
326 | "evening", | |
327 | "night", | |
328 | "second-shift", | |
329 | "third-shift", | |
330 | "weekend" | |
331 | }; | |
332 | static const char * const versions[] =/* ipp-versions-supported values */ | |
333 | { | |
334 | "1.0", | |
335 | "1.1" | |
336 | }; | |
337 | static const ipp_op_t ops[] = /* operations-supported values */ | |
338 | { | |
339 | IPP_PRINT_JOB, | |
340 | IPP_VALIDATE_JOB, | |
341 | IPP_CREATE_JOB, | |
342 | IPP_SEND_DOCUMENT, | |
343 | IPP_CANCEL_JOB, | |
344 | IPP_GET_JOB_ATTRIBUTES, | |
345 | IPP_GET_JOBS, | |
346 | IPP_GET_PRINTER_ATTRIBUTES, | |
347 | IPP_HOLD_JOB, | |
348 | IPP_RELEASE_JOB, | |
349 | IPP_PAUSE_PRINTER, | |
350 | IPP_RESUME_PRINTER, | |
351 | IPP_PURGE_JOBS, | |
352 | IPP_SET_JOB_ATTRIBUTES, | |
353 | IPP_ENABLE_PRINTER, | |
354 | IPP_DISABLE_PRINTER, | |
355 | CUPS_GET_DEFAULT, | |
356 | CUPS_GET_PRINTERS, | |
357 | CUPS_ADD_PRINTER, | |
358 | CUPS_DELETE_PRINTER, | |
359 | CUPS_GET_CLASSES, | |
360 | CUPS_ADD_CLASS, | |
361 | CUPS_DELETE_CLASS, | |
362 | CUPS_ACCEPT_JOBS, | |
363 | CUPS_REJECT_JOBS, | |
364 | CUPS_GET_DEVICES, | |
365 | CUPS_GET_PPDS, | |
366 | IPP_RESTART_JOB | |
367 | }; | |
368 | static const char * const charsets[] =/* charset-supported values */ | |
369 | { | |
370 | "us-ascii", | |
371 | "iso-8859-1", | |
372 | "iso-8859-2", | |
373 | "iso-8859-3", | |
374 | "iso-8859-4", | |
375 | "iso-8859-5", | |
376 | "iso-8859-6", | |
377 | "iso-8859-7", | |
378 | "iso-8859-8", | |
379 | "iso-8859-9", | |
380 | "iso-8859-10", | |
381 | "iso-8859-13", | |
382 | "iso-8859-14", | |
383 | "iso-8859-15", | |
384 | "utf-8", | |
385 | "windows-874", | |
386 | "windows-1250", | |
387 | "windows-1251", | |
388 | "windows-1252", | |
389 | "windows-1253", | |
390 | "windows-1254", | |
391 | "windows-1255", | |
392 | "windows-1256", | |
393 | "windows-1257", | |
394 | "windows-1258", | |
395 | "koi8-r", | |
396 | "koi8-u", | |
397 | }; | |
398 | static const char * const compressions[] = | |
399 | { /* document-compression-supported values */ | |
400 | "none" | |
401 | #ifdef HAVE_LIBZ | |
402 | ,"gzip" | |
403 | #endif /* HAVE_LIBZ */ | |
404 | }; | |
405 | static const char * const multiple_document_handling[] = | |
406 | { /* multiple-document-handling-supported values */ | |
407 | "separate-documents-uncollated-copies", | |
408 | "separate-documents-collated-copies" | |
409 | }; | |
410 | ||
411 | ||
412 | if (CommonData) | |
413 | ippDelete(CommonData); | |
414 | ||
415 | CommonData = ippNew(); | |
416 | ||
417 | ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
418 | "pdl-override-supported", NULL, "not-attempted"); | |
419 | ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
420 | "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]), | |
421 | NULL, versions); | |
422 | ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
423 | "operations-supported", | |
424 | sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops); | |
425 | ippAddBoolean(CommonData, IPP_TAG_PRINTER, | |
426 | "multiple-document-jobs-supported", 1); | |
427 | ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
428 | "multiple-operation-time-out", 60); | |
429 | ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
430 | "multiple-document-handling-supported", | |
431 | sizeof(multiple_document_handling) / | |
432 | sizeof(multiple_document_handling[0]), NULL, | |
433 | multiple_document_handling); | |
434 | ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET, | |
435 | "charset-configured", NULL, DefaultCharset); | |
436 | ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET, | |
437 | "charset-supported", sizeof(charsets) / sizeof(charsets[0]), | |
438 | NULL, charsets); | |
439 | ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, | |
440 | "natural-language-configured", NULL, DefaultLanguage); | |
441 | ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, | |
442 | "generated-natural-language-supported", NULL, DefaultLanguage); | |
443 | ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, | |
444 | "document-format-default", NULL, "application/octet-stream"); | |
445 | ippAddStrings(CommonData, IPP_TAG_PRINTER, | |
446 | (ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY), | |
447 | "document-format-supported", NumMimeTypes, NULL, MimeTypes); | |
448 | ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
449 | "compression-supported", | |
450 | sizeof(compressions) / sizeof(compressions[0]), | |
451 | NULL, compressions); | |
452 | ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
453 | "job-priority-supported", 100); | |
454 | ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
455 | "job-priority-default", 50); | |
456 | ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies); | |
457 | ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
458 | "copies-default", 1); | |
459 | ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1); | |
460 | ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
461 | "number-up-supported", sizeof(nups) / sizeof(nups[0]), nups); | |
462 | ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
463 | "number-up-default", 1); | |
464 | ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
465 | "orientation-requested-supported", 4, (int *)orients); | |
466 | ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
467 | "orientation-requested-default", IPP_PORTRAIT); | |
468 | ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
469 | "job-hold-until-supported", sizeof(holds) / sizeof(holds[0]), | |
470 | NULL, holds); | |
471 | ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
472 | "job-hold-until-default", NULL, "no-hold"); | |
473 | ||
474 | if (NumBanners > 0) | |
475 | { | |
476 | /* | |
477 | * Setup the job-sheets-supported and job-sheets-default attributes... | |
478 | */ | |
479 | ||
480 | if (Classification && !ClassifyOverride) | |
481 | attr = ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME, | |
482 | "job-sheets-supported", NULL, Classification); | |
483 | else | |
484 | attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME, | |
485 | "job-sheets-supported", NumBanners + 1, NULL, NULL); | |
486 | ||
487 | if (attr == NULL) | |
488 | LogMessage(L_EMERG, "SetPrinterAttrs: Unable to allocate memory for " | |
489 | "job-sheets-supported attribute: %s!", | |
490 | strerror(errno)); | |
491 | else if (!Classification || ClassifyOverride) | |
492 | { | |
493 | attr->values[0].string.text = strdup("none"); | |
494 | ||
495 | for (i = 0; i < NumBanners; i ++) | |
496 | attr->values[i + 1].string.text = strdup(Banners[i].name); | |
497 | } | |
498 | } | |
499 | } | |
500 | ||
501 | ||
a9de544f | 502 | /* |
503 | * 'DeleteAllPrinters()' - Delete all printers from the system. | |
504 | */ | |
505 | ||
506 | void | |
507 | DeleteAllPrinters(void) | |
508 | { | |
cbbfcc63 | 509 | printer_t *p, /* Pointer to current printer/class */ |
510 | *next; /* Pointer to next printer in list */ | |
511 | ||
512 | ||
513 | for (p = Printers; p != NULL; p = next) | |
514 | { | |
515 | next = p->next; | |
516 | ||
517 | if (!(p->type & CUPS_PRINTER_CLASS)) | |
9b2fe6bd | 518 | DeletePrinter(p, 0); |
cbbfcc63 | 519 | } |
a9de544f | 520 | } |
521 | ||
522 | ||
523 | /* | |
524 | * 'DeletePrinter()' - Delete a printer from the system. | |
525 | */ | |
526 | ||
527 | void | |
9b2fe6bd | 528 | DeletePrinter(printer_t *p, /* I - Printer to delete */ |
529 | int update) /* I - Update printers.conf? */ | |
a9de544f | 530 | { |
62bcac22 | 531 | int i; /* Looping var */ |
a9de544f | 532 | printer_t *current, /* Current printer in list */ |
533 | *prev; /* Previous printer in list */ | |
9cd605da | 534 | #ifdef __sgi |
535 | char filename[1024]; /* Interface script filename */ | |
536 | #endif /* __sgi */ | |
a9de544f | 537 | |
538 | ||
e63d9801 | 539 | DEBUG_printf(("DeletePrinter(%08x): p->name = \"%s\"...\n", p, p->name)); |
540 | ||
a9de544f | 541 | /* |
542 | * Range check input... | |
543 | */ | |
544 | ||
545 | if (p == NULL) | |
546 | return; | |
547 | ||
a9de544f | 548 | /* |
549 | * Remove the printer from the list... | |
550 | */ | |
551 | ||
552 | for (prev = NULL, current = Printers; | |
553 | current != NULL; | |
554 | prev = current, current = current->next) | |
555 | if (p == current) | |
556 | break; | |
557 | ||
558 | if (current == NULL) | |
559 | { | |
5ea8888e | 560 | LogMessage(L_ERROR, "Tried to delete a non-existent printer %s!\n", |
89b82efe | 561 | p->name); |
a9de544f | 562 | return; |
563 | } | |
564 | ||
565 | if (prev == NULL) | |
566 | Printers = p->next; | |
567 | else | |
568 | prev->next = p->next; | |
569 | ||
9cd605da | 570 | /* |
a6988fb1 | 571 | * Stop printing on this printer... |
9cd605da | 572 | */ |
573 | ||
9b2fe6bd | 574 | StopPrinter(p, update); |
a6988fb1 | 575 | |
576 | /* | |
577 | * Remove the dummy interface/icon/option files under IRIX... | |
578 | */ | |
9cd605da | 579 | |
580 | #ifdef __sgi | |
a6988fb1 | 581 | snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name); |
9cd605da | 582 | unlink(filename); |
583 | ||
a6988fb1 | 584 | snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", |
585 | p->name); | |
9cd605da | 586 | unlink(filename); |
30f1fa61 | 587 | |
a6988fb1 | 588 | snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name); |
30f1fa61 | 589 | unlink(filename); |
9ae34eb7 | 590 | |
591 | snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name); | |
592 | unlink(filename); | |
593 | ||
594 | snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name); | |
595 | unlink(filename); | |
cb9d2abc | 596 | |
597 | snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name); | |
598 | unlink(filename); | |
9cd605da | 599 | #endif /* __sgi */ |
3d299a9d | 600 | |
8d853fdf | 601 | /* |
602 | * If p is the default printer, assign the next one... | |
603 | */ | |
604 | ||
605 | if (p == DefaultPrinter) | |
9ae34eb7 | 606 | { |
8d853fdf | 607 | DefaultPrinter = Printers; |
608 | ||
3a74d6bf | 609 | WritePrintcap(); |
9ae34eb7 | 610 | } |
611 | ||
8d853fdf | 612 | /* |
613 | * Remove this printer from any classes... | |
614 | */ | |
615 | ||
c1511ac0 | 616 | if (!(p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))) |
617 | DeletePrinterFromClasses(p); | |
8d853fdf | 618 | |
3d299a9d | 619 | /* |
a6988fb1 | 620 | * Free all memory used by the printer... |
3d299a9d | 621 | */ |
622 | ||
623 | if (p->printers != NULL) | |
624 | free(p->printers); | |
625 | ||
62bcac22 | 626 | if (MaxPrinterHistory) |
627 | { | |
628 | for (i = 0; i < p->num_history; i ++) | |
629 | ippDelete(p->history[i]); | |
630 | ||
631 | free(p->history); | |
632 | } | |
633 | ||
634 | for (i = 0; i < p->num_reasons; i ++) | |
635 | free(p->reasons[i]); | |
636 | ||
3d299a9d | 637 | ippDelete(p->attrs); |
638 | ||
639 | DeletePrinterFilters(p); | |
640 | ||
d7845573 | 641 | FreePrinterUsers(p); |
04d756fc | 642 | FreeQuotas(p); |
d7845573 | 643 | |
36992080 | 644 | ClearString(&p->uri); |
645 | ClearString(&p->hostname); | |
646 | ClearString(&p->name); | |
647 | ClearString(&p->location); | |
648 | ClearString(&p->make_model); | |
649 | ClearString(&p->info); | |
650 | ClearString(&p->job_sheets[0]); | |
651 | ClearString(&p->job_sheets[1]); | |
652 | ClearString(&p->device_uri); | |
36992080 | 653 | |
3d299a9d | 654 | free(p); |
655 | ||
a6988fb1 | 656 | /* |
657 | * Write a new /etc/printcap file... | |
658 | */ | |
659 | ||
3a74d6bf | 660 | WritePrintcap(); |
a9de544f | 661 | } |
662 | ||
663 | ||
c7fa9d06 | 664 | /* |
20b85438 | 665 | * 'DeletePrinterFilters()' - Delete all MIME filters for a printer. |
c7fa9d06 | 666 | */ |
667 | ||
668 | void | |
669 | DeletePrinterFilters(printer_t *p) /* I - Printer to remove from */ | |
670 | { | |
671 | int i; /* Looping var */ | |
672 | mime_filter_t *filter; /* MIME filter looping var */ | |
673 | ||
674 | ||
675 | /* | |
676 | * Range check input... | |
677 | */ | |
678 | ||
679 | if (p == NULL) | |
680 | return; | |
681 | ||
682 | /* | |
683 | * Remove all filters from the MIME database that have a destination | |
684 | * type == printer... | |
685 | */ | |
686 | ||
687 | for (filter = MimeDatabase->filters, i = MimeDatabase->num_filters; | |
688 | i > 0; | |
689 | i --, filter ++) | |
690 | if (filter->dst == p->filetype) | |
691 | { | |
692 | /* | |
693 | * Delete the current filter... | |
694 | */ | |
695 | ||
696 | MimeDatabase->num_filters --; | |
697 | ||
698 | if (i > 1) | |
ff40b65e | 699 | memmove(filter, filter + 1, sizeof(mime_filter_t) * (i - 1)); |
c7fa9d06 | 700 | |
701 | filter --; | |
702 | } | |
703 | } | |
704 | ||
705 | ||
8bd0441f | 706 | /* |
707 | * 'FindDest()' - Find a destination in the list. | |
708 | */ | |
709 | ||
710 | printer_t * /* O - Destination in list */ | |
711 | FindDest(const char *name) /* I - Name of printer or class to find */ | |
712 | { | |
713 | printer_t *p; /* Current destination */ | |
714 | int diff; /* Difference */ | |
715 | ||
716 | ||
717 | for (p = Printers; p != NULL; p = p->next) | |
718 | if ((diff = strcasecmp(name, p->name)) == 0)/* name == p->name */ | |
719 | return (p); | |
720 | else if (diff < 0) /* name < p->name */ | |
721 | return (NULL); | |
722 | ||
723 | return (NULL); | |
724 | } | |
725 | ||
726 | ||
a9de544f | 727 | /* |
728 | * 'FindPrinter()' - Find a printer in the list. | |
729 | */ | |
730 | ||
731 | printer_t * /* O - Printer in list */ | |
1049abbe | 732 | FindPrinter(const char *name) /* I - Name of printer to find */ |
a9de544f | 733 | { |
734 | printer_t *p; /* Current printer */ | |
8bd0441f | 735 | int diff; /* Difference */ |
a9de544f | 736 | |
737 | ||
738 | for (p = Printers; p != NULL; p = p->next) | |
8bd0441f | 739 | if ((diff = strcasecmp(name, p->name)) == 0 && |
740 | !(p->type & CUPS_PRINTER_CLASS)) /* name == p->name */ | |
741 | return (p); | |
742 | else if (diff < 0) /* name < p->name */ | |
743 | return (NULL); | |
a9de544f | 744 | |
745 | return (NULL); | |
746 | } | |
747 | ||
748 | ||
d7845573 | 749 | /* |
04d756fc | 750 | * 'FreePrinterUsers()' - Free allow/deny users. |
d7845573 | 751 | */ |
752 | ||
753 | void | |
754 | FreePrinterUsers(printer_t *p) /* I - Printer */ | |
755 | { | |
756 | int i; /* Looping var */ | |
757 | ||
758 | ||
759 | if (!p || !p->num_users) | |
760 | return; | |
761 | ||
762 | for (i = 0; i < p->num_users; i ++) | |
763 | free((void *)p->users[i]); | |
764 | ||
765 | free(p->users); | |
766 | ||
767 | p->num_users = 0; | |
768 | p->users = NULL; | |
769 | } | |
770 | ||
771 | ||
a9de544f | 772 | /* |
773 | * 'LoadAllPrinters()' - Load printers from the printers.conf file. | |
774 | */ | |
775 | ||
776 | void | |
777 | LoadAllPrinters(void) | |
778 | { | |
7b0fde61 | 779 | cups_file_t *fp; /* printers.conf file */ |
a9de544f | 780 | int linenum; /* Current line number */ |
781 | int len; /* Length of line */ | |
03081fd2 | 782 | char line[1024], /* Line from file */ |
a9de544f | 783 | name[256], /* Parameter name */ |
784 | *nameptr, /* Pointer into name */ | |
a3e17a89 | 785 | *value, /* Pointer to value */ |
786 | *valueptr; /* Pointer into value */ | |
a9de544f | 787 | printer_t *p; /* Current printer */ |
788 | ||
789 | ||
790 | /* | |
7db52463 | 791 | * Open the printers.conf file... |
a9de544f | 792 | */ |
793 | ||
a6988fb1 | 794 | snprintf(line, sizeof(line), "%s/printers.conf", ServerRoot); |
7b0fde61 | 795 | if ((fp = cupsFileOpen(line, "r")) == NULL) |
d47f8ebe | 796 | { |
797 | LogMessage(L_ERROR, "LoadAllPrinters: Unable to open %s - %s", line, | |
798 | strerror(errno)); | |
a9de544f | 799 | return; |
d47f8ebe | 800 | } |
a9de544f | 801 | |
802 | /* | |
803 | * Read printer configurations until we hit EOF... | |
804 | */ | |
805 | ||
806 | linenum = 0; | |
807 | p = NULL; | |
808 | ||
7b0fde61 | 809 | while (cupsFileGets(fp, line, sizeof(line)) != NULL) |
a9de544f | 810 | { |
811 | linenum ++; | |
812 | ||
813 | /* | |
814 | * Skip comment lines... | |
815 | */ | |
816 | ||
817 | if (line[0] == '#') | |
818 | continue; | |
819 | ||
820 | /* | |
753453e4 | 821 | * Strip trailing whitespace, if any... |
a9de544f | 822 | */ |
823 | ||
824 | len = strlen(line); | |
825 | ||
753453e4 | 826 | while (len > 0 && isspace(line[len - 1])) |
a9de544f | 827 | { |
828 | len --; | |
829 | line[len] = '\0'; | |
830 | } | |
831 | ||
832 | /* | |
833 | * Extract the name from the beginning of the line... | |
834 | */ | |
835 | ||
836 | for (value = line; isspace(*value); value ++); | |
837 | ||
d588a92e | 838 | for (nameptr = name; *value != '\0' && !isspace(*value) && |
839 | nameptr < (name + sizeof(name) - 1);) | |
a9de544f | 840 | *nameptr++ = *value++; |
841 | *nameptr = '\0'; | |
842 | ||
843 | while (isspace(*value)) | |
844 | value ++; | |
845 | ||
846 | if (name[0] == '\0') | |
847 | continue; | |
848 | ||
849 | /* | |
850 | * Decode the directive... | |
851 | */ | |
852 | ||
1d2c70a6 | 853 | if (strcmp(name, "<Printer") == 0 || |
854 | strcmp(name, "<DefaultPrinter") == 0) | |
a9de544f | 855 | { |
856 | /* | |
1d2c70a6 | 857 | * <Printer name> or <DefaultPrinter name> |
a9de544f | 858 | */ |
859 | ||
860 | if (line[len - 1] == '>' && p == NULL) | |
861 | { | |
cbbfcc63 | 862 | /* |
863 | * Add the printer and a base file type... | |
864 | */ | |
865 | ||
a9de544f | 866 | line[len - 1] = '\0'; |
867 | ||
d47f8ebe | 868 | LogMessage(L_DEBUG, "LoadAllPrinters: Loading printer %s...", value); |
869 | ||
c7fa9d06 | 870 | p = AddPrinter(value); |
4139b718 | 871 | p->accepting = 1; |
872 | p->state = IPP_PRINTER_IDLE; | |
cbbfcc63 | 873 | |
874 | /* | |
875 | * Set the default printer as needed... | |
876 | */ | |
877 | ||
1d2c70a6 | 878 | if (strcmp(name, "<DefaultPrinter") == 0) |
cbbfcc63 | 879 | DefaultPrinter = p; |
a9de544f | 880 | } |
881 | else | |
882 | { | |
5ea8888e | 883 | LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.", |
a9de544f | 884 | linenum); |
885 | return; | |
886 | } | |
887 | } | |
888 | else if (strcmp(name, "</Printer>") == 0) | |
889 | { | |
890 | if (p != NULL) | |
e5cf24b2 | 891 | { |
cbbfcc63 | 892 | SetPrinterAttrs(p); |
068e9059 | 893 | AddPrinterHistory(p); |
a9de544f | 894 | p = NULL; |
e5cf24b2 | 895 | } |
a9de544f | 896 | else |
897 | { | |
5ea8888e | 898 | LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.", |
a9de544f | 899 | linenum); |
900 | return; | |
901 | } | |
902 | } | |
903 | else if (p == NULL) | |
904 | { | |
5ea8888e | 905 | LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.", |
a9de544f | 906 | linenum); |
907 | return; | |
908 | } | |
a9de544f | 909 | else if (strcmp(name, "Info") == 0) |
36992080 | 910 | SetString(&p->info, value); |
a74b005d | 911 | else if (strcmp(name, "Location") == 0) |
36992080 | 912 | SetString(&p->location, value); |
a74b005d | 913 | else if (strcmp(name, "DeviceURI") == 0) |
36992080 | 914 | SetString(&p->device_uri, value); |
c7fa9d06 | 915 | else if (strcmp(name, "State") == 0) |
a9de544f | 916 | { |
917 | /* | |
c7fa9d06 | 918 | * Set the initial queue state... |
6abc7437 | 919 | */ |
920 | ||
c7fa9d06 | 921 | if (strcasecmp(value, "idle") == 0) |
05e63c18 | 922 | p->state = IPP_PRINTER_IDLE; |
c7fa9d06 | 923 | else if (strcasecmp(value, "stopped") == 0) |
05e63c18 | 924 | p->state = IPP_PRINTER_STOPPED; |
925 | } | |
03081fd2 | 926 | else if (strcmp(name, "StateMessage") == 0) |
927 | { | |
928 | /* | |
929 | * Set the initial queue state message... | |
930 | */ | |
931 | ||
932 | while (isspace(*value)) | |
933 | value ++; | |
934 | ||
def978d5 | 935 | strlcpy(p->state_message, value, sizeof(p->state_message)); |
03081fd2 | 936 | } |
05e63c18 | 937 | else if (strcmp(name, "Accepting") == 0) |
938 | { | |
939 | /* | |
940 | * Set the initial accepting state... | |
941 | */ | |
942 | ||
943 | if (strcasecmp(value, "yes") == 0) | |
944 | p->accepting = 1; | |
945 | else | |
c7fa9d06 | 946 | p->accepting = 0; |
a9de544f | 947 | } |
a3e17a89 | 948 | else if (strcmp(name, "JobSheets") == 0) |
949 | { | |
aba2fa7e | 950 | /* |
951 | * Set the initial job sheets... | |
952 | */ | |
a3e17a89 | 953 | |
aba2fa7e | 954 | for (valueptr = value; *valueptr && !isspace(*valueptr); valueptr ++); |
a3e17a89 | 955 | |
aba2fa7e | 956 | if (*valueptr) |
957 | *valueptr++ = '\0'; | |
a3e17a89 | 958 | |
36992080 | 959 | SetString(&p->job_sheets[0], value); |
a3e17a89 | 960 | |
aba2fa7e | 961 | while (isspace(*valueptr)) |
962 | valueptr ++; | |
a3e17a89 | 963 | |
aba2fa7e | 964 | if (*valueptr) |
965 | { | |
966 | for (value = valueptr; *valueptr && !isspace(*valueptr); valueptr ++); | |
7db52463 | 967 | |
aba2fa7e | 968 | if (*valueptr) |
969 | *valueptr++ = '\0'; | |
a3e17a89 | 970 | |
36992080 | 971 | SetString(&p->job_sheets[1], value); |
a3e17a89 | 972 | } |
973 | } | |
d7845573 | 974 | else if (strcmp(name, "AllowUser") == 0) |
975 | { | |
976 | p->deny_users = 0; | |
977 | AddPrinterUser(p, value); | |
978 | } | |
979 | else if (strcmp(name, "DenyUser") == 0) | |
980 | { | |
981 | p->deny_users = 1; | |
982 | AddPrinterUser(p, value); | |
983 | } | |
984 | else if (strcmp(name, "QuotaPeriod") == 0) | |
985 | p->quota_period = atoi(value); | |
986 | else if (strcmp(name, "PageLimit") == 0) | |
987 | p->page_limit = atoi(value); | |
988 | else if (strcmp(name, "KLimit") == 0) | |
989 | p->k_limit = atoi(value); | |
c7fa9d06 | 990 | else |
a9de544f | 991 | { |
992 | /* | |
c7fa9d06 | 993 | * Something else we don't understand... |
a9de544f | 994 | */ |
995 | ||
5ea8888e | 996 | LogMessage(L_ERROR, "Unknown configuration directive %s on line %d of printers.conf.", |
c7fa9d06 | 997 | name, linenum); |
a9de544f | 998 | } |
a9de544f | 999 | } |
1000 | ||
7b0fde61 | 1001 | cupsFileClose(fp); |
a9de544f | 1002 | } |
1003 | ||
1004 | ||
d6de4648 | 1005 | /* |
1006 | * 'SaveAllPrinters()' - Save all printer definitions to the printers.conf | |
1007 | * file. | |
1008 | */ | |
1009 | ||
a9de544f | 1010 | void |
1011 | SaveAllPrinters(void) | |
1012 | { | |
d7845573 | 1013 | int i; /* Looping var */ |
7b0fde61 | 1014 | cups_file_t *fp; /* printers.conf file */ |
cc0561c6 | 1015 | char temp[1024]; /* Temporary string */ |
7db52463 | 1016 | char backup[1024]; /* printers.conf.O file */ |
cc0561c6 | 1017 | printer_t *printer; /* Current printer class */ |
cc0561c6 | 1018 | time_t curtime; /* Current time */ |
1019 | struct tm *curdate; /* Current date */ | |
1020 | ||
1021 | ||
1022 | /* | |
1023 | * Create the printers.conf file... | |
1024 | */ | |
1025 | ||
a6988fb1 | 1026 | snprintf(temp, sizeof(temp), "%s/printers.conf", ServerRoot); |
7db52463 | 1027 | snprintf(backup, sizeof(backup), "%s/printers.conf.O", ServerRoot); |
1028 | ||
1029 | if (rename(temp, backup)) | |
1030 | LogMessage(L_ERROR, "Unable to backup printers.conf - %s", strerror(errno)); | |
1031 | ||
7b0fde61 | 1032 | if ((fp = cupsFileOpen(temp, "w")) == NULL) |
cc0561c6 | 1033 | { |
5ea8888e | 1034 | LogMessage(L_ERROR, "Unable to save printers.conf - %s", strerror(errno)); |
7db52463 | 1035 | |
1036 | if (rename(backup, temp)) | |
1037 | LogMessage(L_ERROR, "Unable to restore printers.conf - %s", strerror(errno)); | |
cc0561c6 | 1038 | return; |
1039 | } | |
1040 | else | |
5ea8888e | 1041 | LogMessage(L_INFO, "Saving printers.conf..."); |
cc0561c6 | 1042 | |
35a2ba9d | 1043 | /* |
1044 | * Restrict access to the file... | |
1045 | */ | |
1046 | ||
aa7b8dba | 1047 | fchown(cupsFileNumber(fp), getuid(), Group); |
d59a189c | 1048 | fchmod(cupsFileNumber(fp), ConfigFilePerm); |
35a2ba9d | 1049 | |
cc0561c6 | 1050 | /* |
1051 | * Write a small header to the file... | |
1052 | */ | |
1053 | ||
1054 | curtime = time(NULL); | |
aa3b74e1 | 1055 | curdate = localtime(&curtime); |
8a32fc08 | 1056 | strftime(temp, sizeof(temp) - 1, CUPS_STRFTIME_FORMAT, curdate); |
cc0561c6 | 1057 | |
7b0fde61 | 1058 | cupsFilePuts(fp, "# Printer configuration file for " CUPS_SVERSION "\n"); |
1059 | cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); | |
cc0561c6 | 1060 | |
1061 | /* | |
1062 | * Write each local printer known to the system... | |
1063 | */ | |
1064 | ||
1065 | for (printer = Printers; printer != NULL; printer = printer->next) | |
1066 | { | |
1067 | /* | |
1068 | * Skip remote destinations and printer classes... | |
1069 | */ | |
1070 | ||
1071 | if ((printer->type & CUPS_PRINTER_REMOTE) || | |
29013747 | 1072 | (printer->type & CUPS_PRINTER_CLASS) || |
1073 | (printer->type & CUPS_PRINTER_IMPLICIT)) | |
cc0561c6 | 1074 | continue; |
1075 | ||
1076 | /* | |
1077 | * Write printers as needed... | |
1078 | */ | |
1079 | ||
1080 | if (printer == DefaultPrinter) | |
7b0fde61 | 1081 | cupsFilePrintf(fp, "<DefaultPrinter %s>\n", printer->name); |
cc0561c6 | 1082 | else |
7b0fde61 | 1083 | cupsFilePrintf(fp, "<Printer %s>\n", printer->name); |
cc0561c6 | 1084 | |
36992080 | 1085 | if (printer->info) |
7b0fde61 | 1086 | cupsFilePrintf(fp, "Info %s\n", printer->info); |
753453e4 | 1087 | |
36992080 | 1088 | if (printer->location) |
7b0fde61 | 1089 | cupsFilePrintf(fp, "Location %s\n", printer->location); |
753453e4 | 1090 | |
36992080 | 1091 | if (printer->device_uri) |
7b0fde61 | 1092 | cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri); |
753453e4 | 1093 | |
cc0561c6 | 1094 | if (printer->state == IPP_PRINTER_STOPPED) |
03081fd2 | 1095 | { |
7b0fde61 | 1096 | cupsFilePuts(fp, "State Stopped\n"); |
1097 | cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message); | |
03081fd2 | 1098 | } |
cc0561c6 | 1099 | else |
7b0fde61 | 1100 | cupsFilePuts(fp, "State Idle\n"); |
753453e4 | 1101 | |
05e63c18 | 1102 | if (printer->accepting) |
7b0fde61 | 1103 | cupsFilePuts(fp, "Accepting Yes\n"); |
05e63c18 | 1104 | else |
7b0fde61 | 1105 | cupsFilePuts(fp, "Accepting No\n"); |
753453e4 | 1106 | |
7b0fde61 | 1107 | cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0], |
a3e17a89 | 1108 | printer->job_sheets[1]); |
cc0561c6 | 1109 | |
7b0fde61 | 1110 | cupsFilePrintf(fp, "QuotaPeriod %d\n", printer->quota_period); |
1111 | cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit); | |
1112 | cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit); | |
d7845573 | 1113 | |
1114 | for (i = 0; i < printer->num_users; i ++) | |
7b0fde61 | 1115 | cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow", |
d7845573 | 1116 | printer->users[i]); |
1117 | ||
7b0fde61 | 1118 | cupsFilePuts(fp, "</Printer>\n"); |
dd5cfc84 | 1119 | |
9ae34eb7 | 1120 | #ifdef __sgi |
1121 | /* | |
1122 | * Make IRIX desktop & printer status happy | |
1123 | */ | |
1124 | ||
1125 | write_irix_state(printer); | |
9ae34eb7 | 1126 | #endif /* __sgi */ |
cc0561c6 | 1127 | } |
1128 | ||
7b0fde61 | 1129 | cupsFileClose(fp); |
a9de544f | 1130 | } |
1131 | ||
1132 | ||
f3d580b9 | 1133 | /* |
cbbfcc63 | 1134 | * 'SetPrinterAttrs()' - Set printer attributes based upon the PPD file. |
f3d580b9 | 1135 | */ |
1136 | ||
a9de544f | 1137 | void |
05e63c18 | 1138 | SetPrinterAttrs(printer_t *p) /* I - Printer to setup */ |
f3d580b9 | 1139 | { |
05e63c18 | 1140 | char uri[HTTP_MAX_URI]; /* URI for printer */ |
1141 | char method[HTTP_MAX_URI], /* Method portion of URI */ | |
1142 | username[HTTP_MAX_URI], /* Username portion of URI */ | |
1143 | host[HTTP_MAX_URI], /* Host portion of URI */ | |
1144 | resource[HTTP_MAX_URI]; /* Resource portion of URI */ | |
1145 | int port; /* Port portion of URI */ | |
1146 | int i; /* Looping var */ | |
1147 | char filename[1024]; /* Name of PPD file */ | |
1148 | int num_media; /* Number of media options */ | |
7ebf3a09 | 1149 | location_t *auth; /* Pointer to authentication element */ |
7ebf3a09 | 1150 | const char *auth_supported; /* Authentication supported */ |
753453e4 | 1151 | cups_ptype_t printer_type; /* Printer type data */ |
05e63c18 | 1152 | ppd_file_t *ppd; /* PPD file data */ |
1153 | ppd_option_t *input_slot, /* InputSlot options */ | |
1154 | *media_type, /* MediaType options */ | |
29ece07e | 1155 | *page_size, /* PageSize options */ |
daeeb91c | 1156 | *output_bin, /* OutputBin options */ |
1157 | *media_quality; /* EFMediaQualityMode options */ | |
e532393d | 1158 | ppd_attr_t *ppdattr; /* PPD attribute */ |
05e63c18 | 1159 | ipp_attribute_t *attr; /* Attribute data */ |
1160 | ipp_value_t *val; /* Attribute value */ | |
67c158fa | 1161 | int num_finishings; |
1162 | ipp_finish_t finishings[5]; /* finishings-supported values */ | |
aa7b8dba | 1163 | static const char * const sides[3] = /* sides-supported values */ |
f3d580b9 | 1164 | { |
aa7b8dba | 1165 | "one", |
1166 | "two-long-edge", | |
1167 | "two-short-edge" | |
f3d580b9 | 1168 | }; |
f3d580b9 | 1169 | |
1170 | ||
74ea18d4 | 1171 | DEBUG_printf(("SetPrinterAttrs: entering name = %s, type = %x\n", p->name, |
1172 | p->type)); | |
22902293 | 1173 | |
3f2fa036 | 1174 | /* |
1175 | * Make sure that we have the common attributes defined... | |
1176 | */ | |
1177 | ||
1178 | if (!CommonData) | |
67c158fa | 1179 | CreateCommonData(); |
3f2fa036 | 1180 | |
c7fa9d06 | 1181 | /* |
1182 | * Clear out old filters and add a filter from application/vnd.cups-raw to | |
1183 | * printer/name to handle "raw" printing by users. | |
1184 | */ | |
1185 | ||
1186 | DeletePrinterFilters(p); | |
1187 | AddPrinterFilter(p, "application/vnd.cups-raw 0 -"); | |
1188 | ||
7ebf3a09 | 1189 | /* |
1190 | * Figure out the authentication that is required for the printer. | |
1191 | */ | |
1192 | ||
1193 | auth_supported = "requesting-user-name"; | |
1194 | if (!(p->type & CUPS_PRINTER_REMOTE)) | |
1195 | { | |
1196 | if (p->type & CUPS_PRINTER_CLASS) | |
a6988fb1 | 1197 | snprintf(resource, sizeof(resource), "/classes/%s", p->name); |
7ebf3a09 | 1198 | else |
a6988fb1 | 1199 | snprintf(resource, sizeof(resource), "/printers/%s", p->name); |
7ebf3a09 | 1200 | |
7db52463 | 1201 | if ((auth = FindBest(resource, HTTP_POST)) != NULL) |
1202 | { | |
aba2fa7e | 1203 | if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST) |
7db52463 | 1204 | auth_supported = "basic"; |
1205 | else if (auth->type == AUTH_DIGEST) | |
1206 | auth_supported = "digest"; | |
1207 | } | |
7ebf3a09 | 1208 | } |
1209 | ||
f3d580b9 | 1210 | /* |
1211 | * Create the required IPP attributes for a printer... | |
1212 | */ | |
1213 | ||
1214 | if (p->attrs) | |
1215 | ippDelete(p->attrs); | |
1216 | ||
1217 | p->attrs = ippNew(); | |
1218 | ||
f3d580b9 | 1219 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", |
d6de4648 | 1220 | NULL, p->uri); |
7ebf3a09 | 1221 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, |
1222 | "uri-authentication-supported", NULL, auth_supported); | |
f3d580b9 | 1223 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, |
1224 | "uri-security-supported", NULL, "none"); | |
1225 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL, | |
1226 | p->name); | |
1227 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", | |
36992080 | 1228 | NULL, p->location ? p->location : ""); |
f3d580b9 | 1229 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", |
36992080 | 1230 | NULL, p->info ? p->info : ""); |
f3d580b9 | 1231 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", |
753453e4 | 1232 | NULL, p->uri); |
f3d580b9 | 1233 | |
d7845573 | 1234 | if (p->num_users) |
1235 | { | |
1236 | if (p->deny_users) | |
1237 | ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, | |
1238 | "requesting-user-name-denied", p->num_users, NULL, | |
1239 | p->users); | |
1240 | else | |
1241 | ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, | |
1242 | "requesting-user-name-allowed", p->num_users, NULL, | |
1243 | p->users); | |
1244 | } | |
1245 | ||
04d756fc | 1246 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, |
1247 | "job-quota-period", p->quota_period); | |
1248 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
1249 | "job-k-limit", p->k_limit); | |
1250 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
1251 | "job-page-limit", p->page_limit); | |
1252 | ||
3f2fa036 | 1253 | if (NumBanners > 0 && !(p->type & CUPS_PRINTER_REMOTE)) |
d21a7597 | 1254 | { |
1255 | /* | |
3f2fa036 | 1256 | * Setup the job-sheets-default attribute... |
d21a7597 | 1257 | */ |
1258 | ||
3f2fa036 | 1259 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, |
1260 | "job-sheets-default", 2, NULL, NULL); | |
d21a7597 | 1261 | |
3f2fa036 | 1262 | if (attr != NULL) |
d11458ff | 1263 | { |
3f2fa036 | 1264 | attr->values[0].string.text = strdup(Classification ? |
1265 | Classification : p->job_sheets[0]); | |
1266 | attr->values[1].string.text = strdup(Classification ? | |
1267 | Classification : p->job_sheets[1]); | |
d11458ff | 1268 | } |
d21a7597 | 1269 | } |
1270 | ||
753453e4 | 1271 | printer_type = p->type; |
1272 | ||
a7a1daf4 | 1273 | p->raw = 0; |
1274 | ||
6bc08d08 | 1275 | if (p->type & CUPS_PRINTER_REMOTE) |
1276 | { | |
1277 | /* | |
1278 | * Tell the client this is a remote printer of some type... | |
1279 | */ | |
1280 | ||
6bc08d08 | 1281 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, |
a2c6b8b1 | 1282 | "printer-make-and-model", NULL, p->make_model); |
a7a1daf4 | 1283 | |
1284 | p->raw = 1; | |
6bc08d08 | 1285 | } |
1286 | else | |
f3d580b9 | 1287 | { |
1288 | /* | |
08d0dfa7 | 1289 | * Assign additional attributes depending on whether this is a printer |
1290 | * or class... | |
f3d580b9 | 1291 | */ |
1292 | ||
08d0dfa7 | 1293 | p->type &= ~CUPS_PRINTER_OPTIONS; |
1294 | ||
a2c6b8b1 | 1295 | if (p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) |
cbbfcc63 | 1296 | { |
1297 | /* | |
08d0dfa7 | 1298 | * Add class-specific attributes... |
cbbfcc63 | 1299 | */ |
1300 | ||
a2c6b8b1 | 1301 | if ((p->type & CUPS_PRINTER_IMPLICIT) && p->num_printers > 0) |
1302 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, | |
1303 | "printer-make-and-model", NULL, p->printers[0]->make_model); | |
1304 | else | |
1305 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, | |
1306 | "printer-make-and-model", NULL, "Local Printer Class"); | |
6bc08d08 | 1307 | |
08d0dfa7 | 1308 | if (p->num_printers > 0) |
1309 | { | |
1310 | /* | |
1311 | * Add a list of member URIs and names... | |
1312 | */ | |
cbbfcc63 | 1313 | |
08d0dfa7 | 1314 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, |
1315 | "member-uris", p->num_printers, NULL, NULL); | |
08d0dfa7 | 1316 | p->type |= CUPS_PRINTER_OPTIONS; |
f3d580b9 | 1317 | |
08d0dfa7 | 1318 | for (i = 0; i < p->num_printers; i ++) |
1319 | { | |
d11458ff | 1320 | if (attr != NULL) |
1321 | attr->values[i].string.text = strdup(p->printers[i]->uri); | |
f3d580b9 | 1322 | |
08d0dfa7 | 1323 | p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type; |
1324 | } | |
f3d580b9 | 1325 | |
08d0dfa7 | 1326 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, |
1327 | "member-names", p->num_printers, NULL, NULL); | |
f3d580b9 | 1328 | |
d11458ff | 1329 | if (attr != NULL) |
1330 | { | |
1331 | for (i = 0; i < p->num_printers; i ++) | |
1332 | attr->values[i].string.text = strdup(p->printers[i]->name); | |
1333 | } | |
08d0dfa7 | 1334 | } |
1335 | } | |
1336 | else | |
cbbfcc63 | 1337 | { |
1338 | /* | |
05e63c18 | 1339 | * Add printer-specific attributes... Start by sanitizing the device |
1340 | * URI so it doesn't have a username or password in it... | |
cbbfcc63 | 1341 | */ |
f3d580b9 | 1342 | |
36992080 | 1343 | if (!p->device_uri) |
1344 | strcpy(uri, "file:/dev/null"); | |
1345 | else if (strstr(p->device_uri, "://") != NULL) | |
05e63c18 | 1346 | { |
1347 | /* | |
1348 | * http://..., ipp://..., etc. | |
1349 | */ | |
1350 | ||
1351 | httpSeparate(p->device_uri, method, username, host, &port, resource); | |
513216df | 1352 | if (port) |
a6988fb1 | 1353 | snprintf(uri, sizeof(uri), "%s://%s:%d%s", method, host, port, |
1354 | resource); | |
513216df | 1355 | else |
a6988fb1 | 1356 | snprintf(uri, sizeof(uri), "%s://%s%s", method, host, resource); |
05e63c18 | 1357 | } |
1358 | else | |
1359 | { | |
1360 | /* | |
1361 | * file:..., serial:..., etc. | |
1362 | */ | |
1363 | ||
36992080 | 1364 | strlcpy(uri, p->device_uri, sizeof(uri)); |
05e63c18 | 1365 | } |
1366 | ||
08d0dfa7 | 1367 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, |
05e63c18 | 1368 | uri); |
f3d580b9 | 1369 | |
cbbfcc63 | 1370 | /* |
08d0dfa7 | 1371 | * Assign additional attributes from the PPD file (if any)... |
cbbfcc63 | 1372 | */ |
f3d580b9 | 1373 | |
08d0dfa7 | 1374 | p->type |= CUPS_PRINTER_BW; |
8bc932be | 1375 | finishings[0] = IPP_FINISHINGS_NONE; |
08d0dfa7 | 1376 | num_finishings = 1; |
f3d580b9 | 1377 | |
a6988fb1 | 1378 | snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, |
1379 | p->name); | |
1380 | ||
08d0dfa7 | 1381 | if ((ppd = ppdOpenFile(filename)) != NULL) |
1382 | { | |
1383 | /* | |
1384 | * Add make/model and other various attributes... | |
1385 | */ | |
d6de4648 | 1386 | |
08d0dfa7 | 1387 | if (ppd->color_device) |
1388 | p->type |= CUPS_PRINTER_COLOR; | |
1389 | if (ppd->variable_sizes) | |
1390 | p->type |= CUPS_PRINTER_VARIABLE; | |
1391 | if (!ppd->manual_copies) | |
1392 | p->type |= CUPS_PRINTER_COPIES; | |
e532393d | 1393 | if ((ppdattr = ppdFindAttr(ppd, "cupsFax", NULL)) != NULL) |
1394 | if (ppdattr->value && !strcasecmp(ppdattr->value, "true")) | |
1395 | p->type |= CUPS_PRINTER_FAX; | |
f3d580b9 | 1396 | |
08d0dfa7 | 1397 | ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "color-supported", |
1398 | ppd->color_device); | |
7ebf3a09 | 1399 | if (ppd->throughput) |
1400 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | |
1401 | "pages-per-minute", ppd->throughput); | |
d6de4648 | 1402 | |
753453e4 | 1403 | if (ppd->nickname) |
36992080 | 1404 | SetString(&p->make_model, ppd->nickname); |
753453e4 | 1405 | else if (ppd->modelname) |
36992080 | 1406 | SetString(&p->make_model, ppd->modelname); |
753453e4 | 1407 | else |
36992080 | 1408 | SetString(&p->make_model, "Bad PPD File"); |
a2c6b8b1 | 1409 | |
415199da | 1410 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, |
1411 | "printer-make-and-model", NULL, p->make_model); | |
1412 | ||
08d0dfa7 | 1413 | /* |
1414 | * Add media options from the PPD file... | |
1415 | */ | |
d6de4648 | 1416 | |
08d0dfa7 | 1417 | if ((input_slot = ppdFindOption(ppd, "InputSlot")) != NULL) |
1418 | num_media = input_slot->num_choices; | |
1419 | else | |
1420 | num_media = 0; | |
1421 | ||
1422 | if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL) | |
1423 | num_media += media_type->num_choices; | |
1424 | ||
1425 | if ((page_size = ppdFindOption(ppd, "PageSize")) != NULL) | |
1426 | num_media += page_size->num_choices; | |
1427 | ||
daeeb91c | 1428 | if ((media_quality = ppdFindOption(ppd, "EFMediaQualityMode")) != NULL) |
1429 | num_media += media_quality->num_choices; | |
1430 | ||
00528abb | 1431 | if (num_media == 0) |
e2660aea | 1432 | { |
00528abb | 1433 | LogMessage(L_CRIT, "SetPrinterAttrs: The PPD file for printer %s " |
1434 | "contains no media options and is therefore " | |
1435 | "invalid!", p->name); | |
1436 | } | |
1437 | else | |
1438 | { | |
1439 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
1440 | "media-supported", num_media, NULL, NULL); | |
1441 | if (attr != NULL) | |
d11458ff | 1442 | { |
00528abb | 1443 | val = attr->values; |
1444 | ||
1445 | if (input_slot != NULL) | |
1446 | for (i = 0; i < input_slot->num_choices; i ++, val ++) | |
1447 | val->string.text = strdup(input_slot->choices[i].choice); | |
1448 | ||
1449 | if (media_type != NULL) | |
1450 | for (i = 0; i < media_type->num_choices; i ++, val ++) | |
1451 | val->string.text = strdup(media_type->choices[i].choice); | |
1452 | ||
1453 | if (media_quality != NULL) | |
1454 | for (i = 0; i < media_quality->num_choices; i ++, val ++) | |
1455 | val->string.text = strdup(media_quality->choices[i].choice); | |
1456 | ||
1457 | if (page_size != NULL) | |
1458 | { | |
1459 | for (i = 0; i < page_size->num_choices; i ++, val ++) | |
1460 | val->string.text = strdup(page_size->choices[i].choice); | |
1461 | ||
1462 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", | |
1463 | NULL, page_size->defchoice); | |
1464 | } | |
1465 | else if (input_slot != NULL) | |
1466 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", | |
1467 | NULL, input_slot->defchoice); | |
1468 | else if (media_type != NULL) | |
1469 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", | |
1470 | NULL, media_type->defchoice); | |
1471 | else if (media_quality != NULL) | |
1472 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", | |
1473 | NULL, media_quality->defchoice); | |
1474 | else | |
1475 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", | |
1476 | NULL, "none"); | |
d11458ff | 1477 | } |
e2660aea | 1478 | } |
08d0dfa7 | 1479 | |
29ece07e | 1480 | /* |
1481 | * Output bin... | |
1482 | */ | |
1483 | ||
1484 | if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL) | |
1485 | { | |
1486 | attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, | |
1487 | "output-bin-supported", output_bin->num_choices, | |
1488 | NULL, NULL); | |
1489 | ||
d11458ff | 1490 | if (attr != NULL) |
1491 | { | |
1492 | for (i = 0, val = attr->values; | |
1493 | i < output_bin->num_choices; | |
1494 | i ++, val ++) | |
1495 | val->string.text = strdup(output_bin->choices[i].choice); | |
1496 | } | |
1497 | } | |
29ece07e | 1498 | |
1499 | /* | |
1500 | * Duplexing, etc... | |
1501 | */ | |
1502 | ||
08d0dfa7 | 1503 | if (ppdFindOption(ppd, "Duplex") != NULL) |
1504 | { | |
1505 | p->type |= CUPS_PRINTER_DUPLEX; | |
1506 | ||
1507 | ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-supported", | |
1508 | 3, NULL, sides); | |
1509 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-default", | |
1510 | NULL, "one"); | |
1511 | } | |
1512 | ||
1513 | if (ppdFindOption(ppd, "Collate") != NULL) | |
1514 | p->type |= CUPS_PRINTER_COLLATE; | |
1515 | ||
1516 | if (ppdFindOption(ppd, "StapleLocation") != NULL) | |
1517 | { | |
1518 | p->type |= CUPS_PRINTER_STAPLE; | |
8bc932be | 1519 | finishings[num_finishings++] = IPP_FINISHINGS_STAPLE; |
08d0dfa7 | 1520 | } |
1521 | ||
1522 | if (ppdFindOption(ppd, "BindEdge") != NULL) | |
1523 | { | |
1524 | p->type |= CUPS_PRINTER_BIND; | |
8bc932be | 1525 | finishings[num_finishings++] = IPP_FINISHINGS_BIND; |
08d0dfa7 | 1526 | } |
1527 | ||
1528 | for (i = 0; i < ppd->num_sizes; i ++) | |
1529 | if (ppd->sizes[i].length > 1728) | |
1530 | p->type |= CUPS_PRINTER_LARGE; | |
1531 | else if (ppd->sizes[i].length > 1008) | |
1532 | p->type |= CUPS_PRINTER_MEDIUM; | |
1533 | else | |
1534 | p->type |= CUPS_PRINTER_SMALL; | |
d6de4648 | 1535 | |
08d0dfa7 | 1536 | /* |
1537 | * Add any filters in the PPD file... | |
1538 | */ | |
d6de4648 | 1539 | |
08d0dfa7 | 1540 | DEBUG_printf(("ppd->num_filters = %d\n", ppd->num_filters)); |
1541 | for (i = 0; i < ppd->num_filters; i ++) | |
1542 | { | |
1543 | DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i])); | |
1544 | AddPrinterFilter(p, ppd->filters[i]); | |
1545 | } | |
d6de4648 | 1546 | |
08d0dfa7 | 1547 | if (ppd->num_filters == 0) |
1548 | AddPrinterFilter(p, "application/vnd.cups-postscript 0 -"); | |
d6de4648 | 1549 | |
08d0dfa7 | 1550 | ppdClose(ppd); |
753453e4 | 1551 | |
1552 | printer_type = p->type; | |
cbbfcc63 | 1553 | } |
08d0dfa7 | 1554 | else if (access(filename, 0) == 0) |
cbbfcc63 | 1555 | { |
6897133b | 1556 | int pline; /* PPD line number */ |
1557 | ppd_status_t pstatus; /* PPD load status */ | |
1558 | ||
1559 | ||
1560 | pstatus = ppdLastError(&pline); | |
1561 | ||
5ea8888e | 1562 | LogMessage(L_ERROR, "PPD file for %s cannot be loaded!", p->name); |
7a76892d | 1563 | |
1564 | if (pstatus <= PPD_ALLOC_ERROR) | |
1565 | LogMessage(L_ERROR, "%s", strerror(errno)); | |
1566 | else | |
1567 | LogMessage(L_ERROR, "%s on line %d.", ppdErrorString(pstatus), | |
1568 | pline); | |
cbbfcc63 | 1569 | |
4e43f59e | 1570 | LogMessage(L_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.", |
1571 | filename); | |
1572 | ||
08d0dfa7 | 1573 | AddPrinterFilter(p, "application/vnd.cups-postscript 0 -"); |
cbbfcc63 | 1574 | } |
0c06ac87 | 1575 | else |
1576 | { | |
1577 | /* | |
ef0a945a | 1578 | * If we have an interface script, add a filter entry for it... |
0c06ac87 | 1579 | */ |
1580 | ||
a6988fb1 | 1581 | snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot, |
1582 | p->name); | |
ef0a945a | 1583 | if (access(filename, X_OK) == 0) |
1584 | { | |
1585 | /* | |
1586 | * Yes, we have a System V style interface script; use it! | |
1587 | */ | |
1588 | ||
6bc08d08 | 1589 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, |
1590 | "printer-make-and-model", NULL, "Local System V Printer"); | |
1591 | ||
a6988fb1 | 1592 | snprintf(filename, sizeof(filename), "*/* 0 %s/interfaces/%s", |
1593 | ServerRoot, p->name); | |
ef0a945a | 1594 | AddPrinterFilter(p, filename); |
1595 | } | |
36992080 | 1596 | else if (p->device_uri && |
1597 | strncmp(p->device_uri, "ipp://", 6) == 0 && | |
753453e4 | 1598 | (strstr(p->device_uri, "/printers/") != NULL || |
1599 | strstr(p->device_uri, "/classes/") != NULL)) | |
1600 | { | |
1601 | /* | |
1602 | * Tell the client this is really a hard-wired remote printer. | |
1603 | */ | |
1604 | ||
1605 | printer_type |= CUPS_PRINTER_REMOTE; | |
1606 | ||
1607 | /* | |
1608 | * Reset the printer-uri-supported attribute to point at the | |
1609 | * remote printer... | |
1610 | */ | |
1611 | ||
1612 | attr = ippFindAttribute(p->attrs, "printer-uri-supported", IPP_TAG_URI); | |
1613 | free(attr->values[0].string.text); | |
1614 | attr->values[0].string.text = strdup(p->device_uri); | |
1615 | ||
1616 | /* | |
1617 | * Then set the make-and-model accordingly... | |
1618 | */ | |
1619 | ||
1620 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, | |
1621 | "printer-make-and-model", NULL, "Remote Printer"); | |
1622 | ||
1623 | /* | |
1624 | * Print all files directly... | |
1625 | */ | |
1626 | ||
a7a1daf4 | 1627 | p->raw = 1; |
753453e4 | 1628 | } |
ef0a945a | 1629 | else |
1630 | { | |
1631 | /* | |
2aeb2b1d | 1632 | * Otherwise we have neither - treat this as a "dumb" printer |
1633 | * with no PPD file... | |
ef0a945a | 1634 | */ |
1635 | ||
6bc08d08 | 1636 | ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, |
1637 | "printer-make-and-model", NULL, "Local Raw Printer"); | |
1638 | ||
a7a1daf4 | 1639 | p->raw = 1; |
ef0a945a | 1640 | } |
0c06ac87 | 1641 | } |
ef0a945a | 1642 | |
1643 | ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
1644 | "finishings-supported", num_finishings, (int *)finishings); | |
1645 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, | |
8bc932be | 1646 | "finishings-default", IPP_FINISHINGS_NONE); |
5b88701c | 1647 | } |
cbbfcc63 | 1648 | } |
d6de4648 | 1649 | |
c7fa9d06 | 1650 | /* |
1651 | * Add the CUPS-specific printer-type attribute... | |
1652 | */ | |
1653 | ||
753453e4 | 1654 | ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", |
1655 | printer_type); | |
22902293 | 1656 | |
74ea18d4 | 1657 | DEBUG_printf(("SetPrinterAttrs: leaving name = %s, type = %x\n", p->name, |
1658 | p->type)); | |
957c6597 | 1659 | |
1660 | #ifdef __sgi | |
1661 | /* | |
dd5cfc84 | 1662 | * Write the IRIX printer config and status files... |
9ae34eb7 | 1663 | */ |
1664 | ||
dd5cfc84 | 1665 | write_irix_config(p); |
9ae34eb7 | 1666 | write_irix_state(p); |
957c6597 | 1667 | #endif /* __sgi */ |
f3d580b9 | 1668 | } |
1669 | ||
1670 | ||
62bcac22 | 1671 | /* |
1672 | * 'SetPrinterReasons()' - Set/update the reasons strings. | |
1673 | */ | |
1674 | ||
1675 | void | |
1676 | SetPrinterReasons(printer_t *p, /* I - Printer */ | |
1677 | const char *s) /* I - Reasons strings */ | |
1678 | { | |
1679 | int i; /* Looping var */ | |
1680 | const char *sptr; /* Pointer into reasons */ | |
1681 | char reason[255], /* Reason string */ | |
1682 | *rptr; /* Pointer into reason */ | |
1683 | ||
1684 | ||
1685 | if (s[0] == '-' || s[0] == '+') | |
1686 | { | |
1687 | /* | |
1688 | * Add/remove reasons... | |
1689 | */ | |
1690 | ||
1691 | sptr = s + 1; | |
1692 | } | |
1693 | else | |
1694 | { | |
1695 | /* | |
1696 | * Replace reasons... | |
1697 | */ | |
1698 | ||
1699 | sptr = s; | |
1700 | ||
1701 | for (i = 0; i < p->num_reasons; i ++) | |
1702 | free(p->reasons[i]); | |
1703 | ||
1704 | p->num_reasons = 0; | |
1705 | } | |
1706 | ||
1707 | /* | |
1708 | * Loop through all of the reasons... | |
1709 | */ | |
1710 | ||
1711 | while (*sptr) | |
1712 | { | |
1713 | /* | |
1714 | * Skip leading whitespace and commas... | |
1715 | */ | |
1716 | ||
1717 | while (isspace(*sptr) || *sptr == ',') | |
1718 | sptr ++; | |
1719 | ||
1720 | for (rptr = reason; *sptr && !isspace(*sptr) && *sptr != ','; sptr ++) | |
1721 | if (rptr < (reason + sizeof(reason) - 1)) | |
1722 | *rptr++ = *sptr; | |
1723 | ||
1724 | if (rptr == reason) | |
1725 | break; | |
1726 | ||
1727 | *rptr = '\0'; | |
1728 | ||
1729 | if (s[0] == '-') | |
1730 | { | |
1731 | /* | |
1732 | * Remove reason... | |
1733 | */ | |
1734 | ||
1735 | for (i = 0; i < p->num_reasons; i ++) | |
1736 | if (!strcasecmp(reason, p->reasons[i])) | |
1737 | { | |
1738 | /* | |
1739 | * Found a match, so remove it... | |
1740 | */ | |
1741 | ||
1742 | p->num_reasons --; | |
1743 | free(p->reasons[i]); | |
1744 | ||
1745 | if (i < p->num_reasons) | |
1746 | memmove(p->reasons + i, p->reasons + i + 1, | |
1747 | (p->num_reasons - i) * sizeof(char *)); | |
1748 | ||
1749 | i --; | |
1750 | } | |
1751 | } | |
1752 | else if (s[0] == '+' && | |
1753 | p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) | |
1754 | { | |
1755 | /* | |
1756 | * Add reason... | |
1757 | */ | |
1758 | ||
1759 | for (i = 0; i < p->num_reasons; i ++) | |
1760 | if (!strcasecmp(reason, p->reasons[i])) | |
1761 | break; | |
1762 | ||
1763 | if (i >= p->num_reasons) | |
1764 | { | |
1765 | p->reasons[i] = strdup(reason); | |
1766 | p->num_reasons ++; | |
1767 | } | |
1768 | } | |
1769 | } | |
1770 | } | |
1771 | ||
1772 | ||
f3d580b9 | 1773 | /* |
cbbfcc63 | 1774 | * 'SetPrinterState()' - Update the current state of a printer. |
1775 | */ | |
1776 | ||
1777 | void | |
1778 | SetPrinterState(printer_t *p, /* I - Printer to change */ | |
aa3b74e1 | 1779 | ipp_pstate_t s, /* I - New state */ |
1780 | int update) /* I - Update printers.conf? */ | |
cbbfcc63 | 1781 | { |
1782 | ipp_pstate_t old_state; /* Old printer state */ | |
1783 | ||
1784 | ||
e63d9801 | 1785 | /* |
1786 | * Can't set status of remote printers... | |
1787 | */ | |
1788 | ||
1789 | if (p->type & CUPS_PRINTER_REMOTE) | |
1790 | return; | |
1791 | ||
cbbfcc63 | 1792 | /* |
1793 | * Set the new state... | |
1794 | */ | |
1795 | ||
62bcac22 | 1796 | old_state = p->state; |
1797 | p->state = s; | |
cbbfcc63 | 1798 | |
1799 | if (old_state != s) | |
c802720f | 1800 | { |
62bcac22 | 1801 | p->state_time = time(NULL); |
cbbfcc63 | 1802 | p->browse_time = 0; |
1803 | ||
c802720f | 1804 | #ifdef __sgi |
1805 | write_irix_state(p); | |
1806 | #endif /* __sgi */ | |
1807 | } | |
1808 | ||
62bcac22 | 1809 | AddPrinterHistory(p); |
1810 | ||
cbbfcc63 | 1811 | /* |
1812 | * Save the printer configuration if a printer goes from idle or processing | |
1813 | * to stopped (or visa-versa)... | |
1814 | */ | |
1815 | ||
aa3b74e1 | 1816 | if ((old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED) && |
1817 | update) | |
c8a55d2c | 1818 | { |
1819 | if (p->type & CUPS_PRINTER_CLASS) | |
1820 | SaveAllClasses(); | |
1821 | else | |
1822 | SaveAllPrinters(); | |
1823 | } | |
cbbfcc63 | 1824 | } |
1825 | ||
1826 | ||
1cab4605 | 1827 | /* |
1828 | * 'SortPrinters()' - Sort the printer list when a printer name is changed. | |
1829 | */ | |
1830 | ||
1831 | void | |
1832 | SortPrinters(void) | |
1833 | { | |
1834 | printer_t *current, /* Current printer */ | |
1835 | *prev, /* Previous printer */ | |
1836 | *next; /* Next printer */ | |
d57f94b6 | 1837 | int did_swap; /* Non-zero if we did a swap */ |
1cab4605 | 1838 | |
1839 | ||
d57f94b6 | 1840 | do |
1841 | { | |
1842 | for (did_swap = 0, current = Printers, prev = NULL; current != NULL;) | |
1843 | if (current->next == NULL) | |
1844 | break; | |
1845 | else if (strcasecmp(current->name, current->next->name) > 0) | |
1846 | { | |
1847 | DEBUG_printf(("Swapping %s and %s...\n", current->name, | |
1848 | current->next->name)); | |
a8b216d5 | 1849 | |
d57f94b6 | 1850 | /* |
1851 | * Need to swap these two printers... | |
1852 | */ | |
1cab4605 | 1853 | |
d57f94b6 | 1854 | did_swap = 1; |
1cab4605 | 1855 | |
d57f94b6 | 1856 | if (prev == NULL) |
1857 | Printers = current->next; | |
1858 | else | |
1859 | prev->next = current->next; | |
1cab4605 | 1860 | |
d57f94b6 | 1861 | /* |
1862 | * Yes, we can all get a headache from the next bunch of pointer | |
1863 | * swapping... | |
1864 | */ | |
1865 | ||
1866 | next = current->next; | |
1867 | current->next = next->next; | |
1868 | next->next = current; | |
b5cb0608 | 1869 | prev = next; |
d57f94b6 | 1870 | } |
1871 | else | |
b5cb0608 | 1872 | { |
1873 | prev = current; | |
d57f94b6 | 1874 | current = current->next; |
b5cb0608 | 1875 | } |
d57f94b6 | 1876 | } |
1877 | while (did_swap); | |
1cab4605 | 1878 | } |
1879 | ||
1880 | ||
cbbfcc63 | 1881 | /* |
1882 | * 'StopPrinter()' - Stop a printer from printing any jobs... | |
1883 | */ | |
1884 | ||
1885 | void | |
aa3b74e1 | 1886 | StopPrinter(printer_t *p, /* I - Printer to stop */ |
1887 | int update) /* I - Update printers.conf? */ | |
cbbfcc63 | 1888 | { |
aa3b74e1 | 1889 | job_t *job; /* Active print job */ |
dc4ff34c | 1890 | |
5c8eff27 | 1891 | |
1892 | /* | |
1893 | * Set the printer state... | |
1894 | */ | |
1895 | ||
aa3b74e1 | 1896 | SetPrinterState(p, IPP_PRINTER_STOPPED, update); |
5c8eff27 | 1897 | |
dc4ff34c | 1898 | /* |
1899 | * See if we have a job printing on this printer... | |
1900 | */ | |
1901 | ||
cbbfcc63 | 1902 | if (p->job) |
ac1510ea | 1903 | { |
dc4ff34c | 1904 | /* |
1905 | * Get pointer to job... | |
1906 | */ | |
1907 | ||
1908 | job = (job_t *)p->job; | |
1909 | ||
1910 | /* | |
1911 | * Stop it... | |
1912 | */ | |
1913 | ||
db911fcb | 1914 | StopJob(job->id, 0); |
dc4ff34c | 1915 | |
1916 | /* | |
1917 | * Reset the state to pending... | |
1918 | */ | |
1919 | ||
1920 | job->state->values[0].integer = IPP_JOB_PENDING; | |
1921 | ||
1922 | SaveJob(job->id); | |
ac1510ea | 1923 | } |
cbbfcc63 | 1924 | } |
1925 | ||
1926 | ||
ed3e11d8 | 1927 | /* |
1928 | * 'ValidateDest()' - Validate a printer/class destination. | |
1929 | */ | |
1930 | ||
1931 | const char * /* O - Printer or class name */ | |
1932 | ValidateDest(const char *hostname, /* I - Host name */ | |
1933 | const char *resource, /* I - Resource name */ | |
1934 | cups_ptype_t *dtype) /* O - Type (printer or class) */ | |
1935 | { | |
1936 | printer_t *p; /* Current printer */ | |
9fe0309f | 1937 | char localname[1024], /* Localized hostname */ |
1938 | *lptr, /* Pointer into localized hostname */ | |
1939 | *sptr; /* Pointer into server name */ | |
ed3e11d8 | 1940 | |
1941 | ||
b30416bb | 1942 | DEBUG_printf(("ValidateDest(\"%s\", \"%s\", %p)\n", hostname, resource, dtype)); |
962e5a9f | 1943 | |
ed3e11d8 | 1944 | /* |
1945 | * See if the resource is a class or printer... | |
1946 | */ | |
1947 | ||
1948 | if (strncmp(resource, "/classes/", 9) == 0) | |
1949 | { | |
1950 | /* | |
1951 | * Class... | |
1952 | */ | |
1953 | ||
ed3e11d8 | 1954 | resource += 9; |
1955 | } | |
1956 | else if (strncmp(resource, "/printers/", 10) == 0) | |
1957 | { | |
1958 | /* | |
1959 | * Printer... | |
1960 | */ | |
1961 | ||
ed3e11d8 | 1962 | resource += 10; |
1963 | } | |
1964 | else | |
1965 | { | |
1966 | /* | |
1967 | * Bad resource name... | |
1968 | */ | |
1969 | ||
1970 | return (NULL); | |
1971 | } | |
1972 | ||
1973 | /* | |
ad517a9f | 1974 | * See if the printer or class name exists... |
ed3e11d8 | 1975 | */ |
1976 | ||
ad517a9f | 1977 | if ((p = FindPrinter(resource)) == NULL) |
1978 | p = FindClass(resource); | |
f8226c83 | 1979 | |
ad517a9f | 1980 | if (p == NULL && strchr(resource, '@') == NULL) |
1981 | return (NULL); | |
1982 | else if (p != NULL) | |
1983 | { | |
997cf8b0 | 1984 | *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | |
1985 | CUPS_PRINTER_REMOTE); | |
f8226c83 | 1986 | return (p->name); |
1987 | } | |
ed3e11d8 | 1988 | |
9fe0309f | 1989 | /* |
962e5a9f | 1990 | * Change localhost to the server name... |
9fe0309f | 1991 | */ |
1992 | ||
962e5a9f | 1993 | if (strcasecmp(hostname, "localhost") == 0) |
1994 | hostname = ServerName; | |
1995 | ||
def978d5 | 1996 | strlcpy(localname, hostname, sizeof(localname)); |
9fe0309f | 1997 | |
962e5a9f | 1998 | if (strcasecmp(hostname, ServerName) != 0) |
9fe0309f | 1999 | { |
2000 | /* | |
962e5a9f | 2001 | * Localize the hostname... |
9fe0309f | 2002 | */ |
2003 | ||
962e5a9f | 2004 | lptr = strchr(localname, '.'); |
2005 | sptr = strchr(ServerName, '.'); | |
2006 | ||
2007 | if (sptr != NULL && lptr != NULL) | |
9fe0309f | 2008 | { |
962e5a9f | 2009 | /* |
2010 | * Strip the common domain name components... | |
2011 | */ | |
2012 | ||
2013 | while (lptr != NULL) | |
9fe0309f | 2014 | { |
962e5a9f | 2015 | if (strcasecmp(lptr, sptr) == 0) |
2016 | { | |
2017 | *lptr = '\0'; | |
2018 | break; | |
2019 | } | |
2020 | else | |
2021 | lptr = strchr(lptr + 1, '.'); | |
9fe0309f | 2022 | } |
9fe0309f | 2023 | } |
2024 | } | |
2025 | ||
b30416bb | 2026 | DEBUG_printf(("localized hostname is \"%s\"...\n", localname)); |
ed3e11d8 | 2027 | |
2028 | /* | |
2029 | * Find a matching printer or class... | |
2030 | */ | |
2031 | ||
2032 | for (p = Printers; p != NULL; p = p->next) | |
9fe0309f | 2033 | if (strcasecmp(p->hostname, localname) == 0 && |
f8226c83 | 2034 | strcasecmp(p->name, resource) == 0) |
962e5a9f | 2035 | { |
997cf8b0 | 2036 | *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | |
2037 | CUPS_PRINTER_REMOTE); | |
ed3e11d8 | 2038 | return (p->name); |
962e5a9f | 2039 | } |
ed3e11d8 | 2040 | |
2041 | return (NULL); | |
2042 | } | |
2043 | ||
2044 | ||
cbbfcc63 | 2045 | /* |
3a74d6bf | 2046 | * 'WritePrintcap()' - Write a pseudo-printcap file for older applications |
2047 | * that need it... | |
9cd605da | 2048 | */ |
2049 | ||
3a74d6bf | 2050 | void |
2051 | WritePrintcap(void) | |
9cd605da | 2052 | { |
7b0fde61 | 2053 | cups_file_t *fp; /* printcap file */ |
957c6597 | 2054 | printer_t *p; /* Current printer */ |
9cd605da | 2055 | |
2056 | ||
3a74d6bf | 2057 | #ifdef __sgi |
2058 | /* | |
2059 | * Update the IRIX printer state for the default printer; if | |
2060 | * no printers remain, then the default printer file will be | |
2061 | * removed... | |
2062 | */ | |
2063 | ||
2064 | write_irix_state(DefaultPrinter); | |
2065 | #endif /* __sgi */ | |
2066 | ||
9cd605da | 2067 | /* |
2068 | * See if we have a printcap file; if not, don't bother writing it. | |
2069 | */ | |
2070 | ||
03081fd2 | 2071 | if (!Printcap[0]) |
9cd605da | 2072 | return; |
2073 | ||
2074 | /* | |
7efb04c8 | 2075 | * Open the printcap file... |
9cd605da | 2076 | */ |
2077 | ||
7b0fde61 | 2078 | if ((fp = cupsFileOpen(Printcap, "w")) == NULL) |
9cd605da | 2079 | return; |
2080 | ||
7b40ae49 | 2081 | /* |
2082 | * Put a comment header at the top so that users will know where the | |
2083 | * data has come from... | |
2084 | */ | |
2085 | ||
7b0fde61 | 2086 | cupsFilePuts(fp, "# This file was automatically generated by cupsd(8) from the\n"); |
2087 | cupsFilePrintf(fp, "# %s/printers.conf file. All changes to this file\n", | |
7b40ae49 | 2088 | ServerRoot); |
7b0fde61 | 2089 | cupsFilePuts(fp, "# will be lost.\n"); |
7b40ae49 | 2090 | |
7efb04c8 | 2091 | /* |
2092 | * Write a new printcap with the current list of printers. | |
2093 | */ | |
2094 | ||
2095 | switch (PrintcapFormat) | |
2096 | { | |
2097 | case PRINTCAP_BSD: | |
2098 | /* | |
2099 | * Each printer is put in the file as: | |
2100 | * | |
2101 | * Printer1: | |
2102 | * Printer2: | |
2103 | * Printer3: | |
2104 | * ... | |
2105 | * PrinterN: | |
2106 | */ | |
2107 | ||
7cdd8a45 | 2108 | if (DefaultPrinter) |
7b0fde61 | 2109 | cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter->name, |
a9bc43ad | 2110 | DefaultPrinter->info, ServerName, DefaultPrinter->name); |
7cdd8a45 | 2111 | |
7efb04c8 | 2112 | for (p = Printers; p != NULL; p = p->next) |
7cdd8a45 | 2113 | if (p != DefaultPrinter) |
7b0fde61 | 2114 | cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info, |
a9bc43ad | 2115 | ServerName, p->name); |
7efb04c8 | 2116 | break; |
2117 | ||
2118 | case PRINTCAP_SOLARIS: | |
2119 | /* | |
2120 | * Each printer is put in the file as: | |
2121 | * | |
2122 | * _all:all=Printer1,Printer2,Printer3,...,PrinterN | |
2123 | * _default:use=DefaultPrinter | |
7cdd8a45 | 2124 | * Printer1:\ |
2125 | * :bsdaddr=ServerName,Printer1:\ | |
2126 | * :description=Description: | |
7efb04c8 | 2127 | * Printer2: |
7cdd8a45 | 2128 | * :bsdaddr=ServerName,Printer2:\ |
2129 | * :description=Description: | |
7efb04c8 | 2130 | * Printer3: |
7cdd8a45 | 2131 | * :bsdaddr=ServerName,Printer3:\ |
2132 | * :description=Description: | |
7efb04c8 | 2133 | * ... |
2134 | * PrinterN: | |
7cdd8a45 | 2135 | * :bsdaddr=ServerName,PrinterN:\ |
2136 | * :description=Description: | |
7efb04c8 | 2137 | */ |
2138 | ||
7b0fde61 | 2139 | cupsFilePuts(fp, "_all:all="); |
7efb04c8 | 2140 | for (p = Printers; p != NULL; p = p->next) |
7b0fde61 | 2141 | cupsFilePrintf(fp, "%s%c", p->name, p->next ? ',' : '\n'); |
7efb04c8 | 2142 | |
2143 | if (DefaultPrinter) | |
7b0fde61 | 2144 | cupsFilePrintf(fp, "_default:use=%s\n", DefaultPrinter->name); |
7efb04c8 | 2145 | |
2146 | for (p = Printers; p != NULL; p = p->next) | |
7b0fde61 | 2147 | cupsFilePrintf(fp, "%s:\\\n" |
7cdd8a45 | 2148 | "\t:bsdaddr=%s,%s:\\\n" |
2149 | "\t:description=%s:\n", | |
36992080 | 2150 | p->name, ServerName, p->name, p->info ? p->info : ""); |
7efb04c8 | 2151 | break; |
2152 | } | |
9cd605da | 2153 | |
2154 | /* | |
957c6597 | 2155 | * Close the file... |
9cd605da | 2156 | */ |
2157 | ||
7b0fde61 | 2158 | cupsFileClose(fp); |
9cd605da | 2159 | } |
2160 | ||
2161 | ||
9ae34eb7 | 2162 | #ifdef __sgi |
2163 | /* | |
dd5cfc84 | 2164 | * 'write_irix_config()' - Update the config files used by the IRIX |
2165 | * desktop tools. | |
9ae34eb7 | 2166 | */ |
2167 | ||
2168 | static void | |
7b0fde61 | 2169 | write_irix_config(printer_t *p) /* I - Printer to update */ |
9ae34eb7 | 2170 | { |
7b0fde61 | 2171 | char filename[1024]; /* Interface script filename */ |
2172 | cups_file_t *fp; /* Interface script file */ | |
2173 | int tag; /* Status tag value */ | |
9ae34eb7 | 2174 | |
2175 | ||
dd5cfc84 | 2176 | |
9ae34eb7 | 2177 | /* |
dd5cfc84 | 2178 | * Add dummy interface and GUI scripts to fool SGI's "challenged" printing |
2179 | * tools. First the interface script that tells the tools what kind of | |
2180 | * printer we have... | |
9ae34eb7 | 2181 | */ |
2182 | ||
dd5cfc84 | 2183 | snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name); |
9ae34eb7 | 2184 | |
dd5cfc84 | 2185 | if (p->type & CUPS_PRINTER_CLASS) |
2186 | unlink(filename); | |
7b0fde61 | 2187 | else if ((fp = cupsFileOpen(filename, "w")) != NULL) |
9ae34eb7 | 2188 | { |
7b0fde61 | 2189 | cupsFilePuts(fp, "#!/bin/sh\n"); |
dd5cfc84 | 2190 | |
2191 | if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model", | |
2192 | IPP_TAG_TEXT)) != NULL) | |
7b0fde61 | 2193 | cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text); |
dd5cfc84 | 2194 | else if (p->type & CUPS_PRINTER_CLASS) |
7b0fde61 | 2195 | cupsFilePuts(fp, "NAME=\"Printer Class\"\n"); |
dd5cfc84 | 2196 | else |
7b0fde61 | 2197 | cupsFilePuts(fp, "NAME=\"Remote Destination\"\n"); |
dd5cfc84 | 2198 | |
2199 | if (p->type & CUPS_PRINTER_COLOR) | |
7b0fde61 | 2200 | cupsFilePuts(fp, "TYPE=ColorPostScript\n"); |
dd5cfc84 | 2201 | else |
7b0fde61 | 2202 | cupsFilePuts(fp, "TYPE=MonoPostScript\n"); |
dd5cfc84 | 2203 | |
7b0fde61 | 2204 | cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName); |
2205 | cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name); | |
9ae34eb7 | 2206 | |
7b0fde61 | 2207 | cupsFileClose(fp); |
9ae34eb7 | 2208 | |
dd5cfc84 | 2209 | chmod(filename, 0755); |
9ae34eb7 | 2210 | chown(filename, User, Group); |
2211 | } | |
2212 | ||
2213 | /* | |
dd5cfc84 | 2214 | * Then the member file that tells which device file the queue is connected |
2215 | * to... Networked printers use "/dev/null" in this file, so that's what | |
2216 | * we use (the actual device URI can confuse some apps...) | |
9ae34eb7 | 2217 | */ |
2218 | ||
dd5cfc84 | 2219 | snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name); |
9ae34eb7 | 2220 | |
dd5cfc84 | 2221 | if (p->type & CUPS_PRINTER_CLASS) |
2222 | unlink(filename); | |
7b0fde61 | 2223 | else if ((fp = cupsFileOpen(filename, "w")) != NULL) |
9ae34eb7 | 2224 | { |
7b0fde61 | 2225 | cupsFilePuts(fp, "/dev/null\n"); |
9ae34eb7 | 2226 | |
7b0fde61 | 2227 | cupsFileClose(fp); |
9ae34eb7 | 2228 | |
dd5cfc84 | 2229 | chmod(filename, 0644); |
2230 | chown(filename, User, Group); | |
2231 | } | |
9ae34eb7 | 2232 | |
dd5cfc84 | 2233 | /* |
2234 | * The gui_interface file is a script or program that launches a GUI | |
2235 | * option panel for the printer, using options specified on the | |
2236 | * command-line in the third argument. The option panel must send | |
2237 | * any printing options to stdout on a single line when the user | |
2238 | * accepts them, or nothing if the user cancels the dialog. | |
2239 | * | |
2240 | * The default options panel program is /usr/bin/glpoptions, from | |
2241 | * the ESP Print Pro software. You can select another using the | |
2242 | * PrintcapGUI option. | |
2243 | */ | |
2244 | ||
2245 | snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", p->name); | |
9ae34eb7 | 2246 | |
dd5cfc84 | 2247 | if (p->type & CUPS_PRINTER_CLASS) |
2248 | unlink(filename); | |
7b0fde61 | 2249 | else if ((fp = cupsFileOpen(filename, "w")) != NULL) |
dd5cfc84 | 2250 | { |
7b0fde61 | 2251 | cupsFilePuts(fp, "#!/bin/sh\n"); |
2252 | cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name); | |
9ae34eb7 | 2253 | |
7b0fde61 | 2254 | cupsFileClose(fp); |
9ae34eb7 | 2255 | |
2256 | chmod(filename, 0755); | |
2257 | chown(filename, User, Group); | |
2258 | } | |
2259 | ||
dd5cfc84 | 2260 | /* |
2261 | * The POD config file is needed by the printstatus command to show | |
2262 | * the printer location and device. | |
2263 | */ | |
2264 | ||
2265 | snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name); | |
2266 | ||
2267 | if (p->type & CUPS_PRINTER_CLASS) | |
2268 | unlink(filename); | |
7b0fde61 | 2269 | else if ((fp = cupsFileOpen(filename, "w")) != NULL) |
dd5cfc84 | 2270 | { |
7b0fde61 | 2271 | cupsFilePrintf(fp, "Printer Class | %s\n", |
dd5cfc84 | 2272 | (p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript"); |
7b0fde61 | 2273 | cupsFilePrintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : ""); |
2274 | cupsFilePrintf(fp, "Location Code | %s\n", p->location ? p->location : ""); | |
2275 | cupsFilePrintf(fp, "Physical Location | %s\n", p->info ? p->info : ""); | |
2276 | cupsFilePrintf(fp, "Port Path | %s\n", p->device_uri ? p->device_uri : ""); | |
2277 | cupsFilePrintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name); | |
2278 | cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name); | |
2279 | cupsFilePuts(fp, "Status Update Wait | 10 seconds\n"); | |
dd5cfc84 | 2280 | |
7b0fde61 | 2281 | cupsFileClose(fp); |
dd5cfc84 | 2282 | |
2283 | chmod(filename, 0664); | |
2284 | chown(filename, User, Group); | |
2285 | } | |
2286 | ||
2287 | ||
2288 | /* | |
2289 | * 'write_irix_state()' - Update the status files used by IRIX printing | |
2290 | * desktop tools. | |
2291 | */ | |
2292 | ||
2293 | static void | |
7b0fde61 | 2294 | write_irix_state(printer_t *p) /* I - Printer to update */ |
dd5cfc84 | 2295 | { |
7b0fde61 | 2296 | char filename[1024]; /* Interface script filename */ |
2297 | cups_file_t *fp; /* Interface script file */ | |
2298 | int tag; /* Status tag value */ | |
dd5cfc84 | 2299 | |
2300 | ||
2301 | if (p) | |
2302 | { | |
2303 | /* | |
2304 | * The POD status file is needed for the printstatus window to | |
2305 | * provide the current status of the printer. | |
2306 | */ | |
2307 | ||
2308 | snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name); | |
2309 | ||
2310 | if (p->type & CUPS_PRINTER_CLASS) | |
2311 | unlink(filename); | |
7b0fde61 | 2312 | else if ((fp = cupsFileOpen(filename, "w")) != NULL) |
dd5cfc84 | 2313 | { |
7b0fde61 | 2314 | cupsFilePrintf(fp, "Operational Status | %s\n", |
dd5cfc84 | 2315 | (p->state == IPP_PRINTER_IDLE) ? "Idle" : |
2316 | (p->state == IPP_PRINTER_PROCESSING) ? "Busy" : | |
2317 | "Faulted"); | |
7b0fde61 | 2318 | cupsFilePrintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION); |
2319 | cupsFilePrintf(fp, "Information | 02 00 00 | Device URI: %s\n", | |
36992080 | 2320 | p->device_uri ? p->device_uri : ""); |
7b0fde61 | 2321 | cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n", |
dd5cfc84 | 2322 | p->accepting ? "Accepting" : "Not accepting"); |
7b0fde61 | 2323 | cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message); |
dd5cfc84 | 2324 | |
7b0fde61 | 2325 | cupsFileClose(fp); |
dd5cfc84 | 2326 | |
2327 | chmod(filename, 0664); | |
2328 | chown(filename, User, Group); | |
2329 | } | |
2330 | ||
2331 | /* | |
2332 | * The activeicons file is needed to provide desktop icons for printers: | |
2333 | * | |
2334 | * [ quoted from /usr/lib/print/tagit ] | |
2335 | * | |
2336 | * --- Type of printer tags (base values) | |
2337 | * | |
2338 | * Dumb=66048 # 0x10200 | |
2339 | * DumbColor=66080 # 0x10220 | |
2340 | * Raster=66112 # 0x10240 | |
2341 | * ColorRaster=66144 # 0x10260 | |
2342 | * Plotter=66176 # 0x10280 | |
2343 | * PostScript=66208 # 0x102A0 | |
2344 | * ColorPostScript=66240 # 0x102C0 | |
2345 | * MonoPostScript=66272 # 0x102E0 | |
2346 | * | |
2347 | * --- Printer state modifiers for local printers | |
2348 | * | |
2349 | * Idle=0 # 0x0 | |
2350 | * Busy=1 # 0x1 | |
2351 | * Faulted=2 # 0x2 | |
2352 | * Unknown=3 # 0x3 (Faulted due to unknown reason) | |
2353 | * | |
2354 | * --- Printer state modifiers for network printers | |
2355 | * | |
2356 | * NetIdle=8 # 0x8 | |
2357 | * NetBusy=9 # 0x9 | |
2358 | * NetFaulted=10 # 0xA | |
2359 | * NetUnknown=11 # 0xB (Faulted due to unknown reason) | |
2360 | */ | |
2361 | ||
2362 | snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name); | |
2363 | ||
2364 | if (p->type & CUPS_PRINTER_CLASS) | |
2365 | unlink(filename); | |
7b0fde61 | 2366 | else if ((fp = cupsFileOpen(filename, "w")) != NULL) |
dd5cfc84 | 2367 | { |
2368 | if (p->type & CUPS_PRINTER_COLOR) | |
2369 | tag = 66240; | |
2370 | else | |
2371 | tag = 66272; | |
2372 | ||
2373 | if (p->type & CUPS_PRINTER_REMOTE) | |
2374 | tag |= 8; | |
2375 | ||
2376 | if (p->state == IPP_PRINTER_PROCESSING) | |
2377 | tag |= 1; | |
2378 | ||
2379 | else if (p->state == IPP_PRINTER_STOPPED) | |
2380 | tag |= 2; | |
2381 | ||
7b0fde61 | 2382 | cupsFilePuts(fp, "#!/bin/sh\n"); |
2383 | cupsFilePrintf(fp, "#Tag %d\n", tag); | |
dd5cfc84 | 2384 | |
7b0fde61 | 2385 | cupsFileClose(fp); |
dd5cfc84 | 2386 | |
2387 | chmod(filename, 0755); | |
2388 | chown(filename, User, Group); | |
2389 | } | |
2390 | } | |
2391 | ||
9ae34eb7 | 2392 | /* |
2393 | * The default file is needed by the printers window to show | |
2394 | * the default printer. | |
2395 | */ | |
2396 | ||
2397 | snprintf(filename, sizeof(filename), "/var/spool/lp/default"); | |
2398 | ||
2399 | if (DefaultPrinter != NULL) | |
2400 | { | |
7b0fde61 | 2401 | if ((fp = cupsFileOpen(filename, "w")) != NULL) |
9ae34eb7 | 2402 | { |
7b0fde61 | 2403 | cupsFilePrintf(fp, "%s\n", DefaultPrinter->name); |
9ae34eb7 | 2404 | |
7b0fde61 | 2405 | cupsFileClose(fp); |
9ae34eb7 | 2406 | |
2407 | chmod(filename, 0644); | |
2408 | chown(filename, User, Group); | |
2409 | } | |
2410 | } | |
2411 | else | |
2412 | unlink(filename); | |
2413 | } | |
2414 | #endif /* __sgi */ | |
2415 | ||
2416 | ||
9cd605da | 2417 | /* |
e673c4b4 | 2418 | * End of "$Id: printers.c,v 1.93.2.55 2004/02/24 21:36:59 mike Exp $". |
a129ddbd | 2419 | */ |