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