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