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 34static 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 48ssize_t /* O - Bytes read or -1 on error */ 49cupsBackChannelRead(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{ 53 fd_set input; /* Input set */ 54 struct timeval tval; /* Timeout value */ 55 int status; /* Select status */ 56 57 58 /* 59 * Wait for input ready. 60 */ 61 62 do 63 { 64 cups_setup(&input, &tval, timeout); 65 66 if (timeout < 0.0) 67 status = select(4, &input, NULL, NULL, NULL); 68 else 69 status = select(4, &input, NULL, NULL, &tval); 70 } 71 while (status < 0 && errno != EINTR && errno != EAGAIN); 72 73 if (status < 0) 74 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 return (read(3, buffer, bytes)); 84#endif /* WIN32 */ 85} 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 99ssize_t /* O - Bytes written or -1 on error */ 100cupsBackChannelWrite( 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{ 105 fd_set output; /* Output set */ 106 struct timeval tval; /* Timeout value */ 107 int status; /* Select status */ 108 ssize_t count; /* Current bytes */ 109 size_t total; /* Total bytes */ 110 111 112 /* 113 * Write all bytes... 114 */ 115 116 total = 0; 117 118 while (total < bytes) 119 { 120 /* 121 * Wait for write-ready... 122 */ 123 124 do 125 { 126 cups_setup(&output, &tval, timeout); 127 128 if (timeout < 0.0) 129 status = select(4, NULL, &output, NULL, NULL); 130 else 131 status = select(4, NULL, &output, NULL, &tval); 132 } 133 while (status < 0 && errno != EINTR && errno != EAGAIN); 134 135 if (status <= 0) 136 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 count = write(3, buffer, bytes - total); 146#endif /* WIN32 */ 147 148 if (count < 0) 149 { 150 /* 151 * Write error - abort on fatal errors... 152 */ 153 154 if (errno != EINTR && errno != EAGAIN) 155 return (-1); 156 } 157 else 158 { 159 /* 160 * Write succeeded, update buffer pointer and total count... 161 */ 162 163 buffer += count; 164 total += (size_t)count; 165 } 166 } 167 168 return ((ssize_t)bytes); 169} 170 171 172/* 173 * 'cups_setup()' - Setup select() 174 */ 175 176static void 177cups_setup(fd_set *set, /* I - Set for select() */ 178 struct timeval *tval, /* I - Timer value */ 179 double timeout) /* I - Timeout in seconds */ 180{ 181 tval->tv_sec = (int)timeout; 182 tval->tv_usec = (int)(1000000.0 * (timeout - tval->tv_sec)); 183 184 FD_ZERO(set); 185 FD_SET(3, set); 186} 187