stdin: Abort if the consumer terminates.
[paraslash.git] / string.c
index 51461b2..752fb8f 100644 (file)
--- a/string.c
+++ b/string.c
@@ -91,7 +91,7 @@ __must_check __malloc void *para_calloc(size_t size)
 }
 
 /**
- * Pparaslash's version of strdup().
+ * Paraslash's version of strdup().
  *
  * \param s The string to be duplicated.
  *
@@ -250,33 +250,6 @@ __must_check __malloc char *para_tmpname(void)
        return make_message("%08i", rand());
 }
 
-/**
- * Create unique temporary file.
- *
- * \param template The template to be passed to mkstemp().
- * \param mode The desired mode of the tempfile.
- *
- * This wrapper for mkstemp additionally uses fchmod() to
- * set the given mode of the tempfile if mkstemp() returned success.
- *
- * \return The file descriptor of the temp file just created on success.
- * On errors, a negative value is returned.
- */
-__must_check int para_mkstemp(char *template, mode_t mode)
-{
-       int tmp, fd = mkstemp(template);
-
-       if (fd < 0)
-               return -ERRNO_TO_PARA_ERROR(errno);
-       tmp = fchmod(fd, mode);
-       if (tmp >= 0)
-               return fd;
-       tmp = errno;
-       close(fd);
-       unlink(template);
-       return -ERRNO_TO_PARA_ERROR(tmp);
-}
-
 /**
  * Get the logname of the current user.
  *
@@ -511,7 +484,15 @@ int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler,
  *
  * This function prints into the buffer given by \a b at the offset which is
  * also given by \a b. If there is not enough space to hold the result, the
- * buffer size is doubled until the underlying call to vsnprintf() succeeds.
+ * buffer size is doubled until the underlying call to vsnprintf() succeeds
+ * or the size of the buffer exceeds the maximal size specified in \a pb.
+ *
+ * In the latter case the unmodified \a buf and \a offset values as well as the
+ * private_data pointer of \a b are passed to the \a max_size_handler of \a b.
+ * If this function succeeds, i.e. returns a non-negative value, the offset of
+ * \a b is reset to zero and the given data is written to the beginning of the
+ * buffer.
+ *
  * Upon return, the offset of \a b is adjusted accordingly so that subsequent
  * calls to this function append data to what is already contained in the
  * buffer.
@@ -532,26 +513,35 @@ __printf_2_3 int para_printf(struct para_buffer *b, const char *fmt, ...)
                b->buf = para_malloc(128);
                b->size = 128;
                b->offset = 0;
-       } else if (b->size <= b->offset + 1) {
-               b->size *= 2;
-               b->buf = para_realloc(b->buf, b->size);
        }
        while (1) {
                char *p = b->buf + b->offset;
                size_t size = b->size - b->offset;
                va_list ap;
-               va_start(ap, fmt);
-               ret = vsnprintf(p, size, fmt, ap);
-               va_end(ap);
-               if (ret > -1 && ret < size) { /* success */
-                       b->offset += ret;
-                       break;
+               if (size) {
+                       va_start(ap, fmt);
+                       ret = vsnprintf(p, size, fmt, ap);
+                       va_end(ap);
+                       if (ret > -1 && ret < size) { /* success */
+                               b->offset += ret;
+                               return ret;
+                       }
+               }
+               /* check if we may grow the buffer */
+               if (!b->max_size || 2 * b->size < b->max_size) { /* yes */
+                       /* try again with more space */
+                       b->size *= 2;
+                       b->buf = para_realloc(b->buf, b->size);
+                       continue;
                }
-               /* try again with more space */
-               b->size *= 2;
-               b->buf = para_realloc(b->buf, b->size);
+               /* can't grow buffer */
+               if (!b->offset || !b->max_size_handler) /* message too large */
+                       return -ERRNO_TO_PARA_ERROR(ENOSPC);
+               ret = b->max_size_handler(b->buf, b->offset, b->private_data);
+               if (ret < 0)
+                       return ret;
+               b->offset = 0;
        }
-       return ret;
 }
 
 /** \cond LLONG_MAX and LLONG_LIN might not be defined. */