]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/lpd.c
702c0fb9dfdbdc38f1fe42bd53602c2b32a8d3bc
2 * "$Id: lpd.c 7740 2008-07-14 23:58:05Z mike $"
4 * Line Printer Daemon backend for CUPS.
6 * Copyright 2007-2011 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>
42 # include <sys/socket.h>
43 # include <netinet/in.h>
44 # include <arpa/inet.h>
48 # include <CoreFoundation/CFNumber.h>
49 # include <CoreFoundation/CFPreferences.h>
50 #endif /* __APPLE__ */
57 static char tmpfilename
[1024] = ""; /* Temporary spool file name */
58 static int abort_job
= 0; /* Non-zero if we get SIGTERM */
65 #define MODE_STANDARD 0 /* Queue a copy */
66 #define MODE_STREAM 1 /* Stream a copy */
70 * The order for control and data files in LPD requests...
73 #define ORDER_CONTROL_DATA 0 /* Control file first, then data */
74 #define ORDER_DATA_CONTROL 1 /* Data file first, then control */
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 */
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
,
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
);
106 * 'main()' - Send a file to the printer or server.
110 * printer-uri job-id user title copies options [file]
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 */
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 */
150 * Make sure status messages are not buffered...
153 setbuf(stderr
, NULL
);
156 * Ignore SIGPIPE and catch SIGTERM signals...
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
);
167 sigemptyset(&action
.sa_mask
);
168 sigaddset(&action
.sa_mask
, SIGTERM
);
169 action
.sa_handler
= sigterm_handler
;
170 sigaction(SIGTERM
, &action
, NULL
);
172 signal(SIGPIPE
, SIG_IGN
);
173 signal(SIGTERM
, sigterm_handler
);
174 #endif /* HAVE_SIGSET */
177 * Check command-line...
182 printf("network lpd \"Unknown\" \"%s\"\n",
183 _cupsLangString(cupsLangDefault(), _("LPD/LPR Host or Printer")));
184 return (CUPS_BACKEND_OK
);
186 else if (argc
< 6 || argc
> 7)
188 _cupsLangPrintf(stderr
,
189 _("Usage: %s job-id user title copies options [file]"),
191 return (CUPS_BACKEND_FAILED
);
195 * Extract the hostname and printer name from the URI...
198 while ((device_uri
= cupsBackendDeviceURI(argv
)) == NULL
)
200 _cupsLangPrintFilter(stderr
, "INFO", _("Unable to locate printer."));
203 if (getenv("CLASS") != NULL
)
204 return (CUPS_BACKEND_FAILED
);
207 httpSeparateURI(HTTP_URI_CODING_ALL
, device_uri
, scheme
, sizeof(scheme
),
208 username
, sizeof(username
), hostname
, sizeof(hostname
), &port
,
209 resource
, sizeof(resource
));
212 port
= 515; /* Default to port 515 */
217 * If no username is in the device URI, then use the print job user...
220 strlcpy(username
, argv
[2], sizeof(username
));
224 * See if there are any options...
227 mode
= MODE_STANDARD
;
230 order
= ORDER_CONTROL_DATA
;
231 reserve
= RESERVE_ANY
;
234 contimeout
= 7 * 24 * 60 * 60;
238 * We want to pass UTF-8 characters by default, not re-map them (3071945)
244 * Otherwise we want to re-map UTF-8 to "safe" characters by default...
248 #endif /* __APPLE__ */
250 if ((options
= strchr(resource
, '?')) != NULL
)
253 * Yup, terminate the device name string and move to the first
254 * character of the options...
271 while (*options
&& *options
!= '=' && *options
!= '+' && *options
!= '&')
274 if ((sep
= *options
) != '\0')
285 while (*options
&& *options
!= '+' && *options
!= '&')
295 * Process the option...
298 if (!strcasecmp(name
, "banner"))
304 banner
= !value
[0] || !strcasecmp(value
, "on") ||
305 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
307 else if (!strcasecmp(name
, "format") && value
[0])
310 * Set output format...
313 if (strchr("cdfglnoprtv", value
[0]))
316 _cupsLangPrintFilter(stderr
, "ERROR",
317 _("Unknown format character: \"%c\"."),
320 else if (!strcasecmp(name
, "mode") && value
[0])
323 * Set control/data order...
326 if (!strcasecmp(value
, "standard"))
327 mode
= MODE_STANDARD
;
328 else if (!strcasecmp(value
, "stream"))
331 _cupsLangPrintFilter(stderr
, "ERROR",
332 _("Unknown print mode: \"%s\"."), value
);
334 else if (!strcasecmp(name
, "order") && value
[0])
337 * Set control/data order...
340 if (!strcasecmp(value
, "control,data"))
341 order
= ORDER_CONTROL_DATA
;
342 else if (!strcasecmp(value
, "data,control"))
343 order
= ORDER_DATA_CONTROL
;
345 _cupsLangPrintFilter(stderr
, "ERROR",
346 _("Unknown file order: \"%s\"."), value
);
348 else if (!strcasecmp(name
, "reserve"))
351 * Set port reservation mode...
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
;
361 reserve
= RESERVE_NONE
;
363 else if (!strcasecmp(name
, "manual_copies"))
366 * Set manual copies...
369 manual_copies
= !value
[0] || !strcasecmp(value
, "on") ||
370 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
372 else if (!strcasecmp(name
, "sanitize_title"))
375 * Set sanitize title...
378 sanitize_title
= !value
[0] || !strcasecmp(value
, "on") ||
379 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
381 else if (!strcasecmp(name
, "timeout"))
388 timeout
= atoi(value
);
390 else if (!strcasecmp(name
, "contimeout"))
393 * Set the connection timeout...
397 contimeout
= atoi(value
);
402 if (mode
== MODE_STREAM
)
403 order
= ORDER_CONTROL_DATA
;
406 * Find the printer...
409 snprintf(portname
, sizeof(portname
), "%d", port
);
411 fputs("STATE: +connecting-to-device\n", stderr
);
412 fprintf(stderr
, "DEBUG: Looking up \"%s\"...\n", hostname
);
414 while ((addrlist
= httpAddrGetList(hostname
, AF_UNSPEC
, portname
)) == NULL
)
416 _cupsLangPrintFilter(stderr
, "INFO",
417 _("Unable to locate printer \"%s\"."), hostname
);
420 if (getenv("CLASS") != NULL
)
422 fputs("STATE: -connecting-to-device\n", stderr
);
423 exit(CUPS_BACKEND_FAILED
);
427 snmp_fd
= _cupsSNMPOpen(addrlist
->addr
.addr
.sa_family
);
430 * Wait for data from the filter...
434 if (!backendWaitLoop(snmp_fd
, &(addrlist
->addr
), backendNetworkSideCB
))
435 return (CUPS_BACKEND_OK
);
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
443 if (argc
== 6 && mode
== MODE_STANDARD
)
446 * Copy stdin to a temporary file...
449 if ((fd
= cupsTempFd(tmpfilename
, sizeof(tmpfilename
))) < 0)
451 perror("DEBUG: Unable to create temporary file");
452 return (CUPS_BACKEND_FAILED
);
455 _cupsLangPrintFilter(stderr
, "INFO", _("Copying print data."));
457 backendRunLoop(-1, fd
, snmp_fd
, &(addrlist
->addr
), 0, 0,
458 backendNetworkSideCB
);
463 * Stream from stdin...
472 fd
= open(filename
, O_RDONLY
);
476 _cupsLangPrintError("ERROR", _("Unable to open print file"));
477 return (CUPS_BACKEND_FAILED
);
482 * Sanitize the document title...
485 strlcpy(title
, argv
[3], sizeof(title
));
490 * Sanitize the title string so that we don't cause problems on
496 for (ptr
= title
; *ptr
; ptr
++)
497 if (!isalnum(*ptr
& 255) && !isspace(*ptr
& 255))
509 manual_copies
= atoi(argv
[4]);
515 copies
= atoi(argv
[4]);
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
);
523 fprintf(stderr
, "PAGE: 1 %d\n", atoi(argv
[4]));
526 status
= lpd_queue(hostname
, addrlist
, resource
+ 1, fd
, snmp_fd
, mode
,
527 username
, title
, 1, banner
, format
, order
, reserve
, 1,
528 timeout
, contimeout
);
531 * Remove the temporary file if necessary...
541 _cupsSNMPClose(snmp_fd
);
544 * Return the queue status...
552 * 'lpd_command()' - Send an LPR command sequence and wait for a reply.
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 */
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 */
568 * Don't try to send commands if the job has been canceled...
575 * Format the string...
578 va_start(ap
, format
);
579 bytes
= vsnprintf(buf
, sizeof(buf
), format
, ap
);
582 fprintf(stderr
, "DEBUG: lpd_command %2.2x %s", buf
[0], buf
+ 1);
585 * Send the command...
588 fprintf(stderr
, "DEBUG: Sending command string (%d bytes)...\n", bytes
);
590 if (lpd_write(fd
, buf
, bytes
) < bytes
)
592 perror("DEBUG: Unable to send LPD command");
597 * Read back the status from the command and return it...
600 fputs("DEBUG: Reading command status...\n", stderr
);
604 if (recv(fd
, &status
, 1, 0) < 1)
606 _cupsLangPrintFilter(stderr
, "WARNING",
607 _("Printer did not respond after %d seconds."),
614 fprintf(stderr
, "DEBUG: lpd_command returning %d\n", status
);
621 * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
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 */
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 */
665 * Setup an alarm handler for timeouts...
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
));
673 sigemptyset(&action
.sa_mask
);
674 action
.sa_handler
= lpd_timeout
;
675 sigaction(SIGALRM
, &action
, NULL
);
677 signal(SIGALRM
, lpd_timeout
);
678 #endif /* HAVE_SIGSET */
681 * Remember when we started trying to connect to the printer...
684 start_time
= time(NULL
);
687 * Loop forever trying to print the file...
693 * First try to reserve a port for this connection...
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."));
700 for (lport
= reserve
== RESERVE_RFC1179
? 732 : 1024, addr
= addrlist
,
705 * Stop if this job has been canceled...
709 return (CUPS_BACKEND_FAILED
);
712 * Choose the next priviledged port...
720 if (lport
< 721 && reserve
== RESERVE_RFC1179
)
726 if (geteuid() || !reserve
)
728 if (getuid() || !reserve
)
729 #endif /* HAVE_GETEUID */
732 * Just create a regular socket...
735 if ((fd
= socket(addr
->addr
.addr
.sa_family
, SOCK_STREAM
, 0)) < 0)
737 perror("DEBUG: Unable to create socket");
748 * We're running as root and want to comply with RFC 1179. Reserve a
749 * priviledged lport between 721 and 731...
752 if ((fd
= rresvport_af(&lport
, addr
->addr
.addr
.sa_family
)) < 0)
754 perror("DEBUG: Unable to reserve port");
762 * Connect to the printer or server...
769 return (CUPS_BACKEND_FAILED
);
772 if (!connect(fd
, &(addr
->addr
.addr
), httpAddrLength(&(addr
->addr
))))
781 if (getenv("CLASS") != NULL
)
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.
790 _cupsLangPrintFilter(stderr
, "INFO",
791 _("Unable to contact printer, queuing on next "
792 "printer in class."));
795 * Sleep 5 seconds to keep the job from requeuing too rapidly...
800 return (CUPS_BACKEND_FAILED
);
803 fprintf(stderr
, "DEBUG: Connection error: %s\n", strerror(error
));
805 if (error
== ECONNREFUSED
|| error
== EHOSTDOWN
||
806 error
== EHOSTUNREACH
)
808 if (contimeout
&& (time(NULL
) - start_time
) > contimeout
)
810 _cupsLangPrintFilter(stderr
, "ERROR",
811 _("The printer is not responding."));
812 return (CUPS_BACKEND_FAILED
);
818 _cupsLangPrintFilter(stderr
, "WARNING",
819 _("Network printer \"%s\" may not exist or "
820 "is unavailable at this time."),
825 _cupsLangPrintFilter(stderr
, "WARNING",
826 _("Network printer \"%s\" is unreachable at "
827 "this time."), hostname
);
832 _cupsLangPrintFilter(stderr
, "WARNING",
833 _("Network printer \"%s\" is busy."),
843 else if (error
== EADDRINUSE
)
846 * Try on another port...
853 _cupsLangPrintFilter(stderr
, "ERROR",
854 _("Network printer \"%s\" is not responding."),
860 fputs("STATE: -connecting-to-device\n", stderr
);
861 _cupsLangPrintFilter(stderr
, "INFO", _("Connected to printer."));
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
);
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
);
876 * See if the printer supports SNMP...
880 have_supplies
= !backendSNMPSupplies(snmp_fd
, &(addrlist
->addr
), NULL
,
886 * Check for side-channel requests...
889 backendCheckSideChannel(snmp_fd
, &(addrlist
->addr
));
892 * Next, open the print file and figure out its size...
898 * Use the size from the print file...
901 if (fstat(print_fd
, &filestats
))
905 perror("DEBUG: unable to stat print file");
906 return (CUPS_BACKEND_FAILED
);
909 filestats
.st_size
*= manual_copies
;
914 * Use a "very large value" for the size so that the printer will
915 * keep printing until we close the connection...
918 #ifdef _LARGEFILE_SOURCE
919 filestats
.st_size
= (size_t)(999999999999.0);
921 filestats
.st_size
= 2147483647;
922 #endif /* _LARGEFILE_SOURCE */
926 * Send a job header to the printer, specifying no banner page and
930 if (lpd_command(fd
, timeout
, "\002%s\n",
931 printer
)) /* Receive print job(s) */
934 return (CUPS_BACKEND_FAILED
);
937 httpGetHostname(NULL
, localhost
, sizeof(localhost
));
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
);
948 snprintf(cptr
, sizeof(control
) - (cptr
- control
),
949 "C%.31s\n" /* RFC 1179, Section 7.2 - class name <= 31 chars */
952 cptr
+= strlen(cptr
);
957 snprintf(cptr
, sizeof(control
) - (cptr
- control
), "%cdfA%03d%.15s\n",
958 format
, (int)getpid() % 1000, localhost
);
959 cptr
+= strlen(cptr
);
963 snprintf(cptr
, sizeof(control
) - (cptr
- control
),
965 "N%.131s\n", /* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */
966 (int)getpid() % 1000, localhost
, title
);
968 fprintf(stderr
, "DEBUG: Control file is:\n%s", control
);
970 if (order
== ORDER_CONTROL_DATA
)
973 * Check for side-channel requests...
976 backendCheckSideChannel(snmp_fd
, &(addr
->addr
));
979 * Send the control file...
982 if (lpd_command(fd
, timeout
, "\002%d cfA%03.3d%.15s\n", strlen(control
),
983 (int)getpid() % 1000, localhost
))
987 return (CUPS_BACKEND_FAILED
);
990 fprintf(stderr
, "DEBUG: Sending control file (%u bytes)\n",
991 (unsigned)strlen(control
));
993 if (lpd_write(fd
, control
, strlen(control
) + 1) < (strlen(control
) + 1))
996 perror("DEBUG: Unable to write control file");
1003 if (read(fd
, &status
, 1) < 1)
1005 _cupsLangPrintFilter(stderr
, "WARNING",
1006 _("Printer did not respond after %d seconds."),
1015 _cupsLangPrintFilter(stderr
, "ERROR",
1016 _("Remote host did not accept control file (%d)."),
1019 _cupsLangPrintFilter(stderr
, "INFO",
1020 _("Control file sent successfully."));
1028 * Check for side-channel requests...
1031 backendCheckSideChannel(snmp_fd
, &(addr
->addr
));
1034 * Send the print file...
1037 if (lpd_command(fd
, timeout
, "\003" CUPS_LLFMT
" dfA%03.3d%.15s\n",
1038 CUPS_LLCAST filestats
.st_size
, (int)getpid() % 1000,
1043 return (CUPS_BACKEND_FAILED
);
1046 fprintf(stderr
, "DEBUG: Sending data file (" CUPS_LLFMT
" bytes)\n",
1047 CUPS_LLCAST filestats
.st_size
);
1050 for (copy
= 0; copy
< manual_copies
; copy
++)
1052 lseek(print_fd
, 0, SEEK_SET
);
1054 while ((nbytes
= read(print_fd
, buffer
, sizeof(buffer
))) > 0)
1056 _cupsLangPrintFilter(stderr
, "INFO",
1057 _("Spooling job, %.0f%% complete."),
1058 100.0 * tbytes
/ filestats
.st_size
);
1060 if (lpd_write(fd
, buffer
, nbytes
) < nbytes
)
1062 perror("DEBUG: Unable to send print file to printer");
1070 if (mode
== MODE_STANDARD
)
1072 if (tbytes
< filestats
.st_size
)
1074 else if (lpd_write(fd
, "", 1) < 1)
1076 perror("DEBUG: Unable to send trailing nul to printer");
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...
1090 if (recv(fd
, &status
, 1, 0) < 1)
1092 _cupsLangPrintFilter(stderr
, "WARNING",
1093 _("Printer did not respond after %d seconds."),
1105 _cupsLangPrintFilter(stderr
, "ERROR",
1106 _("Remote host did not accept data file (%d)."),
1109 _cupsLangPrintFilter(stderr
, "INFO",
1110 _("Data file sent successfully."));
1113 if (status
== 0 && order
== ORDER_DATA_CONTROL
)
1116 * Check for side-channel requests...
1119 backendCheckSideChannel(snmp_fd
, &(addr
->addr
));
1122 * Send control file...
1125 if (lpd_command(fd
, timeout
, "\002%d cfA%03.3d%.15s\n", strlen(control
),
1126 (int)getpid() % 1000, localhost
))
1130 return (CUPS_BACKEND_FAILED
);
1133 fprintf(stderr
, "DEBUG: Sending control file (%lu bytes)\n",
1134 (unsigned long)strlen(control
));
1136 if (lpd_write(fd
, control
, strlen(control
) + 1) < (strlen(control
) + 1))
1139 perror("DEBUG: Unable to write control file");
1145 if (read(fd
, &status
, 1) < 1)
1147 _cupsLangPrintFilter(stderr
, "WARNING",
1148 _("Printer did not respond after %d seconds."),
1157 _cupsLangPrintFilter(stderr
, "ERROR",
1158 _("Remote host did not accept control file (%d)."),
1161 _cupsLangPrintFilter(stderr
, "INFO",
1162 _("Control file sent successfully."));
1166 * Collect the final supply levels as needed...
1170 backendSNMPSupplies(snmp_fd
, &(addr
->addr
), NULL
, NULL
);
1173 * Close the socket connection and input file...
1179 return (CUPS_BACKEND_OK
);
1182 * Waiting for a retry...
1189 * If we get here, then the job has been canceled...
1192 return (CUPS_BACKEND_FAILED
);
1197 * 'lpd_timeout()' - Handle timeout alarms...
1201 lpd_timeout(int sig
) /* I - Signal number */
1205 #if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
1206 signal(SIGALRM
, lpd_timeout
);
1207 #endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
1212 * 'lpd_write()' - Write a buffer of data to an LPD server.
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 */
1220 int bytes
, /* Number of bytes written */
1221 total
; /* Total number of bytes written */
1228 while ((bytes
= send(lpd_fd
, buffer
, length
- total
, 0)) >= 0)
1233 if (total
== length
)
1244 #ifndef HAVE_RRESVPORT_AF
1246 * 'rresvport_af()' - A simple implementation of rresvport_af().
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 */
1253 http_addr_t addr
; /* Socket address */
1254 int fd
; /* Socket file descriptor */
1258 * Try to create an IPv4 socket...
1261 if ((fd
= socket(family
, SOCK_STREAM
, 0)) < 0)
1265 * Initialize the address buffer...
1268 memset(&addr
, 0, sizeof(addr
));
1269 addr
.addr
.sa_family
= family
;
1272 * Try to bind the socket to a reserved port...
1278 * Set the port number...
1282 if (family
== AF_INET6
)
1283 addr
.ipv6
.sin6_port
= htons(*port
);
1285 # endif /* AF_INET6 */
1286 addr
.ipv4
.sin_port
= htons(*port
);
1289 * Try binding the port to the socket; return if all is OK...
1292 if (!bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)))
1296 * Stop if we have any error other than "address already in use"...
1299 if (errno
!= EADDRINUSE
)
1311 * Try the next port...
1318 * Wasn't able to bind to a reserved port, so close the socket and return
1330 #endif /* !HAVE_RRESVPORT_AF */
1334 * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
1338 sigterm_handler(int sig
) /* I - Signal */
1340 (void)sig
; /* remove compiler warnings... */
1347 * End of "$Id: lpd.c 7740 2008-07-14 23:58:05Z mike $".