]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/runloop.c
Update more IPP strings.
[thirdparty/cups.git] / backend / runloop.c
CommitLineData
ed486911 1/*
5a1d7a17 2 * Common run loop APIs for CUPS backends.
ed486911 3 *
53f8d64f
MS
4 * Copyright © 2007-2014 by Apple Inc.
5 * Copyright © 2006-2007 by Easy Software Products, all rights reserved.
ed486911 6 *
53f8d64f
MS
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
8 * information.
ed486911 9 */
10
11/*
12 * Include necessary headers.
13 */
14
15#include "backend-private.h"
568fa3fa 16#include <limits.h>
5a1d7a17 17#include <sys/select.h>
ed486911 18
19
09a101d6 20/*
21 * 'backendDrainOutput()' - Drain pending print data to the device.
22 */
23
24int /* O - 0 on success, -1 on error */
25backendDrainOutput(int print_fd, /* I - Print file descriptor */
26 int device_fd) /* I - Device file descriptor */
27{
28 int nfds; /* Maximum file descriptor value + 1 */
29 fd_set input; /* Input set for reading */
30 ssize_t print_bytes, /* Print bytes read */
31 bytes; /* Bytes written */
32 char print_buffer[8192], /* Print data buffer */
33 *print_ptr; /* Pointer into print data buffer */
34 struct timeval timeout; /* Timeout for read... */
35
36
37 fprintf(stderr, "DEBUG: backendDrainOutput(print_fd=%d, device_fd=%d)\n",
38 print_fd, device_fd);
39
40 /*
41 * Figure out the maximum file descriptor value to use with select()...
42 */
43
44 nfds = (print_fd > device_fd ? print_fd : device_fd) + 1;
45
46 /*
47 * Now loop until we are out of data from print_fd...
48 */
49
50 for (;;)
51 {
52 /*
53 * Use select() to determine whether we have data to copy around...
54 */
55
56 FD_ZERO(&input);
57 FD_SET(print_fd, &input);
58
59 timeout.tv_sec = 0;
60 timeout.tv_usec = 0;
61
62 if (select(nfds, &input, NULL, NULL, &timeout) < 0)
63 return (-1);
64
65 if (!FD_ISSET(print_fd, &input))
66 return (0);
67
68 if ((print_bytes = read(print_fd, print_buffer,
69 sizeof(print_buffer))) < 0)
70 {
71 /*
72 * Read error - bail if we don't see EAGAIN or EINTR...
73 */
74
0b1399a2 75 if (errno != EAGAIN && errno != EINTR)
09a101d6 76 {
f3c17241
MS
77 fprintf(stderr, "DEBUG: Read failed: %s\n", strerror(errno));
78 _cupsLangPrintFilter(stderr, "ERROR", _("Unable to read print data."));
09a101d6 79 return (-1);
80 }
81
82 print_bytes = 0;
83 }
84 else if (print_bytes == 0)
85 {
86 /*
87 * End of file, return...
88 */
89
90 return (0);
91 }
92
93 fprintf(stderr, "DEBUG: Read %d bytes of print data...\n",
94 (int)print_bytes);
95
96 for (print_ptr = print_buffer; print_bytes > 0;)
97 {
7e86f2f6 98 if ((bytes = write(device_fd, print_ptr, (size_t)print_bytes)) < 0)
09a101d6 99 {
100 /*
101 * Write error - bail if we don't see an error we can retry...
102 */
103
104 if (errno != ENOSPC && errno != ENXIO && errno != EAGAIN &&
105 errno != EINTR && errno != ENOTTY)
106 {
0837b7e8 107 _cupsLangPrintError("ERROR", _("Unable to write print data"));
09a101d6 108 return (-1);
109 }
110 }
111 else
112 {
113 fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes);
114
115 print_bytes -= bytes;
116 print_ptr += bytes;
117 }
118 }
119 }
120}
121
122
ed486911 123/*
124 * 'backendRunLoop()' - Read and write print and back-channel data.
125 */
126
127ssize_t /* O - Total bytes on success, -1 on error */
f7deaa1a 128backendRunLoop(
c8fef167
MS
129 int print_fd, /* I - Print file descriptor */
130 int device_fd, /* I - Device file descriptor */
131 int snmp_fd, /* I - SNMP socket or -1 if none */
132 http_addr_t *addr, /* I - Address of device */
133 int use_bc, /* I - Use back-channel? */
134 int update_state, /* I - Update printer-state-reasons? */
135 _cups_sccb_t side_cb) /* I - Side-channel callback */
ed486911 136{
137 int nfds; /* Maximum file descriptor value + 1 */
138 fd_set input, /* Input set for reading */
139 output; /* Output set for writing */
140 ssize_t print_bytes, /* Print bytes read */
141 bc_bytes, /* Backchannel bytes read */
142 total_bytes, /* Total bytes written */
143 bytes; /* Bytes written */
144 int paperout; /* "Paper out" status */
8ca02f3c 145 int offline; /* "Off-line" status */
ed486911 146 char print_buffer[8192], /* Print data buffer */
147 *print_ptr, /* Pointer into print data buffer */
148 bc_buffer[1024]; /* Back-channel data buffer */
568fa3fa
MS
149 struct timeval timeout; /* Timeout for select() */
150 time_t curtime, /* Current time */
151 snmp_update = 0;
ed486911 152#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
153 struct sigaction action; /* Actions for POSIX signals */
154#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
155
156
c0e1af83 157 fprintf(stderr,
568fa3fa
MS
158 "DEBUG: backendRunLoop(print_fd=%d, device_fd=%d, snmp_fd=%d, "
159 "addr=%p, use_bc=%d, side_cb=%p)\n",
160 print_fd, device_fd, snmp_fd, addr, use_bc, side_cb);
8ca02f3c 161
ed486911 162 /*
163 * If we are printing data from a print driver on stdin, ignore SIGTERM
164 * so that the driver can finish out any page data, e.g. to eject the
165 * current page. We only do this for stdin printing as otherwise there
166 * is no way to cancel a raw print job...
167 */
168
169 if (!print_fd)
170 {
171#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
172 sigset(SIGTERM, SIG_IGN);
173#elif defined(HAVE_SIGACTION)
174 memset(&action, 0, sizeof(action));
175
176 sigemptyset(&action.sa_mask);
177 action.sa_handler = SIG_IGN;
178 sigaction(SIGTERM, &action, NULL);
179#else
180 signal(SIGTERM, SIG_IGN);
181#endif /* HAVE_SIGSET */
182 }
4e6f60f0
MS
183 else if (print_fd < 0)
184 {
185 /*
186 * Copy print data from stdin, but don't mess with the signal handlers...
187 */
188
189 print_fd = 0;
190 }
ed486911 191
192 /*
193 * Figure out the maximum file descriptor value to use with select()...
194 */
195
196 nfds = (print_fd > device_fd ? print_fd : device_fd) + 1;
197
198 /*
199 * Now loop until we are out of data from print_fd...
200 */
201
b94498cf 202 for (print_bytes = 0, print_ptr = print_buffer, offline = -1,
203 paperout = -1, total_bytes = 0;;)
ed486911 204 {
205 /*
206 * Use select() to determine whether we have data to copy around...
207 */
208
209 FD_ZERO(&input);
210 if (!print_bytes)
211 FD_SET(print_fd, &input);
212 if (use_bc)
213 FD_SET(device_fd, &input);
dd1abb6b 214 if (!print_bytes && side_cb)
f7deaa1a 215 FD_SET(CUPS_SC_FD, &input);
ed486911 216
217 FD_ZERO(&output);
91c84a35 218 if (print_bytes || (!use_bc && !side_cb))
ed486911 219 FD_SET(device_fd, &output);
220
f7deaa1a 221 if (use_bc || side_cb)
8ca02f3c 222 {
568fa3fa
MS
223 timeout.tv_sec = 5;
224 timeout.tv_usec = 0;
225
226 if (select(nfds, &input, &output, NULL, &timeout) < 0)
8ca02f3c 227 {
228 /*
229 * Pause printing to clear any pending errors...
230 */
231
ef55b745 232 if (errno == ENXIO && offline != 1 && update_state)
8ca02f3c 233 {
c5571a1d 234 fputs("STATE: +offline-report\n", stderr);
0837b7e8 235 _cupsLangPrintFilter(stderr, "INFO",
f3c17241 236 _("The printer is not connected."));
8ca02f3c 237 offline = 1;
238 }
b94498cf 239 else if (errno == EINTR && total_bytes == 0)
240 {
241 fputs("DEBUG: Received an interrupt before any bytes were "
c8fef167 242 "written, aborting.\n", stderr);
b94498cf 243 return (0);
244 }
8ca02f3c 245
246 sleep(1);
247 continue;
248 }
249 }
ed486911 250
f7deaa1a 251 /*
252 * Check if we have a side-channel request ready...
253 */
254
255 if (side_cb && FD_ISSET(CUPS_SC_FD, &input))
dd1abb6b
MS
256 {
257 /*
258 * Do the side-channel request, then start back over in the select
259 * loop since it may have read from print_fd...
260 */
261
18ecb428
MS
262 if ((*side_cb)(print_fd, device_fd, snmp_fd, addr, use_bc))
263 side_cb = NULL;
dd1abb6b
MS
264 continue;
265 }
f7deaa1a 266
ed486911 267 /*
268 * Check if we have back-channel data ready...
269 */
270
271 if (FD_ISSET(device_fd, &input))
272 {
273 if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0)
274 {
275 fprintf(stderr,
4d301e69 276 "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data\n",
ed486911 277 CUPS_LLCAST bc_bytes);
7e86f2f6 278 cupsBackChannelWrite(bc_buffer, (size_t)bc_bytes, 1.0);
ed486911 279 }
4b3f67ff
MS
280 else if (bc_bytes < 0 && errno != EAGAIN && errno != EINTR)
281 {
282 fprintf(stderr, "DEBUG: Error reading back-channel data: %s\n",
283 strerror(errno));
284 use_bc = 0;
285 }
7cf5915e
MS
286 else if (bc_bytes == 0)
287 use_bc = 0;
ed486911 288 }
289
290 /*
291 * Check if we have print data ready...
292 */
293
294 if (FD_ISSET(print_fd, &input))
295 {
296 if ((print_bytes = read(print_fd, print_buffer,
297 sizeof(print_buffer))) < 0)
298 {
299 /*
300 * Read error - bail if we don't see EAGAIN or EINTR...
301 */
302
0b1399a2 303 if (errno != EAGAIN && errno != EINTR)
ed486911 304 {
f3c17241
MS
305 fprintf(stderr, "DEBUG: Read failed: %s\n", strerror(errno));
306 _cupsLangPrintFilter(stderr, "ERROR",
307 _("Unable to read print data."));
ed486911 308 return (-1);
309 }
310
311 print_bytes = 0;
312 }
313 else if (print_bytes == 0)
314 {
315 /*
316 * End of file, break out of the loop...
317 */
318
319 break;
320 }
321
322 print_ptr = print_buffer;
8ca02f3c 323
324 fprintf(stderr, "DEBUG: Read %d bytes of print data...\n",
325 (int)print_bytes);
ed486911 326 }
327
328 /*
329 * Check if the device is ready to receive data and we have data to
330 * send...
331 */
332
333 if (print_bytes && FD_ISSET(device_fd, &output))
334 {
7e86f2f6 335 if ((bytes = write(device_fd, print_ptr, (size_t)print_bytes)) < 0)
ed486911 336 {
337 /*
338 * Write error - bail if we don't see an error we can retry...
339 */
340
341 if (errno == ENOSPC)
342 {
ef55b745 343 if (paperout != 1 && update_state)
ed486911 344 {
c5571a1d 345 fputs("STATE: +media-empty-warning\n", stderr);
0837b7e8 346 fputs("DEBUG: Out of paper\n", stderr);
ed486911 347 paperout = 1;
348 }
349 }
8ca02f3c 350 else if (errno == ENXIO)
351 {
ef55b745 352 if (offline != 1 && update_state)
8ca02f3c 353 {
c5571a1d 354 fputs("STATE: +offline-report\n", stderr);
0837b7e8 355 _cupsLangPrintFilter(stderr, "INFO",
f3c17241 356 _("The printer is not connected."));
8ca02f3c 357 offline = 1;
358 }
359 }
ed486911 360 else if (errno != EAGAIN && errno != EINTR && errno != ENOTTY)
361 {
0837b7e8 362 _cupsLangPrintError("ERROR", _("Unable to write print data"));
ed486911 363 return (-1);
364 }
365 }
366 else
367 {
ef55b745 368 if (paperout && update_state)
ed486911 369 {
c5571a1d 370 fputs("STATE: -media-empty-warning\n", stderr);
ed486911 371 paperout = 0;
372 }
373
ef55b745 374 if (offline && update_state)
8ca02f3c 375 {
c5571a1d 376 fputs("STATE: -offline-report\n", stderr);
f3c17241
MS
377 _cupsLangPrintFilter(stderr, "INFO",
378 _("The printer is now connected."));
8ca02f3c 379 offline = 0;
380 }
381
382 fprintf(stderr, "DEBUG: Wrote %d bytes of print data...\n", (int)bytes);
ed486911 383
384 print_bytes -= bytes;
385 print_ptr += bytes;
386 total_bytes += bytes;
387 }
388 }
568fa3fa
MS
389
390 /*
391 * Do SNMP updates periodically...
392 */
393
394 if (snmp_fd >= 0 && time(&curtime) >= snmp_update)
395 {
396 if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL))
397 snmp_update = INT_MAX;
398 else
399 snmp_update = curtime + 5;
400 }
ed486911 401 }
402
403 /*
404 * Return with success...
405 */
406
407 return (total_bytes);
408}
409
410
411/*
c8fef167
MS
412 * 'backendWaitLoop()' - Wait for input from stdin while handling side-channel
413 * queries.
414 */
415
416int /* O - 1 if data is ready, 0 if not */
417backendWaitLoop(
418 int snmp_fd, /* I - SNMP socket or -1 if none */
419 http_addr_t *addr, /* I - Address of device */
f14324a7 420 int use_bc, /* I - Use back-channel? */
c8fef167
MS
421 _cups_sccb_t side_cb) /* I - Side-channel callback */
422{
82cc1f9a
MS
423 int nfds; /* Number of file descriptors */
424 fd_set input; /* Input set for reading */
425 time_t curtime = 0, /* Current time */
426 snmp_update = 0;/* Last SNMP status update */
427 struct timeval timeout; /* Timeout for select() */
c8fef167
MS
428
429
430 fprintf(stderr, "DEBUG: backendWaitLoop(snmp_fd=%d, addr=%p, side_cb=%p)\n",
431 snmp_fd, addr, side_cb);
432
433 /*
434 * Now loop until we receive data from stdin...
435 */
436
82cc1f9a
MS
437 if (snmp_fd >= 0)
438 snmp_update = time(NULL) + 5;
439
c8fef167
MS
440 for (;;)
441 {
442 /*
443 * Use select() to determine whether we have data to copy around...
444 */
445
446 FD_ZERO(&input);
447 FD_SET(0, &input);
448 if (side_cb)
449 FD_SET(CUPS_SC_FD, &input);
450
82cc1f9a
MS
451 if (snmp_fd >= 0)
452 {
453 curtime = time(NULL);
454 timeout.tv_sec = curtime >= snmp_update ? 0 : snmp_update - curtime;
455 timeout.tv_usec = 0;
456
457 nfds = select(CUPS_SC_FD + 1, &input, NULL, NULL, &timeout);
458 }
459 else
460 nfds = select(CUPS_SC_FD + 1, &input, NULL, NULL, NULL);
461
462 if (nfds < 0)
c8fef167
MS
463 {
464 /*
465 * Pause printing to clear any pending errors...
466 */
467
468 if (errno == EINTR)
469 {
470 fputs("DEBUG: Received an interrupt before any bytes were "
471 "written, aborting.\n", stderr);
472 return (0);
473 }
474
475 sleep(1);
476 continue;
477 }
478
479 /*
480 * Check for input on stdin...
481 */
482
483 if (FD_ISSET(0, &input))
484 break;
485
486 /*
487 * Check if we have a side-channel request ready...
488 */
489
490 if (side_cb && FD_ISSET(CUPS_SC_FD, &input))
491 {
492 /*
493 * Do the side-channel request, then start back over in the select
494 * loop since it may have read from print_fd...
495 */
496
f14324a7 497 if ((*side_cb)(0, -1, snmp_fd, addr, use_bc))
c8fef167
MS
498 side_cb = NULL;
499 continue;
500 }
501
502 /*
503 * Do SNMP updates periodically...
504 */
505
82cc1f9a 506 if (snmp_fd >= 0 && curtime >= snmp_update)
c8fef167
MS
507 {
508 if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL))
82cc1f9a 509 snmp_fd = -1;
c8fef167
MS
510 else
511 snmp_update = curtime + 5;
512 }
513 }
514
515 /*
516 * Return with success...
517 */
518
519 return (1);
520}