4 * Line Printer Daemon backend for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
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/".
15 * This file is subject to the Apple OS-Developed Software exception.
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.
29 * Include necessary headers.
32 #include <cups/http-private.h>
33 #include "backend-private.h"
35 #include <sys/types.h>
41 # include <sys/socket.h>
42 # include <netinet/in.h>
43 # include <arpa/inet.h>
47 # include <CoreFoundation/CFNumber.h>
48 # include <CoreFoundation/CFPreferences.h>
49 #endif /* __APPLE__ */
56 static char tmpfilename
[1024] = ""; /* Temporary spool file name */
57 static int abort_job
= 0; /* Non-zero if we get SIGTERM */
64 #define MODE_STANDARD 0 /* Queue a copy */
65 #define MODE_STREAM 1 /* Stream a copy */
69 * The order for control and data files in LPD requests...
72 #define ORDER_CONTROL_DATA 0 /* Control file first, then data */
73 #define ORDER_DATA_CONTROL 1 /* Data file first, then control */
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 */
89 static int lpd_command(int lpd_fd
, int timeout
, char *format
, ...);
90 static int lpd_queue(const char *hostname
, int port
, const char *printer
,
91 int print_fd
, int mode
, const char *user
,
92 const char *title
, int copies
, int banner
,
93 int format
, int order
, int reserve
,
94 int manual_copies
, int timeout
, int contimeout
);
95 static void lpd_timeout(int sig
);
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
);
104 * 'main()' - Send a file to the printer or server.
108 * printer-uri job-id user title copies options [file]
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 */
115 const char *device_uri
; /* Device URI */
116 char method
[255], /* Method 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 int fd
; /* Print file */
128 int status
; /* Status of LPD job */
129 int mode
; /* Print mode */
130 int banner
; /* Print banner page? */
131 int format
; /* Print format */
132 int order
; /* Order of control/data files */
133 int reserve
; /* Reserve priviledged port? */
134 int sanitize_title
; /* Sanitize title string? */
135 int manual_copies
, /* Do manual copies? */
136 timeout
, /* Timeout */
137 contimeout
, /* Connection timeout */
138 copies
; /* Number of copies */
139 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
140 struct sigaction action
; /* Actions for POSIX signals */
141 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
145 * Make sure status messages are not buffered...
148 setbuf(stderr
, NULL
);
151 * Ignore SIGPIPE and catch SIGTERM signals...
155 sigset(SIGPIPE
, SIG_IGN
);
156 sigset(SIGTERM
, sigterm_handler
);
157 #elif defined(HAVE_SIGACTION)
158 memset(&action
, 0, sizeof(action
));
159 action
.sa_handler
= SIG_IGN
;
160 sigaction(SIGPIPE
, &action
, NULL
);
162 sigemptyset(&action
.sa_mask
);
163 sigaddset(&action
.sa_mask
, SIGTERM
);
164 action
.sa_handler
= sigterm_handler
;
165 sigaction(SIGTERM
, &action
, NULL
);
167 signal(SIGPIPE
, SIG_IGN
);
168 signal(SIGTERM
, sigterm_handler
);
169 #endif /* HAVE_SIGSET */
172 * Check command-line...
177 puts("network lpd \"Unknown\" \"LPD/LPR Host or Printer\"");
178 return (CUPS_BACKEND_OK
);
180 else if (argc
< 6 || argc
> 7)
182 _cupsLangPrintf(stderr
,
183 _("Usage: %s job-id user title copies options [file]\n"),
185 return (CUPS_BACKEND_FAILED
);
189 * Extract the hostname and printer name from the URI...
192 if ((device_uri
= cupsBackendDeviceURI(argv
)) == NULL
)
193 return (CUPS_BACKEND_FAILED
);
195 httpSeparateURI(HTTP_URI_CODING_ALL
, device_uri
,
196 method
, sizeof(method
), username
, sizeof(username
),
197 hostname
, sizeof(hostname
), &port
,
198 resource
, sizeof(resource
));
201 port
= 515; /* Default to port 515 */
206 * If no username is in the device URI, then use the print job user...
209 strlcpy(username
, argv
[2], sizeof(username
));
213 * See if there are any options...
216 mode
= MODE_STANDARD
;
219 order
= ORDER_CONTROL_DATA
;
220 reserve
= RESERVE_ANY
;
223 contimeout
= 7 * 24 * 60 * 60;
227 * We want to pass utf-8 characters, not re-map them (3071945)
233 * Get the default timeout from a system preference...
237 CFPropertyListRef pvalue
; /* Preference value */
238 SInt32 toval
; /* Timeout value */
241 pvalue
= CFPreferencesCopyValue(CFSTR("timeout"),
242 CFSTR("com.apple.print.backends"),
243 kCFPreferencesAnyUser
,
244 kCFPreferencesCurrentHost
);
247 if (CFGetTypeID(pvalue
) == CFNumberGetTypeID())
249 CFNumberGetValue(pvalue
, kCFNumberSInt32Type
, &toval
);
250 contimeout
= (int)toval
;
258 #endif /* __APPLE__ */
260 if ((options
= strchr(resource
, '?')) != NULL
)
263 * Yup, terminate the device name string and move to the first
264 * character of the options...
281 while (*options
&& *options
!= '=' && *options
!= '+' && *options
!= '&')
284 if ((sep
= *options
) != '\0')
295 while (*options
&& *options
!= '+' && *options
!= '&')
305 * Process the option...
308 if (!strcasecmp(name
, "banner"))
314 banner
= !value
[0] || !strcasecmp(value
, "on") ||
315 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
317 else if (!strcasecmp(name
, "format") && value
[0])
320 * Set output format...
323 if (strchr("cdfglnoprtv", value
[0]))
326 _cupsLangPrintf(stderr
, _("ERROR: Unknown format character \"%c\"\n"),
329 else if (!strcasecmp(name
, "mode") && value
[0])
332 * Set control/data order...
335 if (!strcasecmp(value
, "standard"))
336 mode
= MODE_STANDARD
;
337 else if (!strcasecmp(value
, "stream"))
340 _cupsLangPrintf(stderr
, _("ERROR: Unknown print mode \"%s\"\n"),
343 else if (!strcasecmp(name
, "order") && value
[0])
346 * Set control/data order...
349 if (!strcasecmp(value
, "control,data"))
350 order
= ORDER_CONTROL_DATA
;
351 else if (!strcasecmp(value
, "data,control"))
352 order
= ORDER_DATA_CONTROL
;
354 _cupsLangPrintf(stderr
, _("ERROR: Unknown file order \"%s\"\n"),
357 else if (!strcasecmp(name
, "reserve"))
360 * Set port reservation mode...
363 if (!value
[0] || !strcasecmp(value
, "on") ||
364 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true") ||
365 !strcasecmp(value
, "rfc1179"))
366 reserve
= RESERVE_RFC1179
;
367 else if (!strcasecmp(value
, "any"))
368 reserve
= RESERVE_ANY
;
370 reserve
= RESERVE_NONE
;
372 else if (!strcasecmp(name
, "manual_copies"))
375 * Set manual copies...
378 manual_copies
= !value
[0] || !strcasecmp(value
, "on") ||
379 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
381 else if (!strcasecmp(name
, "sanitize_title"))
384 * Set sanitize title...
387 sanitize_title
= !value
[0] || !strcasecmp(value
, "on") ||
388 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
390 else if (!strcasecmp(name
, "timeout"))
397 timeout
= atoi(value
);
399 else if (!strcasecmp(name
, "contimeout"))
402 * Set the connection timeout...
406 contimeout
= atoi(value
);
411 if (mode
== MODE_STREAM
)
412 order
= ORDER_CONTROL_DATA
;
415 * If we have 7 arguments, print the file named on the command-line.
416 * Otherwise, copy stdin to a temporary file and print the temporary
420 if (argc
== 6 && mode
== MODE_STANDARD
)
423 * Copy stdin to a temporary file...
426 char buffer
[8192]; /* Buffer for copying */
427 int bytes
; /* Number of bytes read */
430 if ((fd
= cupsTempFd(tmpfilename
, sizeof(tmpfilename
))) < 0)
432 _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
433 return (CUPS_BACKEND_FAILED
);
436 while ((bytes
= fread(buffer
, 1, sizeof(buffer
), stdin
)) > 0)
437 if (write(fd
, buffer
, bytes
) < bytes
)
439 _cupsLangPrintError(_("ERROR: Unable to write to temporary file"));
442 return (CUPS_BACKEND_FAILED
);
448 * Stream from stdin...
457 fd
= open(filename
, O_RDONLY
);
461 _cupsLangPrintf(stderr
, _("ERROR: Unable to open print file %s: %s\n"),
462 filename
, strerror(errno
));
463 return (CUPS_BACKEND_FAILED
);
468 * Sanitize the document title...
471 strlcpy(title
, argv
[3], sizeof(title
));
476 * Sanitize the title string so that we don't cause problems on
482 for (ptr
= title
; *ptr
; ptr
++)
483 if (!isalnum(*ptr
& 255) && !isspace(*ptr
& 255))
495 manual_copies
= atoi(argv
[4]);
501 copies
= atoi(argv
[4]);
504 status
= lpd_queue(hostname
, port
, resource
+ 1, fd
, mode
,
505 username
, title
, copies
,
506 banner
, format
, order
, reserve
, manual_copies
,
507 timeout
, contimeout
);
510 fprintf(stderr
, "PAGE: 1 %d\n", atoi(argv
[4]));
513 status
= lpd_queue(hostname
, port
, resource
+ 1, fd
, mode
,
515 banner
, format
, order
, reserve
, 1,
516 timeout
, contimeout
);
519 * Remove the temporary file if necessary...
529 * Return the queue status...
537 * 'lpd_command()' - Send an LPR command sequence and wait for a reply.
540 static int /* O - Status of command */
541 lpd_command(int fd
, /* I - Socket connection to LPD host */
542 int timeout
, /* I - Seconds to wait for a response */
543 char *format
, /* I - printf()-style format string */
544 ...) /* I - Additional args as necessary */
546 va_list ap
; /* Argument pointer */
547 char buf
[1024]; /* Output buffer */
548 int bytes
; /* Number of bytes to output */
549 char status
; /* Status from command */
553 * Don't try to send commands if the job has been cancelled...
560 * Format the string...
563 va_start(ap
, format
);
564 bytes
= vsnprintf(buf
, sizeof(buf
), format
, ap
);
567 fprintf(stderr
, "DEBUG: lpd_command %2.2x %s", buf
[0], buf
+ 1);
570 * Send the command...
573 fprintf(stderr
, "DEBUG: Sending command string (%d bytes)...\n", bytes
);
575 if (lpd_write(fd
, buf
, bytes
) < bytes
)
577 _cupsLangPrintError(_("ERROR: Unable to send LPD command"));
582 * Read back the status from the command and return it...
585 fputs("DEBUG: Reading command status...\n", stderr
);
589 if (recv(fd
, &status
, 1, 0) < 1)
591 _cupsLangPrintf(stderr
,
592 _("WARNING: Remote host did not respond with command "
593 "status byte after %d seconds!\n"), timeout
);
599 fprintf(stderr
, "DEBUG: lpd_command returning %d\n", status
);
606 * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
609 static int /* O - Zero on success, non-zero on failure */
610 lpd_queue(const char *hostname
, /* I - Host to connect to */
611 int port
, /* I - Port to connect on */
612 const char *printer
, /* I - Printer/queue name */
613 int print_fd
, /* I - File to print */
614 int mode
, /* I - Print mode */
615 const char *user
, /* I - Requesting user */
616 const char *title
, /* I - Job title */
617 int copies
, /* I - Number of copies */
618 int banner
, /* I - Print LPD banner? */
619 int format
, /* I - Format specifier */
620 int order
, /* I - Order of data/control files */
621 int reserve
, /* I - Reserve ports? */
622 int manual_copies
, /* I - Do copies by hand... */
623 int timeout
, /* I - Timeout... */
624 int contimeout
) /* I - Connection timeout */
626 char localhost
[255]; /* Local host name */
627 int error
; /* Error number */
628 struct stat filestats
; /* File statistics */
629 int lport
; /* LPD connection local port */
630 int fd
; /* LPD socket */
631 char control
[10240], /* LPD control 'file' */
632 *cptr
; /* Pointer into control file string */
633 char status
; /* Status byte from command */
634 char portname
[255]; /* Port name */
635 int delay
; /* Delay for retries... */
636 char addrname
[256]; /* Address name */
637 http_addrlist_t
*addrlist
, /* Address list */
638 *addr
; /* Socket address */
639 int snmp_fd
, /* SNMP socket */
640 start_count
, /* Page count via SNMP at start */
641 page_count
; /* Page count via SNMP */
642 int copy
; /* Copies written */
643 time_t start_time
; /* Time of first connect */
644 int recoverable
; /* Recoverable error shown? */
645 size_t nbytes
; /* Number of bytes written */
646 off_t tbytes
; /* Total bytes written */
647 char buffer
[32768]; /* Output buffer */
648 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
649 struct sigaction action
; /* Actions for POSIX signals */
650 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
654 * Setup an alarm handler for timeouts...
657 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
658 sigset(SIGALRM
, lpd_timeout
);
659 #elif defined(HAVE_SIGACTION)
660 memset(&action
, 0, sizeof(action
));
662 sigemptyset(&action
.sa_mask
);
663 action
.sa_handler
= lpd_timeout
;
664 sigaction(SIGALRM
, &action
, NULL
);
666 signal(SIGALRM
, lpd_timeout
);
667 #endif /* HAVE_SIGSET */
670 * Find the printer...
673 sprintf(portname
, "%d", port
);
675 if ((addrlist
= httpAddrGetList(hostname
, AF_UNSPEC
, portname
)) == NULL
)
677 _cupsLangPrintf(stderr
, _("ERROR: Unable to locate printer \'%s\'!\n"),
679 return (CUPS_BACKEND_STOP
);
683 * Remember when we started trying to connect to the printer...
687 start_time
= time(NULL
);
690 * Loop forever trying to print the file...
696 * First try to reserve a port for this connection...
699 fputs("STATE: +connecting-to-device\n", stderr
);
700 _cupsLangPrintf(stderr
,
701 _("INFO: Connecting to %s for printer %s\n"),
704 for (lport
= reserve
== RESERVE_RFC1179
? 732 : 1024, addr
= addrlist
,
709 * Stop if this job has been cancelled...
714 httpAddrFreeList(addrlist
);
716 return (CUPS_BACKEND_FAILED
);
720 * Choose the next priviledged port...
728 if (lport
< 721 && reserve
== RESERVE_RFC1179
)
734 if (geteuid() || !reserve
)
736 if (getuid() || !reserve
)
737 #endif /* HAVE_GETEUID */
740 * Just create a regular socket...
743 if ((fd
= socket(addr
->addr
.addr
.sa_family
, SOCK_STREAM
, 0)) < 0)
745 _cupsLangPrintError(_("ERROR: Unable to create socket"));
756 * We're running as root and want to comply with RFC 1179. Reserve a
757 * priviledged lport between 721 and 731...
760 if ((fd
= rresvport_af(&lport
, addr
->addr
.addr
.sa_family
)) < 0)
762 _cupsLangPrintError(_("ERROR: Unable to reserve port"));
770 * Connect to the printer or server...
775 httpAddrFreeList(addrlist
);
779 return (CUPS_BACKEND_FAILED
);
782 if (!connect(fd
, &(addr
->addr
.addr
), httpAddrLength(&(addr
->addr
))))
792 if (getenv("CLASS") != NULL
)
795 * If the CLASS environment variable is set, the job was submitted
796 * to a class and not to a specific queue. In this case, we want
797 * to abort immediately so that the job can be requeued on the next
798 * available printer in the class.
801 _cupsLangPuts(stderr
,
802 _("INFO: Unable to contact printer, queuing on next "
803 "printer in class...\n"));
805 httpAddrFreeList(addrlist
);
808 * Sleep 5 seconds to keep the job from requeuing too rapidly...
813 return (CUPS_BACKEND_FAILED
);
816 if (error
== ECONNREFUSED
|| error
== EHOSTDOWN
||
817 error
== EHOSTUNREACH
)
819 if (contimeout
&& (time(NULL
) - start_time
) > contimeout
)
821 _cupsLangPuts(stderr
, _("ERROR: Printer not responding!\n"));
822 return (CUPS_BACKEND_FAILED
);
827 _cupsLangPrintf(stderr
,
828 _("WARNING: recoverable: Network host \'%s\' is busy; "
829 "will retry in %d seconds...\n"), hostname
, delay
);
836 else if (error
== EADDRINUSE
)
839 * Try on another port...
848 fprintf(stderr
, "DEBUG: Connection error: %s\n", strerror(errno
));
849 _cupsLangPuts(stderr
,
850 _("ERROR: recoverable: Unable to connect to printer; "
851 "will retry in 30 seconds...\n"));
859 * If we've shown a recoverable error make sure the printer proxies
860 * have a chance to see the recovered message. Not pretty but
861 * necessary for now...
864 fputs("INFO: recovered: \n", stderr
);
868 fputs("STATE: -connecting-to-device\n", stderr
);
869 _cupsLangPrintf(stderr
, _("INFO: Connected to %s...\n"), hostname
);
872 if (addr
->addr
.addr
.sa_family
== AF_INET6
)
873 fprintf(stderr
, "DEBUG: Connected to [%s]:%d (IPv6) (local port %d)...\n",
874 httpAddrString(&addr
->addr
, addrname
, sizeof(addrname
)),
875 ntohs(addr
->addr
.ipv6
.sin6_port
), lport
);
877 #endif /* AF_INET6 */
878 if (addr
->addr
.addr
.sa_family
== AF_INET
)
879 fprintf(stderr
, "DEBUG: Connected to %s:%d (IPv4) (local port %d)...\n",
880 httpAddrString(&addr
->addr
, addrname
, sizeof(addrname
)),
881 ntohs(addr
->addr
.ipv4
.sin_port
), lport
);
884 * See if the printer supports SNMP...
887 if ((snmp_fd
= _cupsSNMPOpen(addr
->addr
.addr
.sa_family
)) >= 0)
889 if (backendSNMPSupplies(snmp_fd
, &(addr
->addr
), &start_count
, NULL
))
895 _cupsSNMPClose(snmp_fd
);
903 * Check for side-channel requests...
906 backendCheckSideChannel(snmp_fd
, &(addr
->addr
));
909 * Next, open the print file and figure out its size...
915 * Use the size from the print file...
918 if (fstat(print_fd
, &filestats
))
920 httpAddrFreeList(addrlist
);
923 _cupsLangPrintError(_("ERROR: unable to stat print file"));
924 return (CUPS_BACKEND_FAILED
);
927 filestats
.st_size
*= manual_copies
;
932 * Use a "very large value" for the size so that the printer will
933 * keep printing until we close the connection...
936 #ifdef _LARGEFILE_SOURCE
937 filestats
.st_size
= (size_t)(999999999999.0);
939 filestats
.st_size
= 2147483647;
940 #endif /* _LARGEFILE_SOURCE */
944 * Send a job header to the printer, specifying no banner page and
948 if (lpd_command(fd
, timeout
, "\002%s\n",
949 printer
)) /* Receive print job(s) */
951 httpAddrFreeList(addrlist
);
953 return (CUPS_BACKEND_FAILED
);
956 httpGetHostname(NULL
, localhost
, sizeof(localhost
));
958 snprintf(control
, sizeof(control
),
959 "H%.31s\n" /* RFC 1179, Section 7.2 - host name <= 31 chars */
960 "P%.31s\n" /* RFC 1179, Section 7.2 - user name <= 31 chars */
961 "J%.99s\n", /* RFC 1179, Section 7.2 - job name <= 99 chars */
962 localhost
, user
, title
);
963 cptr
= control
+ strlen(control
);
967 snprintf(cptr
, sizeof(control
) - (cptr
- control
),
968 "C%.31s\n" /* RFC 1179, Section 7.2 - class name <= 31 chars */
971 cptr
+= strlen(cptr
);
976 snprintf(cptr
, sizeof(control
) - (cptr
- control
), "%cdfA%03d%.15s\n",
977 format
, (int)getpid() % 1000, localhost
);
978 cptr
+= strlen(cptr
);
982 snprintf(cptr
, sizeof(control
) - (cptr
- control
),
984 "N%.131s\n", /* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */
985 (int)getpid() % 1000, localhost
, title
);
987 fprintf(stderr
, "DEBUG: Control file is:\n%s", control
);
989 if (order
== ORDER_CONTROL_DATA
)
992 * Check for side-channel requests...
995 backendCheckSideChannel(snmp_fd
, &(addr
->addr
));
998 * Send the control file...
1001 if (lpd_command(fd
, timeout
, "\002%d cfA%03.3d%.15s\n", strlen(control
),
1002 (int)getpid() % 1000, localhost
))
1004 httpAddrFreeList(addrlist
);
1007 return (CUPS_BACKEND_FAILED
);
1010 _cupsLangPrintf(stderr
, _("INFO: Sending control file (%u bytes)\n"),
1011 (unsigned)strlen(control
));
1013 if (lpd_write(fd
, control
, strlen(control
) + 1) < (strlen(control
) + 1))
1016 _cupsLangPrintError(_("ERROR: Unable to write control file"));
1022 if (read(fd
, &status
, 1) < 1)
1024 _cupsLangPrintf(stderr
,
1025 _("WARNING: Remote host did not respond with control "
1026 "status byte after %d seconds!\n"), timeout
);
1034 _cupsLangPrintf(stderr
,
1035 _("ERROR: Remote host did not accept control file "
1038 _cupsLangPuts(stderr
, _("INFO: Control file sent successfully\n"));
1046 * Check for side-channel requests...
1049 backendCheckSideChannel(snmp_fd
, &(addr
->addr
));
1052 * Send the print file...
1055 if (lpd_command(fd
, timeout
, "\003" CUPS_LLFMT
" dfA%03.3d%.15s\n",
1056 CUPS_LLCAST filestats
.st_size
, (int)getpid() % 1000,
1059 httpAddrFreeList(addrlist
);
1062 return (CUPS_BACKEND_FAILED
);
1065 _cupsLangPrintf(stderr
,
1066 #ifdef HAVE_LONG_LONG
1067 _("INFO: Sending data file (%lld bytes)\n"),
1069 _("INFO: Sending data file (%ld bytes)\n"),
1070 #endif /* HAVE_LONG_LONG */
1071 CUPS_LLCAST filestats
.st_size
);
1074 for (copy
= 0; copy
< manual_copies
; copy
++)
1076 lseek(print_fd
, 0, SEEK_SET
);
1078 while ((nbytes
= read(print_fd
, buffer
, sizeof(buffer
))) > 0)
1080 _cupsLangPrintf(stderr
,
1081 _("INFO: Spooling LPR job, %.0f%% complete...\n"),
1082 100.0 * tbytes
/ filestats
.st_size
);
1084 if (lpd_write(fd
, buffer
, nbytes
) < nbytes
)
1086 _cupsLangPrintError(_("ERROR: Unable to send print file to printer"));
1094 if (mode
== MODE_STANDARD
)
1096 if (tbytes
< filestats
.st_size
)
1098 else if (lpd_write(fd
, "", 1) < 1)
1100 _cupsLangPrintError(_("ERROR: Unable to send trailing nul to printer"));
1106 * Read the status byte from the printer; if we can't read the byte
1107 * back now, we should set status to "errno", however at this point
1108 * we know the printer got the whole file and we don't necessarily
1109 * want to requeue it over and over...
1114 if (recv(fd
, &status
, 1, 0) < 1)
1116 _cupsLangPrintf(stderr
,
1117 _("WARNING: Remote host did not respond with data "
1118 "status byte after %d seconds!\n"), timeout
);
1129 _cupsLangPrintf(stderr
,
1130 _("ERROR: Remote host did not accept data file (%d)\n"),
1133 _cupsLangPuts(stderr
, _("INFO: Data file sent successfully\n"));
1136 if (status
== 0 && order
== ORDER_DATA_CONTROL
)
1139 * Check for side-channel requests...
1142 backendCheckSideChannel(snmp_fd
, &(addr
->addr
));
1145 * Send control file...
1148 if (lpd_command(fd
, timeout
, "\002%d cfA%03.3d%.15s\n", strlen(control
),
1149 (int)getpid() % 1000, localhost
))
1151 httpAddrFreeList(addrlist
);
1154 return (CUPS_BACKEND_FAILED
);
1157 _cupsLangPrintf(stderr
, _("INFO: Sending control file (%lu bytes)\n"),
1158 (unsigned long)strlen(control
));
1160 if (lpd_write(fd
, control
, strlen(control
) + 1) < (strlen(control
) + 1))
1163 _cupsLangPrintError(_("ERROR: Unable to write control file"));
1169 if (read(fd
, &status
, 1) < 1)
1171 _cupsLangPrintf(stderr
,
1172 _("WARNING: Remote host did not respond with control "
1173 "status byte after %d seconds!\n"), timeout
);
1181 _cupsLangPrintf(stderr
,
1182 _("ERROR: Remote host did not accept control file "
1185 _cupsLangPuts(stderr
, _("INFO: Control file sent successfully\n"));
1189 * Collect the final page count as needed...
1194 int printer_state
; /* State of printer */
1197 while (!backendSNMPSupplies(snmp_fd
, &(addr
->addr
), &page_count
,
1199 printer_state
!= CUPS_TC_idle
)
1202 if (page_count
> start_count
)
1203 fprintf(stderr
, "PAGE: total %d\n", page_count
- start_count
);
1207 * Close the socket connection and input file...
1214 httpAddrFreeList(addrlist
);
1216 return (CUPS_BACKEND_OK
);
1220 * Waiting for a retry...
1226 httpAddrFreeList(addrlist
);
1229 * If we get here, then the job has been cancelled...
1232 return (CUPS_BACKEND_FAILED
);
1237 * 'lpd_timeout()' - Handle timeout alarms...
1241 lpd_timeout(int sig
) /* I - Signal number */
1245 #if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
1246 signal(SIGALRM
, lpd_timeout
);
1247 #endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
1252 * 'lpd_write()' - Write a buffer of data to an LPD server.
1255 static int /* O - Number of bytes written or -1 on error */
1256 lpd_write(int lpd_fd
, /* I - LPD socket */
1257 char *buffer
, /* I - Buffer to write */
1258 int length
) /* I - Number of bytes to write */
1260 int bytes
, /* Number of bytes written */
1261 total
; /* Total number of bytes written */
1268 while ((bytes
= send(lpd_fd
, buffer
, length
- total
, 0)) >= 0)
1273 if (total
== length
)
1284 #ifndef HAVE_RRESVPORT_AF
1286 * 'rresvport_af()' - A simple implementation of rresvport_af().
1289 static int /* O - Socket or -1 on error */
1290 rresvport_af(int *port
, /* IO - Port number to bind to */
1291 int family
) /* I - Address family */
1293 http_addr_t addr
; /* Socket address */
1294 int fd
; /* Socket file descriptor */
1298 * Try to create an IPv4 socket...
1301 if ((fd
= socket(family
, SOCK_STREAM
, 0)) < 0)
1305 * Initialize the address buffer...
1308 memset(&addr
, 0, sizeof(addr
));
1309 addr
.addr
.sa_family
= family
;
1312 * Try to bind the socket to a reserved port...
1318 * Set the port number...
1322 if (family
== AF_INET6
)
1323 addr
.ipv6
.sin6_port
= htons(*port
);
1325 # endif /* AF_INET6 */
1326 addr
.ipv4
.sin_port
= htons(*port
);
1329 * Try binding the port to the socket; return if all is OK...
1332 if (!bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)))
1336 * Stop if we have any error other than "address already in use"...
1339 if (errno
!= EADDRINUSE
)
1351 * Try the next port...
1358 * Wasn't able to bind to a reserved port, so close the socket and return
1370 #endif /* !HAVE_RRESVPORT_AF */
1374 * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
1378 sigterm_handler(int sig
) /* I - Signal */
1380 (void)sig
; /* remove compiler warnings... */