/src/cups/cups/backchannel.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Backchannel functions for CUPS. |
3 | | * |
4 | | * Copyright 2007-2014 by Apple Inc. |
5 | | * Copyright 1997-2007 by Easy Software Products. |
6 | | * |
7 | | * These coded instructions, statements, and computer programs are the |
8 | | * property of Apple Inc. and are protected by Federal copyright |
9 | | * law. Distribution and use rights are outlined in the file "LICENSE.txt" |
10 | | * which should have been included with this file. If this file is |
11 | | * missing or damaged, see the license at "http://www.cups.org/". |
12 | | * |
13 | | * This file is subject to the Apple OS-Developed Software exception. |
14 | | */ |
15 | | |
16 | | /* |
17 | | * Include necessary headers... |
18 | | */ |
19 | | |
20 | | #include "cups.h" |
21 | | #include <errno.h> |
22 | | #ifdef _WIN32 |
23 | | # include <io.h> |
24 | | # include <fcntl.h> |
25 | | #else |
26 | | # include <sys/time.h> |
27 | | #endif /* _WIN32 */ |
28 | | |
29 | | |
30 | | /* |
31 | | * Local functions... |
32 | | */ |
33 | | |
34 | | static void cups_setup(fd_set *set, struct timeval *tval, |
35 | | double timeout); |
36 | | |
37 | | |
38 | | /* |
39 | | * 'cupsBackChannelRead()' - Read data from the backchannel. |
40 | | * |
41 | | * Reads up to "bytes" bytes from the backchannel/backend. The "timeout" |
42 | | * parameter controls how many seconds to wait for the data - use 0.0 to |
43 | | * return immediately if there is no data, -1.0 to wait for data indefinitely. |
44 | | * |
45 | | * @since CUPS 1.2/macOS 10.5@ |
46 | | */ |
47 | | |
48 | | ssize_t /* O - Bytes read or -1 on error */ |
49 | | cupsBackChannelRead(char *buffer, /* I - Buffer to read into */ |
50 | | size_t bytes, /* I - Bytes to read */ |
51 | | double timeout) /* I - Timeout in seconds, typically 0.0 to poll */ |
52 | 0 | { |
53 | 0 | fd_set input; /* Input set */ |
54 | 0 | struct timeval tval; /* Timeout value */ |
55 | 0 | int status; /* Select status */ |
56 | | |
57 | | |
58 | | /* |
59 | | * Wait for input ready. |
60 | | */ |
61 | |
|
62 | 0 | do |
63 | 0 | { |
64 | 0 | cups_setup(&input, &tval, timeout); |
65 | |
|
66 | 0 | if (timeout < 0.0) |
67 | 0 | status = select(4, &input, NULL, NULL, NULL); |
68 | 0 | else |
69 | 0 | status = select(4, &input, NULL, NULL, &tval); |
70 | 0 | } |
71 | 0 | while (status < 0 && errno != EINTR && errno != EAGAIN); |
72 | |
|
73 | 0 | if (status < 0) |
74 | 0 | return (-1); /* Timeout! */ |
75 | | |
76 | | /* |
77 | | * Read bytes from the pipe... |
78 | | */ |
79 | | |
80 | | #ifdef _WIN32 |
81 | | return ((ssize_t)_read(3, buffer, (unsigned)bytes)); |
82 | | #else |
83 | 0 | return (read(3, buffer, bytes)); |
84 | 0 | #endif /* _WIN32 */ |
85 | 0 | } |
86 | | |
87 | | |
88 | | /* |
89 | | * 'cupsBackChannelWrite()' - Write data to the backchannel. |
90 | | * |
91 | | * Writes "bytes" bytes to the backchannel/filter. The "timeout" parameter |
92 | | * controls how many seconds to wait for the data to be written - use |
93 | | * 0.0 to return immediately if the data cannot be written, -1.0 to wait |
94 | | * indefinitely. |
95 | | * |
96 | | * @since CUPS 1.2/macOS 10.5@ |
97 | | */ |
98 | | |
99 | | ssize_t /* O - Bytes written or -1 on error */ |
100 | | cupsBackChannelWrite( |
101 | | const char *buffer, /* I - Buffer to write */ |
102 | | size_t bytes, /* I - Bytes to write */ |
103 | | double timeout) /* I - Timeout in seconds, typically 1.0 */ |
104 | 0 | { |
105 | 0 | fd_set output; /* Output set */ |
106 | 0 | struct timeval tval; /* Timeout value */ |
107 | 0 | int status; /* Select status */ |
108 | 0 | ssize_t count; /* Current bytes */ |
109 | 0 | size_t total; /* Total bytes */ |
110 | | |
111 | | |
112 | | /* |
113 | | * Write all bytes... |
114 | | */ |
115 | |
|
116 | 0 | total = 0; |
117 | |
|
118 | 0 | while (total < bytes) |
119 | 0 | { |
120 | | /* |
121 | | * Wait for write-ready... |
122 | | */ |
123 | |
|
124 | 0 | do |
125 | 0 | { |
126 | 0 | cups_setup(&output, &tval, timeout); |
127 | |
|
128 | 0 | if (timeout < 0.0) |
129 | 0 | status = select(4, NULL, &output, NULL, NULL); |
130 | 0 | else |
131 | 0 | status = select(4, NULL, &output, NULL, &tval); |
132 | 0 | } |
133 | 0 | while (status < 0 && errno != EINTR && errno != EAGAIN); |
134 | |
|
135 | 0 | if (status <= 0) |
136 | 0 | return (-1); /* Timeout! */ |
137 | | |
138 | | /* |
139 | | * Write bytes to the pipe... |
140 | | */ |
141 | | |
142 | | #ifdef _WIN32 |
143 | | count = (ssize_t)_write(3, buffer, (unsigned)(bytes - total)); |
144 | | #else |
145 | 0 | count = write(3, buffer, bytes - total); |
146 | 0 | #endif /* _WIN32 */ |
147 | |
|
148 | 0 | if (count < 0) |
149 | 0 | { |
150 | | /* |
151 | | * Write error - abort on fatal errors... |
152 | | */ |
153 | |
|
154 | 0 | if (errno != EINTR && errno != EAGAIN) |
155 | 0 | return (-1); |
156 | 0 | } |
157 | 0 | else |
158 | 0 | { |
159 | | /* |
160 | | * Write succeeded, update buffer pointer and total count... |
161 | | */ |
162 | |
|
163 | 0 | buffer += count; |
164 | 0 | total += (size_t)count; |
165 | 0 | } |
166 | 0 | } |
167 | | |
168 | 0 | return ((ssize_t)bytes); |
169 | 0 | } |
170 | | |
171 | | |
172 | | /* |
173 | | * 'cups_setup()' - Setup select() |
174 | | */ |
175 | | |
176 | | static void |
177 | | cups_setup(fd_set *set, /* I - Set for select() */ |
178 | | struct timeval *tval, /* I - Timer value */ |
179 | | double timeout) /* I - Timeout in seconds */ |
180 | 0 | { |
181 | 0 | tval->tv_sec = (int)timeout; |
182 | 0 | tval->tv_usec = (int)(1000000.0 * (timeout - tval->tv_sec)); |
183 | |
|
184 | 0 | FD_ZERO(set); |
185 | 0 | FD_SET(3, set); |
186 | 0 | } |