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