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