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