Merge branch 't/audioc_cleanups'
authorAndre Noll <maan@systemlinux.org>
Sun, 4 Mar 2012 21:40:27 +0000 (22:40 +0100)
committerAndre Noll <maan@systemlinux.org>
Mon, 5 Mar 2012 07:46:58 +0000 (08:46 +0100)
Has been cooking for long enough.

37 files changed:
NEWS
afh.c
afs.c
afs.cmd
aft.c
attribute.c
audioc.c
audiod.c
blob.c
client_common.c
command.c
command.h
configure.ac
crypt.c
crypt_common.c
dccp_send.c
error.h
fd.c
fd.h
gcc-compat.h
gcrypt.c
ggo/audiod.m4
grab_client.c
gui.c
http_recv.c
http_send.c
interactive.c
net.c
net.h
oss_write.c
para.h
send_common.c
stdout.c
string.c
string.h
udp_send.c
vss.c

diff --git a/NEWS b/NEWS
index 16e8e4e..d9e0d0a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,16 @@
 0.4.10 (to be announced) "heterogeneous vacuum"
 -----------------------------------------------
 
+       - The --no_default_filters option of para_filter has been
+         depricated. It still works but has no effect and will be
+         removed in the next version.
+       - Cleanup and consolidation of the various wrappers for
+         write(), writev(), send() and friends.
+       - The obscure error messages on mmap() failures have been
+         replaced by meaningful messages. This affects mainly
+         para_afh.
+       - para_audioc: Cleanups and memory leak fixes.
+
 -------------------------------------
 0.4.9 (2011-12-06) "hybrid causality"
 -------------------------------------
diff --git a/afh.c b/afh.c
index f2745b6..bffe632 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -124,7 +124,7 @@ static int cat_file(struct afh_info *afhi, int audio_format_id,
                        &header, &size);
                if (size > 0) {
                        PARA_INFO_LOG("writing header (%zu bytes)\n", size);
-                       ret = write(STDOUT_FILENO, header, size); /* FIXME */
+                       ret = write_all(STDOUT_FILENO, header, size);
                        afh_free_header(header, audio_format_id);
                        if (ret < 0)
                                return ret;
@@ -152,7 +152,7 @@ static int cat_file(struct afh_info *afhi, int audio_format_id,
                if (!size)
                        continue;
                PARA_INFO_LOG("writing chunk %lu\n", i);
-               ret = write_all(STDOUT_FILENO, buf, &size);
+               ret = write_all(STDOUT_FILENO, buf, size);
                if (ret < 0)
                        return ret;
        }
@@ -187,8 +187,10 @@ int main(int argc, char **argv)
                int ret2;
                ret = mmap_full_file(conf.inputs[i], O_RDONLY, &audio_file_data,
                        &audio_file_size, &fd);
-               if (ret < 0)
+               if (ret < 0) {
+                       PARA_ERROR_LOG("failed to mmap \"%s\"\n", conf.inputs[i]);
                        goto out;
+               }
                ret = compute_afhi(conf.inputs[i], audio_file_data, audio_file_size,
                        fd, &afhi);
                if (ret < 0)
diff --git a/afs.c b/afs.c
index 263f181..5939cbe 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -26,6 +26,7 @@
 #include "signal.h"
 #include "fd.h"
 #include "mood.h"
+#include "command.h"
 
 /** The osl tables used by afs. \sa blob.c. */
 enum afs_table_num {
@@ -233,7 +234,7 @@ int send_callback_request(callback_function *f, struct osl_object *query,
        if (ret < 0)
                goto out;
        fd = ret;
-       ret = send_bin_buffer(fd, buf, sizeof(buf));
+       ret = write_all(fd, buf, sizeof(buf));
        if (ret < 0)
                goto out;
        /*
@@ -495,7 +496,7 @@ destroy:
 no_admissible_files:
        *(uint32_t *)buf = NO_ADMISSIBLE_FILES;
        *(uint32_t *)(buf + 4) = (uint32_t)0;
-       return send_bin_buffer(server_socket, buf, 8);
+       return write_all(server_socket, buf, 8);
 }
 
 /* Never fails if arg == NULL */
@@ -592,23 +593,27 @@ out:
  */
 int sc_send_result(struct osl_object *result, void *private)
 {
-       struct stream_cipher_context *scc = private;
+       struct command_context *cc = private;
+       int ret;
 
        if (!result->size)
                return 1;
-       return sc_send_bin_buffer(scc, result->data, result->size);
+       ret = sc_send_bin_buffer(&cc->scc, result->data, result->size);
+       if (ret < 0 || ret == result->size)
+               return ret;
+       return -E_SHORT_WRITE;
 }
 
-int com_select(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_select(struct command_context *cc)
 {
        struct osl_object query;
 
-       if (argc != 2)
+       if (cc->argc != 2)
                return -E_AFS_SYNTAX;
-       query.data = argv[1];
-       query.size = strlen(argv[1]) + 1;
+       query.data = cc->argv[1];
+       query.size = strlen(cc->argv[1]) + 1;
        return send_callback_request(com_select_callback, &query,
-               &sc_send_result, scc);
+               &sc_send_result, cc);
 }
 
 static void init_admissible_files(char *arg)
@@ -814,7 +819,7 @@ int pass_buffer_as_shm(char *buf, size_t size, void *fd_ptr)
        ret = shm_detach(shm);
        if (ret < 0)
                goto err;
-       ret = send_bin_buffer(fd, (char *)&shmid, sizeof(int));
+       ret = write_all(fd, (char *)&shmid, sizeof(int));
        if (ret >= 0)
                return ret;
 err:
@@ -1022,7 +1027,7 @@ out:
        free(pb.buf);
 }
 
-int com_init(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_init(struct command_context *cc)
 {
        int i, j, ret;
        uint32_t table_mask = (1 << (NUM_AFS_TABLES + 1)) - 1;
@@ -1032,13 +1037,13 @@ int com_init(struct stream_cipher_context *scc, int argc, char * const * const a
        ret = make_database_dir();
        if (ret < 0)
                return ret;
-       if (argc != 1) {
+       if (cc->argc != 1) {
                table_mask = 0;
-               for (i = 1; i < argc; i++) {
+               for (i = 1; i < cc->argc; i++) {
                        for (j = 0; j < NUM_AFS_TABLES; j++) {
                                struct afs_table *t = &afs_tables[j];
 
-                               if (strcmp(argv[i], t->name))
+                               if (strcmp(cc->argv[i], t->name))
                                        continue;
                                table_mask |= (1 << j);
                                break;
@@ -1048,10 +1053,10 @@ int com_init(struct stream_cipher_context *scc, int argc, char * const * const a
                }
        }
        ret = send_callback_request(create_tables_callback, &query,
-               sc_send_result, scc);
+               sc_send_result, cc);
        if (ret < 0)
                /* ignore return value */
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -1069,13 +1074,13 @@ enum com_check_flags {
        CHECK_PLAYLISTS = 4
 };
 
-int com_check(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_check(struct command_context *cc)
 {
        unsigned flags = 0;
        int i, ret;
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -1096,25 +1101,25 @@ int com_check(struct stream_cipher_context *scc, int argc, char * const * const
                }
                return -E_AFS_SYNTAX;
        }
-       if (i < argc)
+       if (i < cc->argc)
                return -E_AFS_SYNTAX;
        if (!flags)
                flags = ~0U;
        if (flags & CHECK_AFT) {
                ret = send_callback_request(aft_check_callback, NULL,
-                       sc_send_result, scc);
+                       sc_send_result, cc);
                if (ret < 0)
                        return ret;
        }
        if (flags & CHECK_PLAYLISTS) {
                ret = send_callback_request(playlist_check_callback,
-                       NULL, sc_send_result, scc);
+                       NULL, sc_send_result, cc);
                if (ret < 0)
                        return ret;
        }
        if (flags & CHECK_MOODS) {
                ret = send_callback_request(mood_check_callback, NULL,
-                       sc_send_result, scc);
+                       sc_send_result, cc);
                if (ret < 0)
                        return ret;
        }
diff --git a/afs.cmd b/afs.cmd
index 22a0786..c780804 100644 (file)
--- a/afs.cmd
+++ b/afs.cmd
@@ -260,7 +260,7 @@ H: loads the mood named 'foo'.
 ---
 T: add
 N: add@member@
-O: int com_add@member@(struct stream_cipher_context *scc, int argc, char * const * const argv);
+O: int com_add@member@(struct command_context *cc);
 P: AFS_READ | AFS_WRITE
 D: Read data from stdin and add it as a blob to the @member@ table.
 U: add@member@ @member@_name
@@ -273,7 +273,7 @@ H: given name already exists, its contents are replaced by the new data.
 ---
 T: cat
 N: cat@member@
-O: int com_cat@member@(struct stream_cipher_context *scc, int argc, char * const * const argv);
+O: int com_cat@member@(struct command_context *cc);
 P: AFS_READ
 D: Dump the contents of a blob of type @member@ to stdout.
 U: cat@member@ @member@_name
@@ -283,7 +283,7 @@ H: they were previously added.
 ---
 T: ls
 N: ls@member@
-O: int com_ls@member@(struct stream_cipher_context *scc, int argc, char * const * const argv);
+O: int com_ls@member@(struct command_context *cc);
 P: AFS_READ
 D: List blobs of type @member@ matching a pattern.
 U: ls@member@ [-i] [-l] [-r] [pattern]
@@ -303,7 +303,7 @@ H: -r       Reverse sort order.
 ---
 T: rm
 N: rm@member@
-O: int com_rm@member@(struct stream_cipher_context *scc, int argc, char * const * const argv);
+O: int com_rm@member@(struct command_context *cc);
 P: AFS_READ | AFS_WRITE
 D: Remove blob(s) of type @member@ from the @member@ table.
 U: rm@member@ pattern...
@@ -312,7 +312,7 @@ H: any given pattern.
 ---
 T: mv
 N: mv@member@
-O: int com_mv@member@(struct stream_cipher_context *scc, int argc, char * const * const argv);
+O: int com_mv@member@(struct command_context *cc);
 P: AFS_READ | AFS_WRITE
 D: Rename a blob of type @member@.
 U: mv@member@ old_@member@_name new_@member@_name
diff --git a/aft.c b/aft.c
index 9d87c74..f89235a 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -21,6 +21,7 @@
 #include "fd.h"
 #include "ipc.h"
 #include "portable_io.h"
+#include "command.h"
 
 static struct osl_table *audio_file_table;
 static char *status_items;
@@ -1402,7 +1403,7 @@ out:
 /*
  * TODO: flags -h (sort by hash)
  */
-int com_ls(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_ls(struct command_context *cc)
 {
        int i, ret;
        unsigned flags = 0;
@@ -1411,8 +1412,8 @@ int com_ls(struct stream_cipher_context *scc, int argc, char * const * const arg
        struct ls_options opts = {.patterns = NULL};
        struct osl_object query = {.data = &opts, .size = sizeof(opts)};
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -1512,9 +1513,9 @@ int com_ls(struct stream_cipher_context *scc, int argc, char * const * const arg
        opts.flags = flags;
        opts.sorting = sort;
        opts.mode = mode;
-       opts.num_patterns = argc - i;
+       opts.num_patterns = cc->argc - i;
        ret = send_option_arg_callback_request(&query, opts.num_patterns,
-               argv + i, com_ls_callback, sc_send_result, scc);
+               cc->argv + i, com_ls_callback, sc_send_result, cc);
        return ret;
 }
 
@@ -1801,8 +1802,8 @@ out:
 
 /** Used by com_add(). */
 struct private_add_data {
-       /** The socket file descriptor, including stream cipher keys. */
-       struct stream_cipher_context *scc;
+       /** The pointer passed to the original command handler. */
+       struct command_context *cc;
        /** The given add flags. */
        uint32_t flags;
 };
@@ -1857,7 +1858,7 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = sc_send_va_buffer(pad->scc,
+                       send_ret = sc_send_va_buffer(&pad->cc->scc,
                                "lazy-ignore: %s\n", path);
                goto out_free;
        }
@@ -1878,7 +1879,7 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = sc_send_va_buffer(pad->scc,
+                       send_ret = sc_send_va_buffer(&pad->cc->scc,
                                "%s exists, not forcing update\n", path);
                goto out_unmap;
        }
@@ -1896,13 +1897,13 @@ static int add_one_audio_file(const char *path, void *private_data)
        munmap(map.data, map.size);
        close(fd);
        if (pad->flags & ADD_FLAG_VERBOSE) {
-               send_ret = sc_send_va_buffer(pad->scc, "adding %s\n", path);
+               send_ret = sc_send_va_buffer(&pad->cc->scc, "adding %s\n", path);
                if (send_ret < 0)
                        goto out_free;
        }
        save_add_callback_buffer(hash, path, afhi_ptr, pad->flags, format_num, &obj);
        /* Ask afs to consider this entry for adding. */
-       ret = send_callback_request(com_add_callback, &obj, sc_send_result, pad->scc);
+       ret = send_callback_request(com_add_callback, &obj, sc_send_result, pad->cc);
        goto out_free;
 
 out_unmap:
@@ -1910,7 +1911,7 @@ out_unmap:
        munmap(map.data, map.size);
 out_free:
        if (ret < 0 && send_ret >= 0)
-               send_ret = sc_send_va_buffer(pad->scc,
+               send_ret = sc_send_va_buffer(&pad->cc->scc,
                        "failed to add %s (%s)\n", path, para_strerror(-ret));
        free(obj.data);
        if (afhi_ptr) {
@@ -1926,14 +1927,14 @@ out_free:
        return send_ret;
 }
 
-int com_add(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_add(struct command_context *cc)
 {
        int i, ret;
-       struct private_add_data pad = {.scc = scc, .flags = 0};
+       struct private_add_data pad = {.cc = cc, .flags = 0};
        struct stat statbuf;
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -1957,21 +1958,22 @@ int com_add(struct stream_cipher_context *scc, int argc, char * const * const ar
                        continue;
                }
        }
-       if (argc <= i)
+       if (cc->argc <= i)
                return -E_AFT_SYNTAX;
-       for (; i < argc; i++) {
+       for (; i < cc->argc; i++) {
                char *path;
-               ret = verify_path(argv[i], &path);
+               ret = verify_path(cc->argv[i], &path);
                if (ret < 0) {
-                       ret = sc_send_va_buffer(scc, "%s: %s\n", argv[i],
-                               para_strerror(-ret));
+                       ret = sc_send_va_buffer(&cc->scc, "%s: %s\n",
+                               cc->argv[i], para_strerror(-ret));
                        if (ret < 0)
                                return ret;
                        continue;
                }
                ret = stat(path, &statbuf);
                if (ret < 0) {
-                       ret = sc_send_va_buffer(scc, "failed to stat %s (%s)\n", path,
+                       ret = sc_send_va_buffer(&cc->scc,
+                               "failed to stat %s (%s)\n", path,
                                strerror(errno));
                        free(path);
                        if (ret < 0)
@@ -1984,7 +1986,8 @@ int com_add(struct stream_cipher_context *scc, int argc, char * const * const ar
                else
                        ret = add_one_audio_file(path, &pad);
                if (ret < 0) {
-                       sc_send_va_buffer(scc, "%s: %s\n", path, para_strerror(-ret));
+                       sc_send_va_buffer(&cc->scc, "%s: %s\n", path,
+                               para_strerror(-ret));
                        free(path);
                        return ret;
                }
@@ -2112,7 +2115,7 @@ static void com_touch_callback(int fd, const struct osl_object *query)
        free(tad.pb.buf);
 }
 
-int com_touch(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_touch(struct command_context *cc)
 {
        struct com_touch_options cto = {
                .num_played = -1,
@@ -2125,8 +2128,8 @@ int com_touch(struct stream_cipher_context *scc, int argc, char * const * const
        int i, ret;
 
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -2177,12 +2180,12 @@ int com_touch(struct stream_cipher_context *scc, int argc, char * const * const
                }
                break; /* non-option starting with dash */
        }
-       if (i >= argc)
+       if (i >= cc->argc)
                return -E_AFT_SYNTAX;
-       ret = send_option_arg_callback_request(&query, argc - i,
-               argv + i, com_touch_callback, sc_send_result, scc);
+       ret = send_option_arg_callback_request(&query, cc->argc - i,
+               cc->argv + i, com_touch_callback, sc_send_result, cc);
        if (ret < 0)
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -2260,14 +2263,14 @@ static void com_rm_callback(int fd, const struct osl_object *query)
 }
 
 /* TODO options: -r (recursive) */
-int com_rm(struct stream_cipher_context *scc, int argc,  char * const * const argv)
+int com_rm(struct command_context *cc)
 {
        uint32_t flags = 0;
        struct osl_object query = {.data = &flags, .size = sizeof(flags)};
        int i, ret;
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -2288,12 +2291,12 @@ int com_rm(struct stream_cipher_context *scc, int argc,  char * const * const ar
                }
                break;
        }
-       if (i >= argc)
+       if (i >= cc->argc)
                return -E_AFT_SYNTAX;
-       ret = send_option_arg_callback_request(&query, argc - i, argv + i,
-               com_rm_callback, sc_send_result, scc);
+       ret = send_option_arg_callback_request(&query, cc->argc - i,
+               cc->argv + i, com_rm_callback, sc_send_result, cc);
        if (ret < 0)
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -2405,14 +2408,14 @@ out:
        free(cad.pb.buf);
 }
 
-int com_cpsi(struct stream_cipher_context *scc, int argc,  char * const * const argv)
+int com_cpsi(struct command_context *cc)
 {
        unsigned flags = 0;
        int i, ret;
        struct osl_object options = {.data = &flags, .size = sizeof(flags)};
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -2445,14 +2448,14 @@ int com_cpsi(struct stream_cipher_context *scc, int argc,  char * const * const
                }
                break;
        }
-       if (i + 1 >= argc) /* need at least source file and pattern */
+       if (i + 1 >= cc->argc) /* need at least source file and pattern */
                return -E_AFT_SYNTAX;
        if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
                flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
-       ret = send_option_arg_callback_request(&options, argc - i, argv + i,
-               com_cpsi_callback, sc_send_result, scc);
+       ret = send_option_arg_callback_request(&options, cc->argc - i,
+               cc->argv + i, com_cpsi_callback, sc_send_result, cc);
        if (ret < 0)
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -2470,7 +2473,7 @@ static void afs_stat_callback(int fd, const struct osl_object *query)
 /**
  * Get the current afs status items from the afs process and send it.
  *
- * \param scc The stream cipher context for data encryption.
+ * \param cc The command context, used e.g. for data encryption.
  * \param parser_friendly Whether parser-friendly output format should be used.
  *
  * As the contents of the afs status items change in time and the command
@@ -2481,12 +2484,12 @@ static void afs_stat_callback(int fd, const struct osl_object *query)
  *
  * \return The return value of the underyling call to \ref send_callback_request().
  */
-int send_afs_status(struct stream_cipher_context *scc, int parser_friendly)
+int send_afs_status(struct command_context *cc, int parser_friendly)
 {
        struct osl_object query = {.data = &parser_friendly,
                .size = sizeof(parser_friendly)};
 
-       return send_callback_request(afs_stat_callback, &query, sc_send_result, scc);
+       return send_callback_request(afs_stat_callback, &query, sc_send_result, cc);
 }
 
 /* TODO: optionally fix problems by removing offending rows */
index b56a957..1970094 100644 (file)
@@ -16,6 +16,7 @@
 #include "afh.h"
 #include "afs.h"
 #include "ipc.h"
+#include "command.h"
 
 static struct osl_table *attribute_table;
 static int greatest_att_bitnum;
@@ -175,14 +176,14 @@ static void com_lsatt_callback(int fd, const struct osl_object *query)
        free(laad.pb.buf);
 }
 
-int com_lsatt(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_lsatt(struct command_context *cc)
 {
        unsigned flags = 0;
        struct osl_object options = {.data = &flags, .size = sizeof(flags)};
        int ret, i;
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -202,13 +203,13 @@ int com_lsatt(struct stream_cipher_context *scc, int argc, char * const * const
                        continue;
                }
        }
-       ret = send_option_arg_callback_request(&options, argc - i, argv + i,
-               com_lsatt_callback, sc_send_result, scc);
+       ret = send_option_arg_callback_request(&options, cc->argc - i, cc->argv + i,
+               com_lsatt_callback, sc_send_result, cc);
        if (!ret) {
-               if (argc > 1)
-                       ret = sc_send_va_buffer(scc, "no matches\n");
+               if (cc->argc > 1)
+                       ret = sc_send_va_buffer(&cc->scc, "no matches\n");
        } else if (ret < 0)
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -276,12 +277,12 @@ out:
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
-int com_setatt(__a_unused struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_setatt(struct command_context *cc)
 {
-       if (argc < 3)
+       if (cc->argc < 3)
                return -E_ATTR_SYNTAX;
-       return send_standard_callback_request(argc - 1, argv + 1, com_setatt_callback,
-               NULL, NULL);
+       return send_standard_callback_request(cc->argc - 1, cc->argv + 1,
+               com_setatt_callback, NULL, NULL);
 }
 
 struct addatt_event_data {
@@ -357,16 +358,16 @@ out:
        free(pb.buf);
 }
 
-int com_addatt(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_addatt(struct command_context *cc)
 {
        int ret;
 
-       if (argc < 2)
+       if (cc->argc < 2)
                return -E_ATTR_SYNTAX;
-       ret = send_standard_callback_request(argc - 1, argv + 1, com_addatt_callback,
-               sc_send_result, scc);
+       ret = send_standard_callback_request(cc->argc - 1, cc->argv + 1,
+               com_addatt_callback, sc_send_result, cc);
        if (ret < 0)
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -400,16 +401,16 @@ out:
        free(pb.buf);
 }
 
-int com_mvatt(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_mvatt(struct command_context *cc)
 {
        int ret;
 
-       if (argc != 3)
+       if (cc->argc != 3)
                return -E_ATTR_SYNTAX;
-       ret = send_standard_callback_request(argc - 1, argv + 1, com_mvatt_callback,
-               sc_send_result, scc);
+       ret = send_standard_callback_request(cc->argc - 1, cc->argv + 1,
+               com_mvatt_callback, sc_send_result, cc);
        if (ret < 0)
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -472,16 +473,16 @@ static void com_rmatt_callback(int fd, const struct osl_object *query)
        free(raad.pb.buf);
 }
 
-int com_rmatt(struct stream_cipher_context *scc, int argc, char * const * const argv)
+int com_rmatt(struct command_context *cc)
 {
        int ret;
 
-       if (argc < 2)
+       if (cc->argc < 2)
                return -E_ATTR_SYNTAX;
-       ret = send_standard_callback_request(argc - 1, argv + 1, com_rmatt_callback,
-               sc_send_result, scc);
+       ret = send_standard_callback_request(cc->argc - 1, cc->argv + 1,
+               com_rmatt_callback, sc_send_result, cc);
        if (ret < 0)
-               sc_send_va_buffer(scc, "%s\n", para_strerror(-ret));
+               sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
        return ret;
 }
 
index 09b21ba..d3e092e 100644 (file)
--- a/audioc.c
+++ b/audioc.c
@@ -341,7 +341,7 @@ int main(int argc, char *argv[])
                size_t n = ret = recv_bin_buffer(fd, buf, bufsize);
                if (ret <= 0)
                        break;
-               ret = write_all(STDOUT_FILENO, buf, &n);
+               ret = write_all(STDOUT_FILENO, buf, n);
        } while (ret >= 0);
 out:
        free(buf);
index a78757b..d7765e2 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -918,8 +918,10 @@ static int parse_filter_args(void)
 {
        int i, j, ret, af_mask;
 
-       if (!conf.no_default_filters_given)
-               return init_default_filters();
+       if (conf.no_default_filters_given) {
+               PARA_WARNING_LOG("--no_default_filters is deprecated\n");
+               PARA_WARNING_LOG("It has no effect and will be removed soon\n");
+       }
        for (i = 0; i < conf.filter_given; i++) {
                char *arg;
                ret = parse_stream_command(conf.filter_arg[i], &arg);
diff --git a/blob.c b/blob.c
index ee4e405..409e348 100644 (file)
--- a/blob.c
+++ b/blob.c
@@ -18,6 +18,7 @@
 #include "afs.h"
 #include "ipc.h"
 #include "portable_io.h"
+#include "command.h"
 
 /**
  * Compare two osl objects pointing to unsigned integers of 32 bit size.
@@ -163,14 +164,14 @@ static void com_lsblob_callback(struct osl_table *table,
        free(lbad.pb.buf);
 }
 
-static int com_lsblob(callback_function *f, struct stream_cipher_context *scc, int argc, char * const * const argv)
+static int com_lsblob(callback_function *f, struct command_context *cc)
 {
        uint32_t flags = 0;
        struct osl_object options = {.data = &flags, .size = sizeof(flags)};
        int i;
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -193,8 +194,8 @@ static int com_lsblob(callback_function *f, struct stream_cipher_context *scc, i
        }
 //     if (argc > i)
 //             return -E_BLOB_SYNTAX;
-       return send_option_arg_callback_request(&options, argc - i,
-               argv + i, f, sc_send_result, scc);
+       return send_option_arg_callback_request(&options, cc->argc - i,
+               cc->argv + i, f, sc_send_result, cc);
 }
 
 static int cat_blob(struct osl_table *table, struct osl_row *row,
@@ -231,13 +232,12 @@ static void com_catblob_callback(struct osl_table *table, int fd,
        }
 }
 
-static int com_catblob(callback_function *f, struct stream_cipher_context *scc, int argc,
-               char * const * const argv)
+static int com_catblob(callback_function *f, struct command_context *cc)
 {
-       if (argc < 2)
+       if (cc->argc < 2)
                return -E_BLOB_SYNTAX;
-       return send_standard_callback_request(argc - 1, argv + 1, f,
-               sc_send_result, scc);
+       return send_standard_callback_request(cc->argc - 1, cc->argv + 1, f,
+               sc_send_result, cc);
 }
 
 /** Used for removing rows from a blob table. */
@@ -296,13 +296,12 @@ out:
        free(rmbd.pb.buf);
 }
 
-static int com_rmblob(callback_function *f, struct stream_cipher_context *scc, int argc,
-               char * const * const argv)
+static int com_rmblob(callback_function *f, struct command_context *cc)
 {
-       if (argc < 2)
+       if (cc->argc < 2)
                return -E_MOOD_SYNTAX;
-       return send_option_arg_callback_request(NULL, argc - 1, argv + 1, f,
-               sc_send_result, scc);
+       return send_option_arg_callback_request(NULL, cc->argc - 1, cc->argv + 1, f,
+               sc_send_result, cc);
 }
 
 static void com_addblob_callback(struct osl_table *table, __a_unused int fd,
@@ -425,7 +424,7 @@ static int fd2buf(struct stream_cipher_context *scc, unsigned max_size, struct o
  * \return Negative on errors, the return value of the underlying call to
  * send_callback_request() otherwise.
  */
-static int stdin_command(struct stream_cipher_context *scc, struct osl_object *arg_obj,
+static int stdin_command(struct command_context *cc, struct osl_object *arg_obj,
                callback_function *f, unsigned max_len,
                callback_result_handler *result_handler,
                void *private_result_data)
@@ -433,10 +432,10 @@ static int stdin_command(struct stream_cipher_context *scc, struct osl_object *a
        struct osl_object query, stdin_obj;
        int ret;
 
-       ret = sc_send_buffer(scc, AWAITING_DATA_MSG);
+       ret = sc_send_buffer(&cc->scc, AWAITING_DATA_MSG);
        if (ret < 0)
                return ret;
-       ret = fd2buf(scc, max_len, &stdin_obj);
+       ret = fd2buf(&cc->scc, max_len, &stdin_obj);
        if (ret < 0)
                return ret;
        query.size = arg_obj->size + stdin_obj.size;
@@ -449,18 +448,17 @@ static int stdin_command(struct stream_cipher_context *scc, struct osl_object *a
        return ret;
 }
 
-static int com_addblob(callback_function *f, struct stream_cipher_context *scc, int argc,
-               char * const * const argv)
+static int com_addblob(callback_function *f, struct command_context *cc)
 {
        struct osl_object arg_obj;
 
-       if (argc != 2)
+       if (cc->argc != 2)
                return -E_BLOB_SYNTAX;
-       if (!*argv[1]) /* empty name is reserved for the dummy row */
+       if (!*cc->argv[1]) /* empty name is reserved for the dummy row */
                return -E_BLOB_SYNTAX;
-       arg_obj.size = strlen(argv[1]) + 1;
-       arg_obj.data = (char *)argv[1];
-       return stdin_command(scc, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL);
+       arg_obj.size = strlen(cc->argv[1]) + 1;
+       arg_obj.data = (char *)cc->argv[1];
+       return stdin_command(cc, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL);
 }
 
 /* FIXME: Print output to client, not to log file */
@@ -486,13 +484,12 @@ out:
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
-static int com_mvblob(callback_function *f, __a_unused struct stream_cipher_context *scc,
-               int argc, char * const * const argv)
+static int com_mvblob(callback_function *f, struct command_context *cc)
 {
-       if (argc != 3)
+       if (cc->argc != 3)
                return -E_MOOD_SYNTAX;
-       return send_option_arg_callback_request(NULL, argc - 1, argv + 1, f,
-               NULL, NULL);
+       return send_option_arg_callback_request(NULL, cc->argc - 1,
+               cc->argv + 1, f, NULL, NULL);
 }
 
 #define DEFINE_BLOB_COMMAND(cmd_name, table_name, cmd_prefix) \
@@ -500,9 +497,9 @@ static int com_mvblob(callback_function *f, __a_unused struct stream_cipher_cont
        { \
                return com_ ## cmd_name ## blob_callback(table_name ## _table, fd, query); \
        } \
-       int com_ ## cmd_name ## cmd_prefix(struct stream_cipher_context *scc, int argc, char * const * const argv) \
+       int com_ ## cmd_name ## cmd_prefix(struct command_context *cc) \
        { \
-               return com_ ## cmd_name ## blob(com_ ## cmd_name ## cmd_prefix ## _callback, scc, argc, argv); \
+               return com_ ## cmd_name ## blob(com_ ## cmd_name ## cmd_prefix ## _callback, cc); \
        }
 
 static int blob_get_name_by_id(struct osl_table *table, uint32_t id,
index bb421e3..5bd2241 100644 (file)
@@ -188,7 +188,7 @@ static void client_post_select(struct sched *s, struct task *t)
                PARA_INFO_LOG("--> %s\n", buf);
                if (!FD_ISSET(ct->scc.fd, &s->wfds))
                        return;
-               ret = send_buffer(ct->scc.fd, buf);
+               ret = write_buffer(ct->scc.fd, buf);
                if (ret < 0)
                        goto out;
                ct->status = CL_SENT_AUTH;
@@ -218,8 +218,7 @@ static void client_post_select(struct sched *s, struct task *t)
                        SESSION_KEY_LEN);
                hash_to_asc(challenge_hash, buf);
                PARA_INFO_LOG("--> %s\n", buf);
-               ret = send_bin_buffer(ct->scc.fd, (char *)challenge_hash,
-                       HASH_SIZE);
+               ret = write_all(ct->scc.fd, (char *)challenge_hash, HASH_SIZE);
                if (ret < 0)
                        goto out;
                ct->status = CL_SENT_CH_RESPONSE;
index f194a7c..4a464eb 100644 (file)
--- a/command.c
+++ b/command.c
@@ -41,7 +41,7 @@
 extern int mmd_mutex;
 extern struct misc_meta_data *mmd;
 extern struct sender senders[];
-int send_afs_status(struct stream_cipher_context *scc, int parser_friendly);
+int send_afs_status(struct command_context *cc, int parser_friendly);
 
 const char *status_item_list[] = {STATUS_ITEM_ARRAY};
 
@@ -193,29 +193,29 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman
        return 1;
 }
 
-int com_sender(struct stream_cipher_context *scc, int argc, char * const * argv)
+int com_sender(struct command_context *cc)
 {
        int i, ret;
        char *msg = NULL;
        struct sender_command_data scd;
 
-       if (argc < 2) {
+       if (cc->argc < 2) {
                for (i = 0; senders[i].name; i++) {
                        char *tmp = make_message("%s%s\n",
                                msg? msg : "", senders[i].name);
                        free(msg);
                        msg = tmp;
                }
-               ret = sc_send_buffer(scc, msg);
+               ret = sc_send_buffer(&cc->scc, msg);
                free(msg);
                return ret;
        }
-       ret = check_sender_args(argc, argv, &scd);
+       ret = check_sender_args(cc->argc, cc->argv, &scd);
        if (ret < 0) {
                if (scd.sender_num < 0)
                        return ret;
                msg = senders[scd.sender_num].help();
-               ret = sc_send_buffer(scc, msg);
+               ret = sc_send_buffer(&cc->scc, msg);
                free(msg);
                return ret;
        }
@@ -224,7 +224,7 @@ int com_sender(struct stream_cipher_context *scc, int argc, char * const * argv)
        case SENDER_ADD:
        case SENDER_DELETE:
                assert(senders[scd.sender_num].resolve_target);
-               ret = senders[scd.sender_num].resolve_target(argv[3], &scd);
+               ret = senders[scd.sender_num].resolve_target(cc->argv[3], &scd);
                if (ret < 0)
                        return ret;
        }
@@ -244,13 +244,13 @@ int com_sender(struct stream_cipher_context *scc, int argc, char * const * argv)
 }
 
 /* server info */
-int com_si(struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_si(struct command_context *cc)
 {
        int i, ret;
        char *ut;
        char *sender_info = NULL;
 
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        mutex_lock(mmd_mutex);
        for (i = 0; senders[i].name; i++) {
@@ -259,7 +259,7 @@ int com_si(struct stream_cipher_context *scc, int argc, __a_unused char * const
                free(info);
        }
        ut = get_server_uptime_str(now);
-       ret = sc_send_va_buffer(scc, "version: " GIT_VERSION "\n"
+       ret = sc_send_va_buffer(&cc->scc, "version: " GIT_VERSION "\n"
                "up: %s\nplayed: %u\n"
                "server_pid: %d\n"
                "afs_pid: %d\n"
@@ -284,11 +284,11 @@ int com_si(struct stream_cipher_context *scc, int argc, __a_unused char * const
 }
 
 /* version */
-int com_version(struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_version(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
-       return sc_send_buffer(scc, VERSION_TEXT("server")
+       return sc_send_buffer(&cc->scc, VERSION_TEXT("server")
                "built: " BUILD_DATE "\n"
                UNAME_RS ", " CC_VERSION "\n"
        );
@@ -350,7 +350,7 @@ static char *empty_status_items(int parser_friendly)
 #undef EMPTY_STATUS_ITEMS
 
 /* stat */
-int com_stat(struct stream_cipher_context *scc, int argc, char * const * argv)
+int com_stat(struct command_context *cc)
 {
        int i, ret;
        struct misc_meta_data tmp, *nmmd = &tmp;
@@ -360,8 +360,8 @@ int com_stat(struct stream_cipher_context *scc, int argc, char * const * argv)
 
        para_sigaction(SIGUSR1, dummy);
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       for (i = 1; i < cc->argc; i++) {
+               const char *arg = cc->argv[i];
                if (arg[0] != '-')
                        break;
                if (!strcmp(arg, "--")) {
@@ -380,12 +380,12 @@ int com_stat(struct stream_cipher_context *scc, int argc, char * const * argv)
                }
                return -E_COMMAND_SYNTAX;
        }
-       if (i != argc)
+       if (i != cc->argc)
                return -E_COMMAND_SYNTAX;
        for (;;) {
                mmd_dup(nmmd);
                s = get_status(nmmd, parser_friendly);
-               ret = sc_send_buffer(scc, s);
+               ret = sc_send_buffer(&cc->scc, s);
                free(s);
                if (ret < 0)
                        goto out;
@@ -393,11 +393,11 @@ int com_stat(struct stream_cipher_context *scc, int argc, char * const * argv)
                        static char *esi;
                        if (!esi)
                                esi = empty_status_items(parser_friendly);
-                       ret = sc_send_buffer(scc, esi);
+                       ret = sc_send_buffer(&cc->scc, esi);
                        if (ret < 0)
                                goto out;
                } else
-                       send_afs_status(scc, parser_friendly);
+                       send_afs_status(cc, parser_friendly);
                ret = 1;
                if (num > 0 && !--num)
                        goto out;
@@ -449,30 +449,30 @@ static struct server_command *get_cmd_ptr(const char *name, char **handler)
 }
 
 /* help */
-int com_help(struct stream_cipher_context *scc, int argc, char * const * argv)
+int com_help(struct command_context *cc)
 {
        struct server_command *cmd;
        char *perms, *handler;
        int ret;
 
-       if (argc < 2) {
+       if (cc->argc < 2) {
                /* no argument given, print list of commands */
-               if ((ret = send_list_of_commands(scc, server_cmds, "server")) < 0)
+               if ((ret = send_list_of_commands(&cc->scc, server_cmds, "server")) < 0)
                        return ret;
-               return send_list_of_commands(scc, afs_cmds, "afs");
+               return send_list_of_commands(&cc->scc, afs_cmds, "afs");
        }
        /* argument given for help */
-       cmd = get_cmd_ptr(argv[1], &handler);
+       cmd = get_cmd_ptr(cc->argv[1], &handler);
        if (!cmd)
                return -E_BAD_CMD;
        perms = cmd_perms_itohuman(cmd->perms);
-       ret = sc_send_va_buffer(scc,
+       ret = sc_send_va_buffer(&cc->scc,
                "%s - %s\n\n"
                "handler: %s\n"
                "permissions: %s\n"
                "usage: %s\n\n"
                "%s\n",
-               argv[1],
+               cc->argv[1],
                cmd->description,
                handler,
                perms,
@@ -485,39 +485,38 @@ int com_help(struct stream_cipher_context *scc, int argc, char * const * argv)
 }
 
 /* hup */
-int com_hup(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_hup(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        kill(getppid(), SIGHUP);
        return 1;
 }
 
 /* term */
-int com_term(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_term(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        kill(getppid(), SIGTERM);
        return 1;
 }
 
-int com_play(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_play(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        mutex_lock(mmd_mutex);
        mmd->new_vss_status_flags |= VSS_PLAYING;
        mmd->new_vss_status_flags &= ~VSS_NOMORE;
        mutex_unlock(mmd_mutex);
        return 1;
-
 }
 
 /* stop */
-int com_stop(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_stop(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        mutex_lock(mmd_mutex);
        mmd->new_vss_status_flags &= ~VSS_PLAYING;
@@ -528,9 +527,9 @@ int com_stop(__a_unused struct stream_cipher_context *scc, int argc, __a_unused
 }
 
 /* pause */
-int com_pause(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_pause(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        mutex_lock(mmd_mutex);
        if (!vss_paused() && !vss_stopped()) {
@@ -543,9 +542,9 @@ int com_pause(__a_unused struct stream_cipher_context *scc, int argc, __a_unused
 }
 
 /* next */
-int com_next(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_next(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        mutex_lock(mmd_mutex);
        mmd->events++;
@@ -555,9 +554,9 @@ int com_next(__a_unused struct stream_cipher_context *scc, int argc, __a_unused
 }
 
 /* nomore */
-int com_nomore(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv)
+int com_nomore(struct command_context *cc)
 {
-       if (argc != 1)
+       if (cc->argc != 1)
                return -E_COMMAND_SYNTAX;
        mutex_lock(mmd_mutex);
        if (vss_playing() || vss_paused())
@@ -567,16 +566,16 @@ int com_nomore(__a_unused struct stream_cipher_context *scc, int argc, __a_unuse
 }
 
 /* ff */
-int com_ff(__a_unused struct stream_cipher_context *scc, int argc, char * const * argv)
+int com_ff(struct command_context *cc)
 {
        long promille;
        int ret, backwards = 0;
        unsigned i;
        char c;
 
-       if (argc != 2)
+       if (cc->argc != 2)
                return -E_COMMAND_SYNTAX;
-       if (!(ret = sscanf(argv[1], "%u%c", &i, &c)))
+       if (!(ret = sscanf(cc->argv[1], "%u%c", &i, &c)))
                return -E_COMMAND_SYNTAX;
        if (ret > 1 && c == '-')
                backwards = 1; /* jmp backwards */
@@ -606,14 +605,14 @@ out:
 }
 
 /* jmp */
-int com_jmp(__a_unused struct stream_cipher_context *scc, int argc, char * const * argv)
+int com_jmp(struct command_context *cc)
 {
        long unsigned int i;
        int ret;
 
-       if (argc != 2)
+       if (cc->argc != 2)
                return -E_COMMAND_SYNTAX;
-       if (sscanf(argv[1], "%lu", &i) <= 0)
+       if (sscanf(cc->argv[1], "%lu", &i) <= 0)
                return -E_COMMAND_SYNTAX;
        mutex_lock(mmd_mutex);
        ret = -E_NO_AUDIO_FILE;
@@ -733,24 +732,22 @@ static void reset_signals(void)
  */
 __noreturn void handle_connect(int fd, const char *peername)
 {
-       int ret, argc;
+       int ret;
        char buf[4096];
        unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN];
        unsigned char challenge_hash[HASH_SIZE];
-       struct user *u;
-       struct server_command *cmd = NULL;
-       char **argv = NULL;
        char *p, *command = NULL;
        size_t numbytes;
-       struct stream_cipher_context scc = {.fd = fd};
+       struct command_context cc_struct = {.peer = peername}, *cc = &cc_struct;
 
+       cc->scc.fd = fd;
        reset_signals();
        /* we need a blocking fd here as recv() might return EAGAIN otherwise. */
        ret = mark_fd_blocking(fd);
        if (ret < 0)
                goto net_err;
        /* send Welcome message */
-       ret = send_va_buffer(fd, "This is para_server, version "
+       ret = write_va_buffer(fd, "This is para_server, version "
                PACKAGE_VERSION  ".\n" );
        if (ret < 0)
                goto net_err;
@@ -767,10 +764,10 @@ __noreturn void handle_connect(int fd, const char *peername)
                goto net_err;
        p = buf + strlen(AUTH_REQUEST_MSG);
        PARA_DEBUG_LOG("received auth request for user %s\n", p);
-       u = lookup_user(p);
-       if (u) {
+       cc->u = lookup_user(p);
+       if (cc->u) {
                get_random_bytes_or_die(rand_buf, sizeof(rand_buf));
-               ret = pub_encrypt(u->pubkey, rand_buf, sizeof(rand_buf),
+               ret = pub_encrypt(cc->u->pubkey, rand_buf, sizeof(rand_buf),
                        (unsigned char *)buf);
                if (ret < 0)
                        goto net_err;
@@ -786,7 +783,7 @@ __noreturn void handle_connect(int fd, const char *peername)
        }
        PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n",
                CHALLENGE_SIZE, numbytes);
-       ret = send_bin_buffer(fd, buf, numbytes);
+       ret = write_all(fd, buf, numbytes);
        if (ret < 0)
                goto net_err;
        /* recv challenge response */
@@ -796,7 +793,7 @@ __noreturn void handle_connect(int fd, const char *peername)
        numbytes = ret;
        PARA_DEBUG_LOG("received %d bytes challenge response\n", ret);
        ret = -E_BAD_USER;
-       if (!u)
+       if (!cc->u)
                goto net_err;
        /*
         * The correct response is the hash of the first CHALLENGE_SIZE bytes
@@ -810,50 +807,50 @@ __noreturn void handle_connect(int fd, const char *peername)
                goto net_err;
        /* auth successful */
        alarm(0);
-       PARA_INFO_LOG("good auth for %s\n", u->name);
+       PARA_INFO_LOG("good auth for %s\n", cc->u->name);
        /* init stream cipher keys with the second part of the random buffer */
-       scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN);
-       scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN);
-       ret = sc_send_buffer(&scc, PROCEED_MSG);
+       cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN);
+       cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN);
+       ret = sc_send_buffer(&cc->scc, PROCEED_MSG);
        if (ret < 0)
                goto net_err;
-       ret = read_command(&scc, &command);
+       ret = read_command(&cc->scc, &command);
        if (ret == -E_COMMAND_SYNTAX)
                goto err_out;
        if (ret < 0)
                goto net_err;
        ret = -E_BAD_CMD;
-       cmd = parse_cmd(command);
-       if (!cmd)
+       cc->cmd = parse_cmd(command);
+       if (!cc->cmd)
                goto err_out;
        /* valid command, check permissions */
-       ret = check_perms(u->perms, cmd);
+       ret = check_perms(cc->u->perms, cc->cmd);
        if (ret < 0)
                goto err_out;
        /* valid command and sufficient perms */
-       ret = create_argv(command, "\n", &argv);
+       ret = create_argv(command, "\n", &cc->argv);
        if (ret < 0)
                goto err_out;
-       argc = ret;
-       PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name, u->name,
-                       peername);
-       ret = cmd->handler(&scc, argc, argv);
-       free_argv(argv);
+       cc->argc = ret;
+       PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cc->cmd->name,
+               cc->u->name, peername);
+       ret = cc->cmd->handler(cc);
+       free_argv(cc->argv);
        mutex_lock(mmd_mutex);
        mmd->num_commands++;
        mutex_unlock(mmd_mutex);
        if (ret >= 0)
                goto out;
 err_out:
-       sc_send_va_buffer(&scc, "%s\n", para_strerror(-ret));
+       sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(-ret));
 net_err:
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 out:
        free(command);
-       sc_free(scc.recv);
-       sc_free(scc.send);
+       sc_free(cc->scc.recv);
+       sc_free(cc->scc.send);
        mutex_lock(mmd_mutex);
-       if (cmd && (cmd->perms & AFS_WRITE) && ret >= 0)
+       if (cc->cmd && (cc->cmd->perms & AFS_WRITE) && ret >= 0)
                mmd->events++;
        mmd->active_connections--;
        mutex_unlock(mmd_mutex);
index fd87982..05510cc 100644 (file)
--- a/command.h
+++ b/command.h
@@ -1,5 +1,21 @@
 /** \file command.h The structure of server and afs commands. */
 
+/** Per connection data available to command handlers. */
+struct command_context {
+       /** Network address of the peer. */
+       const char *peer;
+       /** The paraslash user that executes this command. */
+       struct user *u;
+       /** Argument count. */
+       int argc;
+       /** Argument vector. */
+       char **argv;
+       /** The command being executed. */
+       struct server_command *cmd;
+       /** File descriptor and crypto keys. */
+       struct stream_cipher_context scc;
+};
+
 /**
  * Defines one command of para_server.
  */
@@ -7,7 +23,7 @@ struct server_command {
        /** The name of the command. */
        const char *name;
        /** Pointer to the function that handles the command. */
-       int (*handler)(struct stream_cipher_context *, int, char * const * const);
+       int (*handler)(struct command_context *);
        /** The privileges a user must have to execute this command. */
        unsigned int perms;
        /** One-line description of the command. */
index 89242d9..b5898ac 100644 (file)
@@ -748,7 +748,7 @@ if test -n "$with_flac_libs"; then
        LDFLAGS="$LDFLAGS $flac_libs"
 fi
 AC_CHECK_HEADER(FLAC/stream_decoder.h, [], have_flac=no)
-AC_CHECK_LIB([FLAC], [FLAC__stream_decoder_init_file], [], have_flac=no)
+AC_CHECK_LIB([FLAC], [FLAC__stream_decoder_init_file], [], have_flac=no, -logg -lm)
 if test "$have_flac" = "yes"; then
        AC_DEFINE(HAVE_FLAC, 1, define to 1 if you want to build the flacdec filter)
        all_errlist_objs="$all_errlist_objs flacdec_filter flac_afh"
diff --git a/crypt.c b/crypt.c
index 69e4a31..f33f769 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -298,7 +298,7 @@ int sc_send_bin_buffer(struct stream_cipher_context *scc, char *buf,
                memcpy(remainder, buf + l1, len - l1);
                RC4(&scc->send->key, len - l1, remainder, tmp + l1);
        }
-       ret = write_all(scc->fd, (char *)tmp, &len);
+       ret = xwrite(scc->fd, (char *)tmp, len);
        free(tmp);
        return ret;
 }
index e02dc6a..5ad4d43 100644 (file)
@@ -337,7 +337,12 @@ int sc_recv_buffer(struct stream_cipher_context *scc, char *buf, size_t size)
 
 int sc_send_buffer(struct stream_cipher_context *scc, char *buf)
 {
-       return sc_send_bin_buffer(scc, buf, strlen(buf));
+       size_t len = strlen(buf);
+       int ret = sc_send_bin_buffer(scc, buf, len);
+
+       if (ret < 0 || ret == len)
+               return ret;
+       return -E_SHORT_WRITE;
 }
 
 __printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc,
@@ -345,9 +350,12 @@ __printf_2_3 int sc_send_va_buffer(struct stream_cipher_context *scc,
 {
        char *msg;
        int ret;
+       va_list ap;
 
-       PARA_VSPRINTF(fmt, msg);
-       ret = sc_send_buffer(scc, msg);
+       va_start(ap, fmt);
+       ret = xvasprintf(&msg, fmt, ap);
+       va_end(ap);
+       ret = sc_send_bin_buffer(scc, msg, ret);
        free(msg);
        return ret;
 }
index fa2a163..cfbc4de 100644 (file)
@@ -104,7 +104,7 @@ static int dccp_init_fec(struct sender_client *sc)
 
 static void dccp_send_fec(struct sender_client *sc, char *buf, size_t len)
 {
-       int ret = write_nonblock(sc->fd, buf, len);
+       int ret = xwrite(sc->fd, buf, len);
 
        if (ret < 0)
                dccp_shutdown_client(sc);
diff --git a/error.h b/error.h
index 63d4d5d..e34d809 100644 (file)
--- a/error.h
+++ b/error.h
@@ -441,6 +441,8 @@ extern const char **para_errlist[];
        PARA_ERROR(FGETS, "fgets error"), \
        PARA_ERROR(EOF, "end of file"), \
        PARA_ERROR(READ_PATTERN, "did not read expected pattern"), \
+       PARA_ERROR(SHORT_WRITE, "unexpected short write"), \
+       PARA_ERROR(EMPTY, "file is empty"), \
 
 
 #define ALSA_WRITE_ERRORS \
diff --git a/fd.c b/fd.c
index 2e05313..3a8406d 100644 (file)
--- a/fd.c
+++ b/fd.c
 #include "fd.h"
 
 /**
- * Write a buffer to a file descriptor, re-write on short writes.
+ * Write an array of buffers to a file descriptor.
  *
  * \param fd The file descriptor.
- * \param buf The buffer to be sent.
- * \param len The length of \a buf.
+ * \param iov Pointer to one or more buffers.
+ * \param iovcnt The number of buffers.
+ *
+ * EAGAIN/EWOULDBLOCK is not considered a fatal error condition. For example
+ * DCCP CCID3 has a sending wait queue which fills up and is emptied
+ * asynchronously. The EAGAIN case means that there is currently no space in
+ * the wait queue, but this can change at any moment.
+ *
+ * \return Negative on fatal errors, number of bytes written else.
  *
- * \return Standard. In any case, the number of bytes that have been written is
- * stored in \a len.
+ * For blocking file descriptors, this function returns either the sum of all
+ * buffer sizes, or the error code of the fatal error that caused the last
+ * write call to fail.
+ *
+ * For nonblocking file descriptors there is a third possibility: Any positive
+ * return value less than the sum of the buffer sizes indicates that some bytes
+ * have been written but the next write would block.
+ *
+ * \sa writev(2), \ref xwrite().
  */
-int write_all(int fd, const char *buf, size_t *len)
+int xwritev(int fd, struct iovec *iov, int iovcnt)
 {
-       size_t total = *len;
-
-       assert(total);
-       *len = 0;
-       while (*len < total) {
-               int ret = write(fd, buf + *len, total - *len);
-               if (ret == -1)
-                       return -ERRNO_TO_PARA_ERROR(errno);
-               *len += ret;
+       size_t written = 0;
+       int i;
+       struct iovec saved_iov, *curiov;
+
+       i = 0;
+       curiov = iov;
+       saved_iov = *curiov;
+       while (i < iovcnt && curiov->iov_len > 0) {
+               ssize_t ret = writev(fd, curiov, iovcnt - i);
+               if (ret >= 0) {
+                       written += ret;
+                       while (ret > 0) {
+                               if (ret < curiov->iov_len) {
+                                       curiov->iov_base += ret;
+                                       curiov->iov_len -= ret;
+                                       break;
+                               }
+                               ret -= curiov->iov_len;
+                               *curiov = saved_iov;
+                               i++;
+                               if (i >= iovcnt)
+                                       return written;
+                               curiov++;
+                               saved_iov = *curiov;
+                       }
+                       continue;
+               }
+               if (errno == EINTR)
+                       /*
+                        * The write() call was interrupted by a signal before
+                        * any data was written. Try again.
+                        */
+                       continue;
+               if (errno == EAGAIN || errno == EWOULDBLOCK)
+                       /*
+                        * We don't consider this an error. Note that POSIX
+                        * allows either error to be returned, and does not
+                        * require these constants to have the same value.
+                        */
+                       return written;
+               /* fatal error */
+               return -ERRNO_TO_PARA_ERROR(errno);
        }
-       return 1;
+       return written;
 }
 
 /**
- * Write a buffer to a non-blocking file descriptor.
+ * Write a buffer to a file descriptor, re-writing on short writes.
  *
  * \param fd The file descriptor.
- * \param buf the buffer to write.
- * \param len the number of bytes of \a buf.
+ * \param buf The buffer to write.
+ * \param len The number of bytes to write.
  *
- * EAGAIN is not considered an error condition.  For example CCID3 has a
- * sending wait queue which fills up and is emptied asynchronously. The EAGAIN
- * case means that there is currently no space in the wait queue, but this can
- * change at any moment.
+ * This is a simple wrapper for \ref xwritev().
  *
- * \return Negative on errors, number of bytes written else.
+ * \return The return value of the underlying call to \ref xwritev().
  */
-int write_nonblock(int fd, const char *buf, size_t len)
+int xwrite(int fd, const char *buf, size_t len)
 {
-       size_t written = 0;
-       int ret = 0;
+       struct iovec iov = {.iov_base = (void *)buf, .iov_len = len};
+       return xwritev(fd, &iov, 1);
+}
+
+/**
+ * Write all data to a file descriptor.
+ *
+ * \param fd The file descriptor.
+ * \param buf The buffer to be sent.
+ * \param len The length of \a buf.
+ *
+ * This is like \ref xwrite() but returns \p -E_SHORT_WRITE if not
+ * all data could be written.
+ *
+ * \return Number of bytes written on success, negative error code else.
+ */
+int write_all(int fd, const char *buf, size_t len)
+{
+       int ret = xwrite(fd, buf, len);
 
-       while (written < len) {
-               size_t num = len - written;
+       if (ret < 0)
+               return ret;
+       if (ret != len)
+               return -E_SHORT_WRITE;
+       return ret;
+}
 
-               ret = write(fd, buf + written, num);
-               if (ret < 0 && errno == EAGAIN)
-                       return written;
-               if (ret < 0)
-                       return -ERRNO_TO_PARA_ERROR(errno);
-               written += ret;
-       }
-       return written;
+/**
+ * Write a buffer given by a format string.
+ *
+ * \param fd The file descriptor.
+ * \param fmt A format string.
+ *
+ * \return The return value of the underlying call to \ref write_all().
+ */
+__printf_2_3 int write_va_buffer(int fd, const char *fmt, ...)
+{
+       char *msg;
+       int ret;
+       va_list ap;
+
+       va_start(ap, fmt);
+       ret = xvasprintf(&msg, fmt, ap);
+       ret = write_all(fd, msg, ret);
+       free(msg);
+       return ret;
 }
 
 /**
@@ -87,7 +163,7 @@ int write_nonblock(int fd, const char *buf, size_t len)
  * If \a rfds is not \p NULL and the (non-blocking) file descriptor \a fd is
  * not set in \a rfds, this function returns early without doing anything.
  * Otherwise The function tries to read up to \a sz bytes from \a fd. As for
- * write_nonblock(), EAGAIN is not considered an error condition. However, EOF
+ * xwrite(), EAGAIN is not considered an error condition. However, EOF
  * is.
  *
  * \return Zero or a negative error code. If the underlying call to readv(2)
@@ -100,7 +176,7 @@ int write_nonblock(int fd, const char *buf, size_t len)
  * have been read before the error occurred. In this case \a num_bytes is
  * positive.
  *
- * \sa \ref write_nonblock(), read(2), readv(2).
+ * \sa \ref xwrite(), read(2), readv(2).
  */
 int readv_nonblock(int fd, struct iovec *iov, int iovcnt, fd_set *rfds,
                size_t *num_bytes)
@@ -541,6 +617,22 @@ int mmap_full_file(const char *path, int open_mode, void **map,
                goto out;
        }
        *size = file_status.st_size;
+       /*
+        * If the file is empty, *size is zero and mmap() would return EINVAL
+        * (Invalid argument). This error is common enough to spend an extra
+        * error code which explicitly states the problem.
+        */
+       ret = -E_EMPTY;
+       if (*size == 0)
+               goto out;
+       /*
+        * If fd refers to a directory, mmap() returns ENODEV (No such device),
+        * at least on Linux. "Is a directory" seems to be more to the point.
+        */
+       ret = -ERRNO_TO_PARA_ERROR(EISDIR);
+       if (S_ISDIR(file_status.st_mode))
+               goto out;
+
        ret = para_mmap(*size, mmap_prot, mmap_flags, fd, 0, map);
 out:
        if (ret < 0 || !fd_ptr)
diff --git a/fd.h b/fd.h
index c87c0ea..30b3411 100644 (file)
--- a/fd.h
+++ b/fd.h
@@ -6,7 +6,8 @@
 
 /** \file fd.h exported symbols from fd.c */
 
-int write_all(int fd, const char *buf, size_t *len);
+int write_all(int fd, const char *buf, size_t len);
+__printf_2_3 int write_va_buffer(int fd, const char *fmt, ...);
 int file_exists(const char *);
 int para_select(int n, fd_set *readfds, fd_set *writefds,
                struct timeval *timeout_tv);
@@ -28,6 +29,21 @@ int readv_nonblock(int fd, struct iovec *iov, int iovcnt, fd_set *rfds,
                size_t *num_bytes);
 int read_nonblock(int fd, void *buf, size_t sz, fd_set *rfds, size_t *num_bytes);
 int read_pattern(int fd, const char *pattern, size_t bufsize, fd_set *rfds);
-int write_nonblock(int fd, const char *buf, size_t len);
+int xwrite(int fd, const char *buf, size_t len);
+int xwritev(int fd, struct iovec *iov, int iovcnt);
 int for_each_file_in_dir(const char *dirname,
                int (*func)(const char *, void *), void *private_data);
+/**
+ * Write a \p NULL-terminated buffer.
+ *
+ * \param fd The file descriptor.
+ * \param buf The null-terminated buffer to be send.
+ *
+ * This is equivalent to write_all(fd, buf, strlen(buf)).
+ *
+ * \return Standard.
+ */
+_static_inline_ int write_buffer(int fd, const char *buf)
+{
+       return write_all(fd, buf, strlen(buf));
+}
index ba1d82e..5d20728 100644 (file)
@@ -5,15 +5,18 @@
 #define __a_aligned(alignment) __attribute__((__aligned__(alignment)))
 
 /*
- * p is the number of the "format string" parameter, and q is
- * the number of the first variadic parameter.
+ * p is the number of the "format string" parameter, and q is the number of the
+ * first variadic parameter. If q is specified as zero, the compiler only
+ * checks the format string for consistency.
  */
 # define __printf(p,q) __attribute__ ((format (printf, p, q)))
 # define __a_const __attribute__ ((const))
+
 /*
- * as direct use of __printf(p,q) confuses doxygen, here are two extra macros
- * for those values p,q that are actually used by paraslash.
+ * As direct use of __printf(p,q) confuses doxygen, here are some extra macros
+ * for those values p,q that are actually used.
  */
+#define  __printf_2_0 __printf(2,0)
 #define  __printf_1_2 __printf(1,2)
 #define  __printf_2_3 __printf(2,3)
 
index 2f38f1a..d11e94c 100644 (file)
--- a/gcrypt.c
+++ b/gcrypt.c
@@ -951,7 +951,7 @@ int sc_send_bin_buffer(struct stream_cipher_context *scc, char *buf,
        gret = gcry_cipher_encrypt(scc->send->handle, tmp, size,
                (unsigned char *)buf, size);
        assert(gret == 0);
-       ret = write_all(scc->fd, (char *)tmp, &size);
+       ret = xwrite(scc->fd, (char *)tmp, size);
        free(tmp);
        return ret;
 }
index 1fe1695..1bc5db1 100644 (file)
@@ -144,40 +144,37 @@ details="
 
 option "no_default_filters" D
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"Configure filters manually"
+"deprecated"
 flag off
 details = "
-       If (and only if) this option is set, the --filter options
-       (see below) take effect. Otherwise, the compiled-in defaults
-       apply.  These defaults depend on the receiver being used as
-       described below.
-
-       For http streams, only a single filter per audio format,
-       the decoder for that format, is activated. On the other hand,
-       since udp and dccp streams are sent fec-encoded by para_server,
-       the client side must feed the output of the receiver into
-       the fecdec filter first. Therefore the default for udp and
-       dccp streams is to activate the fecdec filter, followed by
-       the appropriate decoder.
-
-       You must give this option if you want to use any other filter,
-       for example the amp or the compress filter.
-
+       This option is was deprecated in paraslash-0.4.10 and has no
+       effect any more. It will be removed in the next version.
 "
 
 option "filter" f
 #~~~~~~~~~~~~~~~~
-"Use non-default filters"
-string typestr="filter_spec"
+"Specify the filter configuration."
+string typestr = "filter_spec"
 optional
 multiple
-dependon="no_default_filters"
-details="
+details = "
        This option may be given multiple times. The \"filter_spec\"
        consists of an audio format specifier (see above), the name
        of the filter, and any options for that filter. Note that
        order matters.
 
+       The compiled-in defaults apply to all audio formats for which
+       no --filter option was given. These defaults depend on the
+       receiver being used.
+
+       For HTTP streams, only the decoder for the current audio
+       format is activated. UDP and DCCP streams, on the other
+       hand, are sent FEC-encoded by para_server. In order to play
+       such streams, the receiver output must be FEC-decoded first,
+       i.e. fed to the fecdec filter. Therefore the default for UDP
+       and DCCP streams is to activate the fecdec filter, followed
+       by the decoding filter for the audio format.
+
        Examples:
 
                --filter 'mp3:mp3dec'
index e96fed3..07f779b 100644 (file)
@@ -76,7 +76,7 @@ static int gc_write(struct grab_client *gc, char *buf, size_t len)
                if (gc->mode == GM_SLOPPY)
                        return len;
        }
-       ret = write_nonblock(gc->fd, buf, len);
+       ret = xwrite(gc->fd, buf, len);
        if (ret < 0)
                goto err;
        if (ret > 0)
diff --git a/gui.c b/gui.c
index b7823f0..0316e36 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -336,11 +336,14 @@ static int align_str(WINDOW* win, char *str, unsigned int len,
 __printf_2_3 static void print_in_bar(int color, const char *fmt,...)
 {
        char *msg;
+       va_list ap;
 
        if (!curses_active)
                return;
        wattron(in.win, COLOR_PAIR(color));
-       PARA_VSPRINTF(fmt, msg);
+       va_start(ap, fmt);
+       xvasprintf(&msg, fmt, ap);
+       va_end(ap);
        wmove(in.win, 0, 0);
        align_str(in.win, msg, sb.cols, LEFT);
        free(msg);
@@ -471,10 +474,13 @@ static void rb_add_entry(int color, char *msg)
 __printf_2_3 static void outputf(int color, const char* fmt,...)
 {
        char *msg;
+       va_list ap;
 
        if (!curses_active)
                return;
-       PARA_VSPRINTF(fmt, msg);
+       va_start(ap, fmt);
+       xvasprintf(&msg, fmt, ap);
+       va_end(ap);
        rb_add_entry(color, msg);
        wrefresh(bot.win);
 }
@@ -493,6 +499,7 @@ __printf_2_3 void curses_log(int ll, const char *fmt,...)
 {
        int color;
        char *msg;
+       va_list ap;
 
        if (ll < loglevel || !curses_active)
                return;
@@ -505,7 +512,9 @@ __printf_2_3 void curses_log(int ll, const char *fmt,...)
                default:
                        color = COLOR_ERRMSG;
        }
-       PARA_VSPRINTF(fmt, msg);
+       va_start(ap, fmt);
+       xvasprintf(&msg, fmt, ap);
+       va_end(ap);
        chop(msg);
        rb_add_entry(color, msg);
        wrefresh(bot.win);
index 350f410..c3d918c 100644 (file)
@@ -95,7 +95,7 @@ static void http_recv_post_select(struct sched *s, struct task *t)
                        return;
                rq = make_request_msg();
                PARA_INFO_LOG("sending http request\n");
-               ret = send_va_buffer(rn->fd, "%s", rq);
+               ret = write_va_buffer(rn->fd, "%s", rq);
                free(rq);
                if (ret < 0)
                        goto out;
index 8b705d0..eddc029 100644 (file)
@@ -53,7 +53,7 @@ static struct sender_status http_sender_status, *hss = &http_sender_status;
 
 static int http_send_msg(struct sender_client *sc, const char *msg)
 {
-       int ret = send_buffer(sc->fd, msg);
+       int ret = write_buffer(sc->fd, msg);
 
        if (ret < 0)
                shutdown_client(sc, hss);
@@ -125,7 +125,7 @@ static void http_send_chunk(struct sender_client *sc, struct sender_status *ss,
                ret = queue_chunk_or_shutdown(sc, ss, buf, len);
                goto out;
        }
-       ret = write_nonblock(sc->fd, buf, len);
+       ret = xwrite(sc->fd, buf, len);
        if (ret < 0) {
                shutdown_client(sc, ss);
                goto out;
index e17a7a1..6a29bff 100644 (file)
@@ -292,7 +292,7 @@ static void i9e_post_select(struct sched *s, struct task *t)
        sz = btr_next_buffer(btrn, &buf);
        if (sz == 0)
                goto out;
-       ret = write_nonblock(ici->fds[1], buf, sz);
+       ret = xwrite(ici->fds[1], buf, sz);
        if (ret < 0)
                goto rm_btrn;
        btr_consume(btrn, ret);
diff --git a/net.c b/net.c
index 3ce98ea..92b4306 100644 (file)
--- a/net.c
+++ b/net.c
@@ -689,59 +689,6 @@ struct in_addr extract_v4_addr(const struct sockaddr_storage *ss)
        return ia;
 }
 
-/**
- * Send a binary buffer.
- *
- * \param fd The file descriptor.
- * \param buf The buffer to be sent.
- * \param len The length of \a buf.
- *
- * Send out the buffer and try to resend the remaining part in case of short
- * writes.
- *
- * \return Standard.
- */
-int send_bin_buffer(int fd, const char *buf, size_t len)
-{
-       if (!len)
-               PARA_CRIT_LOG("len == 0\n");
-       return write_all(fd, buf, &len);
-}
-
-/**
- * Send a \p NULL-terminated buffer.
- *
- * \param fd The file descriptor.
- * \param buf The null-terminated buffer to be send.
- *
- * This is equivalent to send_bin_buffer(fd, buf, strlen(buf)).
- *
- * \return Standard.
- */
-int send_buffer(int fd, const char *buf)
-{
-       return send_bin_buffer(fd, buf, strlen(buf));
-}
-
-/**
- * Send a buffer given by a format string.
- *
- * \param fd The file descriptor.
- * \param fmt A format string.
- *
- * \return Standard.
- */
-__printf_2_3 int send_va_buffer(int fd, const char *fmt, ...)
-{
-       char *msg;
-       int ret;
-
-       PARA_VSPRINTF(fmt, msg);
-       ret = send_buffer(fd, msg);
-       free(msg);
-       return ret;
-}
-
 /**
  * Receive data from a file descriptor.
  *
@@ -962,7 +909,7 @@ err:
 #ifndef HAVE_UCRED
 ssize_t send_cred_buffer(int sock, char *buf)
 {
-       return send_buffer(sock, buf);
+       return write_buffer(sock, buf);
 }
 int recv_cred_buffer(int fd, char *buf, size_t size)
 {
diff --git a/net.h b/net.h
index 8eba454..a3ff49e 100644 (file)
--- a/net.h
+++ b/net.h
@@ -141,10 +141,6 @@ extern char *remote_name(int sockfd);
  */
 extern int generic_max_transport_msg_size(int sockfd);
 
-int send_bin_buffer(int, const char *, size_t);
-int send_buffer(int, const char *);
-__printf_2_3 int send_va_buffer(int fd, const char *fmt, ...);
-
 int recv_bin_buffer(int fd, char *buf, size_t size);
 int recv_buffer(int fd, char *buf, size_t size);
 
index 85357f9..f075ce5 100644 (file)
@@ -189,7 +189,7 @@ static void oss_post_select(__a_unused struct sched *s,
        ret = 0;
        if (!FD_ISSET(powd->fd, &s->wfds))
                goto out;
-       ret = write_nonblock(powd->fd, data, frames * powd->bytes_per_frame);
+       ret = xwrite(powd->fd, data, frames * powd->bytes_per_frame);
        if (ret < 0)
                goto out;
        btr_consume(btrn, ret);
diff --git a/para.h b/para.h
index 25cbd16..3b9559e 100644 (file)
--- a/para.h
+++ b/para.h
@@ -113,38 +113,9 @@ extern const char *status_item_list[];
 int for_each_stat_item(char *item_buf, size_t num_bytes,
        int (*item_handler)(int, char *));
 
-/**
- * Write a log message to a dynamically allocated string.
- *
- * \param fmt Usual format string.
- * \param p Result pointer.
- *
- * \sa printf(3). */
-#define PARA_VSPRINTF(fmt, p) \
-{ \
-       int n; \
-       size_t size = 100; \
-       p = para_malloc(size); \
-       while (1) { \
-               va_list ap; \
-               /* Try to print in the allocated space. */ \
-               va_start(ap, fmt); \
-               n = vsnprintf(p, size, fmt, ap); \
-               va_end(ap); \
-               /* If that worked, return the string. */ \
-               if (n > -1 && n < size) \
-                       break; \
-               /* Else try again with more space. */ \
-               if (n > -1) /* glibc 2.1 */ \
-                       size = n + 1; /* precisely what is needed */ \
-               else /* glibc 2.0 */ \
-                       size *= 2; /* twice the old size */ \
-               p = para_realloc(p, size); \
-       } \
-}
 
 /**
- *  Return a random non-negative integer in an interval.
+ * Return a random non-negative integer in an interval.
  *
  * \param max Determines maximal possible return value.
  *
index 71e0852..354c9ed 100644 (file)
@@ -113,7 +113,7 @@ int send_queued_chunks(int fd, struct chunk_queue *cq)
                int ret;
 
                cq_get(qc, &buf, &len);
-               ret = write_nonblock(fd, buf, len);
+               ret = xwrite(fd, buf, len);
                if (ret < 0)
                        return ret;
                cq_update(cq, ret);
index 0f0c0e5..abe7abc 100644 (file)
--- a/stdout.c
+++ b/stdout.c
@@ -68,7 +68,7 @@ static void stdout_post_select(struct sched *s, struct task *t)
                sz = btr_next_buffer(btrn, &buf);
                if (sz == 0)
                        break;
-               ret = write_nonblock(STDOUT_FILENO, buf, sz);
+               ret = xwrite(STDOUT_FILENO, buf, sz);
                if (ret <= 0)
                        break;
                btr_consume(btrn, ret);
index 8c8c50a..a1f2a43 100644 (file)
--- a/string.c
+++ b/string.c
@@ -114,6 +114,64 @@ __must_check __malloc char *para_strdup(const char *s)
        exit(EXIT_FAILURE);
 }
 
+/**
+ * Print a formated message to a dynamically allocated string.
+ *
+ * \param result The formated string is returned here.
+ * \param fmt The format string.
+ * \param ap Initialized list of arguments.
+ *
+ * This function is similar to vasprintf(), a GNU extension which is not in C
+ * or POSIX. It allocates a string large enough to hold the output including
+ * the terminating null byte. The allocated string is returned via the first
+ * argument and must be freed by the caller. However, unlike vasprintf(), this
+ * function calls exit() if insufficient memory is available, while vasprintf()
+ * returns -1 in this case.
+ *
+ * \return Number of bytes written, not including the terminating '\0'.
+ *
+ * \sa printf(3), vsnprintf(3), va_start(3), vasprintf(3), \ref xasprintf().
+ */
+__printf_2_0 unsigned xvasprintf(char **result, const char *fmt, va_list ap)
+{
+       int ret;
+       size_t size;
+       va_list aq;
+
+       va_copy(aq, ap);
+       ret = vsnprintf(NULL, 0, fmt, aq);
+       va_end(aq);
+       assert(ret >= 0);
+       size = ret + 1;
+       *result = para_malloc(size);
+       va_copy(aq, ap);
+       ret = vsnprintf(*result, size, fmt, aq);
+       va_end(aq);
+       assert(ret >= 0 && ret < size);
+       return ret;
+}
+
+/**
+ * Print to a dynamically allocated string, variable number of arguments.
+ *
+ * \param result See \ref xvasprintf().
+ * \param fmt Usual format string.
+ *
+ * \return The return value of the underlying call to \ref xvasprintf().
+ *
+ * \sa \ref xvasprintf() and the references mentioned there.
+ */
+__printf_2_3 unsigned xasprintf(char **result, const char *fmt, ...)
+{
+       va_list ap;
+       unsigned ret;
+
+       va_start(ap, fmt);
+       ret = xvasprintf(result, fmt, ap);
+       va_end(ap);
+       return ret;
+}
+
 /**
  * Allocate a sufficiently large string and print into it.
  *
@@ -125,13 +183,16 @@ __must_check __malloc char *para_strdup(const char *s)
  * \return This function either returns a pointer to a string that must be
  * freed by the caller or aborts without returning.
  *
- * \sa printf(3).
+ * \sa printf(3), xasprintf().
  */
 __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...)
 {
        char *msg;
+       va_list ap;
 
-       PARA_VSPRINTF(fmt, msg);
+       va_start(ap, fmt);
+       xvasprintf(&msg, fmt, ap);
+       va_end(ap);
        return msg;
 }
 
index e5a4f9d..cdc55d2 100644 (file)
--- a/string.h
+++ b/string.h
@@ -60,6 +60,9 @@ __must_check __malloc void *para_realloc(void *p, size_t size);
 __must_check __malloc void *para_malloc(size_t size);
 __must_check __malloc void *para_calloc(size_t size);
 __must_check __malloc char *para_strdup(const char *s);
+
+__printf_2_0 unsigned xvasprintf(char **result, const char *fmt, va_list ap);
+__printf_2_3 unsigned xasprintf(char **result, const char *fmt, ...);
 __must_check __malloc __printf_1_2 char *make_message(const char *fmt, ...);
 __must_check __malloc char *para_strcat(char *a, const char *b);
 __must_check __malloc char *para_dirname(const char *name);
index 1155bcb..3e3950f 100644 (file)
@@ -288,7 +288,7 @@ static void udp_send_fec(struct sender_client *sc, char *buf, size_t len)
        ret = udp_check_socket_state(sc);
        if (ret < 0)
                goto fail;
-       ret = write_nonblock(sc->fd, buf, len);
+       ret = xwrite(sc->fd, buf, len);
        if (ret == -ERRNO_TO_PARA_ERROR(ECONNREFUSED)) {
                /*
                 * Happens if meanwhile an ICMP Destination / Port Unreachable
diff --git a/vss.c b/vss.c
index bfea37a..8f177ba 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -1136,7 +1136,7 @@ static void vss_post_select(struct sched *s, struct task *t)
                recv_afs_result(vsst, &s->rfds);
        else if (FD_ISSET(vsst->afs_socket, &s->wfds)) {
                PARA_NOTICE_LOG("requesting new fd from afs\n");
-               ret = send_buffer(vsst->afs_socket, "new");
+               ret = write_buffer(vsst->afs_socket, "new");
                if (ret < 0)
                        PARA_CRIT_LOG("%s\n", para_strerror(-ret));
                else