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