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