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