]> git.ipfire.org Git - thirdparty/cups.git/blob - backend/lpd.c
41f14913e7313562dd0ed835f71c82fe1ffc01c5
[thirdparty/cups.git] / backend / lpd.c
1 /*
2 * "$Id$"
3 *
4 * Line Printer Daemon backend for CUPS.
5 *
6 * Copyright 2007-2016 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * "LICENSE" which should have been included with this file. If this
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 */
17
18 /*
19 * Include necessary headers.
20 */
21
22 #include <cups/http-private.h>
23 #include "backend-private.h"
24 #include <stdarg.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <stdio.h>
28
29 #ifdef WIN32
30 # include <winsock.h>
31 #else
32 # include <sys/socket.h>
33 # include <netinet/in.h>
34 # include <arpa/inet.h>
35 # include <netdb.h>
36 #endif /* WIN32 */
37 #ifdef __APPLE__
38 # include <CoreFoundation/CFNumber.h>
39 # include <CoreFoundation/CFPreferences.h>
40 #endif /* __APPLE__ */
41
42
43 /*
44 * Globals...
45 */
46
47 static char tmpfilename[1024] = ""; /* Temporary spool file name */
48 static int abort_job = 0; /* Non-zero if we get SIGTERM */
49
50
51 /*
52 * Print mode...
53 */
54
55 #define MODE_STANDARD 0 /* Queue a copy */
56 #define MODE_STREAM 1 /* Stream a copy */
57
58
59 /*
60 * The order for control and data files in LPD requests...
61 */
62
63 #define ORDER_CONTROL_DATA 0 /* Control file first, then data */
64 #define ORDER_DATA_CONTROL 1 /* Data file first, then control */
65
66
67 /*
68 * What to reserve...
69 */
70
71 #define RESERVE_NONE 0 /* Don't reserve a priviledged port */
72 #define RESERVE_RFC1179 1 /* Reserve port 721-731 */
73 #define RESERVE_ANY 2 /* Reserve port 1-1023 */
74
75
76 /*
77 * Local functions...
78 */
79
80 static int cups_rresvport(int *port, int family);
81 static int lpd_command(int lpd_fd, char *format, ...);
82 static int lpd_queue(const char *hostname, http_addrlist_t *addrlist,
83 const char *printer, int print_fd, int snmp_fd,
84 int mode, const char *user, const char *title,
85 int copies, int banner, int format, int order,
86 int reserve, int manual_copies, int timeout,
87 int contimeout, const char *orighost);
88 static ssize_t lpd_write(int lpd_fd, char *buffer, size_t length);
89 static void sigterm_handler(int sig);
90
91
92 /*
93 * 'main()' - Send a file to the printer or server.
94 *
95 * Usage:
96 *
97 * printer-uri job-id user title copies options [file]
98 */
99
100 int /* O - Exit status */
101 main(int argc, /* I - Number of command-line arguments (6 or 7) */
102 char *argv[]) /* I - Command-line arguments */
103 {
104 const char *device_uri; /* Device URI */
105 char scheme[255], /* Scheme in URI */
106 hostname[1024], /* Hostname */
107 username[255], /* Username info */
108 resource[1024], /* Resource info (printer name) */
109 *options, /* Pointer to options */
110 *name, /* Name of option */
111 *value, /* Value of option */
112 sep, /* Separator character */
113 *filename, /* File to print */
114 title[256]; /* Title string */
115 int port; /* Port number */
116 char portname[256]; /* Port name (string) */
117 http_addrlist_t *addrlist; /* List of addresses for printer */
118 int snmp_enabled = 1; /* Is SNMP enabled? */
119 int snmp_fd; /* SNMP socket */
120 int fd; /* Print file */
121 int status; /* Status of LPD job */
122 int mode; /* Print mode */
123 int banner; /* Print banner page? */
124 int format; /* Print format */
125 int order; /* Order of control/data files */
126 int reserve; /* Reserve priviledged port? */
127 int sanitize_title; /* Sanitize title string? */
128 int manual_copies, /* Do manual copies? */
129 timeout, /* Timeout */
130 contimeout, /* Connection timeout */
131 copies; /* Number of copies */
132 ssize_t bytes = 0; /* Initial bytes read */
133 char buffer[16384]; /* Initial print buffer */
134 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
135 struct sigaction action; /* Actions for POSIX signals */
136 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
137 int num_jobopts; /* Number of job options */
138 cups_option_t *jobopts = NULL; /* Job options */
139
140
141 /*
142 * Make sure status messages are not buffered...
143 */
144
145 setbuf(stderr, NULL);
146
147 /*
148 * Ignore SIGPIPE and catch SIGTERM signals...
149 */
150
151 #ifdef HAVE_SIGSET
152 sigset(SIGPIPE, SIG_IGN);
153 sigset(SIGTERM, sigterm_handler);
154 #elif defined(HAVE_SIGACTION)
155 memset(&action, 0, sizeof(action));
156 action.sa_handler = SIG_IGN;
157 sigaction(SIGPIPE, &action, NULL);
158
159 sigemptyset(&action.sa_mask);
160 sigaddset(&action.sa_mask, SIGTERM);
161 action.sa_handler = sigterm_handler;
162 sigaction(SIGTERM, &action, NULL);
163 #else
164 signal(SIGPIPE, SIG_IGN);
165 signal(SIGTERM, sigterm_handler);
166 #endif /* HAVE_SIGSET */
167
168 /*
169 * Check command-line...
170 */
171
172 if (argc == 1)
173 {
174 printf("network lpd \"Unknown\" \"%s\"\n",
175 _cupsLangString(cupsLangDefault(), _("LPD/LPR Host or Printer")));
176 return (CUPS_BACKEND_OK);
177 }
178 else if (argc < 6 || argc > 7)
179 {
180 _cupsLangPrintf(stderr,
181 _("Usage: %s job-id user title copies options [file]"),
182 argv[0]);
183 return (CUPS_BACKEND_FAILED);
184 }
185
186 num_jobopts = cupsParseOptions(argv[5], 0, &jobopts);
187
188 /*
189 * Extract the hostname and printer name from the URI...
190 */
191
192 while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
193 {
194 _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
195 sleep(10);
196
197 if (getenv("CLASS") != NULL)
198 return (CUPS_BACKEND_FAILED);
199 }
200
201 httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
202 username, sizeof(username), hostname, sizeof(hostname), &port,
203 resource, sizeof(resource));
204
205 if (!port)
206 port = 515; /* Default to port 515 */
207
208 if (!username[0])
209 {
210 /*
211 * If no username is in the device URI, then use the print job user...
212 */
213
214 strlcpy(username, argv[2], sizeof(username));
215 }
216
217 /*
218 * See if there are any options...
219 */
220
221 mode = MODE_STANDARD;
222 banner = 0;
223 format = 'l';
224 order = ORDER_CONTROL_DATA;
225 reserve = RESERVE_ANY;
226 manual_copies = 1;
227 timeout = 300;
228 contimeout = 7 * 24 * 60 * 60;
229
230 #ifdef __APPLE__
231 /*
232 * We want to pass UTF-8 characters by default, not re-map them (3071945)
233 */
234
235 sanitize_title = 0;
236 #else
237 /*
238 * Otherwise we want to re-map UTF-8 to "safe" characters by default...
239 */
240
241 sanitize_title = 1;
242 #endif /* __APPLE__ */
243
244 if ((options = strchr(resource, '?')) != NULL)
245 {
246 /*
247 * Yup, terminate the device name string and move to the first
248 * character of the options...
249 */
250
251 *options++ = '\0';
252
253 /*
254 * Parse options...
255 */
256
257 while (*options)
258 {
259 /*
260 * Get the name...
261 */
262
263 name = options;
264
265 while (*options && *options != '=' && *options != '+' && *options != '&')
266 options ++;
267
268 if ((sep = *options) != '\0')
269 *options++ = '\0';
270
271 if (sep == '=')
272 {
273 /*
274 * Get the value...
275 */
276
277 value = options;
278
279 while (*options && *options != '+' && *options != '&')
280 options ++;
281
282 if (*options)
283 *options++ = '\0';
284 }
285 else
286 value = (char *)"";
287
288 /*
289 * Process the option...
290 */
291
292 if (!_cups_strcasecmp(name, "banner"))
293 {
294 /*
295 * Set the banner...
296 */
297
298 banner = !value[0] || !_cups_strcasecmp(value, "on") ||
299 !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
300 }
301 else if (!_cups_strcasecmp(name, "format") && value[0])
302 {
303 /*
304 * Set output format...
305 */
306
307 if (strchr("cdfglnoprtv", value[0]))
308 format = value[0];
309 else
310 _cupsLangPrintFilter(stderr, "ERROR",
311 _("Unknown format character: \"%c\"."),
312 value[0]);
313 }
314 else if (!_cups_strcasecmp(name, "mode") && value[0])
315 {
316 /*
317 * Set control/data order...
318 */
319
320 if (!_cups_strcasecmp(value, "standard"))
321 mode = MODE_STANDARD;
322 else if (!_cups_strcasecmp(value, "stream"))
323 mode = MODE_STREAM;
324 else
325 _cupsLangPrintFilter(stderr, "ERROR",
326 _("Unknown print mode: \"%s\"."), value);
327 }
328 else if (!_cups_strcasecmp(name, "order") && value[0])
329 {
330 /*
331 * Set control/data order...
332 */
333
334 if (!_cups_strcasecmp(value, "control,data"))
335 order = ORDER_CONTROL_DATA;
336 else if (!_cups_strcasecmp(value, "data,control"))
337 order = ORDER_DATA_CONTROL;
338 else
339 _cupsLangPrintFilter(stderr, "ERROR",
340 _("Unknown file order: \"%s\"."), value);
341 }
342 else if (!_cups_strcasecmp(name, "reserve"))
343 {
344 /*
345 * Set port reservation mode...
346 */
347
348 if (!value[0] || !_cups_strcasecmp(value, "on") ||
349 !_cups_strcasecmp(value, "yes") ||
350 !_cups_strcasecmp(value, "true") ||
351 !_cups_strcasecmp(value, "rfc1179"))
352 reserve = RESERVE_RFC1179;
353 else if (!_cups_strcasecmp(value, "any"))
354 reserve = RESERVE_ANY;
355 else
356 reserve = RESERVE_NONE;
357 }
358 else if (!_cups_strcasecmp(name, "manual_copies"))
359 {
360 /*
361 * Set manual copies...
362 */
363
364 manual_copies = !value[0] || !_cups_strcasecmp(value, "on") ||
365 !_cups_strcasecmp(value, "yes") ||
366 !_cups_strcasecmp(value, "true");
367 }
368 else if (!_cups_strcasecmp(name, "sanitize_title"))
369 {
370 /*
371 * Set sanitize title...
372 */
373
374 sanitize_title = !value[0] || !_cups_strcasecmp(value, "on") ||
375 !_cups_strcasecmp(value, "yes") ||
376 !_cups_strcasecmp(value, "true");
377 }
378 else if (!_cups_strcasecmp(name, "snmp"))
379 {
380 /*
381 * Enable/disable SNMP stuff...
382 */
383
384 snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") ||
385 !_cups_strcasecmp(value, "yes") ||
386 !_cups_strcasecmp(value, "true");
387 }
388 else if (!_cups_strcasecmp(name, "timeout"))
389 {
390 /*
391 * Set the timeout...
392 */
393
394 if (atoi(value) > 0)
395 timeout = atoi(value);
396 }
397 else if (!_cups_strcasecmp(name, "contimeout"))
398 {
399 /*
400 * Set the connection timeout...
401 */
402
403 if (atoi(value) > 0)
404 contimeout = atoi(value);
405 }
406 }
407 }
408
409 if (mode == MODE_STREAM)
410 order = ORDER_CONTROL_DATA;
411
412 /*
413 * Find the printer...
414 */
415
416 snprintf(portname, sizeof(portname), "%d", port);
417
418 fputs("STATE: +connecting-to-device\n", stderr);
419 fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
420
421 while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
422 {
423 _cupsLangPrintFilter(stderr, "INFO",
424 _("Unable to locate printer \"%s\"."), hostname);
425 sleep(10);
426
427 if (getenv("CLASS") != NULL)
428 {
429 fputs("STATE: -connecting-to-device\n", stderr);
430 exit(CUPS_BACKEND_FAILED);
431 }
432 }
433
434 if (snmp_enabled)
435 snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
436 else
437 snmp_fd = -1;
438
439 /*
440 * Wait for data from the filter...
441 */
442
443 if (argc == 6)
444 {
445 if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
446 return (CUPS_BACKEND_OK);
447 else if (mode == MODE_STANDARD &&
448 (bytes = read(0, buffer, sizeof(buffer))) <= 0)
449 return (CUPS_BACKEND_OK);
450 }
451
452 /*
453 * If we have 7 arguments, print the file named on the command-line.
454 * Otherwise, copy stdin to a temporary file and print the temporary
455 * file.
456 */
457
458 if (argc == 6 && mode == MODE_STANDARD)
459 {
460 /*
461 * Copy stdin to a temporary file...
462 */
463
464 if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
465 {
466 perror("DEBUG: Unable to create temporary file");
467 return (CUPS_BACKEND_FAILED);
468 }
469
470 _cupsLangPrintFilter(stderr, "INFO", _("Copying print data."));
471
472 if (bytes > 0)
473 write(fd, buffer, (size_t)bytes);
474
475 backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
476 backendNetworkSideCB);
477 }
478 else if (argc == 6)
479 {
480 /*
481 * Stream from stdin...
482 */
483
484 filename = NULL;
485 fd = 0;
486 }
487 else
488 {
489 filename = argv[6];
490 fd = open(filename, O_RDONLY);
491
492 if (fd == -1)
493 {
494 _cupsLangPrintError("ERROR", _("Unable to open print file"));
495 return (CUPS_BACKEND_FAILED);
496 }
497 }
498
499 /*
500 * Sanitize the document title...
501 */
502
503 strlcpy(title, argv[3], sizeof(title));
504
505 if (sanitize_title)
506 {
507 /*
508 * Sanitize the title string so that we don't cause problems on
509 * the remote end...
510 */
511
512 char *ptr;
513
514 for (ptr = title; *ptr; ptr ++)
515 if (!isalnum(*ptr & 255) && !isspace(*ptr & 255))
516 *ptr = '_';
517 }
518
519 /*
520 * Queue the job...
521 */
522
523 if (argc > 6)
524 {
525 if (manual_copies)
526 {
527 manual_copies = atoi(argv[4]);
528 copies = 1;
529 }
530 else
531 {
532 manual_copies = 1;
533 copies = atoi(argv[4]);
534 }
535
536 status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
537 username, title, copies, banner, format, order, reserve,
538 manual_copies, timeout, contimeout,
539 cupsGetOption("job-originating-host-name", num_jobopts,
540 jobopts));
541
542 if (!status)
543 fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4]));
544 }
545 else
546 status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
547 username, title, 1, banner, format, order, reserve, 1,
548 timeout, contimeout,
549 cupsGetOption("job-originating-host-name", num_jobopts,
550 jobopts));
551
552 /*
553 * Remove the temporary file if necessary...
554 */
555
556 if (tmpfilename[0])
557 unlink(tmpfilename);
558
559 if (fd)
560 close(fd);
561
562 if (snmp_fd >= 0)
563 _cupsSNMPClose(snmp_fd);
564
565 /*
566 * Return the queue status...
567 */
568
569 return (status);
570 }
571
572
573 /*
574 * 'cups_rresvport()' - A simple implementation of rresvport_af().
575 */
576
577 static int /* O - Socket or -1 on error */
578 cups_rresvport(int *port, /* IO - Port number to bind to */
579 int family) /* I - Address family */
580 {
581 http_addr_t addr; /* Socket address */
582 int fd; /* Socket file descriptor */
583
584
585 /*
586 * Try to create an IPv4 socket...
587 */
588
589 if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
590 return (-1);
591
592 /*
593 * Initialize the address buffer...
594 */
595
596 memset(&addr, 0, sizeof(addr));
597 addr.addr.sa_family = (sa_family_t)family;
598
599 /*
600 * Try to bind the socket to a reserved port...
601 */
602
603 while (*port > 511)
604 {
605 /*
606 * Set the port number...
607 */
608
609 _httpAddrSetPort(&addr, *port);
610
611 /*
612 * Try binding the port to the socket; return if all is OK...
613 */
614
615 if (!bind(fd, (struct sockaddr *)&addr, (socklen_t)httpAddrLength(&addr)))
616 return (fd);
617
618 /*
619 * Stop if we have any error other than "address already in use"...
620 */
621
622 if (errno != EADDRINUSE)
623 {
624 httpAddrClose(NULL, fd);
625
626 return (-1);
627 }
628
629 /*
630 * Try the next port...
631 */
632
633 (*port)--;
634 }
635
636 /*
637 * Wasn't able to bind to a reserved port, so close the socket and return
638 * -1...
639 */
640
641 #ifdef WIN32
642 closesocket(fd);
643 #else
644 close(fd);
645 #endif /* WIN32 */
646
647 return (-1);
648 }
649
650
651 /*
652 * 'lpd_command()' - Send an LPR command sequence and wait for a reply.
653 */
654
655 static int /* O - Status of command */
656 lpd_command(int fd, /* I - Socket connection to LPD host */
657 char *format, /* I - printf()-style format string */
658 ...) /* I - Additional args as necessary */
659 {
660 va_list ap; /* Argument pointer */
661 char buf[1024]; /* Output buffer */
662 ssize_t bytes; /* Number of bytes to output */
663 char status; /* Status from command */
664
665
666 /*
667 * Don't try to send commands if the job has been canceled...
668 */
669
670 if (abort_job)
671 return (-1);
672
673 /*
674 * Format the string...
675 */
676
677 va_start(ap, format);
678 bytes = vsnprintf(buf, sizeof(buf), format, ap);
679 va_end(ap);
680
681 fprintf(stderr, "DEBUG: lpd_command %2.2x %s", buf[0], buf + 1);
682
683 /*
684 * Send the command...
685 */
686
687 fprintf(stderr, "DEBUG: Sending command string (" CUPS_LLFMT " bytes)...\n", CUPS_LLCAST bytes);
688
689 if (lpd_write(fd, buf, (size_t)bytes) < bytes)
690 {
691 perror("DEBUG: Unable to send LPD command");
692 return (-1);
693 }
694
695 /*
696 * Read back the status from the command and return it...
697 */
698
699 fputs("DEBUG: Reading command status...\n", stderr);
700
701 if (recv(fd, &status, 1, 0) < 1)
702 {
703 _cupsLangPrintFilter(stderr, "WARNING", _("The printer did not respond."));
704 status = (char)errno;
705 }
706
707 fprintf(stderr, "DEBUG: lpd_command returning %d\n", status);
708
709 return (status);
710 }
711
712
713 /*
714 * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
715 */
716
717 static int /* O - Zero on success, non-zero on failure */
718 lpd_queue(const char *hostname, /* I - Host to connect to */
719 http_addrlist_t *addrlist, /* I - List of host addresses */
720 const char *printer, /* I - Printer/queue name */
721 int print_fd, /* I - File to print */
722 int snmp_fd, /* I - SNMP socket */
723 int mode, /* I - Print mode */
724 const char *user, /* I - Requesting user */
725 const char *title, /* I - Job title */
726 int copies, /* I - Number of copies */
727 int banner, /* I - Print LPD banner? */
728 int format, /* I - Format specifier */
729 int order, /* I - Order of data/control files */
730 int reserve, /* I - Reserve ports? */
731 int manual_copies,/* I - Do copies by hand... */
732 int timeout, /* I - Timeout... */
733 int contimeout, /* I - Connection timeout */
734 const char *orighost) /* I - job-originating-host-name */
735 {
736 char localhost[255]; /* Local host name */
737 int error; /* Error number */
738 struct stat filestats; /* File statistics */
739 int lport; /* LPD connection local port */
740 int fd; /* LPD socket */
741 char control[10240], /* LPD control 'file' */
742 *cptr; /* Pointer into control file string */
743 char status; /* Status byte from command */
744 int delay; /* Delay for retries... */
745 char addrname[256]; /* Address name */
746 http_addrlist_t *addr; /* Socket address */
747 int have_supplies; /* Printer supports supply levels? */
748 int copy; /* Copies written */
749 time_t start_time; /* Time of first connect */
750 ssize_t nbytes; /* Number of bytes written */
751 off_t tbytes; /* Total bytes written */
752 char buffer[32768]; /* Output buffer */
753 #ifdef WIN32
754 DWORD tv; /* Timeout in milliseconds */
755 #else
756 struct timeval tv; /* Timeout in secs and usecs */
757 #endif /* WIN32 */
758
759
760 /*
761 * Remember when we started trying to connect to the printer...
762 */
763
764 start_time = time(NULL);
765
766 /*
767 * Loop forever trying to print the file...
768 */
769
770 while (!abort_job)
771 {
772 /*
773 * First try to reserve a port for this connection...
774 */
775
776 fprintf(stderr, "DEBUG: Connecting to %s:%d for printer %s\n", hostname,
777 httpAddrPort(&(addrlist->addr)), printer);
778 _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
779
780 for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist,
781 delay = 5;;
782 addr = addr->next)
783 {
784 /*
785 * Stop if this job has been canceled...
786 */
787
788 if (abort_job)
789 return (CUPS_BACKEND_FAILED);
790
791 /*
792 * Choose the next priviledged port...
793 */
794
795 if (!addr)
796 addr = addrlist;
797
798 lport --;
799
800 if (lport < 721 && reserve == RESERVE_RFC1179)
801 lport = 731;
802 else if (lport < 1)
803 lport = 1023;
804
805 #ifdef HAVE_GETEUID
806 if (geteuid() || !reserve)
807 #else
808 if (getuid() || !reserve)
809 #endif /* HAVE_GETEUID */
810 {
811 /*
812 * Just create a regular socket...
813 */
814
815 if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
816 {
817 perror("DEBUG: Unable to create socket");
818 sleep(1);
819
820 continue;
821 }
822
823 lport = 0;
824 }
825 else
826 {
827 /*
828 * We're running as root and want to comply with RFC 1179. Reserve a
829 * priviledged lport between 721 and 731...
830 */
831
832 if ((fd = cups_rresvport(&lport, addr->addr.addr.sa_family)) < 0)
833 {
834 perror("DEBUG: Unable to reserve port");
835 sleep(1);
836
837 continue;
838 }
839 }
840
841 /*
842 * Connect to the printer or server...
843 */
844
845 if (abort_job)
846 {
847 close(fd);
848
849 return (CUPS_BACKEND_FAILED);
850 }
851
852 if (!connect(fd, &(addr->addr.addr), (socklen_t)httpAddrLength(&(addr->addr))))
853 break;
854
855 error = errno;
856 close(fd);
857
858 if (addr->next)
859 continue;
860
861 if (getenv("CLASS") != NULL)
862 {
863 /*
864 * If the CLASS environment variable is set, the job was submitted
865 * to a class and not to a specific queue. In this case, we want
866 * to abort immediately so that the job can be requeued on the next
867 * available printer in the class.
868 */
869
870 _cupsLangPrintFilter(stderr, "INFO",
871 _("Unable to contact printer, queuing on next "
872 "printer in class."));
873
874 /*
875 * Sleep 5 seconds to keep the job from requeuing too rapidly...
876 */
877
878 sleep(5);
879
880 return (CUPS_BACKEND_FAILED);
881 }
882
883 fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));
884
885 if (error == ECONNREFUSED || error == EHOSTDOWN ||
886 error == EHOSTUNREACH)
887 {
888 if (contimeout && (time(NULL) - start_time) > contimeout)
889 {
890 _cupsLangPrintFilter(stderr, "ERROR",
891 _("The printer is not responding."));
892 return (CUPS_BACKEND_FAILED);
893 }
894
895 switch (error)
896 {
897 case EHOSTDOWN :
898 _cupsLangPrintFilter(stderr, "WARNING",
899 _("The printer may not exist or "
900 "is unavailable at this time."));
901 break;
902
903 case EHOSTUNREACH :
904 _cupsLangPrintFilter(stderr, "WARNING",
905 _("The printer is unreachable at "
906 "this time."));
907 break;
908
909 case ECONNREFUSED :
910 default :
911 _cupsLangPrintFilter(stderr, "WARNING",
912 _("The printer is in use."));
913 break;
914 }
915
916 sleep((unsigned)delay);
917
918 if (delay < 30)
919 delay += 5;
920 }
921 else if (error == EADDRINUSE)
922 {
923 /*
924 * Try on another port...
925 */
926
927 sleep(1);
928 }
929 else
930 {
931 _cupsLangPrintFilter(stderr, "ERROR",
932 _("The printer is not responding."));
933 sleep(30);
934 }
935 }
936
937 /*
938 * Set the timeout...
939 */
940
941 #ifdef WIN32
942 tv = (DWORD)(timeout * 1000);
943
944 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
945 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
946 #else
947 tv.tv_sec = timeout;
948 tv.tv_usec = 0;
949
950 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
951 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
952 #endif /* WIN32 */
953
954 fputs("STATE: -connecting-to-device\n", stderr);
955 _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
956
957 fprintf(stderr, "DEBUG: Connected to %s:%d (local port %d)...\n",
958 httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
959 httpAddrPort(&(addr->addr)), lport);
960
961 /*
962 * See if the printer supports SNMP...
963 */
964
965 if (snmp_fd >= 0)
966 have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), NULL,
967 NULL);
968 else
969 have_supplies = 0;
970
971 /*
972 * Check for side-channel requests...
973 */
974
975 backendCheckSideChannel(snmp_fd, &(addrlist->addr));
976
977 /*
978 * Next, open the print file and figure out its size...
979 */
980
981 if (print_fd)
982 {
983 /*
984 * Use the size from the print file...
985 */
986
987 if (fstat(print_fd, &filestats))
988 {
989 close(fd);
990
991 perror("DEBUG: unable to stat print file");
992 return (CUPS_BACKEND_FAILED);
993 }
994
995 filestats.st_size *= manual_copies;
996 }
997 else
998 {
999 /*
1000 * Use a "very large value" for the size so that the printer will
1001 * keep printing until we close the connection...
1002 */
1003
1004 #ifdef _LARGEFILE_SOURCE
1005 filestats.st_size = (size_t)(999999999999.0);
1006 #else
1007 filestats.st_size = 2147483647;
1008 #endif /* _LARGEFILE_SOURCE */
1009 }
1010
1011 /*
1012 * Send a job header to the printer, specifying no banner page and
1013 * literal output...
1014 */
1015
1016 if (lpd_command(fd, "\002%s\n",
1017 printer)) /* Receive print job(s) */
1018 {
1019 close(fd);
1020 return (CUPS_BACKEND_FAILED);
1021 }
1022
1023 if (orighost && _cups_strcasecmp(orighost, "localhost"))
1024 strlcpy(localhost, orighost, sizeof(localhost));
1025 else
1026 httpGetHostname(NULL, localhost, sizeof(localhost));
1027
1028 snprintf(control, sizeof(control),
1029 "H%.31s\n" /* RFC 1179, Section 7.2 - host name <= 31 chars */
1030 "P%.31s\n" /* RFC 1179, Section 7.2 - user name <= 31 chars */
1031 "J%.99s\n", /* RFC 1179, Section 7.2 - job name <= 99 chars */
1032 localhost, user, title);
1033 cptr = control + strlen(control);
1034
1035 if (banner)
1036 {
1037 snprintf(cptr, sizeof(control) - (size_t)(cptr - control),
1038 "C%.31s\n" /* RFC 1179, Section 7.2 - class name <= 31 chars */
1039 "L%s\n",
1040 localhost, user);
1041 cptr += strlen(cptr);
1042 }
1043
1044 while (copies > 0)
1045 {
1046 snprintf(cptr, sizeof(control) - (size_t)(cptr - control), "%cdfA%03d%.15s\n",
1047 format, (int)getpid() % 1000, localhost);
1048 cptr += strlen(cptr);
1049 copies --;
1050 }
1051
1052 snprintf(cptr, sizeof(control) - (size_t)(cptr - control),
1053 "UdfA%03d%.15s\n"
1054 "N%.131s\n", /* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */
1055 (int)getpid() % 1000, localhost, title);
1056
1057 fprintf(stderr, "DEBUG: Control file is:\n%s", control);
1058
1059 if (order == ORDER_CONTROL_DATA)
1060 {
1061 /*
1062 * Check for side-channel requests...
1063 */
1064
1065 backendCheckSideChannel(snmp_fd, &(addr->addr));
1066
1067 /*
1068 * Send the control file...
1069 */
1070
1071 if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control),
1072 (int)getpid() % 1000, localhost))
1073 {
1074 close(fd);
1075
1076 return (CUPS_BACKEND_FAILED);
1077 }
1078
1079 fprintf(stderr, "DEBUG: Sending control file (%u bytes)\n",
1080 (unsigned)strlen(control));
1081
1082 if ((size_t)lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
1083 {
1084 status = (char)errno;
1085 perror("DEBUG: Unable to write control file");
1086
1087 }
1088 else
1089 {
1090 if (read(fd, &status, 1) < 1)
1091 {
1092 _cupsLangPrintFilter(stderr, "WARNING",
1093 _("The printer did not respond."));
1094 status = (char)errno;
1095 }
1096 }
1097
1098 if (status != 0)
1099 _cupsLangPrintFilter(stderr, "ERROR",
1100 _("Remote host did not accept control file (%d)."),
1101 status);
1102 else
1103 _cupsLangPrintFilter(stderr, "INFO",
1104 _("Control file sent successfully."));
1105 }
1106 else
1107 status = 0;
1108
1109 if (status == 0)
1110 {
1111 /*
1112 * Check for side-channel requests...
1113 */
1114
1115 backendCheckSideChannel(snmp_fd, &(addr->addr));
1116
1117 /*
1118 * Send the print file...
1119 */
1120
1121 if (lpd_command(fd, "\003" CUPS_LLFMT " dfA%03.3d%.15s\n",
1122 CUPS_LLCAST filestats.st_size, (int)getpid() % 1000,
1123 localhost))
1124 {
1125 close(fd);
1126
1127 return (CUPS_BACKEND_FAILED);
1128 }
1129
1130 fprintf(stderr, "DEBUG: Sending data file (" CUPS_LLFMT " bytes)\n",
1131 CUPS_LLCAST filestats.st_size);
1132
1133 tbytes = 0;
1134 for (copy = 0; copy < manual_copies; copy ++)
1135 {
1136 lseek(print_fd, 0, SEEK_SET);
1137
1138 while ((nbytes = read(print_fd, buffer, sizeof(buffer))) > 0)
1139 {
1140 _cupsLangPrintFilter(stderr, "INFO",
1141 _("Spooling job, %.0f%% complete."),
1142 100.0 * tbytes / filestats.st_size);
1143
1144 if (lpd_write(fd, buffer, (size_t)nbytes) < nbytes)
1145 {
1146 perror("DEBUG: Unable to send print file to printer");
1147 break;
1148 }
1149 else
1150 tbytes += nbytes;
1151 }
1152 }
1153
1154 if (mode == MODE_STANDARD)
1155 {
1156 if (tbytes < filestats.st_size)
1157 status = (char)errno;
1158 else if (lpd_write(fd, "", 1) < 1)
1159 {
1160 perror("DEBUG: Unable to send trailing nul to printer");
1161 status = (char)errno;
1162 }
1163 else
1164 {
1165 /*
1166 * Read the status byte from the printer; if we can't read the byte
1167 * back now, we should set status to "errno", however at this point
1168 * we know the printer got the whole file and we don't necessarily
1169 * want to requeue it over and over...
1170 */
1171
1172 if (recv(fd, &status, 1, 0) < 1)
1173 {
1174 _cupsLangPrintFilter(stderr, "WARNING",
1175 _("The printer did not respond."));
1176 status = 0;
1177 }
1178 }
1179 }
1180 else
1181 status = 0;
1182
1183 if (status != 0)
1184 _cupsLangPrintFilter(stderr, "ERROR",
1185 _("Remote host did not accept data file (%d)."),
1186 status);
1187 else
1188 _cupsLangPrintFilter(stderr, "INFO",
1189 _("Data file sent successfully."));
1190 }
1191
1192 if (status == 0 && order == ORDER_DATA_CONTROL)
1193 {
1194 /*
1195 * Check for side-channel requests...
1196 */
1197
1198 backendCheckSideChannel(snmp_fd, &(addr->addr));
1199
1200 /*
1201 * Send control file...
1202 */
1203
1204 if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control),
1205 (int)getpid() % 1000, localhost))
1206 {
1207 close(fd);
1208
1209 return (CUPS_BACKEND_FAILED);
1210 }
1211
1212 fprintf(stderr, "DEBUG: Sending control file (%lu bytes)\n",
1213 (unsigned long)strlen(control));
1214
1215 if ((size_t)lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
1216 {
1217 status = (char)errno;
1218 perror("DEBUG: Unable to write control file");
1219 }
1220 else
1221 {
1222 if (read(fd, &status, 1) < 1)
1223 {
1224 _cupsLangPrintFilter(stderr, "WARNING",
1225 _("The printer did not respond."));
1226 status = (char)errno;
1227 }
1228 }
1229
1230 if (status != 0)
1231 _cupsLangPrintFilter(stderr, "ERROR",
1232 _("Remote host did not accept control file (%d)."),
1233 status);
1234 else
1235 _cupsLangPrintFilter(stderr, "INFO",
1236 _("Control file sent successfully."));
1237 }
1238
1239 fputs("STATE: +cups-waiting-for-job-completed\n", stderr);
1240
1241 /*
1242 * Collect the final supply levels as needed...
1243 */
1244
1245 if (have_supplies)
1246 backendSNMPSupplies(snmp_fd, &(addr->addr), NULL, NULL);
1247
1248 /*
1249 * Close the socket connection and input file...
1250 */
1251
1252 close(fd);
1253
1254 if (status == 0)
1255 return (CUPS_BACKEND_OK);
1256
1257 /*
1258 * Waiting for a retry...
1259 */
1260
1261 sleep(30);
1262 }
1263
1264 /*
1265 * If we get here, then the job has been canceled...
1266 */
1267
1268 return (CUPS_BACKEND_FAILED);
1269 }
1270
1271
1272 /*
1273 * 'lpd_write()' - Write a buffer of data to an LPD server.
1274 */
1275
1276 static ssize_t /* O - Number of bytes written or -1 on error */
1277 lpd_write(int lpd_fd, /* I - LPD socket */
1278 char *buffer, /* I - Buffer to write */
1279 size_t length) /* I - Number of bytes to write */
1280 {
1281 ssize_t bytes, /* Number of bytes written */
1282 total; /* Total number of bytes written */
1283
1284
1285 if (abort_job)
1286 return (-1);
1287
1288 total = 0;
1289 while ((bytes = send(lpd_fd, buffer, length - (size_t)total, 0)) >= 0)
1290 {
1291 total += bytes;
1292 buffer += bytes;
1293
1294 if ((size_t)total == length)
1295 break;
1296 }
1297
1298 if (bytes < 0)
1299 return (-1);
1300 else
1301 return (total);
1302 }
1303
1304
1305 /*
1306 * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
1307 */
1308
1309 static void
1310 sigterm_handler(int sig) /* I - Signal */
1311 {
1312 (void)sig; /* remove compiler warnings... */
1313
1314 abort_job = 1;
1315 }
1316
1317
1318 /*
1319 * End of "$Id$".
1320 */