CUPS patch to log client name
[Samba.git] / source / printing / print_cups.c
blobc283937556653bf2bed77c14d941d042cc125651
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 "printing.h"
23 #ifdef HAVE_CUPS
24 #include <cups/cups.h>
25 #include <cups/language.h>
29 * CUPS printing interface definitions...
32 static int cups_job_delete(int snum, struct printjob *pjob);
33 static int cups_job_pause(int snum, struct printjob *pjob);
34 static int cups_job_resume(int snum, struct printjob *pjob);
35 static int cups_job_submit(int snum, struct printjob *pjob);
36 static int cups_queue_get(int snum, print_queue_struct **q,
37 print_status_struct *status);
38 static int cups_queue_pause(int snum);
39 static int cups_queue_resume(int snum);
42 struct printif cups_printif =
44 cups_queue_get,
45 cups_queue_pause,
46 cups_queue_resume,
47 cups_job_delete,
48 cups_job_pause,
49 cups_job_resume,
50 cups_job_submit,
54 * 'cups_passwd_cb()' - The CUPS password callback...
57 static const char * /* O - Password or NULL */
58 cups_passwd_cb(const char *prompt) /* I - Prompt */
61 * Always return NULL to indicate that no password is available...
64 return (NULL);
69 * 'cups_printer_fn()' - Call a function for every printer known to the
70 * system.
73 void cups_printer_fn(void (*fn)(char *, char *))
75 /* I - Function to call */
76 http_t *http; /* HTTP connection to server */
77 ipp_t *request, /* IPP Request */
78 *response; /* IPP Response */
79 ipp_attribute_t *attr; /* Current attribute */
80 cups_lang_t *language; /* Default language */
81 char *name, /* printer-name attribute */
82 *make_model, /* printer-make-and-model attribute */
83 *info; /* printer-info attribute */
84 static const char *requested[] =/* Requested attributes */
86 "printer-name",
87 "printer-make-and-model",
88 "printer-info"
89 };
92 DEBUG(5,("cups_printer_fn(%p)\n", fn));
95 * Make sure we don't ask for passwords...
98 cupsSetPasswordCB(cups_passwd_cb);
101 * Try to connect to the server...
104 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
106 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
107 cupsServer(), strerror(errno)));
108 return;
112 * Build a CUPS_GET_PRINTERS request, which requires the following
113 * attributes:
115 * attributes-charset
116 * attributes-natural-language
117 * requested-attributes
120 request = ippNew();
122 request->request.op.operation_id = CUPS_GET_PRINTERS;
123 request->request.op.request_id = 1;
125 language = cupsLangDefault();
127 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
128 "attributes-charset", NULL, cupsLangEncoding(language));
130 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
131 "attributes-natural-language", NULL, language->language);
133 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
134 "requested-attributes",
135 (sizeof(requested) / sizeof(requested[0])),
136 NULL, requested);
139 * Do the request and get back a response...
142 if ((response = cupsDoRequest(http, request, "/")) == NULL)
144 DEBUG(0,("Unable to get printer list - %s\n",
145 ippErrorString(cupsLastError())));
146 httpClose(http);
147 return;
150 for (attr = response->attrs; attr != NULL;)
153 * Skip leading attributes until we hit a printer...
156 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
157 attr = attr->next;
159 if (attr == NULL)
160 break;
163 * Pull the needed attributes from this printer...
166 name = NULL;
167 make_model = NULL;
168 info = NULL;
170 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
172 if (strcmp(attr->name, "printer-name") == 0 &&
173 attr->value_tag == IPP_TAG_NAME)
174 name = attr->values[0].string.text;
176 if (strcmp(attr->name, "printer-make-and-model") == 0 &&
177 attr->value_tag == IPP_TAG_TEXT)
178 make_model = attr->values[0].string.text;
180 if (strcmp(attr->name, "printer-info") == 0 &&
181 attr->value_tag == IPP_TAG_TEXT)
182 info = attr->values[0].string.text;
184 attr = attr->next;
188 * See if we have everything needed...
191 if (name == NULL)
192 break;
194 if (info == NULL || !info[0])
195 (*fn)(name, make_model);
196 else
197 (*fn)(name, info);
202 ippDelete(response);
206 * Build a CUPS_GET_CLASSES request, which requires the following
207 * attributes:
209 * attributes-charset
210 * attributes-natural-language
211 * requested-attributes
214 request = ippNew();
216 request->request.op.operation_id = CUPS_GET_CLASSES;
217 request->request.op.request_id = 1;
219 language = cupsLangDefault();
221 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
222 "attributes-charset", NULL, cupsLangEncoding(language));
224 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
225 "attributes-natural-language", NULL, language->language);
227 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
228 "requested-attributes",
229 (sizeof(requested) / sizeof(requested[0])),
230 NULL, requested);
233 * Do the request and get back a response...
236 if ((response = cupsDoRequest(http, request, "/")) == NULL)
238 DEBUG(0,("Unable to get printer list - %s\n",
239 ippErrorString(cupsLastError())));
240 httpClose(http);
241 return;
244 for (attr = response->attrs; attr != NULL;)
247 * Skip leading attributes until we hit a printer...
250 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
251 attr = attr->next;
253 if (attr == NULL)
254 break;
257 * Pull the needed attributes from this printer...
260 name = NULL;
261 make_model = NULL;
262 info = NULL;
264 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
266 if (strcmp(attr->name, "printer-name") == 0 &&
267 attr->value_tag == IPP_TAG_NAME)
268 name = attr->values[0].string.text;
270 if (strcmp(attr->name, "printer-make-and-model") == 0 &&
271 attr->value_tag == IPP_TAG_TEXT)
272 make_model = attr->values[0].string.text;
274 if (strcmp(attr->name, "printer-info") == 0 &&
275 attr->value_tag == IPP_TAG_TEXT)
276 info = attr->values[0].string.text;
278 attr = attr->next;
282 * See if we have everything needed...
285 if (name == NULL)
286 break;
288 if (info == NULL || !info[0])
289 (*fn)(name, make_model);
290 else
291 (*fn)(name, info);
296 ippDelete(response);
299 * Close the connection to the server...
302 httpClose(http);
307 * 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok()
308 * for CUPS.
309 * O - 1 if printer name OK
310 * I - Name of printer
312 int cups_printername_ok(const char *name)
314 http_t *http; /* HTTP connection to server */
315 ipp_t *request, /* IPP Request */
316 *response; /* IPP Response */
317 cups_lang_t *language; /* Default language */
318 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
321 DEBUG(5,("cups_printername_ok(\"%s\")\n", name));
324 * Make sure we don't ask for passwords...
327 cupsSetPasswordCB(cups_passwd_cb);
330 * Try to connect to the server...
333 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
335 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
336 cupsServer(), strerror(errno)));
337 return (0);
341 * Build an IPP_GET_PRINTER_ATTRS request, which requires the following
342 * attributes:
344 * attributes-charset
345 * attributes-natural-language
346 * requested-attributes
347 * printer-uri
350 request = ippNew();
352 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
353 request->request.op.request_id = 1;
355 language = cupsLangDefault();
357 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
358 "attributes-charset", NULL, cupsLangEncoding(language));
360 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
361 "attributes-natural-language", NULL, language->language);
363 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
364 "requested-attributes", NULL, "printer-uri");
366 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", name);
368 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
369 "printer-uri", NULL, uri);
372 * Do the request and get back a response...
375 if ((response = cupsDoRequest(http, request, "/")) == NULL)
377 DEBUG(0,("Unable to get printer status for %s - %s\n", name,
378 ippErrorString(cupsLastError())));
379 httpClose(http);
380 return (0);
383 httpClose(http);
385 if (response->request.status.status_code >= IPP_OK_CONFLICT)
387 DEBUG(0,("Unable to get printer status for %s - %s\n", name,
388 ippErrorString(response->request.status.status_code)));
389 ippDelete(response);
390 return (0);
392 else
394 ippDelete(response);
395 return (1);
401 * 'cups_job_delete()' - Delete a job.
404 static int
405 cups_job_delete(int snum, struct printjob *pjob)
407 int ret; /* Return value */
408 http_t *http; /* HTTP connection to server */
409 ipp_t *request, /* IPP Request */
410 *response; /* IPP Response */
411 cups_lang_t *language; /* Default language */
412 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
415 DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
418 * Make sure we don't ask for passwords...
421 cupsSetPasswordCB(cups_passwd_cb);
424 * Try to connect to the server...
427 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
429 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
430 cupsServer(), strerror(errno)));
431 return (1);
435 * Build an IPP_CANCEL_JOB request, which requires the following
436 * attributes:
438 * attributes-charset
439 * attributes-natural-language
440 * job-uri
441 * requesting-user-name
444 request = ippNew();
446 request->request.op.operation_id = IPP_CANCEL_JOB;
447 request->request.op.request_id = 1;
449 language = cupsLangDefault();
451 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
452 "attributes-charset", NULL, cupsLangEncoding(language));
454 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
455 "attributes-natural-language", NULL, language->language);
457 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
459 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
461 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
462 NULL, pjob->user);
465 * Do the request and get back a response...
468 ret = 1;
470 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
472 if (response->request.status.status_code >= IPP_OK_CONFLICT)
473 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
474 ippErrorString(cupsLastError())));
475 else
476 ret = 0;
478 ippDelete(response);
480 else
481 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
482 ippErrorString(cupsLastError())));
484 httpClose(http);
486 return (ret);
491 * 'cups_job_pause()' - Pause a job.
494 static int
495 cups_job_pause(int snum, struct printjob *pjob)
497 int ret; /* Return value */
498 http_t *http; /* HTTP connection to server */
499 ipp_t *request, /* IPP Request */
500 *response; /* IPP Response */
501 cups_lang_t *language; /* Default language */
502 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
505 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
508 * Make sure we don't ask for passwords...
511 cupsSetPasswordCB(cups_passwd_cb);
514 * Try to connect to the server...
517 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
519 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
520 cupsServer(), strerror(errno)));
521 return (1);
525 * Build an IPP_HOLD_JOB request, which requires the following
526 * attributes:
528 * attributes-charset
529 * attributes-natural-language
530 * job-uri
531 * requesting-user-name
534 request = ippNew();
536 request->request.op.operation_id = IPP_HOLD_JOB;
537 request->request.op.request_id = 1;
539 language = cupsLangDefault();
541 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
542 "attributes-charset", NULL, cupsLangEncoding(language));
544 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
545 "attributes-natural-language", NULL, language->language);
547 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
549 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
551 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
552 NULL, pjob->user);
555 * Do the request and get back a response...
558 ret = 1;
560 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
562 if (response->request.status.status_code >= IPP_OK_CONFLICT)
563 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
564 ippErrorString(cupsLastError())));
565 else
566 ret = 0;
568 ippDelete(response);
570 else
571 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
572 ippErrorString(cupsLastError())));
574 httpClose(http);
576 return (ret);
581 * 'cups_job_resume()' - Resume a paused job.
584 static int
585 cups_job_resume(int snum, struct printjob *pjob)
587 int ret; /* Return value */
588 http_t *http; /* HTTP connection to server */
589 ipp_t *request, /* IPP Request */
590 *response; /* IPP Response */
591 cups_lang_t *language; /* Default language */
592 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
595 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
598 * Make sure we don't ask for passwords...
601 cupsSetPasswordCB(cups_passwd_cb);
604 * Try to connect to the server...
607 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
609 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
610 cupsServer(), strerror(errno)));
611 return (1);
615 * Build an IPP_RELEASE_JOB request, which requires the following
616 * attributes:
618 * attributes-charset
619 * attributes-natural-language
620 * job-uri
621 * requesting-user-name
624 request = ippNew();
626 request->request.op.operation_id = IPP_RELEASE_JOB;
627 request->request.op.request_id = 1;
629 language = cupsLangDefault();
631 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
632 "attributes-charset", NULL, cupsLangEncoding(language));
634 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
635 "attributes-natural-language", NULL, language->language);
637 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
639 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
641 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
642 NULL, pjob->user);
645 * Do the request and get back a response...
648 ret = 1;
650 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
652 if (response->request.status.status_code >= IPP_OK_CONFLICT)
653 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
654 ippErrorString(cupsLastError())));
655 else
656 ret = 0;
658 ippDelete(response);
660 else
661 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
662 ippErrorString(cupsLastError())));
664 httpClose(http);
666 return (ret);
671 * 'cups_job_submit()' - Submit a job for printing.
674 static int
675 cups_job_submit(int snum, struct printjob *pjob)
677 int ret; /* Return value */
678 http_t *http; /* HTTP connection to server */
679 ipp_t *request, /* IPP Request */
680 *response; /* IPP Response */
681 cups_lang_t *language; /* Default language */
682 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
685 DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
688 * Make sure we don't ask for passwords...
691 cupsSetPasswordCB(cups_passwd_cb);
694 * Try to connect to the server...
697 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
699 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
700 cupsServer(), strerror(errno)));
701 return (1);
705 * Build an IPP_PRINT_JOB request, which requires the following
706 * attributes:
708 * attributes-charset
709 * attributes-natural-language
710 * printer-uri
711 * requesting-user-name
712 * [document-data]
715 request = ippNew();
717 request->request.op.operation_id = IPP_PRINT_JOB;
718 request->request.op.request_id = 1;
720 language = cupsLangDefault();
722 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
723 "attributes-charset", NULL, cupsLangEncoding(language));
725 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
726 "attributes-natural-language", NULL, language->language);
728 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
729 PRINTERNAME(snum));
731 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
732 "printer-uri", NULL, uri);
734 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
735 NULL, pjob->user);
737 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
738 "job-originating-host-name", NULL,
739 get_remote_machine_name());
741 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
742 pjob->jobname);
745 * Do the request and get back a response...
748 slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
750 ret = 1;
751 if ((response = cupsDoFileRequest(http, request, uri,
752 pjob->filename)) != NULL)
754 if (response->request.status.status_code >= IPP_OK_CONFLICT)
755 DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
756 ippErrorString(cupsLastError())));
757 else
758 ret = 0;
760 ippDelete(response);
762 else
763 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
764 ippErrorString(cupsLastError())));
766 httpClose(http);
768 if ( ret == 0 )
769 unlink(pjob->filename);
770 /* else print_job_end will do it for us */
772 return (ret);
777 * 'cups_queue_get()' - Get all the jobs in the print queue.
780 static int
781 cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status)
783 http_t *http; /* HTTP connection to server */
784 ipp_t *request, /* IPP Request */
785 *response; /* IPP Response */
786 ipp_attribute_t *attr; /* Current attribute */
787 cups_lang_t *language; /* Default language */
788 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
789 int qcount, /* Number of active queue entries */
790 qalloc; /* Number of queue entries allocated */
791 print_queue_struct *queue, /* Queue entries */
792 *temp; /* Temporary pointer for queue */
793 const char *user_name, /* job-originating-user-name attribute */
794 *job_name; /* job-name attribute */
795 int job_id; /* job-id attribute */
796 int job_k_octets; /* job-k-octets attribute */
797 time_t job_time; /* time-at-creation attribute */
798 ipp_jstate_t job_status; /* job-status attribute */
799 int job_priority; /* job-priority attribute */
800 static const char *jattrs[] = /* Requested job attributes */
802 "job-id",
803 "job-k-octets",
804 "job-name",
805 "job-originating-user-name",
806 "job-priority",
807 "job-state",
808 "time-at-creation",
810 static const char *pattrs[] = /* Requested printer attributes */
812 "printer-state",
813 "printer-state-message"
817 DEBUG(5,("cups_queue_get(%d, %p, %p)\n", snum, q, status));
820 * Make sure we don't ask for passwords...
823 cupsSetPasswordCB(cups_passwd_cb);
826 * Try to connect to the server...
829 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
831 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
832 cupsServer(), strerror(errno)));
833 return (0);
837 * Generate the printer URI...
840 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
841 PRINTERNAME(snum));
844 * Build an IPP_GET_JOBS request, which requires the following
845 * attributes:
847 * attributes-charset
848 * attributes-natural-language
849 * requested-attributes
850 * printer-uri
853 request = ippNew();
855 request->request.op.operation_id = IPP_GET_JOBS;
856 request->request.op.request_id = 1;
858 language = cupsLangDefault();
860 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
861 "attributes-charset", NULL, cupsLangEncoding(language));
863 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
864 "attributes-natural-language", NULL, language->language);
866 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
867 "requested-attributes",
868 (sizeof(jattrs) / sizeof(jattrs[0])),
869 NULL, jattrs);
871 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
872 "printer-uri", NULL, uri);
875 * Do the request and get back a response...
878 if ((response = cupsDoRequest(http, request, "/")) == NULL)
880 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
881 ippErrorString(cupsLastError())));
882 httpClose(http);
883 return (0);
886 if (response->request.status.status_code >= IPP_OK_CONFLICT)
888 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
889 ippErrorString(response->request.status.status_code)));
890 ippDelete(response);
891 httpClose(http);
893 return (0);
897 * Process the jobs...
900 qcount = 0;
901 qalloc = 0;
902 queue = NULL;
904 for (attr = response->attrs; attr != NULL; attr = attr->next)
907 * Skip leading attributes until we hit a job...
910 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
911 attr = attr->next;
913 if (attr == NULL)
914 break;
917 * Allocate memory as needed...
919 if (qcount >= qalloc)
921 qalloc += 16;
923 temp = Realloc(queue, sizeof(print_queue_struct) * qalloc);
925 if (temp == NULL)
927 DEBUG(0,("cups_queue_get: Not enough memory!"));
928 ippDelete(response);
929 httpClose(http);
931 SAFE_FREE(queue);
932 return (0);
935 queue = temp;
938 temp = queue + qcount;
939 memset(temp, 0, sizeof(print_queue_struct));
942 * Pull the needed attributes from this job...
945 job_id = 0;
946 job_priority = 50;
947 job_status = IPP_JOB_PENDING;
948 job_time = 0;
949 job_k_octets = 0;
950 user_name = NULL;
951 job_name = NULL;
953 while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
955 if (attr->name == NULL)
957 attr = attr->next;
958 break;
961 if (strcmp(attr->name, "job-id") == 0 &&
962 attr->value_tag == IPP_TAG_INTEGER)
963 job_id = attr->values[0].integer;
965 if (strcmp(attr->name, "job-k-octets") == 0 &&
966 attr->value_tag == IPP_TAG_INTEGER)
967 job_k_octets = attr->values[0].integer;
969 if (strcmp(attr->name, "job-priority") == 0 &&
970 attr->value_tag == IPP_TAG_INTEGER)
971 job_priority = attr->values[0].integer;
973 if (strcmp(attr->name, "job-state") == 0 &&
974 attr->value_tag == IPP_TAG_ENUM)
975 job_status = (ipp_jstate_t)(attr->values[0].integer);
977 if (strcmp(attr->name, "time-at-creation") == 0 &&
978 attr->value_tag == IPP_TAG_INTEGER)
979 job_time = attr->values[0].integer;
981 if (strcmp(attr->name, "job-name") == 0 &&
982 attr->value_tag == IPP_TAG_NAME)
983 job_name = attr->values[0].string.text;
985 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
986 attr->value_tag == IPP_TAG_NAME)
987 user_name = attr->values[0].string.text;
989 attr = attr->next;
993 * See if we have everything needed...
996 if (user_name == NULL || job_name == NULL || job_id == 0)
998 if (attr == NULL)
999 break;
1000 else
1001 continue;
1004 temp->job = job_id;
1005 temp->size = job_k_octets * 1024;
1006 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
1007 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
1008 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
1009 LPQ_PRINTING;
1010 temp->priority = job_priority;
1011 temp->time = job_time;
1012 strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
1013 strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);
1015 qcount ++;
1017 if (attr == NULL)
1018 break;
1021 ippDelete(response);
1024 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
1025 * following attributes:
1027 * attributes-charset
1028 * attributes-natural-language
1029 * requested-attributes
1030 * printer-uri
1033 request = ippNew();
1035 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1036 request->request.op.request_id = 1;
1038 language = cupsLangDefault();
1040 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1041 "attributes-charset", NULL, cupsLangEncoding(language));
1043 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1044 "attributes-natural-language", NULL, language->language);
1046 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1047 "requested-attributes",
1048 (sizeof(pattrs) / sizeof(pattrs[0])),
1049 NULL, pattrs);
1051 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1052 "printer-uri", NULL, uri);
1055 * Do the request and get back a response...
1058 if ((response = cupsDoRequest(http, request, "/")) == NULL)
1060 DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
1061 ippErrorString(cupsLastError())));
1062 httpClose(http);
1063 *q = queue;
1064 return (qcount);
1067 if (response->request.status.status_code >= IPP_OK_CONFLICT)
1069 DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
1070 ippErrorString(response->request.status.status_code)));
1071 ippDelete(response);
1072 httpClose(http);
1073 *q = queue;
1074 return (qcount);
1078 * Get the current printer status and convert it to the SAMBA values.
1081 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
1083 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
1084 status->status = LPSTAT_STOPPED;
1085 else
1086 status->status = LPSTAT_OK;
1089 if ((attr = ippFindAttribute(response, "printer-state-message",
1090 IPP_TAG_TEXT)) != NULL)
1091 fstrcpy(status->message, attr->values[0].string.text);
1093 ippDelete(response);
1096 * Return the job queue...
1099 httpClose(http);
1101 *q = queue;
1102 return (qcount);
1107 * 'cups_queue_pause()' - Pause a print queue.
1110 static int
1111 cups_queue_pause(int snum)
1113 extern userdom_struct current_user_info;
1114 int ret; /* Return value */
1115 http_t *http; /* HTTP connection to server */
1116 ipp_t *request, /* IPP Request */
1117 *response; /* IPP Response */
1118 cups_lang_t *language; /* Default language */
1119 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1122 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1125 * Make sure we don't ask for passwords...
1128 cupsSetPasswordCB(cups_passwd_cb);
1131 * Try to connect to the server...
1134 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
1136 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1137 cupsServer(), strerror(errno)));
1138 return (1);
1142 * Build an IPP_PAUSE_PRINTER request, which requires the following
1143 * attributes:
1145 * attributes-charset
1146 * attributes-natural-language
1147 * printer-uri
1148 * requesting-user-name
1151 request = ippNew();
1153 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1154 request->request.op.request_id = 1;
1156 language = cupsLangDefault();
1158 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1159 "attributes-charset", NULL, cupsLangEncoding(language));
1161 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1162 "attributes-natural-language", NULL, language->language);
1164 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1165 PRINTERNAME(snum));
1167 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1169 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1170 NULL, current_user_info.unix_name);
1173 * Do the request and get back a response...
1176 ret = 1;
1178 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
1180 if (response->request.status.status_code >= IPP_OK_CONFLICT)
1181 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1182 ippErrorString(cupsLastError())));
1183 else
1184 ret = 0;
1186 ippDelete(response);
1188 else
1189 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1190 ippErrorString(cupsLastError())));
1192 httpClose(http);
1194 return (ret);
1199 * 'cups_queue_resume()' - Restart a print queue.
1202 static int
1203 cups_queue_resume(int snum)
1205 extern userdom_struct current_user_info;
1206 int ret; /* Return value */
1207 http_t *http; /* HTTP connection to server */
1208 ipp_t *request, /* IPP Request */
1209 *response; /* IPP Response */
1210 cups_lang_t *language; /* Default language */
1211 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1214 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1217 * Make sure we don't ask for passwords...
1220 cupsSetPasswordCB(cups_passwd_cb);
1223 * Try to connect to the server...
1226 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
1228 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1229 cupsServer(), strerror(errno)));
1230 return (1);
1234 * Build an IPP_RESUME_PRINTER request, which requires the following
1235 * attributes:
1237 * attributes-charset
1238 * attributes-natural-language
1239 * printer-uri
1240 * requesting-user-name
1243 request = ippNew();
1245 request->request.op.operation_id = IPP_RESUME_PRINTER;
1246 request->request.op.request_id = 1;
1248 language = cupsLangDefault();
1250 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1251 "attributes-charset", NULL, cupsLangEncoding(language));
1253 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1254 "attributes-natural-language", NULL, language->language);
1256 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1257 PRINTERNAME(snum));
1259 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1261 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1262 NULL, current_user_info.unix_name);
1265 * Do the request and get back a response...
1268 ret = 1;
1270 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
1272 if (response->request.status.status_code >= IPP_OK_CONFLICT)
1273 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1274 ippErrorString(cupsLastError())));
1275 else
1276 ret = 0;
1278 ippDelete(response);
1280 else
1281 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1282 ippErrorString(cupsLastError())));
1284 httpClose(http);
1286 return (ret);
1290 #else
1291 /* this keeps fussy compilers happy */
1292 void print_cups_dummy(void) {}
1293 #endif /* HAVE_CUPS */