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