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