Home | History | Annotate | Download | only in cups
      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 {
     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 
     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 {
    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 
    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 {
    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