]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/printers.c
Mirror 1.1.x changes.
[thirdparty/cups.git] / scheduler / printers.c
CommitLineData
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
64static 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
72printer_t * /* O - New printer */
1049abbe 73AddPrinter(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
161void
d7845573 162AddPrinterFilter(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
217void
218AddPrinterHistory(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
277void
278AddPrinterUser(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
307void
308CreateCommonData(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
506void
507DeleteAllPrinters(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
527void
9b2fe6bd 528DeletePrinter(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
668void
669DeletePrinterFilters(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
710printer_t * /* O - Destination in list */
711FindDest(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
731printer_t * /* O - Printer in list */
1049abbe 732FindPrinter(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
753void
754FreePrinterUsers(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
776void
777LoadAllPrinters(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 1010void
1011SaveAllPrinters(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 1137void
05e63c18 1138SetPrinterAttrs(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
1675void
1676SetPrinterReasons(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
1777void
1778SetPrinterState(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
1831void
1832SortPrinters(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
1885void
aa3b74e1 1886StopPrinter(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
1931const char * /* O - Printer or class name */
1932ValidateDest(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 2050void
2051WritePrintcap(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
2168static void
7b0fde61 2169write_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
2293static void
7b0fde61 2294write_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 */