]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/printers.c
Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / printers.c
CommitLineData
ef416fc2 1/*
4400e98d 2 * "$Id: printers.c 5047 2006-02-02 05:14:15Z mike $"
ef416fc2 3 *
4 * Printer routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
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
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * cupsdAddPrinter() - Add a printer to the system.
27 * cupsdAddPrinterFilter() - Add a MIME filter for a printer.
28 * cupsdAddPrinterHistory() - Add the current printer state to the history.
29 * cupsdAddPrinterUser() - Add a user to the ACL.
30 * cupsdDeleteAllPrinters() - Delete all printers from the system.
31 * cupsdDeletePrinter() - Delete a printer from the system.
32 * cupsdDeletePrinterFilters() - Delete all MIME filters for a printer.
33 * cupsdFindPrinter() - Find a printer in the list.
34 * cupsdFreePrinterUsers() - Free allow/deny users.
35 * cupsdLoadAllPrinters() - Load printers from the printers.conf file.
fa73b229 36 * cupsdSaveAllPrinters() - Save all printer definitions to the
37 * printers.conf file.
38 * cupsdSetPrinterAttrs() - Set printer attributes based upon the PPD
39 * file.
ef416fc2 40 * cupsdSetPrinterReasons() - Set/update the reasons strings.
41 * cupsdSetPrinterState() - Update the current state of a printer.
42 * cupsdStopPrinter() - Stop a printer from printing any jobs...
43 * cupsdUpdatePrinters() - Update printers after a partial reload.
44 * cupsdValidateDest() - Validate a printer/class destination.
45 * cupsdWritePrintcap() - Write a pseudo-printcap file for older
46 * applications that need it...
47 * cupsdSanitizeURI() - Sanitize a device URI...
48 * compare_printers() - Compare two printers.
49 * write_irix_config() - Update the config files used by the IRIX
50 * desktop tools.
fa73b229 51 * write_irix_state() - Update the status files used by IRIX
52 * printing desktop tools.
ef416fc2 53 */
54
55/*
56 * Include necessary headers...
57 */
58
59#include "cupsd.h"
60
61
62/*
63 * Local functions...
64 */
65
66static int compare_printers(void *first, void *second, void *data);
67#ifdef __sgi
68static void write_irix_config(cupsd_printer_t *p);
69static void write_irix_state(cupsd_printer_t *p);
70#endif /* __sgi */
71
72
73/*
74 * 'cupsdAddPrinter()' - Add a printer to the system.
75 */
76
77cupsd_printer_t * /* O - New printer */
78cupsdAddPrinter(const char *name) /* I - Name of printer */
79{
80 cupsd_printer_t *p; /* New printer */
81
82
83 /*
84 * Range check input...
85 */
86
87 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddPrinter(\"%s\")", name);
88
89 /*
90 * Create a new printer entity...
91 */
92
93 if ((p = calloc(1, sizeof(cupsd_printer_t))) == NULL)
94 {
95 cupsdLogMessage(CUPSD_LOG_CRIT, "Unable to allocate memory for printer - %s",
96 strerror(errno));
97 return (NULL);
98 }
99
100 cupsdSetString(&p->name, name);
101 cupsdSetString(&p->info, name);
102 cupsdSetString(&p->hostname, ServerName);
103
104 cupsdSetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName, LocalPort, name);
105 cupsdSetStringf(&p->device_uri, "file:/dev/null");
106
107 p->state = IPP_PRINTER_STOPPED;
108 p->state_time = time(NULL);
109 p->accepting = 0;
fa73b229 110 p->shared = DefaultShared;
ef416fc2 111 p->filetype = mimeAddType(MimeDatabase, "printer", name);
112
113 cupsdSetString(&p->job_sheets[0], "none");
114 cupsdSetString(&p->job_sheets[1], "none");
115
116 cupsdSetString(&p->error_policy, "stop-printer");
117 cupsdSetString(&p->op_policy, DefaultPolicy);
118
119 p->op_policy_ptr = DefaultPolicyPtr;
120
121 if (MaxPrinterHistory)
122 p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *));
123
124 /*
125 * Insert the printer in the printer list alphabetically...
126 */
127
128 if (!Printers)
129 Printers = cupsArrayNew(compare_printers, NULL);
130
131 cupsArrayAdd(Printers, p);
132
133 if (!ImplicitPrinters)
134 ImplicitPrinters = cupsArrayNew(compare_printers, NULL);
135
136 /*
137 * Return the new printer...
138 */
139
140 return (p);
141}
142
143
144/*
145 * 'cupsdAddPrinterFilter()' - Add a MIME filter for a printer.
146 */
147
148void
149cupsdAddPrinterFilter(
150 cupsd_printer_t *p, /* I - Printer to add to */
151 const char *filter) /* I - Filter to add */
152{
ef416fc2 153 char super[MIME_MAX_SUPER], /* Super-type for filter */
154 type[MIME_MAX_TYPE], /* Type for filter */
155 program[1024]; /* Program/filter name */
156 int cost; /* Cost of filter */
fa73b229 157 mime_type_t *temptype; /* MIME type looping var */
ef416fc2 158
159
160 /*
161 * Range check input...
162 */
163
164 if (p == NULL || p->filetype == NULL || filter == NULL)
165 return;
166
167 /*
168 * Parse the filter string; it should be in the following format:
169 *
170 * super/type cost program
171 */
172
173 if (sscanf(filter, "%15[^/]/%31s%d%1023s", super, type, &cost, program) != 4)
174 {
175 cupsdLogMessage(CUPSD_LOG_ERROR,
176 "cupsdAddPrinterFilter: Invalid filter string \"%s\"!",
177 filter);
178 return;
179 }
180
181 /*
182 * Add the filter to the MIME database, supporting wildcards as needed...
183 */
184
fa73b229 185 for (temptype = mimeFirstType(MimeDatabase);
186 temptype;
187 temptype = mimeNextType(MimeDatabase))
188 if (((super[0] == '*' && strcasecmp(temptype->super, "printer")) ||
189 !strcasecmp(temptype->super, super)) &&
190 (type[0] == '*' || !strcasecmp(temptype->type, type)))
ef416fc2 191 {
192 cupsdLogMessage(CUPSD_LOG_DEBUG2, "Adding filter %s/%s %s/%s %d %s",
fa73b229 193 temptype->super, temptype->type,
ef416fc2 194 p->filetype->super, p->filetype->type,
195 cost, program);
fa73b229 196 mimeAddFilter(MimeDatabase, temptype, p->filetype, cost, program);
ef416fc2 197 }
198}
199
200
201/*
202 * 'cupsdAddPrinterHistory()' - Add the current printer state to the history.
203 */
204
205void
206cupsdAddPrinterHistory(
207 cupsd_printer_t *p) /* I - Printer */
208{
209 ipp_t *history; /* History collection */
210
211
212 /*
213 * Stop early if we aren't keeping history data...
214 */
215
216 if (MaxPrinterHistory <= 0)
217 return;
218
219 /*
220 * Retire old history data as needed...
221 */
222
223 p->sequence_number ++;
224
225 if (p->num_history >= MaxPrinterHistory)
226 {
227 p->num_history --;
228 ippDelete(p->history[0]);
229 memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *));
230 }
231
232 /*
233 * Create a collection containing the current printer-state, printer-up-time,
234 * printer-state-message, and printer-state-reasons attributes.
235 */
236
237 history = ippNew();
238 ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
239 p->state);
240 ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-accepting-jobs",
241 p->accepting);
fa73b229 242 ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-shared", p->shared);
ef416fc2 243 ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message",
244 NULL, p->state_message);
e00b005a 245#ifdef __APPLE__
246 if (p->recoverable)
247 ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT,
248 "com.apple.print.recoverable-message", NULL, p->recoverable);
249#endif /* __APPLE__ */
ef416fc2 250 if (p->num_reasons == 0)
251 ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
252 "printer-state-reasons", NULL,
253 p->state == IPP_PRINTER_STOPPED ? "paused" : "none");
254 else
255 ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
256 "printer-state-reasons", p->num_reasons, NULL,
257 (const char * const *)p->reasons);
258 ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
259 "printer-state-change-time", p->state_time);
260 ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
261 "printer-state-sequence-number", p->sequence_number);
262
263 p->history[p->num_history] = history;
264 p->num_history ++;
265}
266
267
268/*
269 * 'cupsdAddPrinterUser()' - Add a user to the ACL.
270 */
271
272void
273cupsdAddPrinterUser(
274 cupsd_printer_t *p, /* I - Printer */
275 const char *username) /* I - User */
276{
277 const char **temp; /* Temporary array pointer */
278
279
280 if (!p || !username)
281 return;
282
283 if (p->num_users == 0)
284 temp = malloc(sizeof(char **));
285 else
286 temp = realloc(p->users, sizeof(char **) * (p->num_users + 1));
287
288 if (!temp)
289 return;
290
291 p->users = temp;
292 temp += p->num_users;
293
294 if ((*temp = strdup(username)) != NULL)
295 p->num_users ++;
296}
297
298
299/*
300 * 'cupsdCreateCommonData()' - Create the common printer data.
301 */
302
303void
304cupsdCreateCommonData(void)
305{
306 int i; /* Looping var */
307 ipp_attribute_t *attr; /* Attribute data */
308 static const int nups[] = /* number-up-supported values */
309 { 1, 2, 4, 6, 9, 16 };
310 static const ipp_orient_t orients[4] =/* orientation-requested-supported values */
311 {
312 IPP_PORTRAIT,
313 IPP_LANDSCAPE,
314 IPP_REVERSE_LANDSCAPE,
315 IPP_REVERSE_PORTRAIT
316 };
317 static const char * const holds[] = /* job-hold-until-supported values */
318 {
319 "no-hold",
320 "indefinite",
321 "day-time",
322 "evening",
323 "night",
324 "second-shift",
325 "third-shift",
326 "weekend"
327 };
328 static const char * const versions[] =/* ipp-versions-supported values */
329 {
330 "1.0",
331 "1.1"
332 };
333 static const ipp_op_t ops[] = /* operations-supported values */
334 {
335 IPP_PRINT_JOB,
336 IPP_VALIDATE_JOB,
337 IPP_CREATE_JOB,
338 IPP_SEND_DOCUMENT,
339 IPP_CANCEL_JOB,
340 IPP_GET_JOB_ATTRIBUTES,
341 IPP_GET_JOBS,
342 IPP_GET_PRINTER_ATTRIBUTES,
343 IPP_HOLD_JOB,
344 IPP_RELEASE_JOB,
345 IPP_PAUSE_PRINTER,
346 IPP_RESUME_PRINTER,
347 IPP_PURGE_JOBS,
348 IPP_SET_JOB_ATTRIBUTES,
349 IPP_CREATE_PRINTER_SUBSCRIPTION,
350 IPP_CREATE_JOB_SUBSCRIPTION,
351 IPP_GET_SUBSCRIPTION_ATTRIBUTES,
352 IPP_GET_SUBSCRIPTIONS,
353 IPP_RENEW_SUBSCRIPTION,
354 IPP_CANCEL_SUBSCRIPTION,
355 IPP_GET_NOTIFICATIONS,
356 IPP_ENABLE_PRINTER,
357 IPP_DISABLE_PRINTER,
358 CUPS_GET_DEFAULT,
359 CUPS_GET_PRINTERS,
360 CUPS_ADD_PRINTER,
361 CUPS_DELETE_PRINTER,
362 CUPS_GET_CLASSES,
363 CUPS_ADD_CLASS,
364 CUPS_DELETE_CLASS,
365 CUPS_ACCEPT_JOBS,
366 CUPS_REJECT_JOBS,
367 CUPS_SET_DEFAULT,
368 CUPS_GET_DEVICES,
369 CUPS_GET_PPDS,
370 CUPS_MOVE_JOB,
371 CUPS_AUTHENTICATE_JOB,
372 IPP_RESTART_JOB
373 };
374 static const char * const charsets[] =/* charset-supported values */
375 {
376 "us-ascii",
377 "utf-8"
378 };
379 static const char * const compressions[] =
380 { /* document-compression-supported values */
381 "none"
382#ifdef HAVE_LIBZ
383 ,"gzip"
384#endif /* HAVE_LIBZ */
385 };
386 static const char * const multiple_document_handling[] =
387 { /* multiple-document-handling-supported values */
388 "separate-documents-uncollated-copies",
389 "separate-documents-collated-copies"
390 };
391 static const char * const errors[] = /* printer-error-policy-supported values */
392 {
393 "abort-job",
394 "retry-job",
395 "stop-printer"
396 };
397 static const char * const notify_attrs[] =
398 { /* notify-attributes-supported values */
399 "printer-state-change-time",
400 "notify-lease-expiration-time",
401 "notify-subscriber-user-name"
402 };
403 static const char * const notify_events[] =
404 { /* notify-events-supported values */
405 "job-completed",
406 "job-config-changed",
407 "job-created",
408 "job-progress",
409 "job-state-changed",
410 "job-stopped",
411 "printer-added",
412 "printer-changed",
413 "printer-config-changed",
414 "printer-deleted",
415 "printer-finishings-changed",
416 "printer-media-changed",
417 "printer-modified",
418 "printer-restarted",
419 "printer-shutdown",
420 "printer-state-changed",
421 "printer-stopped",
422 "server-audit",
423 "server-restarted",
424 "server-started",
425 "server-stopped"
426 };
427
428
429 if (CommonData)
430 ippDelete(CommonData);
431
432 CommonData = ippNew();
433
434 /*
435 * This list of attributes is sorted to improve performance when the
436 * client provides a requested-attributes attribute...
437 */
438
439 /* charset-configured */
440 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET,
441 "charset-configured", NULL, DefaultCharset);
442
443 /* charset-supported */
444 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET,
445 "charset-supported", sizeof(charsets) / sizeof(charsets[0]),
446 NULL, charsets);
447
448 /* compression-supported */
449 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
450 "compression-supported",
451 sizeof(compressions) / sizeof(compressions[0]),
452 NULL, compressions);
453
454 /* TODO: move to printer-specific section! */
455 /* copies-default */
456 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
457 "copies-default", 1);
458
459 /* copies-supported */
460 ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies);
461
462 /* TODO: move to printer-specific section! */
463 /* document-format-default */
464 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
465 "document-format-default", NULL, "application/octet-stream");
466
467 /* document-format-supported */
468 ippAddStrings(CommonData, IPP_TAG_PRINTER,
469 (ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
470 "document-format-supported", NumMimeTypes, NULL, MimeTypes);
471
472 /* generated-natural-language-supported */
473 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
474 "generated-natural-language-supported", NULL, DefaultLanguage);
475
476 /* ipp-versions-supported */
477 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
478 "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]),
479 NULL, versions);
480
481 /* TODO: move to printer-specific section! */
482 /* job-hold-until-default */
483 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
484 "job-hold-until-default", NULL, "no-hold");
485
486 /* job-hold-until-supported */
487 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
488 "job-hold-until-supported", sizeof(holds) / sizeof(holds[0]),
489 NULL, holds);
490
491 /* TODO: move to printer-specific section! */
492 /* job-priority-default */
493 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
494 "job-priority-default", 50);
495
496 /* job-priority-supported */
497 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
498 "job-priority-supported", 100);
499
500 /* job-sheets-supported */
fa73b229 501 if (cupsArrayCount(Banners) > 0)
ef416fc2 502 {
503 /*
504 * Setup the job-sheets-supported attribute...
505 */
506
507 if (Classification && !ClassifyOverride)
508 attr = ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
509 "job-sheets-supported", NULL, Classification);
510 else
511 attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
fa73b229 512 "job-sheets-supported", cupsArrayCount(Banners) + 1,
513 NULL, NULL);
ef416fc2 514
515 if (attr == NULL)
516 cupsdLogMessage(CUPSD_LOG_EMERG,
517 "cupsdSetPrinterAttrs: Unable to allocate memory for "
518 "job-sheets-supported attribute: %s!", strerror(errno));
519 else if (!Classification || ClassifyOverride)
520 {
fa73b229 521 cupsd_banner_t *banner; /* Current banner */
522
523
4400e98d 524 attr->values[0].string.text = _cups_sp_alloc("none");
ef416fc2 525
fa73b229 526 for (i = 1, banner = (cupsd_banner_t *)cupsArrayFirst(Banners);
527 banner;
528 i ++, banner = (cupsd_banner_t *)cupsArrayNext(Banners))
4400e98d 529 attr->values[i].string.text = _cups_sp_alloc(banner->name);
ef416fc2 530 }
531 }
532 else
533 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
534 "job-sheets-supported", NULL, "none");
535
536 /* multiple-document-handling-supported */
537 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
538 "multiple-document-handling-supported",
539 sizeof(multiple_document_handling) /
540 sizeof(multiple_document_handling[0]), NULL,
541 multiple_document_handling);
542
543 /* multiple-document-jobs-supported */
544 ippAddBoolean(CommonData, IPP_TAG_PRINTER,
545 "multiple-document-jobs-supported", 1);
546
547 /* multiple-operation-time-out */
548 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
549 "multiple-operation-time-out", 60);
550
551 /* natural-language-configured */
552 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
553 "natural-language-configured", NULL, DefaultLanguage);
554
555 /* notify-attributes-supported */
556 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
557 "notify-attributes-supported",
558 (int)(sizeof(notify_attrs) / sizeof(notify_attrs[0])),
559 NULL, notify_attrs);
560
561 /* TODO: move to printer-specific section! */
562 /* notify-lease-duration-default */
563 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
564 "notify-lease-duration-default", DefaultLeaseDuration);
565
566 /* notify-lease-duration-supported */
567 ippAddRange(CommonData, IPP_TAG_PRINTER,
568 "notify-lease-duration-supported", 0,
569 MaxLeaseDuration ? MaxLeaseDuration : 2147483647);
570
571 /* notify-max-events-supported */
572 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
573 "notify-max-events-supported", MaxEvents);
574
575 /* notify-notify-events-default */
576 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
577 "notify-events-default", NULL, "job-completed");
578
579 /* notify-notify-events-supported */
580 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
581 "notify-events-supported",
582 (int)(sizeof(notify_events) / sizeof(notify_events[0])),
583 NULL, notify_events);
584
585 /* notify-pull-method-supported */
586 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
587 "notify-pull-method-supported", NULL, "ippget");
588
589 /* TODO: scan notifier directory */
590 /* notify-schemes-supported */
591 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
592 "notify-schemes-supported", NULL, "mailto");
593
594 /* TODO: move to printer-specific section! */
595 /* number-up-default */
596 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
597 "number-up-default", 1);
598
599 /* number-up-supported */
600 ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
601 "number-up-supported", sizeof(nups) / sizeof(nups[0]), nups);
602
603 /* operations-supported */
604 ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
605 "operations-supported",
606 sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops);
607
608 /* TODO: move to printer-specific section! */
609 /* orientation-requested-default */
610 ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
611 "orientation-requested-default", IPP_PORTRAIT);
612
613 /* orientation-requested-supported */
614 ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
615 "orientation-requested-supported", 4, (int *)orients);
616
617 /* page-ranges-supported */
618 ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1);
619
620 /* pdf-override-supported */
621 ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
622 "pdl-override-supported", NULL, "not-attempted");
623
624 /* printer-error-policy-supported */
625 ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
626 "printer-error-policy-supported",
627 sizeof(errors) / sizeof(errors[0]), NULL, errors);
628
629 /* printer-op-policy-supported */
630 attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
631 "printer-op-policy-supported", NumPolicies, NULL, NULL);
632 for (i = 0; i < NumPolicies; i ++)
4400e98d 633 attr->values[i].string.text = _cups_sp_alloc(Policies[i]->name);
ef416fc2 634}
635
636
637/*
638 * 'cupsdDeleteAllPrinters()' - Delete all printers from the system.
639 */
640
641void
642cupsdDeleteAllPrinters(void)
643{
644 cupsd_printer_t *p; /* Pointer to current printer/class */
645
646
647 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
648 p;
649 p = (cupsd_printer_t *)cupsArrayNext(Printers))
650 if (!(p->type & CUPS_PRINTER_CLASS))
651 cupsdDeletePrinter(p, 0);
652}
653
654
655/*
656 * 'cupsdDeletePrinter()' - Delete a printer from the system.
657 */
658
659void
660cupsdDeletePrinter(
661 cupsd_printer_t *p, /* I - Printer to delete */
662 int update) /* I - Update printers.conf? */
663{
664 int i; /* Looping var */
665#ifdef __sgi
666 char filename[1024]; /* Interface script filename */
667#endif /* __sgi */
668
669
670 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeletePrinter(p=%p(%s), update=%d)",
671 p, p->name, update);
672
673 /*
674 * Save the current position in the Printers array...
675 */
676
677 cupsArraySave(Printers);
678
679 /*
680 * Stop printing on this printer...
681 */
682
683 cupsdStopPrinter(p, update);
684
685 /*
686 * If this printer is the next for browsing, point to the next one...
687 */
688
689 if (p == BrowseNext)
690 {
691 cupsArrayFind(Printers, p);
692 BrowseNext = (cupsd_printer_t *)cupsArrayNext(Printers);
693 }
694
695 /*
696 * Remove the printer from the list...
697 */
698
699 cupsArrayRemove(Printers, p);
700
701 /*
702 * Remove the dummy interface/icon/option files under IRIX...
703 */
704
705#ifdef __sgi
706 snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
707 unlink(filename);
708
709 snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui",
710 p->name);
711 unlink(filename);
712
713 snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
714 unlink(filename);
715
716 snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
717 unlink(filename);
718
719 snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
720 unlink(filename);
721
722 snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
723 unlink(filename);
724#endif /* __sgi */
725
726 /*
e00b005a 727 * If p is the default printer, assign a different one...
ef416fc2 728 */
729
730 if (p == DefaultPrinter)
e00b005a 731 {
732 DefaultPrinter = NULL;
733
734 if (UseNetworkDefault)
735 {
736 /*
737 * Find the first network default printer and use it...
738 */
739
740 cupsd_printer_t *dp; /* New default printer */
741
742
743 for (dp = (cupsd_printer_t *)cupsArrayFirst(Printers);
744 dp;
745 dp = (cupsd_printer_t *)cupsArrayNext(Printers))
746 if (dp != p && (dp->type & CUPS_PRINTER_DEFAULT))
747 {
748 DefaultPrinter = p;
749 break;
750 }
751 }
752 }
ef416fc2 753
754 /*
755 * Remove this printer from any classes and send a browse delete message...
756 */
757
758 if (!(p->type & CUPS_PRINTER_IMPLICIT))
759 {
760 cupsdDeletePrinterFromClasses(p);
761 cupsdSendBrowseDelete(p);
762 }
763
764 /*
765 * Free all memory used by the printer...
766 */
767
768 if (p->printers != NULL)
769 free(p->printers);
770
771 if (MaxPrinterHistory)
772 {
773 for (i = 0; i < p->num_history; i ++)
774 ippDelete(p->history[i]);
775
776 free(p->history);
777 }
778
779 for (i = 0; i < p->num_reasons; i ++)
780 free(p->reasons[i]);
781
782 ippDelete(p->attrs);
783
784 cupsdDeletePrinterFilters(p);
785
fa73b229 786 mimeDeleteType(MimeDatabase, p->filetype);
787
ef416fc2 788 cupsdFreePrinterUsers(p);
789 cupsdFreeQuotas(p);
790
791 cupsdClearString(&p->uri);
792 cupsdClearString(&p->hostname);
793 cupsdClearString(&p->name);
794 cupsdClearString(&p->location);
795 cupsdClearString(&p->make_model);
796 cupsdClearString(&p->info);
797 cupsdClearString(&p->job_sheets[0]);
798 cupsdClearString(&p->job_sheets[1]);
799 cupsdClearString(&p->device_uri);
800 cupsdClearString(&p->port_monitor);
801 cupsdClearString(&p->op_policy);
802 cupsdClearString(&p->error_policy);
803
e00b005a 804#ifdef __APPLE__
805 cupsdClearString(&p->recoverable);
806#endif /* __APPLE__ */
807
ef416fc2 808 free(p);
809
810 /*
811 * Restore the previous position in the Printers array...
812 */
813
814 cupsArrayRestore(Printers);
815}
816
817
818/*
819 * 'cupsdDeletePrinterFilters()' - Delete all MIME filters for a printer.
820 */
821
822void
823cupsdDeletePrinterFilters(
824 cupsd_printer_t *p) /* I - Printer to remove from */
825{
ef416fc2 826 mime_filter_t *filter; /* MIME filter looping var */
827
828
829 /*
830 * Range check input...
831 */
832
833 if (p == NULL)
834 return;
835
836 /*
837 * Remove all filters from the MIME database that have a destination
838 * type == printer...
839 */
840
fa73b229 841 for (filter = mimeFirstFilter(MimeDatabase);
842 filter;
843 filter = mimeNextFilter(MimeDatabase))
ef416fc2 844 if (filter->dst == p->filetype)
845 {
846 /*
847 * Delete the current filter...
848 */
849
fa73b229 850 mimeDeleteFilter(MimeDatabase, filter);
ef416fc2 851 }
852}
853
854
855/*
856 * 'cupsdFindDest()' - Find a destination in the list.
857 */
858
859cupsd_printer_t * /* O - Destination in list */
860cupsdFindDest(const char *name) /* I - Name of printer or class to find */
861{
862 cupsd_printer_t key; /* Search key */
863
864
865 key.name = (char *)name;
866 return ((cupsd_printer_t *)cupsArrayFind(Printers, &key));
867}
868
869
870/*
871 * 'cupsdFindPrinter()' - Find a printer in the list.
872 */
873
874cupsd_printer_t * /* O - Printer in list */
875cupsdFindPrinter(const char *name) /* I - Name of printer to find */
876{
877 cupsd_printer_t *p; /* Printer in list */
878
879
880 if ((p = cupsdFindDest(name)) != NULL && (p->type & CUPS_PRINTER_CLASS))
881 return (NULL);
882 else
883 return (p);
884}
885
886
887/*
888 * 'cupsdFreePrinterUsers()' - Free allow/deny users.
889 */
890
891void
892cupsdFreePrinterUsers(
893 cupsd_printer_t *p) /* I - Printer */
894{
895 int i; /* Looping var */
896
897
898 if (!p || !p->num_users)
899 return;
900
901 for (i = 0; i < p->num_users; i ++)
902 free((void *)p->users[i]);
903
904 free(p->users);
905
906 p->num_users = 0;
907 p->users = NULL;
908}
909
910
911/*
912 * 'cupsdLoadAllPrinters()' - Load printers from the printers.conf file.
913 */
914
915void
916cupsdLoadAllPrinters(void)
917{
918 cups_file_t *fp; /* printers.conf file */
919 int linenum; /* Current line number */
920 char line[1024], /* Line from file */
921 *value, /* Pointer to value */
922 *valueptr; /* Pointer into value */
923 cupsd_printer_t *p; /* Current printer */
924
925
926 /*
927 * Open the printers.conf file...
928 */
929
930 snprintf(line, sizeof(line), "%s/printers.conf", ServerRoot);
931 if ((fp = cupsFileOpen(line, "r")) == NULL)
932 {
fa73b229 933 if (errno != ENOENT)
934 cupsdLogMessage(CUPSD_LOG_ERROR,
935 "cupsdLoadAllPrinters: Unable to open %s - %s", line,
936 strerror(errno));
ef416fc2 937 return;
938 }
939
940 /*
941 * Read printer configurations until we hit EOF...
942 */
943
944 linenum = 0;
945 p = NULL;
946
947 while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
948 {
949 /*
950 * Decode the directive...
951 */
952
953 if (!strcasecmp(line, "<Printer") ||
954 !strcasecmp(line, "<DefaultPrinter"))
955 {
956 /*
957 * <Printer name> or <DefaultPrinter name>
958 */
959
960 if (p == NULL && value)
961 {
962 /*
963 * Add the printer and a base file type...
964 */
965
966 cupsdLogMessage(CUPSD_LOG_DEBUG,
967 "cupsdLoadAllPrinters: Loading printer %s...", value);
968
969 p = cupsdAddPrinter(value);
970 p->accepting = 1;
971 p->state = IPP_PRINTER_IDLE;
972
973 /*
974 * Set the default printer as needed...
975 */
976
977 if (!strcasecmp(line, "<DefaultPrinter"))
978 DefaultPrinter = p;
979 }
980 else
981 {
982 cupsdLogMessage(CUPSD_LOG_ERROR,
983 "Syntax error on line %d of printers.conf.", linenum);
984 return;
985 }
986 }
987 else if (!strcasecmp(line, "</Printer>"))
988 {
989 if (p != NULL)
990 {
991 /*
992 * Close out the current printer...
993 */
994
995 cupsdSetPrinterAttrs(p);
996 cupsdAddPrinterHistory(p);
997
998 if (p->device_uri && strncmp(p->device_uri, "file:", 5) &&
999 p->state != IPP_PRINTER_STOPPED)
1000 {
1001 /*
1002 * See if the backend exists...
1003 */
1004
1005 snprintf(line, sizeof(line), "%s/backend/%s", ServerBin,
1006 p->device_uri);
1007
1008 if ((valueptr = strchr(line + strlen(ServerBin), ':')) != NULL)
1009 *valueptr = '\0'; /* Chop everything but URI scheme */
1010
1011 if (access(line, 0))
1012 {
1013 /*
1014 * Backend does not exist, stop printer...
1015 */
1016
1017 p->state = IPP_PRINTER_STOPPED;
1018 snprintf(p->state_message, sizeof(p->state_message),
1019 "Backend %s does not exist!", line);
1020 }
1021 }
1022
1023 p = NULL;
1024 }
1025 else
1026 {
1027 cupsdLogMessage(CUPSD_LOG_ERROR,
1028 "Syntax error on line %d of printers.conf.", linenum);
1029 return;
1030 }
1031 }
1032 else if (!p)
1033 {
1034 cupsdLogMessage(CUPSD_LOG_ERROR,
1035 "Syntax error on line %d of printers.conf.", linenum);
1036 return;
1037 }
1038 else if (!strcasecmp(line, "Info"))
1039 {
1040 if (value)
1041 cupsdSetString(&p->info, value);
1042 }
1043 else if (!strcasecmp(line, "Location"))
1044 {
1045 if (value)
1046 cupsdSetString(&p->location, value);
1047 }
1048 else if (!strcasecmp(line, "DeviceURI"))
1049 {
1050 if (value)
1051 cupsdSetString(&p->device_uri, value);
1052 else
1053 {
1054 cupsdLogMessage(CUPSD_LOG_ERROR,
1055 "Syntax error on line %d of printers.conf.", linenum);
1056 return;
1057 }
1058 }
1059 else if (!strcasecmp(line, "PortMonitor"))
1060 {
1061 if (value && strcmp(value, "none"))
1062 cupsdSetString(&p->port_monitor, value);
1063 else if (value)
1064 cupsdClearString(&p->port_monitor);
1065 else
1066 {
1067 cupsdLogMessage(CUPSD_LOG_ERROR,
1068 "Syntax error on line %d of printers.conf.", linenum);
1069 return;
1070 }
1071 }
1072 else if (!strcasecmp(line, "State"))
1073 {
1074 /*
1075 * Set the initial queue state...
1076 */
1077
1078 if (value && !strcasecmp(value, "idle"))
1079 p->state = IPP_PRINTER_IDLE;
1080 else if (value && !strcasecmp(value, "stopped"))
1081 p->state = IPP_PRINTER_STOPPED;
1082 else
1083 {
1084 cupsdLogMessage(CUPSD_LOG_ERROR,
1085 "Syntax error on line %d of printers.conf.", linenum);
1086 return;
1087 }
1088 }
1089 else if (!strcasecmp(line, "StateMessage"))
1090 {
1091 /*
1092 * Set the initial queue state message...
1093 */
1094
1095 if (value)
1096 strlcpy(p->state_message, value, sizeof(p->state_message));
1097 }
1098 else if (!strcasecmp(line, "StateTime"))
1099 {
1100 /*
1101 * Set the state time...
1102 */
1103
1104 if (value)
1105 p->state_time = atoi(value);
1106 }
1107 else if (!strcasecmp(line, "Accepting"))
1108 {
1109 /*
1110 * Set the initial accepting state...
1111 */
1112
1113 if (value &&
1114 (!strcasecmp(value, "yes") ||
1115 !strcasecmp(value, "on") ||
1116 !strcasecmp(value, "true")))
1117 p->accepting = 1;
1118 else if (value &&
1119 (!strcasecmp(value, "no") ||
1120 !strcasecmp(value, "off") ||
1121 !strcasecmp(value, "false")))
1122 p->accepting = 0;
1123 else
1124 {
1125 cupsdLogMessage(CUPSD_LOG_ERROR,
1126 "Syntax error on line %d of printers.conf.", linenum);
1127 return;
1128 }
1129 }
1130 else if (!strcasecmp(line, "Shared"))
1131 {
1132 /*
1133 * Set the initial shared state...
1134 */
1135
1136 if (value &&
1137 (!strcasecmp(value, "yes") ||
1138 !strcasecmp(value, "on") ||
1139 !strcasecmp(value, "true")))
1140 p->shared = 1;
1141 else if (value &&
1142 (!strcasecmp(value, "no") ||
1143 !strcasecmp(value, "off") ||
1144 !strcasecmp(value, "false")))
1145 p->shared = 0;
1146 else
1147 {
1148 cupsdLogMessage(CUPSD_LOG_ERROR,
1149 "Syntax error on line %d of printers.conf.", linenum);
1150 return;
1151 }
1152 }
1153 else if (!strcasecmp(line, "JobSheets"))
1154 {
1155 /*
1156 * Set the initial job sheets...
1157 */
1158
1159 if (value)
1160 {
1161 for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
1162
1163 if (*valueptr)
1164 *valueptr++ = '\0';
1165
1166 cupsdSetString(&p->job_sheets[0], value);
1167
1168 while (isspace(*valueptr & 255))
1169 valueptr ++;
1170
1171 if (*valueptr)
1172 {
1173 for (value = valueptr; *valueptr && !isspace(*valueptr & 255); valueptr ++);
1174
1175 if (*valueptr)
1176 *valueptr++ = '\0';
1177
1178 cupsdSetString(&p->job_sheets[1], value);
1179 }
1180 }
1181 else
1182 {
1183 cupsdLogMessage(CUPSD_LOG_ERROR,
1184 "Syntax error on line %d of printers.conf.", linenum);
1185 return;
1186 }
1187 }
1188 else if (!strcasecmp(line, "AllowUser"))
1189 {
1190 if (value)
1191 {
1192 p->deny_users = 0;
1193 cupsdAddPrinterUser(p, value);
1194 }
1195 else
1196 {
1197 cupsdLogMessage(CUPSD_LOG_ERROR,
1198 "Syntax error on line %d of printers.conf.", linenum);
1199 return;
1200 }
1201 }
1202 else if (!strcasecmp(line, "DenyUser"))
1203 {
1204 if (value)
1205 {
1206 p->deny_users = 1;
1207 cupsdAddPrinterUser(p, value);
1208 }
1209 else
1210 {
1211 cupsdLogMessage(CUPSD_LOG_ERROR,
1212 "Syntax error on line %d of printers.conf.", linenum);
1213 return;
1214 }
1215 }
1216 else if (!strcasecmp(line, "QuotaPeriod"))
1217 {
1218 if (value)
1219 p->quota_period = atoi(value);
1220 else
1221 {
1222 cupsdLogMessage(CUPSD_LOG_ERROR,
1223 "Syntax error on line %d of printers.conf.", linenum);
1224 return;
1225 }
1226 }
1227 else if (!strcasecmp(line, "PageLimit"))
1228 {
1229 if (value)
1230 p->page_limit = atoi(value);
1231 else
1232 {
1233 cupsdLogMessage(CUPSD_LOG_ERROR,
1234 "Syntax error on line %d of printers.conf.", linenum);
1235 return;
1236 }
1237 }
1238 else if (!strcasecmp(line, "KLimit"))
1239 {
1240 if (value)
1241 p->k_limit = atoi(value);
1242 else
1243 {
1244 cupsdLogMessage(CUPSD_LOG_ERROR,
1245 "Syntax error on line %d of printers.conf.", linenum);
1246 return;
1247 }
1248 }
1249 else if (!strcasecmp(line, "OpPolicy"))
1250 {
1251 if (value)
1252 cupsdSetString(&p->op_policy, value);
1253 else
1254 {
1255 cupsdLogMessage(CUPSD_LOG_ERROR,
1256 "Syntax error on line %d of printers.conf.", linenum);
1257 return;
1258 }
1259 }
1260 else if (!strcasecmp(line, "ErrorPolicy"))
1261 {
1262 if (value)
1263 cupsdSetString(&p->error_policy, value);
1264 else
1265 {
1266 cupsdLogMessage(CUPSD_LOG_ERROR,
1267 "Syntax error on line %d of printers.conf.", linenum);
1268 return;
1269 }
1270 }
1271 else
1272 {
1273 /*
1274 * Something else we don't understand...
1275 */
1276
1277 cupsdLogMessage(CUPSD_LOG_ERROR,
1278 "Unknown configuration directive %s on line %d of printers.conf.",
1279 line, linenum);
1280 }
1281 }
1282
1283 cupsFileClose(fp);
1284}
1285
1286
1287/*
1288 * 'cupsdSaveAllPrinters()' - Save all printer definitions to the printers.conf
1289 * file.
1290 */
1291
1292void
1293cupsdSaveAllPrinters(void)
1294{
1295 int i; /* Looping var */
1296 cups_file_t *fp; /* printers.conf file */
1297 char temp[1024]; /* Temporary string */
1298 char backup[1024]; /* printers.conf.O file */
1299 cupsd_printer_t *printer; /* Current printer class */
1300 time_t curtime; /* Current time */
1301 struct tm *curdate; /* Current date */
1302
1303
1304 /*
1305 * Create the printers.conf file...
1306 */
1307
1308 snprintf(temp, sizeof(temp), "%s/printers.conf", ServerRoot);
1309 snprintf(backup, sizeof(backup), "%s/printers.conf.O", ServerRoot);
1310
1311 if (rename(temp, backup))
1312 {
1313 if (errno != ENOENT)
1314 cupsdLogMessage(CUPSD_LOG_ERROR,
1315 "Unable to backup printers.conf - %s", strerror(errno));
1316 }
1317
1318 if ((fp = cupsFileOpen(temp, "w")) == NULL)
1319 {
1320 cupsdLogMessage(CUPSD_LOG_ERROR,
1321 "Unable to save printers.conf - %s", strerror(errno));
1322
1323 if (rename(backup, temp))
1324 cupsdLogMessage(CUPSD_LOG_ERROR,
1325 "Unable to restore printers.conf - %s", strerror(errno));
1326 return;
1327 }
1328 else
1329 cupsdLogMessage(CUPSD_LOG_INFO, "Saving printers.conf...");
1330
1331 /*
1332 * Restrict access to the file...
1333 */
1334
1335 fchown(cupsFileNumber(fp), getuid(), Group);
fa73b229 1336 fchmod(cupsFileNumber(fp), 0600);
ef416fc2 1337
1338 /*
1339 * Write a small header to the file...
1340 */
1341
1342 curtime = time(NULL);
1343 curdate = localtime(&curtime);
1344 strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate);
1345
1346 cupsFilePuts(fp, "# Printer configuration file for " CUPS_SVERSION "\n");
1347 cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp);
1348
1349 /*
1350 * Write each local printer known to the system...
1351 */
1352
1353 for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
1354 printer;
1355 printer = (cupsd_printer_t *)cupsArrayNext(Printers))
1356 {
1357 /*
1358 * Skip remote destinations and printer classes...
1359 */
1360
1361 if ((printer->type & CUPS_PRINTER_REMOTE) ||
1362 (printer->type & CUPS_PRINTER_CLASS) ||
1363 (printer->type & CUPS_PRINTER_IMPLICIT))
1364 continue;
1365
1366 /*
1367 * Write printers as needed...
1368 */
1369
1370 if (printer == DefaultPrinter)
1371 cupsFilePrintf(fp, "<DefaultPrinter %s>\n", printer->name);
1372 else
1373 cupsFilePrintf(fp, "<Printer %s>\n", printer->name);
1374
1375 if (printer->info)
1376 cupsFilePrintf(fp, "Info %s\n", printer->info);
1377
1378 if (printer->location)
1379 cupsFilePrintf(fp, "Location %s\n", printer->location);
1380
1381 if (printer->device_uri)
1382 cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
1383
1384 if (printer->port_monitor)
1385 cupsFilePrintf(fp, "PortMonitor %s\n", printer->port_monitor);
1386
1387 if (printer->state == IPP_PRINTER_STOPPED)
1388 {
1389 cupsFilePuts(fp, "State Stopped\n");
1390 cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message);
1391 }
1392 else
1393 cupsFilePuts(fp, "State Idle\n");
1394
1395 cupsFilePrintf(fp, "StateTime %d\n", (int)printer->state_time);
1396
1397 if (printer->accepting)
1398 cupsFilePuts(fp, "Accepting Yes\n");
1399 else
1400 cupsFilePuts(fp, "Accepting No\n");
1401
1402 if (printer->shared)
1403 cupsFilePuts(fp, "Shared Yes\n");
1404 else
1405 cupsFilePuts(fp, "Shared No\n");
1406
1407 cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
1408 printer->job_sheets[1]);
1409
1410 cupsFilePrintf(fp, "QuotaPeriod %d\n", printer->quota_period);
1411 cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit);
1412 cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit);
1413
1414 for (i = 0; i < printer->num_users; i ++)
1415 cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
1416 printer->users[i]);
1417
1418 if (printer->op_policy)
1419 cupsFilePrintf(fp, "OpPolicy %s\n", printer->op_policy);
1420 if (printer->error_policy)
1421 cupsFilePrintf(fp, "ErrorPolicy %s\n", printer->error_policy);
1422
1423 cupsFilePuts(fp, "</Printer>\n");
1424
1425#ifdef __sgi
1426 /*
1427 * Make IRIX desktop & printer status happy
1428 */
1429
1430 write_irix_state(printer);
1431#endif /* __sgi */
1432 }
1433
1434 cupsFileClose(fp);
1435}
1436
1437
1438/*
1439 * 'cupsdSetPrinterAttrs()' - Set printer attributes based upon the PPD file.
1440 */
1441
1442void
1443cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
1444{
1445 char uri[HTTP_MAX_URI];
1446 /* URI for printer */
1447 char resource[HTTP_MAX_URI];
1448 /* Resource portion of URI */
1449 int i; /* Looping var */
1450 char filename[1024]; /* Name of PPD file */
1451 int num_media; /* Number of media options */
1452 cupsd_location_t *auth; /* Pointer to authentication element */
1453 const char *auth_supported;/* Authentication supported */
e00b005a 1454 cups_ptype_t printer_type; /* Printer type data */
ef416fc2 1455 ppd_file_t *ppd; /* PPD file data */
1456 ppd_option_t *input_slot, /* InputSlot options */
1457 *media_type, /* MediaType options */
1458 *page_size, /* PageSize options */
1459 *output_bin, /* OutputBin options */
1460 *media_quality; /* EFMediaQualityMode options */
1461 ppd_attr_t *ppdattr; /* PPD attribute */
1462 ipp_attribute_t *attr; /* Attribute data */
1463 ipp_value_t *val; /* Attribute value */
1464 int num_finishings; /* Number of finishings */
1465 ipp_finish_t finishings[5]; /* finishings-supported values */
1466 static const char * const sides[3] = /* sides-supported values */
1467 {
1468 "one",
1469 "two-long-edge",
1470 "two-short-edge"
1471 };
1472
1473
1474 DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name,
1475 p->type));
1476
1477 /*
1478 * Make sure that we have the common attributes defined...
1479 */
1480
1481 if (!CommonData)
1482 cupsdCreateCommonData();
1483
1484 /*
1485 * Clear out old filters, if any...
1486 */
1487
1488 cupsdDeletePrinterFilters(p);
1489
1490 /*
1491 * Figure out the authentication that is required for the printer.
1492 */
1493
1494 auth_supported = "requesting-user-name";
1495 if (!(p->type & CUPS_PRINTER_REMOTE))
1496 {
1497 if (p->type & CUPS_PRINTER_CLASS)
1498 snprintf(resource, sizeof(resource), "/classes/%s", p->name);
1499 else
1500 snprintf(resource, sizeof(resource), "/printers/%s", p->name);
1501
1502 if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL)
1503 auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
1504
1505 if (auth)
1506 {
1507 if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST)
1508 auth_supported = "basic";
1509 else if (auth->type == AUTH_DIGEST)
1510 auth_supported = "digest";
1511
1512 if (auth->type != AUTH_NONE)
1513 p->type |= CUPS_PRINTER_AUTHENTICATED;
1514 else
1515 p->type &= ~CUPS_PRINTER_AUTHENTICATED;
1516 }
1517 else
1518 p->type &= ~CUPS_PRINTER_AUTHENTICATED;
1519 }
1520
1521 /*
1522 * Create the required IPP attributes for a printer...
1523 */
1524
1525 if (p->attrs)
1526 ippDelete(p->attrs);
1527
1528 p->attrs = ippNew();
1529
1530 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
1531 "uri-authentication-supported", NULL, auth_supported);
1532 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
1533 "uri-security-supported", NULL, "none");
1534 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL,
1535 p->name);
1536 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
1537 NULL, p->location ? p->location : "");
1538 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
1539 NULL, p->info ? p->info : "");
1540 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info",
1541 NULL, p->uri);
1542
1543 if (p->num_users)
1544 {
1545 if (p->deny_users)
1546 ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
1547 "requesting-user-name-denied", p->num_users, NULL,
1548 p->users);
1549 else
1550 ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
1551 "requesting-user-name-allowed", p->num_users, NULL,
1552 p->users);
1553 }
1554
1555 ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
1556 "job-quota-period", p->quota_period);
1557 ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
1558 "job-k-limit", p->k_limit);
1559 ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
1560 "job-page-limit", p->page_limit);
1561
fa73b229 1562 if (cupsArrayCount(Banners) > 0 && !(p->type & CUPS_PRINTER_REMOTE))
ef416fc2 1563 {
1564 /*
1565 * Setup the job-sheets-default attribute...
1566 */
1567
1568 attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
1569 "job-sheets-default", 2, NULL, NULL);
1570
1571 if (attr != NULL)
1572 {
4400e98d 1573 attr->values[0].string.text = _cups_sp_alloc(Classification ?
ef416fc2 1574 Classification : p->job_sheets[0]);
4400e98d 1575 attr->values[1].string.text = _cups_sp_alloc(Classification ?
ef416fc2 1576 Classification : p->job_sheets[1]);
1577 }
1578 }
1579
e00b005a 1580 printer_type = p->type;
ef416fc2 1581
1582 p->raw = 0;
1583
1584 if (p->type & CUPS_PRINTER_REMOTE)
1585 {
1586 /*
1587 * Tell the client this is a remote printer of some type...
1588 */
1589
1590 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
1591 "printer-uri-supported", NULL, p->uri);
1592
1593 if (p->make_model)
1594 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
1595 "printer-make-and-model", NULL, p->make_model);
1596
fa73b229 1597 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1598 p->uri);
1599
ef416fc2 1600 p->raw = 1;
1601 }
1602 else
1603 {
1604 /*
1605 * Assign additional attributes depending on whether this is a printer
1606 * or class...
1607 */
1608
1609 p->type &= ~CUPS_PRINTER_OPTIONS;
1610
1611 if (p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
1612 {
1613 p->raw = 1;
1614
1615 /*
1616 * Add class-specific attributes...
1617 */
1618
1619 if ((p->type & CUPS_PRINTER_IMPLICIT) && p->num_printers > 0 &&
1620 p->printers[0]->make_model)
1621 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
1622 "printer-make-and-model", NULL, p->printers[0]->make_model);
1623 else
1624 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
1625 "printer-make-and-model", NULL, "Local Printer Class");
1626
fa73b229 1627 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1628 "file:///dev/null");
1629
ef416fc2 1630 if (p->num_printers > 0)
1631 {
1632 /*
1633 * Add a list of member URIs and names...
1634 */
1635
1636 attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
1637 "member-uris", p->num_printers, NULL, NULL);
1638 p->type |= CUPS_PRINTER_OPTIONS;
1639
1640 for (i = 0; i < p->num_printers; i ++)
1641 {
1642 if (attr != NULL)
4400e98d 1643 attr->values[i].string.text = _cups_sp_alloc(p->printers[i]->uri);
ef416fc2 1644
1645 p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
1646 }
1647
1648 attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
1649 "member-names", p->num_printers, NULL, NULL);
1650
1651 if (attr != NULL)
1652 {
1653 for (i = 0; i < p->num_printers; i ++)
4400e98d 1654 attr->values[i].string.text = _cups_sp_alloc(p->printers[i]->name);
ef416fc2 1655 }
1656 }
1657 }
1658 else
1659 {
1660 /*
1661 * Add printer-specific attributes... Start by sanitizing the device
1662 * URI so it doesn't have a username or password in it...
1663 */
1664
1665 if (!p->device_uri)
1666 strcpy(uri, "file:/dev/null");
1667 else if (strstr(p->device_uri, "://") != NULL)
1668 {
1669 /*
1670 * http://..., ipp://..., etc.
1671 */
1672
1673 cupsdSanitizeURI(p->device_uri, uri, sizeof(uri));
1674 }
1675 else
1676 {
1677 /*
1678 * file:..., serial:..., etc.
1679 */
1680
1681 strlcpy(uri, p->device_uri, sizeof(uri));
1682 }
1683
1684 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
1685 uri);
1686
1687 /*
1688 * Assign additional attributes from the PPD file (if any)...
1689 */
1690
1691 p->type |= CUPS_PRINTER_BW;
1692 finishings[0] = IPP_FINISHINGS_NONE;
1693 num_finishings = 1;
1694
1695 snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
1696 p->name);
1697
1698 if ((ppd = ppdOpenFile(filename)) != NULL)
1699 {
1700 /*
1701 * Add make/model and other various attributes...
1702 */
1703
1704 if (ppd->color_device)
1705 p->type |= CUPS_PRINTER_COLOR;
1706 if (ppd->variable_sizes)
1707 p->type |= CUPS_PRINTER_VARIABLE;
1708 if (!ppd->manual_copies)
1709 p->type |= CUPS_PRINTER_COPIES;
1710 if ((ppdattr = ppdFindAttr(ppd, "cupsFax", NULL)) != NULL)
1711 if (ppdattr->value && !strcasecmp(ppdattr->value, "true"))
1712 p->type |= CUPS_PRINTER_FAX;
1713
1714 ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "color-supported",
1715 ppd->color_device);
1716 if (ppd->throughput)
1717 ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
1718 "pages-per-minute", ppd->throughput);
1719
1720 if (ppd->nickname)
1721 cupsdSetString(&p->make_model, ppd->nickname);
1722 else if (ppd->modelname)
1723 cupsdSetString(&p->make_model, ppd->modelname);
1724 else
1725 cupsdSetString(&p->make_model, "Bad PPD File");
1726
1727 if (p->make_model)
1728 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
1729 "printer-make-and-model", NULL, p->make_model);
1730
1731 /*
1732 * Add media options from the PPD file...
1733 */
1734
1735 if ((input_slot = ppdFindOption(ppd, "InputSlot")) != NULL)
1736 num_media = input_slot->num_choices;
1737 else
1738 num_media = 0;
1739
1740 if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL)
1741 num_media += media_type->num_choices;
1742
1743 if ((page_size = ppdFindOption(ppd, "PageSize")) != NULL)
1744 num_media += page_size->num_choices;
1745
1746 if ((media_quality = ppdFindOption(ppd, "EFMediaQualityMode")) != NULL)
1747 num_media += media_quality->num_choices;
1748
1749 if (num_media == 0)
1750 {
1751 cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdSetPrinterAttrs: The PPD file for printer %s "
1752 "contains no media options and is therefore "
1753 "invalid!", p->name);
1754 }
1755 else
1756 {
1757 attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
1758 "media-supported", num_media, NULL, NULL);
1759 if (attr != NULL)
1760 {
1761 val = attr->values;
1762
1763 if (input_slot != NULL)
1764 for (i = 0; i < input_slot->num_choices; i ++, val ++)
4400e98d 1765 val->string.text = _cups_sp_alloc(input_slot->choices[i].choice);
ef416fc2 1766
1767 if (media_type != NULL)
1768 for (i = 0; i < media_type->num_choices; i ++, val ++)
4400e98d 1769 val->string.text = _cups_sp_alloc(media_type->choices[i].choice);
ef416fc2 1770
1771 if (media_quality != NULL)
1772 for (i = 0; i < media_quality->num_choices; i ++, val ++)
4400e98d 1773 val->string.text = _cups_sp_alloc(media_quality->choices[i].choice);
ef416fc2 1774
1775 if (page_size != NULL)
1776 {
1777 for (i = 0; i < page_size->num_choices; i ++, val ++)
4400e98d 1778 val->string.text = _cups_sp_alloc(page_size->choices[i].choice);
ef416fc2 1779
1780 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
1781 NULL, page_size->defchoice);
1782 }
1783 else if (input_slot != NULL)
1784 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
1785 NULL, input_slot->defchoice);
1786 else if (media_type != NULL)
1787 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
1788 NULL, media_type->defchoice);
1789 else if (media_quality != NULL)
1790 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
1791 NULL, media_quality->defchoice);
1792 else
1793 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
1794 NULL, "none");
1795 }
1796 }
1797
1798 /*
1799 * Output bin...
1800 */
1801
1802 if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL)
1803 {
1804 attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
1805 "output-bin-supported", output_bin->num_choices,
1806 NULL, NULL);
1807
1808 if (attr != NULL)
1809 {
1810 for (i = 0, val = attr->values;
1811 i < output_bin->num_choices;
1812 i ++, val ++)
4400e98d 1813 val->string.text = _cups_sp_alloc(output_bin->choices[i].choice);
ef416fc2 1814 }
1815 }
1816
1817 /*
1818 * Duplexing, etc...
1819 */
1820
1821 if (ppdFindOption(ppd, "Duplex") != NULL)
1822 {
1823 p->type |= CUPS_PRINTER_DUPLEX;
1824
1825 ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-supported",
1826 3, NULL, sides);
1827 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-default",
1828 NULL, "one");
1829 }
1830
1831 if (ppdFindOption(ppd, "Collate") != NULL)
1832 p->type |= CUPS_PRINTER_COLLATE;
1833
1834 if (ppdFindOption(ppd, "StapleLocation") != NULL)
1835 {
1836 p->type |= CUPS_PRINTER_STAPLE;
1837 finishings[num_finishings++] = IPP_FINISHINGS_STAPLE;
1838 }
1839
1840 if (ppdFindOption(ppd, "BindEdge") != NULL)
1841 {
1842 p->type |= CUPS_PRINTER_BIND;
1843 finishings[num_finishings++] = IPP_FINISHINGS_BIND;
1844 }
1845
1846 for (i = 0; i < ppd->num_sizes; i ++)
1847 if (ppd->sizes[i].length > 1728)
1848 p->type |= CUPS_PRINTER_LARGE;
1849 else if (ppd->sizes[i].length > 1008)
1850 p->type |= CUPS_PRINTER_MEDIUM;
1851 else
1852 p->type |= CUPS_PRINTER_SMALL;
1853
1854 /*
1855 * Add a filter from application/vnd.cups-raw to printer/name to
1856 * handle "raw" printing by users.
1857 */
1858
1859 cupsdAddPrinterFilter(p, "application/vnd.cups-raw 0 -");
1860
1861 /*
1862 * Add any filters in the PPD file...
1863 */
1864
1865 DEBUG_printf(("ppd->num_filters = %d\n", ppd->num_filters));
1866 for (i = 0; i < ppd->num_filters; i ++)
1867 {
1868 DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i]));
1869 cupsdAddPrinterFilter(p, ppd->filters[i]);
1870 }
1871
1872 if (ppd->num_filters == 0)
1873 {
1874 /*
1875 * If there are no filters, add a PostScript printing filter.
1876 */
1877
1878 cupsdAddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
1879 }
1880
1881 /*
1882 * Show current and available port monitors for this printer...
1883 */
1884
1885 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "port-monitor",
1886 NULL, p->port_monitor ? p->port_monitor : "none");
1887
1888
1889 for (i = 1, ppdattr = ppdFindAttr(ppd, "cupsPortMonitor", NULL);
1890 ppdattr;
1891 i ++, ppdattr = ppdFindNextAttr(ppd, "cupsPortMonitor", NULL));
1892
1893 if (ppd->protocols)
1894 {
1895 if (strstr(ppd->protocols, "TBCP"))
1896 i ++;
1897 else if (strstr(ppd->protocols, "BCP"))
1898 i ++;
1899 }
1900
1901 attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
1902 "port-monitor-supported", i, NULL, NULL);
1903
4400e98d 1904 attr->values[0].string.text = _cups_sp_alloc("none");
ef416fc2 1905
1906 for (i = 1, ppdattr = ppdFindAttr(ppd, "cupsPortMonitor", NULL);
1907 ppdattr;
1908 i ++, ppdattr = ppdFindNextAttr(ppd, "cupsPortMonitor", NULL))
4400e98d 1909 attr->values[i].string.text = _cups_sp_alloc(ppdattr->value);
ef416fc2 1910
1911 if (ppd->protocols)
1912 {
1913 if (strstr(ppd->protocols, "TBCP"))
4400e98d 1914 attr->values[i].string.text = _cups_sp_alloc("tbcp");
ef416fc2 1915 else if (strstr(ppd->protocols, "BCP"))
4400e98d 1916 attr->values[i].string.text = _cups_sp_alloc("bcp");
ef416fc2 1917 }
1918
1919 /*
1920 * Close the PPD and set the type...
1921 */
1922
1923 ppdClose(ppd);
1924
e00b005a 1925 printer_type = p->type;
ef416fc2 1926 }
1927 else if (!access(filename, 0))
1928 {
1929 int pline; /* PPD line number */
1930 ppd_status_t pstatus; /* PPD load status */
1931
1932
1933 pstatus = ppdLastError(&pline);
1934
1935 cupsdLogMessage(CUPSD_LOG_ERROR, "PPD file for %s cannot be loaded!", p->name);
1936
1937 if (pstatus <= PPD_ALLOC_ERROR)
1938 cupsdLogMessage(CUPSD_LOG_ERROR, "%s", strerror(errno));
1939 else
1940 cupsdLogMessage(CUPSD_LOG_ERROR, "%s on line %d.", ppdErrorString(pstatus),
1941 pline);
1942
1943 cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.",
1944 filename);
1945
1946 /*
1947 * Add a filter from application/vnd.cups-raw to printer/name to
1948 * handle "raw" printing by users.
1949 */
1950
1951 cupsdAddPrinterFilter(p, "application/vnd.cups-raw 0 -");
1952
1953 /*
1954 * Add a PostScript filter, since this is still possibly PS printer.
1955 */
1956
1957 cupsdAddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
1958 }
1959 else
1960 {
1961 /*
1962 * If we have an interface script, add a filter entry for it...
1963 */
1964
1965 snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot,
1966 p->name);
1967 if (access(filename, X_OK) == 0)
1968 {
1969 /*
1970 * Yes, we have a System V style interface script; use it!
1971 */
1972
1973 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
1974 "printer-make-and-model", NULL, "Local System V Printer");
1975
1976 snprintf(filename, sizeof(filename), "*/* 0 %s/interfaces/%s",
1977 ServerRoot, p->name);
1978 cupsdAddPrinterFilter(p, filename);
1979 }
1980 else if (p->device_uri &&
1981 !strncmp(p->device_uri, "ipp://", 6) &&
1982 (strstr(p->device_uri, "/printers/") != NULL ||
1983 strstr(p->device_uri, "/classes/") != NULL))
1984 {
1985 /*
1986 * Tell the client this is really a hard-wired remote printer.
1987 */
1988
e00b005a 1989 printer_type |= CUPS_PRINTER_REMOTE;
ef416fc2 1990
1991 /*
1992 * Point the printer-uri-supported attribute to the
1993 * remote printer...
1994 */
1995
1996 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
1997 "printer-uri-supported", NULL, p->device_uri);
1998
1999 /*
2000 * Then set the make-and-model accordingly...
2001 */
2002
2003 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
2004 "printer-make-and-model", NULL, "Remote Printer");
2005
2006 /*
2007 * Print all files directly...
2008 */
2009
2010 p->raw = 1;
2011 }
2012 else
2013 {
2014 /*
2015 * Otherwise we have neither - treat this as a "dumb" printer
2016 * with no PPD file...
2017 */
2018
2019 ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
2020 "printer-make-and-model", NULL, "Local Raw Printer");
2021
2022 p->raw = 1;
2023 }
2024 }
2025
2026 ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
2027 "finishings-supported", num_finishings, (int *)finishings);
2028 ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
2029 "finishings-default", IPP_FINISHINGS_NONE);
2030 }
2031 }
2032
ef416fc2 2033 DEBUG_printf(("cupsdSetPrinterAttrs: leaving name = %s, type = %x\n", p->name,
2034 p->type));
2035
2036#ifdef __sgi
2037 /*
2038 * Write the IRIX printer config and status files...
2039 */
2040
2041 write_irix_config(p);
2042 write_irix_state(p);
2043#endif /* __sgi */
2044}
2045
2046
2047/*
2048 * 'cupsdSetPrinterReasons()' - Set/update the reasons strings.
2049 */
2050
2051void
2052cupsdSetPrinterReasons(
2053 cupsd_printer_t *p, /* I - Printer */
2054 const char *s) /* I - Reasons strings */
2055{
2056 int i; /* Looping var */
2057 const char *sptr; /* Pointer into reasons */
2058 char reason[255], /* Reason string */
2059 *rptr; /* Pointer into reason */
2060
2061
2062 if (s[0] == '-' || s[0] == '+')
2063 {
2064 /*
2065 * Add/remove reasons...
2066 */
2067
2068 sptr = s + 1;
2069 }
2070 else
2071 {
2072 /*
2073 * Replace reasons...
2074 */
2075
2076 sptr = s;
2077
2078 for (i = 0; i < p->num_reasons; i ++)
2079 free(p->reasons[i]);
2080
2081 p->num_reasons = 0;
2082 }
2083
2084 /*
2085 * Loop through all of the reasons...
2086 */
2087
2088 while (*sptr)
2089 {
2090 /*
2091 * Skip leading whitespace and commas...
2092 */
2093
2094 while (isspace(*sptr & 255) || *sptr == ',')
2095 sptr ++;
2096
2097 for (rptr = reason; *sptr && !isspace(*sptr & 255) && *sptr != ','; sptr ++)
2098 if (rptr < (reason + sizeof(reason) - 1))
2099 *rptr++ = *sptr;
2100
2101 if (rptr == reason)
2102 break;
2103
2104 *rptr = '\0';
2105
2106 if (s[0] == '-')
2107 {
2108 /*
2109 * Remove reason...
2110 */
2111
2112 for (i = 0; i < p->num_reasons; i ++)
2113 if (!strcasecmp(reason, p->reasons[i]))
2114 {
2115 /*
2116 * Found a match, so remove it...
2117 */
2118
2119 p->num_reasons --;
2120 free(p->reasons[i]);
2121
2122 if (i < p->num_reasons)
2123 memmove(p->reasons + i, p->reasons + i + 1,
2124 (p->num_reasons - i) * sizeof(char *));
2125
2126 i --;
2127 }
2128 }
2129 else if (p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
2130 {
2131 /*
2132 * Add reason...
2133 */
2134
2135 for (i = 0; i < p->num_reasons; i ++)
2136 if (!strcasecmp(reason, p->reasons[i]))
2137 break;
2138
2139 if (i >= p->num_reasons)
2140 {
2141 p->reasons[i] = strdup(reason);
2142 p->num_reasons ++;
2143 }
2144 }
2145 }
2146}
2147
2148
2149/*
2150 * 'cupsdSetPrinterState()' - Update the current state of a printer.
2151 */
2152
2153void
2154cupsdSetPrinterState(
2155 cupsd_printer_t *p, /* I - Printer to change */
2156 ipp_pstate_t s, /* I - New state */
2157 int update) /* I - Update printers.conf? */
2158{
2159 ipp_pstate_t old_state; /* Old printer state */
2160
2161
2162 /*
2163 * Can't set status of remote printers...
2164 */
2165
2166 if (p->type & CUPS_PRINTER_REMOTE)
2167 return;
2168
2169 /*
2170 * Set the new state...
2171 */
2172
2173 old_state = p->state;
2174 p->state = s;
2175
2176 if (old_state != s)
2177 {
2178 /*
2179 * Let the browse code know this needs to be updated...
2180 */
2181
2182 BrowseNext = p;
2183 p->state_time = time(NULL);
2184 p->browse_time = 0;
2185
2186#ifdef __sgi
2187 write_irix_state(p);
2188#endif /* __sgi */
2189 }
2190
2191 cupsdAddPrinterHistory(p);
2192
2193 /*
2194 * Save the printer configuration if a printer goes from idle or processing
2195 * to stopped (or visa-versa)...
2196 */
2197
2198 if ((old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED) &&
2199 update)
2200 {
2201 if (p->type & CUPS_PRINTER_CLASS)
2202 cupsdSaveAllClasses();
2203 else
2204 cupsdSaveAllPrinters();
2205 }
2206}
2207
2208
2209/*
2210 * 'cupsdStopPrinter()' - Stop a printer from printing any jobs...
2211 */
2212
2213void
2214cupsdStopPrinter(cupsd_printer_t *p, /* I - Printer to stop */
2215 int update)/* I - Update printers.conf? */
2216{
2217 cupsd_job_t *job; /* Active print job */
2218
2219
2220 /*
2221 * Set the printer state...
2222 */
2223
2224 cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, update);
2225
2226 /*
2227 * See if we have a job printing on this printer...
2228 */
2229
2230 if (p->job)
2231 {
2232 /*
2233 * Get pointer to job...
2234 */
2235
2236 job = (cupsd_job_t *)p->job;
2237
2238 /*
2239 * Stop it...
2240 */
2241
2242 cupsdStopJob(job, 0);
2243
2244 /*
2245 * Reset the state to pending...
2246 */
2247
2248 job->state->values[0].integer = IPP_JOB_PENDING;
2249
2250 cupsdSaveJob(job);
2251 }
2252}
2253
2254
2255/*
2256 * 'cupsdUpdatePrinters()' - Update printers after a partial reload.
2257 */
2258
2259void
2260cupsdUpdatePrinters(void)
2261{
2262 cupsd_printer_t *p; /* Current printer */
2263
2264
2265 /*
2266 * Loop through the printers and recreate the printer attributes
2267 * for any local printers since the policy and/or access control
2268 * stuff may have changed. Also, if browsing is disabled, remove
2269 * any remote printers...
2270 */
2271
2272 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
2273 p;
2274 p = (cupsd_printer_t *)cupsArrayNext(Printers))
2275 {
2276 if (!Browsing && (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_REMOTE)))
2277 {
2278 if (p->type & CUPS_PRINTER_IMPLICIT)
2279 cupsArrayRemove(ImplicitPrinters, p);
2280
2281 cupsArraySave(Printers);
2282 cupsdDeletePrinter(p, 0);
2283 cupsArrayRestore(Printers);
2284 continue;
2285 }
2286 else if (!(p->type & CUPS_PRINTER_REMOTE))
2287 cupsdSetPrinterAttrs(p);
2288
2289 /*
2290 * Update the operation policy pointer...
2291 */
2292
2293 if ((p->op_policy_ptr = cupsdFindPolicy(p->op_policy)) == NULL)
2294 p->op_policy_ptr = DefaultPolicyPtr;
2295 }
2296}
2297
2298
2299/*
2300 * 'cupsdValidateDest()' - Validate a printer/class destination.
2301 */
2302
2303const char * /* O - Printer or class name */
2304cupsdValidateDest(
2305 const char *hostname, /* I - Host name */
2306 const char *resource, /* I - Resource name */
2307 cups_ptype_t *dtype, /* O - Type (printer or class) */
2308 cupsd_printer_t **printer) /* O - Printer pointer */
2309{
2310 cupsd_printer_t *p; /* Current printer */
2311 char localname[1024],/* Localized hostname */
2312 *lptr, /* Pointer into localized hostname */
2313 *sptr; /* Pointer into server name */
2314
2315
2316 DEBUG_printf(("cupsdValidateDest(\"%s\", \"%s\", %p, %p)\n", hostname, resource,
2317 dtype, printer));
2318
2319 /*
2320 * Initialize return values...
2321 */
2322
2323 if (printer)
2324 *printer = NULL;
2325
2326 *dtype = (cups_ptype_t)0;
2327
2328 /*
2329 * See if the resource is a class or printer...
2330 */
2331
2332 if (!strncmp(resource, "/classes/", 9))
2333 {
2334 /*
2335 * Class...
2336 */
2337
2338 resource += 9;
2339 }
2340 else if (!strncmp(resource, "/printers/", 10))
2341 {
2342 /*
2343 * Printer...
2344 */
2345
2346 resource += 10;
2347 }
2348 else
2349 {
2350 /*
2351 * Bad resource name...
2352 */
2353
2354 return (NULL);
2355 }
2356
2357 /*
2358 * See if the printer or class name exists...
2359 */
2360
2361 p = cupsdFindDest(resource);
2362
2363 if (p == NULL && strchr(resource, '@') == NULL)
2364 return (NULL);
2365 else if (p != NULL)
2366 {
2367 if (printer)
2368 *printer = p;
2369
2370 *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
2371 CUPS_PRINTER_REMOTE);
2372 return (p->name);
2373 }
2374
2375 /*
2376 * Change localhost to the server name...
2377 */
2378
2379 if (!strcasecmp(hostname, "localhost"))
2380 hostname = ServerName;
2381
2382 strlcpy(localname, hostname, sizeof(localname));
2383
2384 if (!strcasecmp(hostname, ServerName))
2385 {
2386 /*
2387 * Localize the hostname...
2388 */
2389
2390 lptr = strchr(localname, '.');
2391 sptr = strchr(ServerName, '.');
2392
2393 if (sptr != NULL && lptr != NULL)
2394 {
2395 /*
2396 * Strip the common domain name components...
2397 */
2398
2399 while (lptr != NULL)
2400 {
2401 if (!strcasecmp(lptr, sptr))
2402 {
2403 *lptr = '\0';
2404 break;
2405 }
2406 else
2407 lptr = strchr(lptr + 1, '.');
2408 }
2409 }
2410 }
2411
2412 DEBUG_printf(("localized hostname is \"%s\"...\n", localname));
2413
2414 /*
2415 * Find a matching printer or class...
2416 */
2417
2418 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
2419 p;
2420 p = (cupsd_printer_t *)cupsArrayNext(Printers))
2421 if (!strcasecmp(p->hostname, localname) &&
2422 !strcasecmp(p->name, resource))
2423 {
2424 if (printer)
2425 *printer = p;
2426
2427 *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
2428 CUPS_PRINTER_REMOTE);
2429 return (p->name);
2430 }
2431
2432 return (NULL);
2433}
2434
2435
2436/*
2437 * 'cupsdWritePrintcap()' - Write a pseudo-printcap file for older applications
2438 * that need it...
2439 */
2440
2441void
2442cupsdWritePrintcap(void)
2443{
2444 cups_file_t *fp; /* printcap file */
2445 cupsd_printer_t *p; /* Current printer */
2446
2447
2448#ifdef __sgi
2449 /*
2450 * Update the IRIX printer state for the default printer; if
2451 * no printers remain, then the default printer file will be
2452 * removed...
2453 */
2454
2455 write_irix_state(DefaultPrinter);
2456#endif /* __sgi */
2457
2458 /*
2459 * See if we have a printcap file; if not, don't bother writing it.
2460 */
2461
2462 if (!Printcap || !*Printcap)
2463 return;
2464
2465 /*
2466 * Open the printcap file...
2467 */
2468
2469 if ((fp = cupsFileOpen(Printcap, "w")) == NULL)
2470 return;
2471
2472 /*
2473 * Put a comment header at the top so that users will know where the
2474 * data has come from...
2475 */
2476
2477 cupsFilePuts(fp, "# This file was automatically generated by cupsd(8) from the\n");
2478 cupsFilePrintf(fp, "# %s/printers.conf file. All changes to this file\n",
2479 ServerRoot);
2480 cupsFilePuts(fp, "# will be lost.\n");
2481
2482 if (Printers)
2483 {
2484 /*
2485 * Write a new printcap with the current list of printers.
2486 */
2487
2488 switch (PrintcapFormat)
2489 {
2490 case PRINTCAP_BSD:
2491 /*
2492 * Each printer is put in the file as:
2493 *
2494 * Printer1:
2495 * Printer2:
2496 * Printer3:
2497 * ...
2498 * PrinterN:
2499 */
2500
2501 if (DefaultPrinter)
2502 cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter->name,
2503 DefaultPrinter->info, ServerName, DefaultPrinter->name);
2504
2505 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
2506 p;
2507 p = (cupsd_printer_t *)cupsArrayNext(Printers))
2508 if (p != DefaultPrinter)
2509 cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info,
2510 ServerName, p->name);
2511 break;
2512
2513 case PRINTCAP_SOLARIS:
2514 /*
2515 * Each printer is put in the file as:
2516 *
2517 * _all:all=Printer1,Printer2,Printer3,...,PrinterN
2518 * _default:use=DefaultPrinter
2519 * Printer1:\
2520 * :bsdaddr=ServerName,Printer1:\
2521 * :description=Description:
2522 * Printer2:
2523 * :bsdaddr=ServerName,Printer2:\
2524 * :description=Description:
2525 * Printer3:
2526 * :bsdaddr=ServerName,Printer3:\
2527 * :description=Description:
2528 * ...
2529 * PrinterN:
2530 * :bsdaddr=ServerName,PrinterN:\
2531 * :description=Description:
2532 */
2533
2534 cupsFilePuts(fp, "_all:all=");
2535 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
2536 p;
2537 p = (cupsd_printer_t *)cupsArrayCurrent(Printers))
2538 cupsFilePrintf(fp, "%s%c", p->name,
2539 cupsArrayNext(Printers) ? ',' : '\n');
2540
2541 if (DefaultPrinter)
2542 cupsFilePrintf(fp, "_default:use=%s\n", DefaultPrinter->name);
2543
2544 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
2545 p;
2546 p = (cupsd_printer_t *)cupsArrayNext(Printers))
2547 cupsFilePrintf(fp, "%s:\\\n"
2548 "\t:bsdaddr=%s,%s:\\\n"
2549 "\t:description=%s:\n",
2550 p->name, ServerName, p->name, p->info ? p->info : "");
2551 break;
2552 }
2553 }
2554
2555 /*
2556 * Close the file...
2557 */
2558
2559 cupsFileClose(fp);
2560}
2561
2562
2563/*
2564 * 'cupsdSanitizeURI()' - Sanitize a device URI...
2565 */
2566
2567char * /* O - New device URI */
2568cupsdSanitizeURI(const char *uri, /* I - Original device URI */
2569 char *buffer, /* O - New device URI */
2570 int buflen) /* I - Size of new device URI buffer */
2571{
2572 char *start, /* Start of data after scheme */
2573 *slash, /* First slash after scheme:// */
2574 *ptr; /* Pointer into user@host:port part */
2575
2576
2577 /*
2578 * Range check input...
2579 */
2580
2581 if (!uri || !buffer || buflen < 2)
2582 return (NULL);
2583
2584 /*
2585 * Copy the device URI to the new buffer...
2586 */
2587
2588 strlcpy(buffer, uri, buflen);
2589
2590 /*
2591 * Find the end of the scheme:// part...
2592 */
2593
2594 if ((ptr = strchr(buffer, ':')) == NULL)
2595 return (buffer); /* No scheme: part... */
2596
2597 for (start = ptr + 1; *start; start ++)
2598 if (*start != '/')
2599 break;
2600
2601 /*
2602 * Find the next slash (/) in the URI...
2603 */
2604
2605 if ((slash = strchr(start, '/')) == NULL)
2606 slash = start + strlen(start); /* No slash, point to the end */
2607
2608 /*
2609 * Check for an @ sign before the slash...
2610 */
2611
2612 if ((ptr = strchr(start, '@')) != NULL && ptr < slash)
2613 {
2614 /*
2615 * Found an @ sign and it is before the resource part, so we have
2616 * an authentication string. Copy the remaining URI over the
2617 * authentication string...
2618 */
2619
2620 _cups_strcpy(start, ptr + 1);
2621 }
2622
2623 /*
2624 * Return the new device URI...
2625 */
2626
2627 return (buffer);
2628}
2629
2630
2631/*
2632 * 'compare_printers()' - Compare two printers.
2633 */
2634
2635static int /* O - Result of comparison */
2636compare_printers(void *first, /* I - First printer */
2637 void *second, /* I - Second printer */
2638 void *data) /* I - App data (not used) */
2639{
2640 return (strcasecmp(((cupsd_printer_t *)first)->name,
2641 ((cupsd_printer_t *)second)->name));
2642}
2643
2644
2645#ifdef __sgi
2646/*
2647 * 'write_irix_config()' - Update the config files used by the IRIX
2648 * desktop tools.
2649 */
2650
2651static void
2652write_irix_config(cupsd_printer_t *p) /* I - Printer to update */
2653{
2654 char filename[1024]; /* Interface script filename */
2655 cups_file_t *fp; /* Interface script file */
2656
2657
2658
2659 /*
2660 * Add dummy interface and GUI scripts to fool SGI's "challenged" printing
2661 * tools. First the interface script that tells the tools what kind of
2662 * printer we have...
2663 */
2664
2665 snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
2666
2667 if (p->type & CUPS_PRINTER_CLASS)
2668 unlink(filename);
2669 else if ((fp = cupsFileOpen(filename, "w")) != NULL)
2670 {
2671 cupsFilePuts(fp, "#!/bin/sh\n");
2672
2673 if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model",
2674 IPP_TAG_TEXT)) != NULL)
2675 cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text);
2676 else if (p->type & CUPS_PRINTER_CLASS)
2677 cupsFilePuts(fp, "NAME=\"Printer Class\"\n");
2678 else
2679 cupsFilePuts(fp, "NAME=\"Remote Destination\"\n");
2680
2681 if (p->type & CUPS_PRINTER_COLOR)
2682 cupsFilePuts(fp, "TYPE=ColorPostScript\n");
2683 else
2684 cupsFilePuts(fp, "TYPE=MonoPostScript\n");
2685
2686 cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName);
2687 cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name);
2688
2689 cupsFileClose(fp);
2690
2691 chmod(filename, 0755);
2692 chown(filename, User, Group);
2693 }
2694
2695 /*
2696 * Then the member file that tells which device file the queue is connected
2697 * to... Networked printers use "/dev/null" in this file, so that's what
2698 * we use (the actual device URI can confuse some apps...)
2699 */
2700
2701 snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
2702
2703 if (p->type & CUPS_PRINTER_CLASS)
2704 unlink(filename);
2705 else if ((fp = cupsFileOpen(filename, "w")) != NULL)
2706 {
2707 cupsFilePuts(fp, "/dev/null\n");
2708
2709 cupsFileClose(fp);
2710
2711 chmod(filename, 0644);
2712 chown(filename, User, Group);
2713 }
2714
2715 /*
2716 * The gui_interface file is a script or program that launches a GUI
2717 * option panel for the printer, using options specified on the
2718 * command-line in the third argument. The option panel must send
2719 * any printing options to stdout on a single line when the user
2720 * accepts them, or nothing if the user cancels the dialog.
2721 *
2722 * The default options panel program is /usr/bin/glpoptions, from
2723 * the ESP Print Pro software. You can select another using the
2724 * PrintcapGUI option.
2725 */
2726
2727 snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", p->name);
2728
2729 if (p->type & CUPS_PRINTER_CLASS)
2730 unlink(filename);
2731 else if ((fp = cupsFileOpen(filename, "w")) != NULL)
2732 {
2733 cupsFilePuts(fp, "#!/bin/sh\n");
2734 cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name);
2735
2736 cupsFileClose(fp);
2737
2738 chmod(filename, 0755);
2739 chown(filename, User, Group);
2740 }
2741
2742 /*
2743 * The POD config file is needed by the printstatus command to show
2744 * the printer location and device.
2745 */
2746
2747 snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
2748
2749 if (p->type & CUPS_PRINTER_CLASS)
2750 unlink(filename);
2751 else if ((fp = cupsFileOpen(filename, "w")) != NULL)
2752 {
2753 cupsFilePrintf(fp, "Printer Class | %s\n",
2754 (p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript");
2755 cupsFilePrintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : "");
2756 cupsFilePrintf(fp, "Location Code | %s\n", p->location ? p->location : "");
2757 cupsFilePrintf(fp, "Physical Location | %s\n", p->info ? p->info : "");
2758 cupsFilePrintf(fp, "Port Path | %s\n", p->device_uri ? p->device_uri : "");
2759 cupsFilePrintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name);
2760 cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name);
2761 cupsFilePuts(fp, "Status Update Wait | 10 seconds\n");
2762
2763 cupsFileClose(fp);
2764
2765 chmod(filename, 0664);
2766 chown(filename, User, Group);
2767 }
2768}
2769
2770
2771/*
2772 * 'write_irix_state()' - Update the status files used by IRIX printing
2773 * desktop tools.
2774 */
2775
2776static void
2777write_irix_state(cupsd_printer_t *p) /* I - Printer to update */
2778{
2779 char filename[1024]; /* Interface script filename */
2780 cups_file_t *fp; /* Interface script file */
2781 int tag; /* Status tag value */
2782
2783
2784 if (p)
2785 {
2786 /*
2787 * The POD status file is needed for the printstatus window to
2788 * provide the current status of the printer.
2789 */
2790
2791 snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
2792
2793 if (p->type & CUPS_PRINTER_CLASS)
2794 unlink(filename);
2795 else if ((fp = cupsFileOpen(filename, "w")) != NULL)
2796 {
2797 cupsFilePrintf(fp, "Operational Status | %s\n",
2798 (p->state == IPP_PRINTER_IDLE) ? "Idle" :
2799 (p->state == IPP_PRINTER_PROCESSING) ? "Busy" :
2800 "Faulted");
2801 cupsFilePrintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION);
2802 cupsFilePrintf(fp, "Information | 02 00 00 | Device URI: %s\n",
2803 p->device_uri ? p->device_uri : "");
2804 cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n",
2805 p->accepting ? "Accepting" : "Not accepting");
2806 cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message);
2807
2808 cupsFileClose(fp);
2809
2810 chmod(filename, 0664);
2811 chown(filename, User, Group);
2812 }
2813
2814 /*
2815 * The activeicons file is needed to provide desktop icons for printers:
2816 *
2817 * [ quoted from /usr/lib/print/tagit ]
2818 *
2819 * --- Type of printer tags (base values)
2820 *
2821 * Dumb=66048 # 0x10200
2822 * DumbColor=66080 # 0x10220
2823 * Raster=66112 # 0x10240
2824 * ColorRaster=66144 # 0x10260
2825 * Plotter=66176 # 0x10280
2826 * PostScript=66208 # 0x102A0
2827 * ColorPostScript=66240 # 0x102C0
2828 * MonoPostScript=66272 # 0x102E0
2829 *
2830 * --- Printer state modifiers for local printers
2831 *
2832 * Idle=0 # 0x0
2833 * Busy=1 # 0x1
2834 * Faulted=2 # 0x2
2835 * Unknown=3 # 0x3 (Faulted due to unknown reason)
2836 *
2837 * --- Printer state modifiers for network printers
2838 *
2839 * NetIdle=8 # 0x8
2840 * NetBusy=9 # 0x9
2841 * NetFaulted=10 # 0xA
2842 * NetUnknown=11 # 0xB (Faulted due to unknown reason)
2843 */
2844
2845 snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
2846
2847 if (p->type & CUPS_PRINTER_CLASS)
2848 unlink(filename);
2849 else if ((fp = cupsFileOpen(filename, "w")) != NULL)
2850 {
2851 if (p->type & CUPS_PRINTER_COLOR)
2852 tag = 66240;
2853 else
2854 tag = 66272;
2855
2856 if (p->type & CUPS_PRINTER_REMOTE)
2857 tag |= 8;
2858
2859 if (p->state == IPP_PRINTER_PROCESSING)
2860 tag |= 1;
2861
2862 else if (p->state == IPP_PRINTER_STOPPED)
2863 tag |= 2;
2864
2865 cupsFilePuts(fp, "#!/bin/sh\n");
2866 cupsFilePrintf(fp, "#Tag %d\n", tag);
2867
2868 cupsFileClose(fp);
2869
2870 chmod(filename, 0755);
2871 chown(filename, User, Group);
2872 }
2873 }
2874
2875 /*
2876 * The default file is needed by the printers window to show
2877 * the default printer.
2878 */
2879
2880 snprintf(filename, sizeof(filename), "/var/spool/lp/default");
2881
2882 if (DefaultPrinter != NULL)
2883 {
2884 if ((fp = cupsFileOpen(filename, "w")) != NULL)
2885 {
2886 cupsFilePrintf(fp, "%s\n", DefaultPrinter->name);
2887
2888 cupsFileClose(fp);
2889
2890 chmod(filename, 0644);
2891 chown(filename, User, Group);
2892 }
2893 }
2894 else
2895 unlink(filename);
2896}
2897#endif /* __sgi */
2898
2899
2900/*
4400e98d 2901 * End of "$Id: printers.c 5047 2006-02-02 05:14:15Z mike $".
ef416fc2 2902 */