X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=recv_common.c;h=948de4745dda8c62bce88f31ec8362650ae85de0;hp=0393d7641abbae85e9645e260417551d4e7fea8b;hb=3b0a8fdb191309652e71e104a8f3705d55a93d3e;hpb=a87d4a87ac7418084eb78f0bcb3accff1388df3a diff --git a/recv_common.c b/recv_common.c index 0393d764..948de474 100644 --- a/recv_common.c +++ b/recv_common.c @@ -1,86 +1,141 @@ -/* - * Copyright (C) 2006 Andre Noll - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ +/* Copyright (C) 2006 Andre Noll , see file COPYING. */ /** \file recv_common.c common functions of para_recv and para_audiod */ -#include "para.h" +#include +#include +#include +#include "recv_cmd.lsg.h" +#include "para.h" +#include "error.h" #include "list.h" #include "sched.h" +#include "buffer_tree.h" #include "recv.h" #include "string.h" -DEFINE_RECEIVER_ARRAY; -static void *parse_receiver_args(int receiver_num, char *options) +/** + * Call the init function of each paraslash receiver. + * + * Receivers employ the user_data feature of the lopsub library: Each receiver + * of the recv_cmd suite defines a struct receiver as its user data. + * recv_init() obtains a pointer to this structure by calling lls_user_data(). + * If the receiver has an init function (i.e., if ->init is not NULL), ->init() + * is called to initialize the receiver. + */ +void recv_init(void) { - struct receiver *r = &receivers[receiver_num]; - char **argv; - int argc, i; - void *conf; + int i; + FOR_EACH_RECEIVER(i) { + const struct lls_command *cmd = RECV_CMD(i); + const struct receiver *r = lls_user_data(cmd); + if (r && r->init) + r->init(); + } +} -// PARA_DEBUG_LOG("%s, options: %s\n", r->name, -// options? options : "(none)"); - if (options) { - PARA_DEBUG_LOG("options: %s\n", options); - argc = split_args(options, &argv, " \t"); - for (i = argc - 1; i >= 0; i--) - argv[i + 1] = argv[i]; - argv[0] = para_strdup(r->name); - argc += 1; - PARA_DEBUG_LOG("argc = %d, argv[0]: %s\n", argc, argv[0]); - } else { +/** + * Check if the given string is a valid receiver specifier. + * + * \param ra string of the form receiver_name [options...] + * \param lprp Filled in on success, undefined else. + * + * This function checks whether \a ra starts with the name of a receiver, + * optionally followed by options for that receiver. If a valid receiver name + * was found the remaining part of \a ra is passed to the receiver's config + * parser. + * + * If a NULL pointer or an empty string is passed as the first argument, the + * hhtp receiver with no options is assumed. + * + * \return On success the number of the receiver is returned. On errors, the + * function calls exit(EXIT_FAILURE). + */ +int check_receiver_arg(const char *ra, struct lls_parse_result **lprp) +{ + int ret, argc, receiver_num; + char *errctx = NULL, **argv; + const struct lls_command *cmd; + + *lprp = NULL; + if (!ra || !*ra) { argc = 1; argv = para_malloc(2 * sizeof(char*)); - argv[0] = NULL; + argv[0] = para_strdup("http"); argv[1] = NULL; + } else { + ret = create_argv(ra, " \t\n", &argv); + if (ret < 0) { + PARA_EMERG_LOG("%s\n", para_strerror(-ret)); + exit(EXIT_FAILURE); + } + argc = ret; } - conf = r->parse_config(argc, argv); - if (!conf) { - for (i = 0; i < argc; i++) - free(argv[i]); - free(argv); - return NULL; + ret = lls(lls_lookup_subcmd(argv[0], recv_cmd_suite, &errctx)); + if (ret < 0) { + PARA_EMERG_LOG("%s: %s\n", errctx? errctx : argv[0], + para_strerror(-ret)); + exit(EXIT_FAILURE); } - return conf; + receiver_num = ret; + cmd = RECV_CMD(receiver_num); + ret = lls(lls_parse(argc, argv, cmd, lprp, &errctx)); + if (ret < 0) { + if (errctx) + PARA_ERROR_LOG("%s\n", errctx); + PARA_EMERG_LOG("%s\n", para_strerror(-ret)); + exit(EXIT_FAILURE); + } + ret = receiver_num; + free_argv(argv); + return ret; } -void *check_receiver_arg(char *ra, int *receiver_num) +/** + * Print out the help texts to all receivers. + * + * \param detailed Whether to print the short or the detailed help. + */ +void print_receiver_helps(bool detailed) { - int j; + int i; - PARA_DEBUG_LOG("checking %s\n", ra); - for (j = 0; receivers[j].name; j++) { - const char *name = receivers[j].name; - size_t len = strlen(name); - char c; - if (strlen(ra) < len) - continue; - if (strncmp(name, ra, len)) - continue; - c = ra[len]; - if (c && c != ' ') + printf("\nAvailable receivers: "); + FOR_EACH_RECEIVER(i) { + const struct lls_command *cmd = RECV_CMD(i); + printf("%s%s", i? " " : "", lls_command_name(cmd)); + } + printf("\n\n"); + FOR_EACH_RECEIVER(i) { + const struct lls_command *cmd = RECV_CMD(i); + char *help = detailed? lls_long_help(cmd) : lls_short_help(cmd); + if (!help) continue; - if (c && !receivers[j].parse_config) - return NULL; - *receiver_num = j; - return parse_receiver_args(j, c? ra + len + 1: NULL); + printf("%s\n", help); + free(help); } - PARA_ERROR_LOG("%s", "receiver not found\n"); - return NULL; +} + +/** + * Simple pre-select hook, used by all receivers. + * + * \param s Scheduler info. + * \param rn The receiver node. + * + * This requests a minimal delay from the scheduler if the status of the buffer + * tree node indicates an error/eof condition. No file descriptors are added to + * the fd sets of \a s. + * + * \return The status of the btr node of the receiver node, i.e. the return + * value of the underlying call to \ref btr_node_status(). + */ +int generic_recv_pre_select(struct sched *s, struct receiver_node *rn) +{ + int ret = btr_node_status(rn->btrn, 0, BTR_NT_ROOT); + + if (ret < 0) + sched_min_delay(s); + return ret; }