• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Line Printer Daemon backend for CUPS.
3  *
4  * Copyright © 2007-2019 by Apple Inc.
5  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6  *
7  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8  * information.
9  */
10 
11 /*
12  * Include necessary headers.
13  */
14 
15 #include <cups/http-private.h>
16 #include "backend-private.h"
17 #include <stdarg.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <stdio.h>
21 
22 #ifdef _WIN32
23 #  include <winsock.h>
24 #else
25 #  include <sys/socket.h>
26 #  include <netinet/in.h>
27 #  include <arpa/inet.h>
28 #  include <netdb.h>
29 #endif /* _WIN32 */
30 #ifdef __APPLE__
31 #  include <CoreFoundation/CFNumber.h>
32 #  include <CoreFoundation/CFPreferences.h>
33 #endif /* __APPLE__ */
34 
35 
36 /*
37  * Globals...
38  */
39 
40 static char	tmpfilename[1024] = "";	/* Temporary spool file name */
41 static int	abort_job = 0;		/* Non-zero if we get SIGTERM */
42 
43 
44 /*
45  * Print mode...
46  */
47 
48 #define MODE_STANDARD		0	/* Queue a copy */
49 #define MODE_STREAM		1	/* Stream a copy */
50 
51 
52 /*
53  * The order for control and data files in LPD requests...
54  */
55 
56 #define ORDER_CONTROL_DATA	0	/* Control file first, then data */
57 #define ORDER_DATA_CONTROL	1	/* Data file first, then control */
58 
59 
60 /*
61  * What to reserve...
62  */
63 
64 #define RESERVE_NONE		0	/* Don't reserve a priviledged port */
65 #define RESERVE_RFC1179		1	/* Reserve port 721-731 */
66 #define RESERVE_ANY		2	/* Reserve port 1-1023 */
67 
68 
69 /*
70  * Local functions...
71  */
72 
73 static int	cups_rresvport(int *port, int family);
74 static int	lpd_command(int lpd_fd, char *format, ...)
75 #    ifdef __GNUC__
76 __attribute__ ((__format__ (__printf__, 2, 3)))
77 #    endif /* __GNUC__ */
78 ;
79 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));
80 static ssize_t	lpd_write(int lpd_fd, char *buffer, size_t length);
81 static void	sigterm_handler(int sig);
82 
83 
84 /*
85  * 'main()' - Send a file to the printer or server.
86  *
87  * Usage:
88  *
89  *    printer-uri job-id user title copies options [file]
90  */
91 
92 int					/* O - Exit status */
main(int argc,char * argv[])93 main(int  argc,				/* I - Number of command-line arguments (6 or 7) */
94      char *argv[])			/* I - Command-line arguments */
95 {
96   const char	*device_uri;		/* Device URI */
97   char		scheme[255],		/* Scheme in URI */
98 		hostname[1024],		/* Hostname */
99 		username[255],		/* Username info */
100 		resource[1024],		/* Resource info (printer name) */
101 		*options,		/* Pointer to options */
102 		*name,			/* Name of option */
103 		*value,			/* Value of option */
104 		sep,			/* Separator character */
105 		*filename,		/* File to print */
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 priviledged 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     filename = NULL;
464     fd       = 0;
465   }
466   else
467   {
468     filename = argv[6];
469     fd       = open(filename, O_RDONLY);
470 
471     if (fd == -1)
472     {
473       _cupsLangPrintError("ERROR", _("Unable to open print file"));
474       return (CUPS_BACKEND_FAILED);
475     }
476   }
477 
478  /*
479   * Sanitize the document title...
480   */
481 
482   strlcpy(title, argv[3], sizeof(title));
483 
484   if (sanitize_title)
485   {
486    /*
487     * Sanitize the title string so that we don't cause problems on
488     * the remote end...
489     */
490 
491     char *ptr;
492 
493     for (ptr = title; *ptr; ptr ++)
494       if (!isalnum(*ptr & 255) && !isspace(*ptr & 255))
495 	*ptr = '_';
496   }
497 
498  /*
499   * Queue the job...
500   */
501 
502   if (argc > 6)
503   {
504     if (manual_copies)
505     {
506       manual_copies = atoi(argv[4]);
507       copies        = 1;
508     }
509     else
510     {
511       manual_copies = 1;
512       copies        = atoi(argv[4]);
513     }
514 
515     status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
516                        username, title, copies, banner, format, order, reserve,
517 		       manual_copies, timeout, contimeout,
518 		       cupsGetOption("job-originating-host-name", num_jobopts,
519 		                     jobopts));
520 
521     if (!status)
522       fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4]));
523   }
524   else
525     status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
526                        username, title, 1, banner, format, order, reserve, 1,
527 		       timeout, contimeout,
528 		       cupsGetOption("job-originating-host-name", num_jobopts,
529 		                     jobopts));
530 
531  /*
532   * Remove the temporary file if necessary...
533   */
534 
535   if (tmpfilename[0])
536     unlink(tmpfilename);
537 
538   if (fd)
539     close(fd);
540 
541   if (snmp_fd >= 0)
542     _cupsSNMPClose(snmp_fd);
543 
544  /*
545   * Return the queue status...
546   */
547 
548   return (status);
549 }
550 
551 
552 /*
553  * 'cups_rresvport()' - A simple implementation of rresvport_af().
554  */
555 
556 static int				/* O  - Socket or -1 on error */
cups_rresvport(int * port,int family)557 cups_rresvport(int *port,		/* IO - Port number to bind to */
558                int family)		/* I  - Address family */
559 {
560   http_addr_t	addr;			/* Socket address */
561   int		fd;			/* Socket file descriptor */
562 
563 
564  /*
565   * Try to create an IPv4 socket...
566   */
567 
568   if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
569     return (-1);
570 
571  /*
572   * Initialize the address buffer...
573   */
574 
575   memset(&addr, 0, sizeof(addr));
576   addr.addr.sa_family = (sa_family_t)family;
577 
578  /*
579   * Try to bind the socket to a reserved port...
580   */
581 
582   while (*port > 511)
583   {
584    /*
585     * Set the port number...
586     */
587 
588     _httpAddrSetPort(&addr, *port);
589 
590    /*
591     * Try binding the port to the socket; return if all is OK...
592     */
593 
594     if (!bind(fd, (struct sockaddr *)&addr, (socklen_t)httpAddrLength(&addr)))
595       return (fd);
596 
597    /*
598     * Stop if we have any error other than "address already in use"...
599     */
600 
601     if (errno != EADDRINUSE)
602     {
603       httpAddrClose(NULL, fd);
604 
605       return (-1);
606     }
607 
608    /*
609     * Try the next port...
610     */
611 
612     (*port)--;
613   }
614 
615  /*
616   * Wasn't able to bind to a reserved port, so close the socket and return
617   * -1...
618   */
619 
620 #ifdef _WIN32
621   closesocket(fd);
622 #else
623   close(fd);
624 #endif /* _WIN32 */
625 
626   return (-1);
627 }
628 
629 
630 /*
631  * 'lpd_command()' - Send an LPR command sequence and wait for a reply.
632  */
633 
634 static int			/* O - Status of command */
lpd_command(int fd,char * format,...)635 lpd_command(int  fd,		/* I - Socket connection to LPD host */
636             char *format,	/* I - printf()-style format string */
637             ...)		/* I - Additional args as necessary */
638 {
639   va_list	ap;		/* Argument pointer */
640   char		buf[1024];	/* Output buffer */
641   ssize_t	bytes;		/* Number of bytes to output */
642   char		status;		/* Status from command */
643 
644 
645  /*
646   * Don't try to send commands if the job has been canceled...
647   */
648 
649   if (abort_job)
650     return (-1);
651 
652  /*
653   * Format the string...
654   */
655 
656   va_start(ap, format);
657   bytes = vsnprintf(buf, sizeof(buf), format, ap);
658   va_end(ap);
659 
660   fprintf(stderr, "DEBUG: lpd_command %2.2x %s", buf[0], buf + 1);
661 
662  /*
663   * Send the command...
664   */
665 
666   fprintf(stderr, "DEBUG: Sending command string (" CUPS_LLFMT " bytes)...\n", CUPS_LLCAST bytes);
667 
668   if (lpd_write(fd, buf, (size_t)bytes) < bytes)
669   {
670     perror("DEBUG: Unable to send LPD command");
671     return (-1);
672   }
673 
674  /*
675   * Read back the status from the command and return it...
676   */
677 
678   fputs("DEBUG: Reading command status...\n", stderr);
679 
680   if (recv(fd, &status, 1, 0) < 1)
681   {
682     _cupsLangPrintFilter(stderr, "WARNING", _("The printer did not respond."));
683     status = (char)errno;
684   }
685 
686   fprintf(stderr, "DEBUG: lpd_command returning %d\n", status);
687 
688   return (status);
689 }
690 
691 
692 /*
693  * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
694  */
695 
696 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)697 lpd_queue(const char      *hostname,	/* I - Host to connect to */
698           http_addrlist_t *addrlist,	/* I - List of host addresses */
699           const char      *printer,	/* I - Printer/queue name */
700 	  int             print_fd,	/* I - File to print */
701 	  int             snmp_fd,	/* I - SNMP socket */
702 	  int             mode,		/* I - Print mode */
703           const char      *user,	/* I - Requesting user */
704 	  const char      *title,	/* I - Job title */
705 	  int             copies,	/* I - Number of copies */
706 	  int             banner,	/* I - Print LPD banner? */
707           int             format,	/* I - Format specifier */
708           int             order,	/* I - Order of data/control files */
709 	  int             reserve,	/* I - Reserve ports? */
710 	  int             manual_copies,/* I - Do copies by hand... */
711 	  int             timeout,	/* I - Timeout... */
712 	  int             contimeout,	/* I - Connection timeout */
713 	  const char      *orighost)	/* I - job-originating-host-name */
714 {
715   char			localhost[255];	/* Local host name */
716   int			error;		/* Error number */
717   struct stat		filestats;	/* File statistics */
718   int			lport;		/* LPD connection local port */
719   int			fd;		/* LPD socket */
720   char			control[10240],	/* LPD control 'file' */
721 			*cptr;		/* Pointer into control file string */
722   char			status;		/* Status byte from command */
723   int			delay;		/* Delay for retries... */
724   char			addrname[256];	/* Address name */
725   http_addrlist_t	*addr;		/* Socket address */
726   int			have_supplies;	/* Printer supports supply levels? */
727   int			copy;		/* Copies written */
728   time_t		start_time;	/* Time of first connect */
729   ssize_t		nbytes;		/* Number of bytes written */
730   off_t			tbytes;		/* Total bytes written */
731   char			buffer[32768];	/* Output buffer */
732 #ifdef _WIN32
733   DWORD			tv;		/* Timeout in milliseconds */
734 #else
735   struct timeval	tv;		/* Timeout in secs and usecs */
736 #endif /* _WIN32 */
737 
738 
739  /*
740   * Remember when we started trying to connect to the printer...
741   */
742 
743   start_time = time(NULL);
744 
745  /*
746   * Loop forever trying to print the file...
747   */
748 
749   while (!abort_job)
750   {
751    /*
752     * First try to reserve a port for this connection...
753     */
754 
755     fprintf(stderr, "DEBUG: Connecting to %s:%d for printer %s\n", hostname,
756             httpAddrPort(&(addrlist->addr)), printer);
757     _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
758 
759     for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist,
760              delay = 5;;
761          addr = addr->next)
762     {
763      /*
764       * Stop if this job has been canceled...
765       */
766 
767       if (abort_job)
768         return (CUPS_BACKEND_FAILED);
769 
770      /*
771       * Choose the next priviledged port...
772       */
773 
774       if (!addr)
775         addr = addrlist;
776 
777       lport --;
778 
779       if (lport < 721 && reserve == RESERVE_RFC1179)
780 	lport = 731;
781       else if (lport < 1)
782 	lport = 1023;
783 
784 #ifdef HAVE_GETEUID
785       if (geteuid() || !reserve)
786 #else
787       if (getuid() || !reserve)
788 #endif /* HAVE_GETEUID */
789       {
790        /*
791 	* Just create a regular socket...
792 	*/
793 
794 	if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
795 	{
796 	  perror("DEBUG: Unable to create socket");
797 	  sleep(1);
798 
799           continue;
800 	}
801 
802         lport = 0;
803       }
804       else
805       {
806        /*
807 	* We're running as root and want to comply with RFC 1179.  Reserve a
808 	* priviledged lport between 721 and 731...
809 	*/
810 
811 	if ((fd = cups_rresvport(&lport, addr->addr.addr.sa_family)) < 0)
812 	{
813 	  perror("DEBUG: Unable to reserve port");
814 	  sleep(1);
815 
816 	  continue;
817 	}
818       }
819 
820      /*
821       * Connect to the printer or server...
822       */
823 
824       if (abort_job)
825       {
826 	close(fd);
827 
828 	return (CUPS_BACKEND_FAILED);
829       }
830 
831       if (!connect(fd, &(addr->addr.addr), (socklen_t)httpAddrLength(&(addr->addr))))
832 	break;
833 
834       error = errno;
835       close(fd);
836 
837       if (addr->next)
838         continue;
839 
840       if (getenv("CLASS") != NULL)
841       {
842        /*
843         * If the CLASS environment variable is set, the job was submitted
844 	* to a class and not to a specific queue.  In this case, we want
845 	* to abort immediately so that the job can be requeued on the next
846 	* available printer in the class.
847 	*/
848 
849         _cupsLangPrintFilter(stderr, "INFO",
850 			     _("Unable to contact printer, queuing on next "
851 			       "printer in class."));
852 
853        /*
854         * Sleep 5 seconds to keep the job from requeuing too rapidly...
855 	*/
856 
857 	sleep(5);
858 
859         return (CUPS_BACKEND_FAILED);
860       }
861 
862       fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));
863 
864       if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH || errno == ETIMEDOUT || errno == ENOTCONN)
865       {
866         if (contimeout && (time(NULL) - start_time) > contimeout)
867 	{
868 	  _cupsLangPrintFilter(stderr, "ERROR",
869 			       _("The printer is not responding."));
870 	  return (CUPS_BACKEND_FAILED);
871 	}
872 
873 	switch (error)
874 	{
875 	  case EHOSTDOWN :
876 	      _cupsLangPrintFilter(stderr, "WARNING",
877 			           _("The printer may not exist or "
878 			             "is unavailable at this time."));
879 	      break;
880 
881 	  case EHOSTUNREACH :
882 	  default :
883 	      _cupsLangPrintFilter(stderr, "WARNING",
884 			           _("The printer is unreachable at "
885 				     "this time."));
886 	      break;
887 
888 	  case ECONNREFUSED :
889 	      _cupsLangPrintFilter(stderr, "WARNING",
890 	                           _("The printer is in use."));
891 	      break;
892         }
893 
894 	sleep((unsigned)delay);
895 
896 	if (delay < 30)
897 	  delay += 5;
898       }
899       else if (error == EADDRINUSE)
900       {
901        /*
902 	* Try on another port...
903 	*/
904 
905 	sleep(1);
906       }
907       else
908       {
909 	_cupsLangPrintFilter(stderr, "ERROR",
910 	                     _("The printer is not responding."));
911 	sleep(30);
912       }
913     }
914 
915    /*
916     * Set the timeout...
917     */
918 
919 #ifdef _WIN32
920     tv = (DWORD)(timeout * 1000);
921 
922     setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
923     setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
924 #else
925     tv.tv_sec  = timeout;
926     tv.tv_usec = 0;
927 
928     setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
929     setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
930 #endif /* _WIN32 */
931 
932     fputs("STATE: -connecting-to-device\n", stderr);
933     _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
934 
935     fprintf(stderr, "DEBUG: Connected to %s:%d (local port %d)...\n",
936 	    httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
937 	    httpAddrPort(&(addr->addr)), lport);
938 
939    /*
940     * See if the printer supports SNMP...
941     */
942 
943     if (snmp_fd >= 0)
944       have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), NULL,
945                                            NULL);
946     else
947       have_supplies = 0;
948 
949    /*
950     * Check for side-channel requests...
951     */
952 
953     backendCheckSideChannel(snmp_fd, &(addrlist->addr));
954 
955    /*
956     * Next, open the print file and figure out its size...
957     */
958 
959     if (print_fd)
960     {
961      /*
962       * Use the size from the print file...
963       */
964 
965       if (fstat(print_fd, &filestats))
966       {
967 	close(fd);
968 
969 	perror("DEBUG: unable to stat print file");
970 	return (CUPS_BACKEND_FAILED);
971       }
972 
973       filestats.st_size *= manual_copies;
974     }
975     else
976     {
977      /*
978       * Use a "very large value" for the size so that the printer will
979       * keep printing until we close the connection...
980       */
981 
982 #ifdef _LARGEFILE_SOURCE
983       filestats.st_size = (size_t)(999999999999.0);
984 #else
985       filestats.st_size = 2147483647;
986 #endif /* _LARGEFILE_SOURCE */
987     }
988 
989    /*
990     * Send a job header to the printer, specifying no banner page and
991     * literal output...
992     */
993 
994     if (lpd_command(fd, "\002%s\n",
995                     printer))		/* Receive print job(s) */
996     {
997       close(fd);
998       return (CUPS_BACKEND_FAILED);
999     }
1000 
1001     if (orighost && _cups_strcasecmp(orighost, "localhost"))
1002       strlcpy(localhost, orighost, sizeof(localhost));
1003     else
1004       httpGetHostname(NULL, localhost, sizeof(localhost));
1005 
1006     snprintf(control, sizeof(control),
1007              "H%.31s\n"		/* RFC 1179, Section 7.2 - host name <= 31 chars */
1008 	     "P%.31s\n"		/* RFC 1179, Section 7.2 - user name <= 31 chars */
1009 	     "J%.99s\n",	/* RFC 1179, Section 7.2 - job name <= 99 chars */
1010 	     localhost, user, title);
1011     cptr = control + strlen(control);
1012 
1013     if (banner)
1014     {
1015       snprintf(cptr, sizeof(control) - (size_t)(cptr - control),
1016                "C%.31s\n"	/* RFC 1179, Section 7.2 - class name <= 31 chars */
1017 	       "L%s\n",
1018                localhost, user);
1019       cptr   += strlen(cptr);
1020     }
1021 
1022     while (copies > 0)
1023     {
1024       snprintf(cptr, sizeof(control) - (size_t)(cptr - control), "%cdfA%03d%.15s\n",
1025                format, (int)getpid() % 1000, localhost);
1026       cptr   += strlen(cptr);
1027       copies --;
1028     }
1029 
1030     snprintf(cptr, sizeof(control) - (size_t)(cptr - control),
1031              "UdfA%03d%.15s\n"
1032 	     "N%.131s\n",	/* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */
1033              (int)getpid() % 1000, localhost, title);
1034 
1035     fprintf(stderr, "DEBUG: Control file is:\n%s", control);
1036 
1037     if (order == ORDER_CONTROL_DATA)
1038     {
1039      /*
1040       * Check for side-channel requests...
1041       */
1042 
1043       backendCheckSideChannel(snmp_fd, &(addr->addr));
1044 
1045      /*
1046       * Send the control file...
1047       */
1048 
1049       if (lpd_command(fd, "\002%d cfA%03d%.15s\n", (int)strlen(control),
1050                       (int)getpid() % 1000, localhost))
1051       {
1052 	close(fd);
1053 
1054         return (CUPS_BACKEND_FAILED);
1055       }
1056 
1057       fprintf(stderr, "DEBUG: Sending control file (%u bytes)\n",
1058 	      (unsigned)strlen(control));
1059 
1060       if ((size_t)lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
1061       {
1062 	status = (char)errno;
1063 	perror("DEBUG: Unable to write control file");
1064 
1065       }
1066       else
1067       {
1068         if (read(fd, &status, 1) < 1)
1069 	{
1070 	  _cupsLangPrintFilter(stderr, "WARNING",
1071 	                       _("The printer did not respond."));
1072 	  status = (char)errno;
1073 	}
1074       }
1075 
1076       if (status != 0)
1077 	_cupsLangPrintFilter(stderr, "ERROR",
1078 			     _("Remote host did not accept control file (%d)."),
1079 			     status);
1080       else
1081 	_cupsLangPrintFilter(stderr, "INFO",
1082 	                     _("Control file sent successfully."));
1083     }
1084     else
1085       status = 0;
1086 
1087     if (status == 0)
1088     {
1089      /*
1090       * Check for side-channel requests...
1091       */
1092 
1093       backendCheckSideChannel(snmp_fd, &(addr->addr));
1094 
1095      /*
1096       * Send the print file...
1097       */
1098 
1099       if (lpd_command(fd, "\003" CUPS_LLFMT " dfA%03d%.15s\n",
1100                       CUPS_LLCAST filestats.st_size, (int)getpid() % 1000,
1101 		      localhost))
1102       {
1103 	close(fd);
1104 
1105         return (CUPS_BACKEND_FAILED);
1106       }
1107 
1108       fprintf(stderr, "DEBUG: Sending data file (" CUPS_LLFMT " bytes)\n",
1109 	      CUPS_LLCAST filestats.st_size);
1110 
1111       tbytes = 0;
1112       for (copy = 0; copy < manual_copies; copy ++)
1113       {
1114 	lseek(print_fd, 0, SEEK_SET);
1115 
1116 	while ((nbytes = read(print_fd, buffer, sizeof(buffer))) > 0)
1117 	{
1118 	  _cupsLangPrintFilter(stderr, "INFO",
1119 			       _("Spooling job, %.0f%% complete."),
1120 			       100.0 * tbytes / filestats.st_size);
1121 
1122 	  if (lpd_write(fd, buffer, (size_t)nbytes) < nbytes)
1123 	  {
1124 	    perror("DEBUG: Unable to send print file to printer");
1125             break;
1126 	  }
1127 	  else
1128             tbytes += nbytes;
1129 	}
1130       }
1131 
1132       if (mode == MODE_STANDARD)
1133       {
1134 	if (tbytes < filestats.st_size)
1135 	  status = (char)errno;
1136 	else if (lpd_write(fd, "", 1) < 1)
1137 	{
1138 	  perror("DEBUG: Unable to send trailing nul to printer");
1139 	  status = (char)errno;
1140 	}
1141 	else
1142 	{
1143 	 /*
1144           * Read the status byte from the printer; if we can't read the byte
1145 	  * back now, we should set status to "errno", however at this point
1146 	  * we know the printer got the whole file and we don't necessarily
1147 	  * want to requeue it over and over...
1148 	  */
1149 
1150           if (recv(fd, &status, 1, 0) < 1)
1151 	  {
1152 	    _cupsLangPrintFilter(stderr, "WARNING",
1153 			         _("The printer did not respond."));
1154 	    status = 0;
1155           }
1156 	}
1157       }
1158       else
1159         status = 0;
1160 
1161       if (status != 0)
1162 	_cupsLangPrintFilter(stderr, "ERROR",
1163 			     _("Remote host did not accept data file (%d)."),
1164 			     status);
1165       else
1166 	_cupsLangPrintFilter(stderr, "INFO",
1167 	                     _("Data file sent successfully."));
1168     }
1169 
1170     if (status == 0 && order == ORDER_DATA_CONTROL)
1171     {
1172      /*
1173       * Check for side-channel requests...
1174       */
1175 
1176       backendCheckSideChannel(snmp_fd, &(addr->addr));
1177 
1178      /*
1179       * Send control file...
1180       */
1181 
1182       if (lpd_command(fd, "\002%d cfA%03d%.15s\n", (int)strlen(control),
1183                       (int)getpid() % 1000, localhost))
1184       {
1185 	close(fd);
1186 
1187         return (CUPS_BACKEND_FAILED);
1188       }
1189 
1190       fprintf(stderr, "DEBUG: Sending control file (%lu bytes)\n",
1191 	      (unsigned long)strlen(control));
1192 
1193       if ((size_t)lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
1194       {
1195 	status = (char)errno;
1196 	perror("DEBUG: Unable to write control file");
1197       }
1198       else
1199       {
1200         if (read(fd, &status, 1) < 1)
1201 	{
1202 	  _cupsLangPrintFilter(stderr, "WARNING",
1203 			       _("The printer did not respond."));
1204 	  status = (char)errno;
1205 	}
1206       }
1207 
1208       if (status != 0)
1209 	_cupsLangPrintFilter(stderr, "ERROR",
1210 			     _("Remote host did not accept control file (%d)."),
1211 			     status);
1212       else
1213 	_cupsLangPrintFilter(stderr, "INFO",
1214 	                     _("Control file sent successfully."));
1215     }
1216 
1217     fputs("STATE: +cups-waiting-for-job-completed\n", stderr);
1218 
1219    /*
1220     * Collect the final supply levels as needed...
1221     */
1222 
1223     if (have_supplies)
1224       backendSNMPSupplies(snmp_fd, &(addr->addr), NULL, NULL);
1225 
1226    /*
1227     * Close the socket connection and input file...
1228     */
1229 
1230     close(fd);
1231 
1232     if (status == 0)
1233       return (CUPS_BACKEND_OK);
1234 
1235    /*
1236     * Waiting for a retry...
1237     */
1238 
1239     sleep(30);
1240   }
1241 
1242  /*
1243   * If we get here, then the job has been canceled...
1244   */
1245 
1246   return (CUPS_BACKEND_FAILED);
1247 }
1248 
1249 
1250 /*
1251  * 'lpd_write()' - Write a buffer of data to an LPD server.
1252  */
1253 
1254 static ssize_t				/* O - Number of bytes written or -1 on error */
lpd_write(int lpd_fd,char * buffer,size_t length)1255 lpd_write(int     lpd_fd,		/* I - LPD socket */
1256           char    *buffer,		/* I - Buffer to write */
1257 	  size_t  length)		/* I - Number of bytes to write */
1258 {
1259   ssize_t	bytes,			/* Number of bytes written */
1260 		total;			/* Total number of bytes written */
1261 
1262 
1263   if (abort_job)
1264     return (-1);
1265 
1266   total = 0;
1267   while ((bytes = send(lpd_fd, buffer, length - (size_t)total, 0)) >= 0)
1268   {
1269     total  += bytes;
1270     buffer += bytes;
1271 
1272     if ((size_t)total == length)
1273       break;
1274   }
1275 
1276   if (bytes < 0)
1277     return (-1);
1278   else
1279     return (total);
1280 }
1281 
1282 
1283 /*
1284  * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
1285  */
1286 
1287 static void
sigterm_handler(int sig)1288 sigterm_handler(int sig)		/* I - Signal */
1289 {
1290   (void)sig;	/* remove compiler warnings... */
1291 
1292   abort_job = 1;
1293 }
1294