xref: /aosp_15_r20/external/libcups/backend/socket.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * AppSocket backend for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers.
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include <cups/http-private.h>
16*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
17*5e7646d2SAndroid Build Coastguard Worker #include <stdarg.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <sys/types.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <sys/stat.h>
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
22*5e7646d2SAndroid Build Coastguard Worker #  include <winsock.h>
23*5e7646d2SAndroid Build Coastguard Worker #else
24*5e7646d2SAndroid Build Coastguard Worker #  include <unistd.h>
25*5e7646d2SAndroid Build Coastguard Worker #  include <fcntl.h>
26*5e7646d2SAndroid Build Coastguard Worker #  include <sys/socket.h>
27*5e7646d2SAndroid Build Coastguard Worker #  include <netinet/in.h>
28*5e7646d2SAndroid Build Coastguard Worker #  include <arpa/inet.h>
29*5e7646d2SAndroid Build Coastguard Worker #  include <netdb.h>
30*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
31*5e7646d2SAndroid Build Coastguard Worker 
32*5e7646d2SAndroid Build Coastguard Worker 
33*5e7646d2SAndroid Build Coastguard Worker /*
34*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
35*5e7646d2SAndroid Build Coastguard Worker  */
36*5e7646d2SAndroid Build Coastguard Worker 
37*5e7646d2SAndroid Build Coastguard Worker static ssize_t	wait_bc(int device_fd, int secs);
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker 
40*5e7646d2SAndroid Build Coastguard Worker /*
41*5e7646d2SAndroid Build Coastguard Worker  * 'main()' - Send a file to the printer or server.
42*5e7646d2SAndroid Build Coastguard Worker  *
43*5e7646d2SAndroid Build Coastguard Worker  * Usage:
44*5e7646d2SAndroid Build Coastguard Worker  *
45*5e7646d2SAndroid Build Coastguard Worker  *    printer-uri job-id user title copies options [file]
46*5e7646d2SAndroid Build Coastguard Worker  */
47*5e7646d2SAndroid Build Coastguard Worker 
48*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit status */
main(int argc,char * argv[])49*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line arguments (6 or 7) */
50*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
51*5e7646d2SAndroid Build Coastguard Worker {
52*5e7646d2SAndroid Build Coastguard Worker   const char	*device_uri;		/* Device URI */
53*5e7646d2SAndroid Build Coastguard Worker   char		scheme[255],		/* Scheme in URI */
54*5e7646d2SAndroid Build Coastguard Worker 		hostname[1024],		/* Hostname */
55*5e7646d2SAndroid Build Coastguard Worker 		username[255],		/* Username info (not used) */
56*5e7646d2SAndroid Build Coastguard Worker 		resource[1024],		/* Resource info (not used) */
57*5e7646d2SAndroid Build Coastguard Worker 		*options,		/* Pointer to options */
58*5e7646d2SAndroid Build Coastguard Worker 		*name,			/* Name of option */
59*5e7646d2SAndroid Build Coastguard Worker 		*value,			/* Value of option */
60*5e7646d2SAndroid Build Coastguard Worker 		sep;			/* Option separator */
61*5e7646d2SAndroid Build Coastguard Worker   int		print_fd;		/* Print file */
62*5e7646d2SAndroid Build Coastguard Worker   int		copies;			/* Number of copies to print */
63*5e7646d2SAndroid Build Coastguard Worker   time_t	start_time;		/* Time of first connect */
64*5e7646d2SAndroid Build Coastguard Worker   int		contimeout;		/* Connection timeout */
65*5e7646d2SAndroid Build Coastguard Worker   int		waiteof;		/* Wait for end-of-file? */
66*5e7646d2SAndroid Build Coastguard Worker   int		port;			/* Port number */
67*5e7646d2SAndroid Build Coastguard Worker   int		delay;			/* Delay for retries... */
68*5e7646d2SAndroid Build Coastguard Worker   int		device_fd;		/* AppSocket */
69*5e7646d2SAndroid Build Coastguard Worker   int		error;			/* Error code (if any) */
70*5e7646d2SAndroid Build Coastguard Worker   http_addrlist_t *addrlist,		/* Address list */
71*5e7646d2SAndroid Build Coastguard Worker 		*addr;			/* Connected address */
72*5e7646d2SAndroid Build Coastguard Worker   char		addrname[256];		/* Address name */
73*5e7646d2SAndroid Build Coastguard Worker   int		snmp_enabled = 1;	/* Is SNMP enabled? */
74*5e7646d2SAndroid Build Coastguard Worker   int		snmp_fd,		/* SNMP socket */
75*5e7646d2SAndroid Build Coastguard Worker 		start_count,		/* Page count via SNMP at start */
76*5e7646d2SAndroid Build Coastguard Worker 		page_count,		/* Page count via SNMP */
77*5e7646d2SAndroid Build Coastguard Worker 		have_supplies;		/* Printer supports supply levels? */
78*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes = 0,		/* Initial bytes read */
79*5e7646d2SAndroid Build Coastguard Worker 		tbytes;			/* Total number of bytes written */
80*5e7646d2SAndroid Build Coastguard Worker   char		buffer[1024];		/* Initial print buffer */
81*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
82*5e7646d2SAndroid Build Coastguard Worker   struct sigaction action;		/* Actions for POSIX signals */
83*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
84*5e7646d2SAndroid Build Coastguard Worker 
85*5e7646d2SAndroid Build Coastguard Worker 
86*5e7646d2SAndroid Build Coastguard Worker  /*
87*5e7646d2SAndroid Build Coastguard Worker   * Make sure status messages are not buffered...
88*5e7646d2SAndroid Build Coastguard Worker   */
89*5e7646d2SAndroid Build Coastguard Worker 
90*5e7646d2SAndroid Build Coastguard Worker   setbuf(stderr, NULL);
91*5e7646d2SAndroid Build Coastguard Worker 
92*5e7646d2SAndroid Build Coastguard Worker  /*
93*5e7646d2SAndroid Build Coastguard Worker   * Ignore SIGPIPE signals...
94*5e7646d2SAndroid Build Coastguard Worker   */
95*5e7646d2SAndroid Build Coastguard Worker 
96*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET
97*5e7646d2SAndroid Build Coastguard Worker   sigset(SIGPIPE, SIG_IGN);
98*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
99*5e7646d2SAndroid Build Coastguard Worker   memset(&action, 0, sizeof(action));
100*5e7646d2SAndroid Build Coastguard Worker   action.sa_handler = SIG_IGN;
101*5e7646d2SAndroid Build Coastguard Worker   sigaction(SIGPIPE, &action, NULL);
102*5e7646d2SAndroid Build Coastguard Worker #else
103*5e7646d2SAndroid Build Coastguard Worker   signal(SIGPIPE, SIG_IGN);
104*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
105*5e7646d2SAndroid Build Coastguard Worker 
106*5e7646d2SAndroid Build Coastguard Worker  /*
107*5e7646d2SAndroid Build Coastguard Worker   * Check command-line...
108*5e7646d2SAndroid Build Coastguard Worker   */
109*5e7646d2SAndroid Build Coastguard Worker 
110*5e7646d2SAndroid Build Coastguard Worker   if (argc == 1)
111*5e7646d2SAndroid Build Coastguard Worker   {
112*5e7646d2SAndroid Build Coastguard Worker     printf("network socket \"Unknown\" \"%s\"\n",
113*5e7646d2SAndroid Build Coastguard Worker            _cupsLangString(cupsLangDefault(), _("AppSocket/HP JetDirect")));
114*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_OK);
115*5e7646d2SAndroid Build Coastguard Worker   }
116*5e7646d2SAndroid Build Coastguard Worker   else if (argc < 6 || argc > 7)
117*5e7646d2SAndroid Build Coastguard Worker   {
118*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintf(stderr,
119*5e7646d2SAndroid Build Coastguard Worker                     _("Usage: %s job-id user title copies options [file]"),
120*5e7646d2SAndroid Build Coastguard Worker                     argv[0]);
121*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_FAILED);
122*5e7646d2SAndroid Build Coastguard Worker   }
123*5e7646d2SAndroid Build Coastguard Worker 
124*5e7646d2SAndroid Build Coastguard Worker  /*
125*5e7646d2SAndroid Build Coastguard Worker   * If we have 7 arguments, print the file named on the command-line.
126*5e7646d2SAndroid Build Coastguard Worker   * Otherwise, send stdin instead...
127*5e7646d2SAndroid Build Coastguard Worker   */
128*5e7646d2SAndroid Build Coastguard Worker 
129*5e7646d2SAndroid Build Coastguard Worker   if (argc == 6)
130*5e7646d2SAndroid Build Coastguard Worker   {
131*5e7646d2SAndroid Build Coastguard Worker     print_fd = 0;
132*5e7646d2SAndroid Build Coastguard Worker     copies   = 1;
133*5e7646d2SAndroid Build Coastguard Worker   }
134*5e7646d2SAndroid Build Coastguard Worker   else
135*5e7646d2SAndroid Build Coastguard Worker   {
136*5e7646d2SAndroid Build Coastguard Worker    /*
137*5e7646d2SAndroid Build Coastguard Worker     * Try to open the print file...
138*5e7646d2SAndroid Build Coastguard Worker     */
139*5e7646d2SAndroid Build Coastguard Worker 
140*5e7646d2SAndroid Build Coastguard Worker     if ((print_fd = open(argv[6], O_RDONLY)) < 0)
141*5e7646d2SAndroid Build Coastguard Worker     {
142*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintError("ERROR", _("Unable to open print file"));
143*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_FAILED);
144*5e7646d2SAndroid Build Coastguard Worker     }
145*5e7646d2SAndroid Build Coastguard Worker 
146*5e7646d2SAndroid Build Coastguard Worker     copies = atoi(argv[4]);
147*5e7646d2SAndroid Build Coastguard Worker   }
148*5e7646d2SAndroid Build Coastguard Worker 
149*5e7646d2SAndroid Build Coastguard Worker  /*
150*5e7646d2SAndroid Build Coastguard Worker   * Extract the hostname and port number from the URI...
151*5e7646d2SAndroid Build Coastguard Worker   */
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker   while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
154*5e7646d2SAndroid Build Coastguard Worker   {
155*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
156*5e7646d2SAndroid Build Coastguard Worker     sleep(10);
157*5e7646d2SAndroid Build Coastguard Worker 
158*5e7646d2SAndroid Build Coastguard Worker     if (getenv("CLASS") != NULL)
159*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_FAILED);
160*5e7646d2SAndroid Build Coastguard Worker   }
161*5e7646d2SAndroid Build Coastguard Worker 
162*5e7646d2SAndroid Build Coastguard Worker   httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
163*5e7646d2SAndroid Build Coastguard Worker                   username, sizeof(username), hostname, sizeof(hostname), &port,
164*5e7646d2SAndroid Build Coastguard Worker 		  resource, sizeof(resource));
165*5e7646d2SAndroid Build Coastguard Worker 
166*5e7646d2SAndroid Build Coastguard Worker   if (port == 0)
167*5e7646d2SAndroid Build Coastguard Worker     port = 9100;	/* Default to HP JetDirect/Tektronix PhaserShare */
168*5e7646d2SAndroid Build Coastguard Worker 
169*5e7646d2SAndroid Build Coastguard Worker  /*
170*5e7646d2SAndroid Build Coastguard Worker   * Get options, if any...
171*5e7646d2SAndroid Build Coastguard Worker   */
172*5e7646d2SAndroid Build Coastguard Worker 
173*5e7646d2SAndroid Build Coastguard Worker   waiteof    = 1;
174*5e7646d2SAndroid Build Coastguard Worker   contimeout = 7 * 24 * 60 * 60;
175*5e7646d2SAndroid Build Coastguard Worker 
176*5e7646d2SAndroid Build Coastguard Worker   if ((options = strchr(resource, '?')) != NULL)
177*5e7646d2SAndroid Build Coastguard Worker   {
178*5e7646d2SAndroid Build Coastguard Worker    /*
179*5e7646d2SAndroid Build Coastguard Worker     * Yup, terminate the device name string and move to the first
180*5e7646d2SAndroid Build Coastguard Worker     * character of the options...
181*5e7646d2SAndroid Build Coastguard Worker     */
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker     *options++ = '\0';
184*5e7646d2SAndroid Build Coastguard Worker 
185*5e7646d2SAndroid Build Coastguard Worker    /*
186*5e7646d2SAndroid Build Coastguard Worker     * Parse options...
187*5e7646d2SAndroid Build Coastguard Worker     */
188*5e7646d2SAndroid Build Coastguard Worker 
189*5e7646d2SAndroid Build Coastguard Worker     while (*options)
190*5e7646d2SAndroid Build Coastguard Worker     {
191*5e7646d2SAndroid Build Coastguard Worker      /*
192*5e7646d2SAndroid Build Coastguard Worker       * Get the name...
193*5e7646d2SAndroid Build Coastguard Worker       */
194*5e7646d2SAndroid Build Coastguard Worker 
195*5e7646d2SAndroid Build Coastguard Worker       name = options;
196*5e7646d2SAndroid Build Coastguard Worker 
197*5e7646d2SAndroid Build Coastguard Worker       while (*options && *options != '=' && *options != '+' && *options != '&')
198*5e7646d2SAndroid Build Coastguard Worker         options ++;
199*5e7646d2SAndroid Build Coastguard Worker 
200*5e7646d2SAndroid Build Coastguard Worker       if ((sep = *options) != '\0')
201*5e7646d2SAndroid Build Coastguard Worker         *options++ = '\0';
202*5e7646d2SAndroid Build Coastguard Worker 
203*5e7646d2SAndroid Build Coastguard Worker       if (sep == '=')
204*5e7646d2SAndroid Build Coastguard Worker       {
205*5e7646d2SAndroid Build Coastguard Worker        /*
206*5e7646d2SAndroid Build Coastguard Worker         * Get the value...
207*5e7646d2SAndroid Build Coastguard Worker 	*/
208*5e7646d2SAndroid Build Coastguard Worker 
209*5e7646d2SAndroid Build Coastguard Worker         value = options;
210*5e7646d2SAndroid Build Coastguard Worker 
211*5e7646d2SAndroid Build Coastguard Worker 	while (*options && *options != '+' && *options != '&')
212*5e7646d2SAndroid Build Coastguard Worker 	  options ++;
213*5e7646d2SAndroid Build Coastguard Worker 
214*5e7646d2SAndroid Build Coastguard Worker         if (*options)
215*5e7646d2SAndroid Build Coastguard Worker 	  *options++ = '\0';
216*5e7646d2SAndroid Build Coastguard Worker       }
217*5e7646d2SAndroid Build Coastguard Worker       else
218*5e7646d2SAndroid Build Coastguard Worker         value = (char *)"";
219*5e7646d2SAndroid Build Coastguard Worker 
220*5e7646d2SAndroid Build Coastguard Worker      /*
221*5e7646d2SAndroid Build Coastguard Worker       * Process the option...
222*5e7646d2SAndroid Build Coastguard Worker       */
223*5e7646d2SAndroid Build Coastguard Worker 
224*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(name, "waiteof"))
225*5e7646d2SAndroid Build Coastguard Worker       {
226*5e7646d2SAndroid Build Coastguard Worker        /*
227*5e7646d2SAndroid Build Coastguard Worker         * Set the wait-for-eof value...
228*5e7646d2SAndroid Build Coastguard Worker 	*/
229*5e7646d2SAndroid Build Coastguard Worker 
230*5e7646d2SAndroid Build Coastguard Worker         waiteof = !value[0] || !_cups_strcasecmp(value, "on") ||
231*5e7646d2SAndroid Build Coastguard Worker 		  !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
232*5e7646d2SAndroid Build Coastguard Worker       }
233*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "snmp"))
234*5e7646d2SAndroid Build Coastguard Worker       {
235*5e7646d2SAndroid Build Coastguard Worker         /*
236*5e7646d2SAndroid Build Coastguard Worker          * Enable/disable SNMP stuff...
237*5e7646d2SAndroid Build Coastguard Worker          */
238*5e7646d2SAndroid Build Coastguard Worker 
239*5e7646d2SAndroid Build Coastguard Worker          snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") ||
240*5e7646d2SAndroid Build Coastguard Worker                         !_cups_strcasecmp(value, "yes") ||
241*5e7646d2SAndroid Build Coastguard Worker                         !_cups_strcasecmp(value, "true");
242*5e7646d2SAndroid Build Coastguard Worker       }
243*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "contimeout"))
244*5e7646d2SAndroid Build Coastguard Worker       {
245*5e7646d2SAndroid Build Coastguard Worker        /*
246*5e7646d2SAndroid Build Coastguard Worker         * Set the connection timeout...
247*5e7646d2SAndroid Build Coastguard Worker 	*/
248*5e7646d2SAndroid Build Coastguard Worker 
249*5e7646d2SAndroid Build Coastguard Worker 	if (atoi(value) > 0)
250*5e7646d2SAndroid Build Coastguard Worker 	  contimeout = atoi(value);
251*5e7646d2SAndroid Build Coastguard Worker       }
252*5e7646d2SAndroid Build Coastguard Worker     }
253*5e7646d2SAndroid Build Coastguard Worker   }
254*5e7646d2SAndroid Build Coastguard Worker 
255*5e7646d2SAndroid Build Coastguard Worker  /*
256*5e7646d2SAndroid Build Coastguard Worker   * Then try finding the remote host...
257*5e7646d2SAndroid Build Coastguard Worker   */
258*5e7646d2SAndroid Build Coastguard Worker 
259*5e7646d2SAndroid Build Coastguard Worker   start_time = time(NULL);
260*5e7646d2SAndroid Build Coastguard Worker 
261*5e7646d2SAndroid Build Coastguard Worker   addrlist = backendLookup(hostname, port, NULL);
262*5e7646d2SAndroid Build Coastguard Worker 
263*5e7646d2SAndroid Build Coastguard Worker  /*
264*5e7646d2SAndroid Build Coastguard Worker   * See if the printer supports SNMP...
265*5e7646d2SAndroid Build Coastguard Worker   */
266*5e7646d2SAndroid Build Coastguard Worker 
267*5e7646d2SAndroid Build Coastguard Worker   if (snmp_enabled)
268*5e7646d2SAndroid Build Coastguard Worker     snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
269*5e7646d2SAndroid Build Coastguard Worker   else
270*5e7646d2SAndroid Build Coastguard Worker     snmp_fd = -1;
271*5e7646d2SAndroid Build Coastguard Worker 
272*5e7646d2SAndroid Build Coastguard Worker   if (snmp_fd >= 0)
273*5e7646d2SAndroid Build Coastguard Worker     have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr),
274*5e7646d2SAndroid Build Coastguard Worker                                          &start_count, NULL);
275*5e7646d2SAndroid Build Coastguard Worker   else
276*5e7646d2SAndroid Build Coastguard Worker     have_supplies = start_count = 0;
277*5e7646d2SAndroid Build Coastguard Worker 
278*5e7646d2SAndroid Build Coastguard Worker  /*
279*5e7646d2SAndroid Build Coastguard Worker   * Wait for data from the filter...
280*5e7646d2SAndroid Build Coastguard Worker   */
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker   if (print_fd == 0)
283*5e7646d2SAndroid Build Coastguard Worker   {
284*5e7646d2SAndroid Build Coastguard Worker     if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 1, backendNetworkSideCB))
285*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_OK);
286*5e7646d2SAndroid Build Coastguard Worker     else if ((bytes = read(0, buffer, sizeof(buffer))) <= 0)
287*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_OK);
288*5e7646d2SAndroid Build Coastguard Worker   }
289*5e7646d2SAndroid Build Coastguard Worker 
290*5e7646d2SAndroid Build Coastguard Worker  /*
291*5e7646d2SAndroid Build Coastguard Worker   * Connect to the printer...
292*5e7646d2SAndroid Build Coastguard Worker   */
293*5e7646d2SAndroid Build Coastguard Worker 
294*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
295*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
296*5e7646d2SAndroid Build Coastguard Worker 
297*5e7646d2SAndroid Build Coastguard Worker   for (delay = 5;;)
298*5e7646d2SAndroid Build Coastguard Worker   {
299*5e7646d2SAndroid Build Coastguard Worker     if ((addr = httpAddrConnect(addrlist, &device_fd)) == NULL)
300*5e7646d2SAndroid Build Coastguard Worker     {
301*5e7646d2SAndroid Build Coastguard Worker       error     = errno;
302*5e7646d2SAndroid Build Coastguard Worker       device_fd = -1;
303*5e7646d2SAndroid Build Coastguard Worker 
304*5e7646d2SAndroid Build Coastguard Worker       if (getenv("CLASS") != NULL)
305*5e7646d2SAndroid Build Coastguard Worker       {
306*5e7646d2SAndroid Build Coastguard Worker        /*
307*5e7646d2SAndroid Build Coastguard Worker         * If the CLASS environment variable is set, the job was submitted
308*5e7646d2SAndroid Build Coastguard Worker 	* to a class and not to a specific queue.  In this case, we want
309*5e7646d2SAndroid Build Coastguard Worker 	* to abort immediately so that the job can be requeued on the next
310*5e7646d2SAndroid Build Coastguard Worker 	* available printer in the class.
311*5e7646d2SAndroid Build Coastguard Worker 	*/
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPrintFilter(stderr, "INFO",
314*5e7646d2SAndroid Build Coastguard Worker 			     _("Unable to contact printer, queuing on next "
315*5e7646d2SAndroid Build Coastguard Worker 			       "printer in class."));
316*5e7646d2SAndroid Build Coastguard Worker 
317*5e7646d2SAndroid Build Coastguard Worker        /*
318*5e7646d2SAndroid Build Coastguard Worker         * Sleep 5 seconds to keep the job from requeuing too rapidly...
319*5e7646d2SAndroid Build Coastguard Worker 	*/
320*5e7646d2SAndroid Build Coastguard Worker 
321*5e7646d2SAndroid Build Coastguard Worker 	sleep(5);
322*5e7646d2SAndroid Build Coastguard Worker 
323*5e7646d2SAndroid Build Coastguard Worker         return (CUPS_BACKEND_FAILED);
324*5e7646d2SAndroid Build Coastguard Worker       }
325*5e7646d2SAndroid Build Coastguard Worker 
326*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));
327*5e7646d2SAndroid Build Coastguard Worker 
328*5e7646d2SAndroid Build Coastguard Worker       if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH || errno == ETIMEDOUT || errno == ENOTCONN)
329*5e7646d2SAndroid Build Coastguard Worker       {
330*5e7646d2SAndroid Build Coastguard Worker         if (contimeout && (time(NULL) - start_time) > contimeout)
331*5e7646d2SAndroid Build Coastguard Worker 	{
332*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "ERROR",
333*5e7646d2SAndroid Build Coastguard Worker 	                       _("The printer is not responding."));
334*5e7646d2SAndroid Build Coastguard Worker 	  return (CUPS_BACKEND_FAILED);
335*5e7646d2SAndroid Build Coastguard Worker 	}
336*5e7646d2SAndroid Build Coastguard Worker 
337*5e7646d2SAndroid Build Coastguard Worker 	switch (error)
338*5e7646d2SAndroid Build Coastguard Worker 	{
339*5e7646d2SAndroid Build Coastguard Worker 	  case EHOSTDOWN :
340*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintFilter(stderr, "WARNING",
341*5e7646d2SAndroid Build Coastguard Worker 				   _("The printer may not exist or "
342*5e7646d2SAndroid Build Coastguard Worker 				     "is unavailable at this time."));
343*5e7646d2SAndroid Build Coastguard Worker 	      break;
344*5e7646d2SAndroid Build Coastguard Worker 
345*5e7646d2SAndroid Build Coastguard Worker 	  case EHOSTUNREACH :
346*5e7646d2SAndroid Build Coastguard Worker 	  default :
347*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintFilter(stderr, "WARNING",
348*5e7646d2SAndroid Build Coastguard Worker 				   _("The printer is unreachable at this "
349*5e7646d2SAndroid Build Coastguard Worker 				     "time."));
350*5e7646d2SAndroid Build Coastguard Worker 	      break;
351*5e7646d2SAndroid Build Coastguard Worker 
352*5e7646d2SAndroid Build Coastguard Worker 	  case ECONNREFUSED :
353*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintFilter(stderr, "WARNING",
354*5e7646d2SAndroid Build Coastguard Worker 	                           _("The printer is in use."));
355*5e7646d2SAndroid Build Coastguard Worker 	      break;
356*5e7646d2SAndroid Build Coastguard Worker         }
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker 	sleep((unsigned)delay);
359*5e7646d2SAndroid Build Coastguard Worker 
360*5e7646d2SAndroid Build Coastguard Worker 	if (delay < 30)
361*5e7646d2SAndroid Build Coastguard Worker 	  delay += 5;
362*5e7646d2SAndroid Build Coastguard Worker       }
363*5e7646d2SAndroid Build Coastguard Worker       else
364*5e7646d2SAndroid Build Coastguard Worker       {
365*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "ERROR",
366*5e7646d2SAndroid Build Coastguard Worker 	                     _("The printer is not responding."));
367*5e7646d2SAndroid Build Coastguard Worker 	sleep(30);
368*5e7646d2SAndroid Build Coastguard Worker       }
369*5e7646d2SAndroid Build Coastguard Worker     }
370*5e7646d2SAndroid Build Coastguard Worker     else
371*5e7646d2SAndroid Build Coastguard Worker       break;
372*5e7646d2SAndroid Build Coastguard Worker   }
373*5e7646d2SAndroid Build Coastguard Worker 
374*5e7646d2SAndroid Build Coastguard Worker   fputs("STATE: -connecting-to-device\n", stderr);
375*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: Connected to %s:%d...\n",
378*5e7646d2SAndroid Build Coastguard Worker 	  httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
379*5e7646d2SAndroid Build Coastguard Worker 	  httpAddrPort(&(addr->addr)));
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker  /*
382*5e7646d2SAndroid Build Coastguard Worker   * Print everything...
383*5e7646d2SAndroid Build Coastguard Worker   */
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker   tbytes = 0;
386*5e7646d2SAndroid Build Coastguard Worker 
387*5e7646d2SAndroid Build Coastguard Worker   if (bytes > 0)
388*5e7646d2SAndroid Build Coastguard Worker     tbytes += write(device_fd, buffer, (size_t)bytes);
389*5e7646d2SAndroid Build Coastguard Worker 
390*5e7646d2SAndroid Build Coastguard Worker   while (copies > 0 && tbytes >= 0)
391*5e7646d2SAndroid Build Coastguard Worker   {
392*5e7646d2SAndroid Build Coastguard Worker     copies --;
393*5e7646d2SAndroid Build Coastguard Worker 
394*5e7646d2SAndroid Build Coastguard Worker     if (print_fd != 0)
395*5e7646d2SAndroid Build Coastguard Worker     {
396*5e7646d2SAndroid Build Coastguard Worker       fputs("PAGE: 1 1\n", stderr);
397*5e7646d2SAndroid Build Coastguard Worker       lseek(print_fd, 0, SEEK_SET);
398*5e7646d2SAndroid Build Coastguard Worker     }
399*5e7646d2SAndroid Build Coastguard Worker 
400*5e7646d2SAndroid Build Coastguard Worker     if ((bytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1, 0, backendNetworkSideCB)) < 0)
401*5e7646d2SAndroid Build Coastguard Worker       tbytes = -1;
402*5e7646d2SAndroid Build Coastguard Worker     else
403*5e7646d2SAndroid Build Coastguard Worker       tbytes = bytes;
404*5e7646d2SAndroid Build Coastguard Worker 
405*5e7646d2SAndroid Build Coastguard Worker     if (print_fd != 0 && tbytes >= 0)
406*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
407*5e7646d2SAndroid Build Coastguard Worker   }
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker   fputs("STATE: +cups-waiting-for-job-completed\n", stderr);
410*5e7646d2SAndroid Build Coastguard Worker 
411*5e7646d2SAndroid Build Coastguard Worker   if (waiteof && tbytes >= 0)
412*5e7646d2SAndroid Build Coastguard Worker   {
413*5e7646d2SAndroid Build Coastguard Worker    /*
414*5e7646d2SAndroid Build Coastguard Worker     * Shutdown the socket and wait for the other end to finish...
415*5e7646d2SAndroid Build Coastguard Worker     */
416*5e7646d2SAndroid Build Coastguard Worker 
417*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "INFO", _("Waiting for printer to finish."));
418*5e7646d2SAndroid Build Coastguard Worker 
419*5e7646d2SAndroid Build Coastguard Worker     shutdown(device_fd, 1);
420*5e7646d2SAndroid Build Coastguard Worker 
421*5e7646d2SAndroid Build Coastguard Worker     while (wait_bc(device_fd, 90) > 0);
422*5e7646d2SAndroid Build Coastguard Worker   }
423*5e7646d2SAndroid Build Coastguard Worker 
424*5e7646d2SAndroid Build Coastguard Worker  /*
425*5e7646d2SAndroid Build Coastguard Worker   * Collect the final page count as needed...
426*5e7646d2SAndroid Build Coastguard Worker   */
427*5e7646d2SAndroid Build Coastguard Worker 
428*5e7646d2SAndroid Build Coastguard Worker   if (have_supplies &&
429*5e7646d2SAndroid Build Coastguard Worker       !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &page_count, NULL) &&
430*5e7646d2SAndroid Build Coastguard Worker       page_count > start_count)
431*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
432*5e7646d2SAndroid Build Coastguard Worker 
433*5e7646d2SAndroid Build Coastguard Worker  /*
434*5e7646d2SAndroid Build Coastguard Worker   * Close the socket connection...
435*5e7646d2SAndroid Build Coastguard Worker   */
436*5e7646d2SAndroid Build Coastguard Worker 
437*5e7646d2SAndroid Build Coastguard Worker   close(device_fd);
438*5e7646d2SAndroid Build Coastguard Worker 
439*5e7646d2SAndroid Build Coastguard Worker   httpAddrFreeList(addrlist);
440*5e7646d2SAndroid Build Coastguard Worker 
441*5e7646d2SAndroid Build Coastguard Worker  /*
442*5e7646d2SAndroid Build Coastguard Worker   * Close the input file and return...
443*5e7646d2SAndroid Build Coastguard Worker   */
444*5e7646d2SAndroid Build Coastguard Worker 
445*5e7646d2SAndroid Build Coastguard Worker   if (print_fd != 0)
446*5e7646d2SAndroid Build Coastguard Worker     close(print_fd);
447*5e7646d2SAndroid Build Coastguard Worker 
448*5e7646d2SAndroid Build Coastguard Worker   return (tbytes >= 0 ? CUPS_BACKEND_OK : CUPS_BACKEND_FAILED);
449*5e7646d2SAndroid Build Coastguard Worker }
450*5e7646d2SAndroid Build Coastguard Worker 
451*5e7646d2SAndroid Build Coastguard Worker 
452*5e7646d2SAndroid Build Coastguard Worker /*
453*5e7646d2SAndroid Build Coastguard Worker  * 'wait_bc()' - Wait for back-channel data...
454*5e7646d2SAndroid Build Coastguard Worker  */
455*5e7646d2SAndroid Build Coastguard Worker 
456*5e7646d2SAndroid Build Coastguard Worker static ssize_t				/* O - # bytes read or -1 on error */
wait_bc(int device_fd,int secs)457*5e7646d2SAndroid Build Coastguard Worker wait_bc(int device_fd,			/* I - Socket */
458*5e7646d2SAndroid Build Coastguard Worker         int secs)			/* I - Seconds to wait */
459*5e7646d2SAndroid Build Coastguard Worker {
460*5e7646d2SAndroid Build Coastguard Worker   struct timeval timeout;		/* Timeout for select() */
461*5e7646d2SAndroid Build Coastguard Worker   fd_set	input;			/* Input set for select() */
462*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes;			/* Number of back-channel bytes read */
463*5e7646d2SAndroid Build Coastguard Worker   char		buffer[1024];		/* Back-channel buffer */
464*5e7646d2SAndroid Build Coastguard Worker 
465*5e7646d2SAndroid Build Coastguard Worker 
466*5e7646d2SAndroid Build Coastguard Worker  /*
467*5e7646d2SAndroid Build Coastguard Worker   * Wait up to "secs" seconds for backchannel data...
468*5e7646d2SAndroid Build Coastguard Worker   */
469*5e7646d2SAndroid Build Coastguard Worker 
470*5e7646d2SAndroid Build Coastguard Worker   timeout.tv_sec  = secs;
471*5e7646d2SAndroid Build Coastguard Worker   timeout.tv_usec = 0;
472*5e7646d2SAndroid Build Coastguard Worker 
473*5e7646d2SAndroid Build Coastguard Worker   FD_ZERO(&input);
474*5e7646d2SAndroid Build Coastguard Worker   FD_SET(device_fd, &input);
475*5e7646d2SAndroid Build Coastguard Worker 
476*5e7646d2SAndroid Build Coastguard Worker   if (select(device_fd + 1, &input, NULL, NULL, &timeout) > 0)
477*5e7646d2SAndroid Build Coastguard Worker   {
478*5e7646d2SAndroid Build Coastguard Worker    /*
479*5e7646d2SAndroid Build Coastguard Worker     * Grab the data coming back and spit it out to stderr...
480*5e7646d2SAndroid Build Coastguard Worker     */
481*5e7646d2SAndroid Build Coastguard Worker 
482*5e7646d2SAndroid Build Coastguard Worker     if ((bytes = read(device_fd, buffer, sizeof(buffer))) > 0)
483*5e7646d2SAndroid Build Coastguard Worker     {
484*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Received %d bytes of back-channel data\n",
485*5e7646d2SAndroid Build Coastguard Worker 	      (int)bytes);
486*5e7646d2SAndroid Build Coastguard Worker       cupsBackChannelWrite(buffer, (size_t)bytes, 1.0);
487*5e7646d2SAndroid Build Coastguard Worker     }
488*5e7646d2SAndroid Build Coastguard Worker 
489*5e7646d2SAndroid Build Coastguard Worker     return (bytes);
490*5e7646d2SAndroid Build Coastguard Worker   }
491*5e7646d2SAndroid Build Coastguard Worker   else
492*5e7646d2SAndroid Build Coastguard Worker     return (-1);
493*5e7646d2SAndroid Build Coastguard Worker }
494