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