2 * "$Id: lpd.c 6403 2007-03-27 16:00:56Z mike $"
4 * Line Printer Daemon backend for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * main() - Send a file to the printer or server.
29 * lpd_command() - Send an LPR command sequence and wait for a reply.
30 * lpd_queue() - Queue a file using the Line Printer Daemon protocol.
31 * lpd_timeout() - Handle timeout alarms...
32 * lpd_write() - Write a buffer of data to an LPD server.
33 * rresvport_af() - A simple implementation of rresvport_af().
34 * sigterm_handler() - Handle 'terminate' signals that stop the backend.
38 * Include necessary headers.
41 #include <cups/backend.h>
42 #include <cups/http-private.h>
43 #include <cups/cups.h>
44 #include <cups/i18n.h>
49 #include <cups/string.h>
51 #include <sys/types.h>
58 # include <sys/socket.h>
59 # include <netinet/in.h>
60 # include <arpa/inet.h>
64 # include <CoreFoundation/CFNumber.h>
65 # include <CoreFoundation/CFPreferences.h>
66 #endif /* __APPLE__ */
73 static char tmpfilename
[1024] = ""; /* Temporary spool file name */
74 static int abort_job
= 0; /* Non-zero if we get SIGTERM */
81 #define MODE_STANDARD 0 /* Queue a copy */
82 #define MODE_STREAM 1 /* Stream a copy */
86 * The order for control and data files in LPD requests...
89 #define ORDER_CONTROL_DATA 0 /* Control file first, then data */
90 #define ORDER_DATA_CONTROL 1 /* Data file first, then control */
97 #define RESERVE_NONE 0 /* Don't reserve a priviledged port */
98 #define RESERVE_RFC1179 1 /* Reserve port 721-731 */
99 #define RESERVE_ANY 2 /* Reserve port 1-1023 */
106 static int lpd_command(int lpd_fd
, int timeout
, char *format
, ...);
107 static int lpd_queue(const char *hostname
, int port
, const char *printer
,
108 int print_fd
, int mode
, const char *user
,
109 const char *title
, int copies
, int banner
,
110 int format
, int order
, int reserve
,
111 int manual_copies
, int timeout
, int contimeout
);
112 static void lpd_timeout(int sig
);
113 static int lpd_write(int lpd_fd
, char *buffer
, int length
);
114 #ifndef HAVE_RRESVPORT_AF
115 static int rresvport_af(int *port
, int family
);
116 #endif /* !HAVE_RRESVPORT_AF */
117 static void sigterm_handler(int sig
);
121 * 'main()' - Send a file to the printer or server.
125 * printer-uri job-id user title copies options [file]
128 int /* O - Exit status */
129 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
130 char *argv
[]) /* I - Command-line arguments */
132 char method
[255], /* Method in URI */
133 hostname
[1024], /* Hostname */
134 username
[255], /* Username info */
135 resource
[1024], /* Resource info (printer name) */
136 *options
, /* Pointer to options */
137 name
[255], /* Name of option */
138 value
[255], /* Value of option */
139 *ptr
, /* Pointer into name or value */
140 *filename
, /* File to print */
141 title
[256]; /* Title string */
142 int port
; /* Port number */
143 int fd
; /* Print file */
144 int status
; /* Status of LPD job */
145 int mode
; /* Print mode */
146 int banner
; /* Print banner page? */
147 int format
; /* Print format */
148 int order
; /* Order of control/data files */
149 int reserve
; /* Reserve priviledged port? */
150 int sanitize_title
; /* Sanitize title string? */
151 int manual_copies
, /* Do manual copies? */
152 timeout
, /* Timeout */
153 contimeout
, /* Connection timeout */
154 copies
; /* Number of copies */
155 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
156 struct sigaction action
; /* Actions for POSIX signals */
157 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
161 * Make sure status messages are not buffered...
164 setbuf(stderr
, NULL
);
167 * Ignore SIGPIPE and catch SIGTERM signals...
171 sigset(SIGPIPE
, SIG_IGN
);
172 sigset(SIGTERM
, sigterm_handler
);
173 #elif defined(HAVE_SIGACTION)
174 memset(&action
, 0, sizeof(action
));
175 action
.sa_handler
= SIG_IGN
;
176 sigaction(SIGPIPE
, &action
, NULL
);
178 sigemptyset(&action
.sa_mask
);
179 sigaddset(&action
.sa_mask
, SIGTERM
);
180 action
.sa_handler
= sigterm_handler
;
181 sigaction(SIGTERM
, &action
, NULL
);
183 signal(SIGPIPE
, SIG_IGN
);
184 signal(SIGTERM
, sigterm_handler
);
185 #endif /* HAVE_SIGSET */
188 * Check command-line...
193 puts("network lpd \"Unknown\" \"LPD/LPR Host or Printer\"");
194 return (CUPS_BACKEND_OK
);
196 else if (argc
< 6 || argc
> 7)
198 fprintf(stderr
, _("Usage: %s job-id user title copies options [file]\n"),
200 return (CUPS_BACKEND_FAILED
);
204 * Extract the hostname and printer name from the URI...
207 httpSeparateURI(HTTP_URI_CODING_ALL
, cupsBackendDeviceURI(argv
),
208 method
, sizeof(method
), username
, sizeof(username
),
209 hostname
, sizeof(hostname
), &port
,
210 resource
, sizeof(resource
));
215 * If no username is in the device URI, then use the print job user...
218 strlcpy(username
, argv
[2], sizeof(username
));
222 * See if there are any options...
225 mode
= MODE_STANDARD
;
228 order
= ORDER_CONTROL_DATA
;
229 reserve
= RESERVE_ANY
;
232 contimeout
= 7 * 24 * 60 * 60;
236 * We want to pass utf-8 characters, not re-map them (3071945)
242 * Get the default timeout from a system preference...
246 CFPropertyListRef pvalue
; /* Preference value */
247 SInt32 toval
; /* Timeout value */
250 pvalue
= CFPreferencesCopyValue(CFSTR("timeout"),
251 CFSTR("com.apple.print.backends"),
252 kCFPreferencesAnyUser
,
253 kCFPreferencesCurrentHost
);
256 if (CFGetTypeID(pvalue
) == CFNumberGetTypeID())
258 CFNumberGetValue(pvalue
, kCFNumberSInt32Type
, &toval
);
259 contimeout
= (int)toval
;
267 #endif /* __APPLE__ */
269 if ((options
= strchr(resource
, '?')) != NULL
)
272 * Yup, terminate the device name string and move to the first
273 * character of the options...
288 for (ptr
= name
; *options
&& *options
!= '=';)
289 if (ptr
< (name
+ sizeof(name
) - 1))
301 for (ptr
= value
; *options
&& *options
!= '+' && *options
!= '&';)
302 if (ptr
< (value
+ sizeof(value
) - 1))
306 if (*options
== '+' || *options
== '&')
313 * Process the option...
316 if (!strcasecmp(name
, "banner"))
322 banner
= !value
[0] || !strcasecmp(value
, "on") ||
323 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
325 else if (!strcasecmp(name
, "format") && value
[0])
328 * Set output format...
331 if (strchr("cdfglnoprtv", value
[0]))
334 fprintf(stderr
, _("ERROR: Unknown format character \"%c\"\n"),
337 else if (!strcasecmp(name
, "mode") && value
[0])
340 * Set control/data order...
343 if (!strcasecmp(value
, "standard"))
344 order
= MODE_STANDARD
;
345 else if (!strcasecmp(value
, "stream"))
348 fprintf(stderr
, _("ERROR: Unknown print mode \"%s\"\n"), value
);
350 else if (!strcasecmp(name
, "order") && value
[0])
353 * Set control/data order...
356 if (!strcasecmp(value
, "control,data"))
357 order
= ORDER_CONTROL_DATA
;
358 else if (!strcasecmp(value
, "data,control"))
359 order
= ORDER_DATA_CONTROL
;
361 fprintf(stderr
, _("ERROR: Unknown file order \"%s\"\n"), value
);
363 else if (!strcasecmp(name
, "reserve"))
366 * Set port reservation mode...
369 if (!value
[0] || !strcasecmp(value
, "on") ||
370 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true") ||
371 !strcasecmp(value
, "rfc1179"))
372 reserve
= RESERVE_RFC1179
;
373 else if (!strcasecmp(value
, "any"))
374 reserve
= RESERVE_ANY
;
376 reserve
= RESERVE_NONE
;
378 else if (!strcasecmp(name
, "manual_copies"))
381 * Set manual copies...
384 manual_copies
= !value
[0] || !strcasecmp(value
, "on") ||
385 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
387 else if (!strcasecmp(name
, "sanitize_title"))
390 * Set sanitize title...
393 sanitize_title
= !value
[0] || !strcasecmp(value
, "on") ||
394 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
396 else if (!strcasecmp(name
, "timeout"))
403 timeout
= atoi(value
);
405 else if (!strcasecmp(name
, "contimeout"))
408 * Set the connection timeout...
412 contimeout
= atoi(value
);
417 if (mode
== MODE_STREAM
)
418 order
= ORDER_CONTROL_DATA
;
421 * If we have 7 arguments, print the file named on the command-line.
422 * Otherwise, copy stdin to a temporary file and print the temporary
426 if (argc
== 6 && mode
== MODE_STANDARD
)
429 * Copy stdin to a temporary file...
432 char buffer
[8192]; /* Buffer for copying */
433 int bytes
; /* Number of bytes read */
436 if ((fd
= cupsTempFd(tmpfilename
, sizeof(tmpfilename
))) < 0)
438 perror("ERROR: unable to create temporary file");
439 return (CUPS_BACKEND_FAILED
);
442 while ((bytes
= fread(buffer
, 1, sizeof(buffer
), stdin
)) > 0)
443 if (write(fd
, buffer
, bytes
) < bytes
)
445 perror("ERROR: unable to write to temporary file");
448 return (CUPS_BACKEND_FAILED
);
451 filename
= tmpfilename
;
456 * Stream from stdin...
465 fd
= open(filename
, O_RDONLY
);
469 fprintf(stderr
, _("ERROR: Unable to open print file %s: %s\n"),
470 filename
, strerror(errno
));
471 return (CUPS_BACKEND_FAILED
);
476 * Sanitize the document title...
479 strlcpy(title
, argv
[3], sizeof(title
));
484 * Sanitize the title string so that we don't cause problems on
488 for (ptr
= title
; *ptr
; ptr
++)
489 if (!isalnum(*ptr
& 255) && !isspace(*ptr
& 255))
501 manual_copies
= atoi(argv
[4]);
507 copies
= atoi(argv
[4]);
510 status
= lpd_queue(hostname
, port
, resource
+ 1, fd
, mode
,
511 username
, title
, copies
,
512 banner
, format
, order
, reserve
, manual_copies
,
513 timeout
, contimeout
);
516 fprintf(stderr
, "PAGE: 1 %d\n", atoi(argv
[4]));
519 status
= lpd_queue(hostname
, port
, resource
+ 1, fd
, mode
,
521 banner
, format
, order
, reserve
, 1,
522 timeout
, contimeout
);
525 * Remove the temporary file if necessary...
535 * Return the queue status...
543 * 'lpd_command()' - Send an LPR command sequence and wait for a reply.
546 static int /* O - Status of command */
547 lpd_command(int fd
, /* I - Socket connection to LPD host */
548 int timeout
, /* I - Seconds to wait for a response */
549 char *format
, /* I - printf()-style format string */
550 ...) /* I - Additional args as necessary */
552 va_list ap
; /* Argument pointer */
553 char buf
[1024]; /* Output buffer */
554 int bytes
; /* Number of bytes to output */
555 char status
; /* Status from command */
559 * Don't try to send commands if the job has been cancelled...
566 * Format the string...
569 va_start(ap
, format
);
570 bytes
= vsnprintf(buf
, sizeof(buf
), format
, ap
);
573 fprintf(stderr
, "DEBUG: lpd_command %2.2x %s", buf
[0], buf
+ 1);
576 * Send the command...
579 fprintf(stderr
, "DEBUG: Sending command string (%d bytes)...\n", bytes
);
581 if (lpd_write(fd
, buf
, bytes
) < bytes
)
583 perror("ERROR: Unable to send LPD command");
588 * Read back the status from the command and return it...
591 fputs("DEBUG: Reading command status...\n", stderr
);
595 if (recv(fd
, &status
, 1, 0) < 1)
598 _("WARNING: Remote host did not respond with command status "
599 "byte after %d seconds!\n"), timeout
);
605 fprintf(stderr
, "DEBUG: lpd_command returning %d\n", status
);
612 * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
615 static int /* O - Zero on success, non-zero on failure */
616 lpd_queue(const char *hostname
, /* I - Host to connect to */
617 int port
, /* I - Port to connect on */
618 const char *printer
, /* I - Printer/queue name */
619 int print_fd
, /* I - File to print */
620 int mode
, /* I - Print mode */
621 const char *user
, /* I - Requesting user */
622 const char *title
, /* I - Job title */
623 int copies
, /* I - Number of copies */
624 int banner
, /* I - Print LPD banner? */
625 int format
, /* I - Format specifier */
626 int order
, /* I - Order of data/control files */
627 int reserve
, /* I - Reserve ports? */
628 int manual_copies
, /* I - Do copies by hand... */
629 int timeout
, /* I - Timeout... */
630 int contimeout
) /* I - Connection timeout */
632 char localhost
[255]; /* Local host name */
633 int error
; /* Error number */
634 struct stat filestats
; /* File statistics */
635 int lport
; /* LPD connection local port */
636 int fd
; /* LPD socket */
637 char control
[10240], /* LPD control 'file' */
638 *cptr
; /* Pointer into control file string */
639 char status
; /* Status byte from command */
640 char portname
[255]; /* Port name */
641 int delay
; /* Delay for retries... */
642 char addrname
[256]; /* Address name */
643 http_addrlist_t
*addrlist
, /* Address list */
644 *addr
; /* Socket address */
645 int copy
; /* Copies written */
646 time_t start_time
; /* Time of first connect */
647 int recoverable
; /* Recoverable error shown? */
648 size_t nbytes
; /* Number of bytes written */
649 off_t tbytes
; /* Total bytes written */
650 char buffer
[32768]; /* Output buffer */
651 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
652 struct sigaction action
; /* Actions for POSIX signals */
653 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
657 * Setup an alarm handler for timeouts...
660 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
661 sigset(SIGALRM
, lpd_timeout
);
662 #elif defined(HAVE_SIGACTION)
663 memset(&action
, 0, sizeof(action
));
665 sigemptyset(&action
.sa_mask
);
666 action
.sa_handler
= lpd_timeout
;
667 sigaction(SIGALRM
, &action
, NULL
);
669 signal(SIGALRM
, lpd_timeout
);
670 #endif /* HAVE_SIGSET */
673 * Find the printer...
676 sprintf(portname
, "%d", port
);
678 if ((addrlist
= httpAddrGetList(hostname
, AF_UNSPEC
, portname
)) == NULL
)
680 fprintf(stderr
, _("ERROR: Unable to locate printer \'%s\'!\n"), hostname
);
681 return (CUPS_BACKEND_STOP
);
685 * Remember when we started trying to connect to the printer...
689 start_time
= time(NULL
);
692 * Loop forever trying to print the file...
698 * First try to reserve a port for this connection...
701 fputs("STATE: +connecting-to-device\n", stderr
);
703 _("INFO: Attempting to connect to host %s for printer %s\n"),
706 for (lport
= reserve
== RESERVE_RFC1179
? 732 : 1024, addr
= addrlist
,
711 * Stop if this job has been cancelled...
716 httpAddrFreeList(addrlist
);
718 return (CUPS_BACKEND_FAILED
);
722 * Choose the next priviledged port...
730 if (lport
< 721 && reserve
== RESERVE_RFC1179
)
736 if (geteuid() || !reserve
)
738 if (getuid() || !reserve
)
739 #endif /* HAVE_GETEUID */
742 * Just create a regular socket...
745 if ((fd
= socket(addr
->addr
.addr
.sa_family
, SOCK_STREAM
, 0)) < 0)
747 perror("ERROR: Unable to create socket");
758 * We're running as root and want to comply with RFC 1179. Reserve a
759 * priviledged lport between 721 and 731...
762 if ((fd
= rresvport_af(&lport
, addr
->addr
.addr
.sa_family
)) < 0)
764 perror("ERROR: Unable to reserve port");
772 * Connect to the printer or server...
777 httpAddrFreeList(addrlist
);
781 return (CUPS_BACKEND_FAILED
);
784 if (!connect(fd
, &(addr
->addr
.addr
), httpAddrLength(&(addr
->addr
))))
794 if (getenv("CLASS") != NULL
)
797 * If the CLASS environment variable is set, the job was submitted
798 * to a class and not to a specific queue. In this case, we want
799 * to abort immediately so that the job can be requeued on the next
800 * available printer in the class.
803 fputs(_("INFO: Unable to contact printer, queuing on next "
804 "printer in class...\n"), stderr
);
806 httpAddrFreeList(addrlist
);
809 * Sleep 5 seconds to keep the job from requeuing too rapidly...
814 return (CUPS_BACKEND_FAILED
);
817 if (error
== ECONNREFUSED
|| error
== EHOSTDOWN
||
818 error
== EHOSTUNREACH
)
820 if (contimeout
&& (time(NULL
) - start_time
) > contimeout
)
822 fputs(_("ERROR: Printer not responding!\n"), stderr
);
823 return (CUPS_BACKEND_FAILED
);
829 _("WARNING: recoverable: Network host \'%s\' is busy; will "
830 "retry in %d seconds...\n"),
838 else if (error
== EADDRINUSE
)
841 * Try on another port...
850 fprintf(stderr
, "DEBUG: Connection error: %s\n", strerror(errno
));
851 fputs(_("ERROR: recoverable: Unable to connect to printer; will "
852 "retry in 30 seconds...\n"), stderr
);
860 * If we've shown a recoverable error make sure the printer proxies
861 * have a chance to see the recovered message. Not pretty but
862 * necessary for now...
865 fputs("INFO: recovered: \n", stderr
);
869 fputs("STATE: -connecting-to-device\n", stderr
);
870 fprintf(stderr
, _("INFO: Connected to %s...\n"), hostname
);
873 if (addr
->addr
.addr
.sa_family
== AF_INET6
)
874 fprintf(stderr
, "DEBUG: Connected to [%s]:%d (IPv6) (local port %d)...\n",
875 httpAddrString(&addr
->addr
, addrname
, sizeof(addrname
)),
876 ntohs(addr
->addr
.ipv6
.sin6_port
), lport
);
878 #endif /* AF_INET6 */
879 if (addr
->addr
.addr
.sa_family
== AF_INET
)
880 fprintf(stderr
, "DEBUG: Connected to %s:%d (IPv4) (local port %d)...\n",
881 httpAddrString(&addr
->addr
, addrname
, sizeof(addrname
)),
882 ntohs(addr
->addr
.ipv4
.sin_port
), lport
);
885 * Next, open the print file and figure out its size...
891 * Use the size from the print file...
894 if (fstat(print_fd
, &filestats
))
896 httpAddrFreeList(addrlist
);
899 perror("ERROR: unable to stat print file");
900 return (CUPS_BACKEND_FAILED
);
903 filestats
.st_size
*= manual_copies
;
908 * Use a "very large value" for the size so that the printer will
909 * keep printing until we close the connection...
912 #ifdef _LARGEFILE_SOURCE
913 filestats
.st_size
= (size_t)(999999999999.0);
915 filestats
.st_size
= 2147483647;
916 #endif /* _LARGEFILE_SOURCE */
920 * Send a job header to the printer, specifying no banner page and
924 if (lpd_command(fd
, timeout
, "\002%s\n",
925 printer
)) /* Receive print job(s) */
927 httpAddrFreeList(addrlist
);
929 return (CUPS_BACKEND_FAILED
);
932 httpGetHostname(NULL
, localhost
, sizeof(localhost
));
934 snprintf(control
, sizeof(control
),
935 "H%.31s\n" /* RFC 1179, Section 7.2 - host name <= 31 chars */
936 "P%.31s\n" /* RFC 1179, Section 7.2 - user name <= 31 chars */
937 "J%.99s\n", /* RFC 1179, Section 7.2 - job name <= 99 chars */
938 localhost
, user
, title
);
939 cptr
= control
+ strlen(control
);
943 snprintf(cptr
, sizeof(control
) - (cptr
- control
),
944 "C%.31s\n" /* RFC 1179, Section 7.2 - class name <= 31 chars */
947 cptr
+= strlen(cptr
);
952 snprintf(cptr
, sizeof(control
) - (cptr
- control
), "%cdfA%03d%.15s\n",
953 format
, (int)getpid() % 1000, localhost
);
954 cptr
+= strlen(cptr
);
958 snprintf(cptr
, sizeof(control
) - (cptr
- control
),
960 "N%.131s\n", /* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */
961 (int)getpid() % 1000, localhost
, title
);
963 fprintf(stderr
, "DEBUG: Control file is:\n%s", control
);
965 if (order
== ORDER_CONTROL_DATA
)
967 if (lpd_command(fd
, timeout
, "\002%d cfA%03.3d%.15s\n", strlen(control
),
968 (int)getpid() % 1000, localhost
))
970 httpAddrFreeList(addrlist
);
973 return (CUPS_BACKEND_FAILED
);
976 fprintf(stderr
, _("INFO: Sending control file (%u bytes)\n"),
977 (unsigned)strlen(control
));
979 if (lpd_write(fd
, control
, strlen(control
) + 1) < (strlen(control
) + 1))
982 perror("ERROR: Unable to write control file");
988 if (read(fd
, &status
, 1) < 1)
991 _("WARNING: Remote host did not respond with control "
992 "status byte after %d seconds!\n"), timeout
);
1001 _("ERROR: Remote host did not accept control file (%d)\n"),
1004 fputs(_("INFO: Control file sent successfully\n"), stderr
);
1012 * Send the print file...
1015 if (lpd_command(fd
, timeout
, "\003" CUPS_LLFMT
" dfA%03.3d%.15s\n",
1016 CUPS_LLCAST filestats
.st_size
, (int)getpid() % 1000,
1019 httpAddrFreeList(addrlist
);
1022 return (CUPS_BACKEND_FAILED
);
1026 #ifdef HAVE_LONG_LONG
1027 _("INFO: Sending data file (%lld bytes)\n"),
1029 _("INFO: Sending data file (%ld bytes)\n"),
1030 #endif /* HAVE_LONG_LONG */
1031 CUPS_LLCAST filestats
.st_size
);
1034 for (copy
= 0; copy
< manual_copies
; copy
++)
1036 lseek(print_fd
, 0, SEEK_SET
);
1038 while ((nbytes
= read(print_fd
, buffer
, sizeof(buffer
))) > 0)
1040 fprintf(stderr
, _("INFO: Spooling LPR job, %.0f%% complete...\n"),
1041 100.0 * tbytes
/ filestats
.st_size
);
1043 if (lpd_write(fd
, buffer
, nbytes
) < nbytes
)
1045 perror("ERROR: Unable to send print file to printer");
1053 if (mode
== MODE_STANDARD
)
1055 if (tbytes
< filestats
.st_size
)
1057 else if (lpd_write(fd
, "", 1) < 1)
1059 perror("ERROR: Unable to send trailing nul to printer");
1065 * Read the status byte from the printer; if we can't read the byte
1066 * back now, we should set status to "errno", however at this point
1067 * we know the printer got the whole file and we don't necessarily
1068 * want to requeue it over and over...
1073 if (recv(fd
, &status
, 1, 0) < 1)
1076 _("WARNING: Remote host did not respond with data "
1077 "status byte after %d seconds!\n"), timeout
);
1088 fprintf(stderr
, _("ERROR: Remote host did not accept data file (%d)\n"),
1091 fputs(_("INFO: Data file sent successfully\n"), stderr
);
1094 if (status
== 0 && order
== ORDER_DATA_CONTROL
)
1096 if (lpd_command(fd
, timeout
, "\002%d cfA%03.3d%.15s\n", strlen(control
),
1097 (int)getpid() % 1000, localhost
))
1099 httpAddrFreeList(addrlist
);
1102 return (CUPS_BACKEND_FAILED
);
1105 fprintf(stderr
, _("INFO: Sending control file (%lu bytes)\n"),
1106 (unsigned long)strlen(control
));
1108 if (lpd_write(fd
, control
, strlen(control
) + 1) < (strlen(control
) + 1))
1111 perror("ERROR: Unable to write control file");
1117 if (read(fd
, &status
, 1) < 1)
1120 _("WARNING: Remote host did not respond with control "
1121 "status byte after %d seconds!\n"), timeout
);
1130 _("ERROR: Remote host did not accept control file (%d)\n"),
1133 fputs(_("INFO: Control file sent successfully\n"), stderr
);
1137 * Close the socket connection and input file...
1144 httpAddrFreeList(addrlist
);
1146 return (CUPS_BACKEND_OK
);
1150 * Waiting for a retry...
1156 httpAddrFreeList(addrlist
);
1159 * If we get here, then the job has been cancelled...
1162 return (CUPS_BACKEND_FAILED
);
1167 * 'lpd_timeout()' - Handle timeout alarms...
1171 lpd_timeout(int sig
) /* I - Signal number */
1175 #if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
1176 signal(SIGALRM
, lpd_timeout
);
1177 #endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
1182 * 'lpd_write()' - Write a buffer of data to an LPD server.
1185 static int /* O - Number of bytes written or -1 on error */
1186 lpd_write(int lpd_fd
, /* I - LPD socket */
1187 char *buffer
, /* I - Buffer to write */
1188 int length
) /* I - Number of bytes to write */
1190 int bytes
, /* Number of bytes written */
1191 total
; /* Total number of bytes written */
1198 while ((bytes
= send(lpd_fd
, buffer
, length
- total
, 0)) >= 0)
1203 if (total
== length
)
1214 #ifndef HAVE_RRESVPORT_AF
1216 * 'rresvport_af()' - A simple implementation of rresvport_af().
1219 static int /* O - Socket or -1 on error */
1220 rresvport_af(int *port
, /* IO - Port number to bind to */
1221 int family
) /* I - Address family */
1223 http_addr_t addr
; /* Socket address */
1224 int fd
; /* Socket file descriptor */
1228 * Try to create an IPv4 socket...
1231 if ((fd
= socket(family
, SOCK_STREAM
, 0)) < 0)
1235 * Initialize the address buffer...
1238 memset(&addr
, 0, sizeof(addr
));
1239 addr
.addr
.sa_family
= family
;
1242 * Try to bind the socket to a reserved port...
1248 * Set the port number...
1252 if (family
== AF_INET6
)
1253 addr
.ipv6
.sin6_port
= htons(*port
);
1255 # endif /* AF_INET6 */
1256 addr
.ipv4
.sin_port
= htons(*port
);
1259 * Try binding the port to the socket; return if all is OK...
1262 if (!bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)))
1266 * Stop if we have any error other than "address already in use"...
1269 if (errno
!= EADDRINUSE
)
1281 * Try the next port...
1288 * Wasn't able to bind to a reserved port, so close the socket and return
1300 #endif /* !HAVE_RRESVPORT_AF */
1304 * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
1308 sigterm_handler(int sig
) /* I - Signal */
1310 (void)sig
; /* remove compiler warnings... */
1317 * End of "$Id: lpd.c 6403 2007-03-27 16:00:56Z mike $".