r14683: Get rid of hardcoded output file. With no arg, print to stdout,
[Samba.git] / source / printing / print_cups.c
blobafa301bbea1b643c7364df421661b065ec76bcde
1 /*
2 * Support code for the Common UNIX Printing System ("CUPS")
4 * Copyright 1999-2003 by Michael R Sweet.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
22 #include "printing.h"
24 #ifdef HAVE_CUPS
25 #include <cups/cups.h>
26 #include <cups/language.h>
30 * 'cups_passwd_cb()' - The CUPS password callback...
33 static const char * /* O - Password or NULL */
34 cups_passwd_cb(const char *prompt) /* I - Prompt */
37 * Always return NULL to indicate that no password is available...
40 return (NULL);
43 static const char *cups_server(void)
45 if ((lp_cups_server() != NULL) && (strlen(lp_cups_server()) > 0)) {
46 DEBUG(10, ("cups server explicitly set to %s\n",
47 lp_cups_server()));
48 return lp_cups_server();
51 DEBUG(10, ("cups server left to default %s\n", cupsServer()));
52 return cupsServer();
55 BOOL cups_cache_reload(void)
57 http_t *http = NULL; /* HTTP connection to server */
58 ipp_t *request = NULL, /* IPP Request */
59 *response = NULL; /* IPP Response */
60 ipp_attribute_t *attr; /* Current attribute */
61 cups_lang_t *language = NULL; /* Default language */
62 char *name, /* printer-name attribute */
63 *info; /* printer-info attribute */
64 static const char *requested[] =/* Requested attributes */
66 "printer-name",
67 "printer-info"
68 };
69 BOOL ret = False;
71 DEBUG(5, ("reloading cups printcap cache\n"));
74 * Make sure we don't ask for passwords...
77 cupsSetPasswordCB(cups_passwd_cb);
80 * Try to connect to the server...
83 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
84 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
85 cups_server(), strerror(errno)));
86 goto out;
90 * Build a CUPS_GET_PRINTERS request, which requires the following
91 * attributes:
93 * attributes-charset
94 * attributes-natural-language
95 * requested-attributes
98 request = ippNew();
100 request->request.op.operation_id = CUPS_GET_PRINTERS;
101 request->request.op.request_id = 1;
103 language = cupsLangDefault();
105 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
106 "attributes-charset", NULL, cupsLangEncoding(language));
108 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
109 "attributes-natural-language", NULL, language->language);
111 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
112 "requested-attributes",
113 (sizeof(requested) / sizeof(requested[0])),
114 NULL, requested);
117 * Do the request and get back a response...
120 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
121 DEBUG(0,("Unable to get printer list - %s\n",
122 ippErrorString(cupsLastError())));
123 goto out;
126 for (attr = response->attrs; attr != NULL;) {
128 * Skip leading attributes until we hit a printer...
131 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
132 attr = attr->next;
134 if (attr == NULL)
135 break;
138 * Pull the needed attributes from this printer...
141 name = NULL;
142 info = NULL;
144 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
145 if (strcmp(attr->name, "printer-name") == 0 &&
146 attr->value_tag == IPP_TAG_NAME)
147 name = attr->values[0].string.text;
149 if (strcmp(attr->name, "printer-info") == 0 &&
150 attr->value_tag == IPP_TAG_TEXT)
151 info = attr->values[0].string.text;
153 attr = attr->next;
157 * See if we have everything needed...
160 if (name == NULL)
161 break;
163 if (!pcap_cache_add(name, info)) {
164 goto out;
168 ippDelete(response);
169 response = NULL;
172 * Build a CUPS_GET_CLASSES request, which requires the following
173 * attributes:
175 * attributes-charset
176 * attributes-natural-language
177 * requested-attributes
180 request = ippNew();
182 request->request.op.operation_id = CUPS_GET_CLASSES;
183 request->request.op.request_id = 1;
185 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
186 "attributes-charset", NULL, cupsLangEncoding(language));
188 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
189 "attributes-natural-language", NULL, language->language);
191 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
192 "requested-attributes",
193 (sizeof(requested) / sizeof(requested[0])),
194 NULL, requested);
197 * Do the request and get back a response...
200 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
201 DEBUG(0,("Unable to get printer list - %s\n",
202 ippErrorString(cupsLastError())));
203 goto out;
206 for (attr = response->attrs; attr != NULL;) {
208 * Skip leading attributes until we hit a printer...
211 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
212 attr = attr->next;
214 if (attr == NULL)
215 break;
218 * Pull the needed attributes from this printer...
221 name = NULL;
222 info = NULL;
224 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
225 if (strcmp(attr->name, "printer-name") == 0 &&
226 attr->value_tag == IPP_TAG_NAME)
227 name = attr->values[0].string.text;
229 if (strcmp(attr->name, "printer-info") == 0 &&
230 attr->value_tag == IPP_TAG_TEXT)
231 info = attr->values[0].string.text;
233 attr = attr->next;
237 * See if we have everything needed...
240 if (name == NULL)
241 break;
243 if (!pcap_cache_add(name, info)) {
244 goto out;
248 ret = True;
250 out:
251 if (response)
252 ippDelete(response);
254 if (language)
255 cupsLangFree(language);
257 if (http)
258 httpClose(http);
260 return ret;
265 * 'cups_job_delete()' - Delete a job.
268 static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
270 int ret = 1; /* Return value */
271 http_t *http = NULL; /* HTTP connection to server */
272 ipp_t *request = NULL, /* IPP Request */
273 *response = NULL; /* IPP Response */
274 cups_lang_t *language = NULL; /* Default language */
275 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
278 DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
281 * Make sure we don't ask for passwords...
284 cupsSetPasswordCB(cups_passwd_cb);
287 * Try to connect to the server...
290 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
291 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
292 cups_server(), strerror(errno)));
293 goto out;
297 * Build an IPP_CANCEL_JOB request, which requires the following
298 * attributes:
300 * attributes-charset
301 * attributes-natural-language
302 * job-uri
303 * requesting-user-name
306 request = ippNew();
308 request->request.op.operation_id = IPP_CANCEL_JOB;
309 request->request.op.request_id = 1;
311 language = cupsLangDefault();
313 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
314 "attributes-charset", NULL, cupsLangEncoding(language));
316 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
317 "attributes-natural-language", NULL, language->language);
319 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
321 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
323 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
324 NULL, pjob->user);
327 * Do the request and get back a response...
330 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
331 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
332 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
333 ippErrorString(cupsLastError())));
334 } else {
335 ret = 0;
337 } else {
338 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
339 ippErrorString(cupsLastError())));
342 out:
343 if (response)
344 ippDelete(response);
346 if (language)
347 cupsLangFree(language);
349 if (http)
350 httpClose(http);
352 return ret;
357 * 'cups_job_pause()' - Pause a job.
360 static int cups_job_pause(int snum, struct printjob *pjob)
362 int ret = 1; /* Return value */
363 http_t *http = NULL; /* HTTP connection to server */
364 ipp_t *request = NULL, /* IPP Request */
365 *response = NULL; /* IPP Response */
366 cups_lang_t *language = NULL; /* Default language */
367 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
370 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
373 * Make sure we don't ask for passwords...
376 cupsSetPasswordCB(cups_passwd_cb);
379 * Try to connect to the server...
382 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
383 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
384 cups_server(), strerror(errno)));
385 goto out;
389 * Build an IPP_HOLD_JOB request, which requires the following
390 * attributes:
392 * attributes-charset
393 * attributes-natural-language
394 * job-uri
395 * requesting-user-name
398 request = ippNew();
400 request->request.op.operation_id = IPP_HOLD_JOB;
401 request->request.op.request_id = 1;
403 language = cupsLangDefault();
405 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
406 "attributes-charset", NULL, cupsLangEncoding(language));
408 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
409 "attributes-natural-language", NULL, language->language);
411 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
413 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
415 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
416 NULL, pjob->user);
419 * Do the request and get back a response...
422 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
423 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
424 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
425 ippErrorString(cupsLastError())));
426 } else {
427 ret = 0;
429 } else {
430 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
431 ippErrorString(cupsLastError())));
434 out:
435 if (response)
436 ippDelete(response);
438 if (language)
439 cupsLangFree(language);
441 if (http)
442 httpClose(http);
444 return ret;
449 * 'cups_job_resume()' - Resume a paused job.
452 static int cups_job_resume(int snum, struct printjob *pjob)
454 int ret = 1; /* Return value */
455 http_t *http = NULL; /* HTTP connection to server */
456 ipp_t *request = NULL, /* IPP Request */
457 *response = NULL; /* IPP Response */
458 cups_lang_t *language = NULL; /* Default language */
459 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
462 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
465 * Make sure we don't ask for passwords...
468 cupsSetPasswordCB(cups_passwd_cb);
471 * Try to connect to the server...
474 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
475 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
476 cups_server(), strerror(errno)));
477 goto out;
481 * Build an IPP_RELEASE_JOB request, which requires the following
482 * attributes:
484 * attributes-charset
485 * attributes-natural-language
486 * job-uri
487 * requesting-user-name
490 request = ippNew();
492 request->request.op.operation_id = IPP_RELEASE_JOB;
493 request->request.op.request_id = 1;
495 language = cupsLangDefault();
497 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
498 "attributes-charset", NULL, cupsLangEncoding(language));
500 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
501 "attributes-natural-language", NULL, language->language);
503 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
505 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
507 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
508 NULL, pjob->user);
511 * Do the request and get back a response...
514 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
515 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
516 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
517 ippErrorString(cupsLastError())));
518 } else {
519 ret = 0;
521 } else {
522 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
523 ippErrorString(cupsLastError())));
526 out:
527 if (response)
528 ippDelete(response);
530 if (language)
531 cupsLangFree(language);
533 if (http)
534 httpClose(http);
536 return ret;
541 * 'cups_job_submit()' - Submit a job for printing.
544 static int cups_job_submit(int snum, struct printjob *pjob)
546 int ret = 1; /* Return value */
547 http_t *http = NULL; /* HTTP connection to server */
548 ipp_t *request = NULL, /* IPP Request */
549 *response = NULL; /* IPP Response */
550 cups_lang_t *language = NULL; /* Default language */
551 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
552 char *clientname = NULL; /* hostname of client for job-originating-host attribute */
553 pstring new_jobname;
554 int num_options = 0;
555 cups_option_t *options = NULL;
557 DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
560 * Make sure we don't ask for passwords...
563 cupsSetPasswordCB(cups_passwd_cb);
566 * Try to connect to the server...
569 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
570 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
571 cups_server(), strerror(errno)));
572 goto out;
576 * Build an IPP_PRINT_JOB request, which requires the following
577 * attributes:
579 * attributes-charset
580 * attributes-natural-language
581 * printer-uri
582 * requesting-user-name
583 * [document-data]
586 request = ippNew();
588 request->request.op.operation_id = IPP_PRINT_JOB;
589 request->request.op.request_id = 1;
591 language = cupsLangDefault();
593 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
594 "attributes-charset", NULL, cupsLangEncoding(language));
596 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
597 "attributes-natural-language", NULL, language->language);
599 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
600 PRINTERNAME(snum));
602 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
603 "printer-uri", NULL, uri);
605 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
606 NULL, pjob->user);
608 clientname = client_name();
609 if (strcmp(clientname, "UNKNOWN") == 0) {
610 clientname = client_addr();
613 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
614 "job-originating-host-name", NULL,
615 clientname);
617 pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX,
618 (unsigned int)pjob->smbjob, pjob->jobname);
620 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
621 new_jobname);
624 * add any options defined in smb.conf
627 num_options = 0;
628 options = NULL;
629 num_options = cupsParseOptions(lp_cups_options(snum), num_options, &options);
631 if ( num_options )
632 cupsEncodeOptions(request, num_options, options);
635 * Do the request and get back a response...
638 slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
640 if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
641 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
642 DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
643 ippErrorString(cupsLastError())));
644 } else {
645 ret = 0;
647 } else {
648 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
649 ippErrorString(cupsLastError())));
652 if ( ret == 0 )
653 unlink(pjob->filename);
654 /* else print_job_end will do it for us */
656 out:
657 if (response)
658 ippDelete(response);
660 if (language)
661 cupsLangFree(language);
663 if (http)
664 httpClose(http);
666 return ret;
670 * 'cups_queue_get()' - Get all the jobs in the print queue.
673 static int cups_queue_get(const char *sharename,
674 enum printing_types printing_type,
675 char *lpq_command,
676 print_queue_struct **q,
677 print_status_struct *status)
679 fstring printername;
680 http_t *http = NULL; /* HTTP connection to server */
681 ipp_t *request = NULL, /* IPP Request */
682 *response = NULL; /* IPP Response */
683 ipp_attribute_t *attr = NULL; /* Current attribute */
684 cups_lang_t *language = NULL; /* Default language */
685 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
686 int qcount = 0, /* Number of active queue entries */
687 qalloc = 0; /* Number of queue entries allocated */
688 print_queue_struct *queue = NULL, /* Queue entries */
689 *temp; /* Temporary pointer for queue */
690 const char *user_name, /* job-originating-user-name attribute */
691 *job_name; /* job-name attribute */
692 int job_id; /* job-id attribute */
693 int job_k_octets; /* job-k-octets attribute */
694 time_t job_time; /* time-at-creation attribute */
695 ipp_jstate_t job_status; /* job-status attribute */
696 int job_priority; /* job-priority attribute */
697 static const char *jattrs[] = /* Requested job attributes */
699 "job-id",
700 "job-k-octets",
701 "job-name",
702 "job-originating-user-name",
703 "job-priority",
704 "job-state",
705 "time-at-creation",
707 static const char *pattrs[] = /* Requested printer attributes */
709 "printer-state",
710 "printer-state-message"
713 *q = NULL;
715 /* HACK ALERT!!! The problem with support the 'printer name'
716 option is that we key the tdb off the sharename. So we will
717 overload the lpq_command string to pass in the printername
718 (which is basically what we do for non-cups printers ... using
719 the lpq_command to get the queue listing). */
721 fstrcpy( printername, lpq_command );
723 DEBUG(5,("cups_queue_get(%s, %p, %p)\n", printername, q, status));
726 * Make sure we don't ask for passwords...
729 cupsSetPasswordCB(cups_passwd_cb);
732 * Try to connect to the server...
735 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
736 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
737 cups_server(), strerror(errno)));
738 goto out;
742 * Generate the printer URI...
745 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
748 * Build an IPP_GET_JOBS request, which requires the following
749 * attributes:
751 * attributes-charset
752 * attributes-natural-language
753 * requested-attributes
754 * printer-uri
757 request = ippNew();
759 request->request.op.operation_id = IPP_GET_JOBS;
760 request->request.op.request_id = 1;
762 language = cupsLangDefault();
764 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
765 "attributes-charset", NULL, cupsLangEncoding(language));
767 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
768 "attributes-natural-language", NULL, language->language);
770 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
771 "requested-attributes",
772 (sizeof(jattrs) / sizeof(jattrs[0])),
773 NULL, jattrs);
775 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
776 "printer-uri", NULL, uri);
779 * Do the request and get back a response...
782 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
783 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
784 ippErrorString(cupsLastError())));
785 goto out;
788 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
789 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
790 ippErrorString(response->request.status.status_code)));
791 goto out;
795 * Process the jobs...
798 qcount = 0;
799 qalloc = 0;
800 queue = NULL;
802 for (attr = response->attrs; attr != NULL; attr = attr->next) {
804 * Skip leading attributes until we hit a job...
807 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
808 attr = attr->next;
810 if (attr == NULL)
811 break;
814 * Allocate memory as needed...
816 if (qcount >= qalloc) {
817 qalloc += 16;
819 queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
821 if (queue == NULL) {
822 DEBUG(0,("cups_queue_get: Not enough memory!"));
823 qcount = 0;
824 goto out;
828 temp = queue + qcount;
829 memset(temp, 0, sizeof(print_queue_struct));
832 * Pull the needed attributes from this job...
835 job_id = 0;
836 job_priority = 50;
837 job_status = IPP_JOB_PENDING;
838 job_time = 0;
839 job_k_octets = 0;
840 user_name = NULL;
841 job_name = NULL;
843 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
844 if (attr->name == NULL) {
845 attr = attr->next;
846 break;
849 if (strcmp(attr->name, "job-id") == 0 &&
850 attr->value_tag == IPP_TAG_INTEGER)
851 job_id = attr->values[0].integer;
853 if (strcmp(attr->name, "job-k-octets") == 0 &&
854 attr->value_tag == IPP_TAG_INTEGER)
855 job_k_octets = attr->values[0].integer;
857 if (strcmp(attr->name, "job-priority") == 0 &&
858 attr->value_tag == IPP_TAG_INTEGER)
859 job_priority = attr->values[0].integer;
861 if (strcmp(attr->name, "job-state") == 0 &&
862 attr->value_tag == IPP_TAG_ENUM)
863 job_status = (ipp_jstate_t)(attr->values[0].integer);
865 if (strcmp(attr->name, "time-at-creation") == 0 &&
866 attr->value_tag == IPP_TAG_INTEGER)
867 job_time = attr->values[0].integer;
869 if (strcmp(attr->name, "job-name") == 0 &&
870 attr->value_tag == IPP_TAG_NAME)
871 job_name = attr->values[0].string.text;
873 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
874 attr->value_tag == IPP_TAG_NAME)
875 user_name = attr->values[0].string.text;
877 attr = attr->next;
881 * See if we have everything needed...
884 if (user_name == NULL || job_name == NULL || job_id == 0) {
885 if (attr == NULL)
886 break;
887 else
888 continue;
891 temp->job = job_id;
892 temp->size = job_k_octets * 1024;
893 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
894 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
895 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
896 LPQ_PRINTING;
897 temp->priority = job_priority;
898 temp->time = job_time;
899 strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
900 strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);
902 qcount ++;
904 if (attr == NULL)
905 break;
908 ippDelete(response);
909 response = NULL;
912 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
913 * following attributes:
915 * attributes-charset
916 * attributes-natural-language
917 * requested-attributes
918 * printer-uri
921 request = ippNew();
923 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
924 request->request.op.request_id = 1;
926 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
927 "attributes-charset", NULL, cupsLangEncoding(language));
929 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
930 "attributes-natural-language", NULL, language->language);
932 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
933 "requested-attributes",
934 (sizeof(pattrs) / sizeof(pattrs[0])),
935 NULL, pattrs);
937 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
938 "printer-uri", NULL, uri);
941 * Do the request and get back a response...
944 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
945 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
946 ippErrorString(cupsLastError())));
947 *q = queue;
948 goto out;
951 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
952 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
953 ippErrorString(response->request.status.status_code)));
954 *q = queue;
955 goto out;
959 * Get the current printer status and convert it to the SAMBA values.
962 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
963 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
964 status->status = LPSTAT_STOPPED;
965 else
966 status->status = LPSTAT_OK;
969 if ((attr = ippFindAttribute(response, "printer-state-message",
970 IPP_TAG_TEXT)) != NULL)
971 fstrcpy(status->message, attr->values[0].string.text);
974 * Return the job queue...
977 *q = queue;
979 out:
980 if (response)
981 ippDelete(response);
983 if (language)
984 cupsLangFree(language);
986 if (http)
987 httpClose(http);
989 return qcount;
994 * 'cups_queue_pause()' - Pause a print queue.
997 static int cups_queue_pause(int snum)
999 extern userdom_struct current_user_info;
1000 int ret = 1; /* Return value */
1001 http_t *http = NULL; /* HTTP connection to server */
1002 ipp_t *request = NULL, /* IPP Request */
1003 *response = NULL; /* IPP Response */
1004 cups_lang_t *language = NULL; /* Default language */
1005 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1008 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1011 * Make sure we don't ask for passwords...
1014 cupsSetPasswordCB(cups_passwd_cb);
1017 * Try to connect to the server...
1020 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
1021 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1022 cups_server(), strerror(errno)));
1023 goto out;
1027 * Build an IPP_PAUSE_PRINTER request, which requires the following
1028 * attributes:
1030 * attributes-charset
1031 * attributes-natural-language
1032 * printer-uri
1033 * requesting-user-name
1036 request = ippNew();
1038 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1039 request->request.op.request_id = 1;
1041 language = cupsLangDefault();
1043 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1044 "attributes-charset", NULL, cupsLangEncoding(language));
1046 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1047 "attributes-natural-language", NULL, language->language);
1049 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1050 PRINTERNAME(snum));
1052 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1054 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1055 NULL, current_user_info.unix_name);
1058 * Do the request and get back a response...
1061 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1062 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1063 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1064 ippErrorString(cupsLastError())));
1065 } else {
1066 ret = 0;
1068 } else {
1069 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1070 ippErrorString(cupsLastError())));
1073 out:
1074 if (response)
1075 ippDelete(response);
1077 if (language)
1078 cupsLangFree(language);
1080 if (http)
1081 httpClose(http);
1083 return ret;
1088 * 'cups_queue_resume()' - Restart a print queue.
1091 static int cups_queue_resume(int snum)
1093 extern userdom_struct current_user_info;
1094 int ret = 1; /* Return value */
1095 http_t *http = NULL; /* HTTP connection to server */
1096 ipp_t *request = NULL, /* IPP Request */
1097 *response = NULL; /* IPP Response */
1098 cups_lang_t *language = NULL; /* Default language */
1099 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1102 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1105 * Make sure we don't ask for passwords...
1108 cupsSetPasswordCB(cups_passwd_cb);
1111 * Try to connect to the server...
1114 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
1115 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1116 cups_server(), strerror(errno)));
1117 goto out;
1121 * Build an IPP_RESUME_PRINTER request, which requires the following
1122 * attributes:
1124 * attributes-charset
1125 * attributes-natural-language
1126 * printer-uri
1127 * requesting-user-name
1130 request = ippNew();
1132 request->request.op.operation_id = IPP_RESUME_PRINTER;
1133 request->request.op.request_id = 1;
1135 language = cupsLangDefault();
1137 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1138 "attributes-charset", NULL, cupsLangEncoding(language));
1140 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1141 "attributes-natural-language", NULL, language->language);
1143 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1144 PRINTERNAME(snum));
1146 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1148 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1149 NULL, current_user_info.unix_name);
1152 * Do the request and get back a response...
1155 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1156 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1157 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1158 ippErrorString(cupsLastError())));
1159 } else {
1160 ret = 0;
1162 } else {
1163 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1164 ippErrorString(cupsLastError())));
1167 out:
1168 if (response)
1169 ippDelete(response);
1171 if (language)
1172 cupsLangFree(language);
1174 if (http)
1175 httpClose(http);
1177 return ret;
1180 /*******************************************************************
1181 * CUPS printing interface definitions...
1182 ******************************************************************/
1184 struct printif cups_printif =
1186 PRINT_CUPS,
1187 cups_queue_get,
1188 cups_queue_pause,
1189 cups_queue_resume,
1190 cups_job_delete,
1191 cups_job_pause,
1192 cups_job_resume,
1193 cups_job_submit,
1196 #else
1197 /* this keeps fussy compilers happy */
1198 void print_cups_dummy(void) {}
1199 #endif /* HAVE_CUPS */