X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=audiod_command.c;h=b4c50dc86118a6d9f3c756f7d6b2c40a87c34ca9;hp=6bf5ac8600812ef6642c12ee2f5e0e1273ab3e84;hb=1afd45b1b5c80e73c017ef27c54f0696a40f4e33;hpb=b43af255d4514b68c98b23fb220306cf5ba1df60 diff --git a/audiod_command.c b/audiod_command.c index 6bf5ac86..b4c50dc8 100644 --- a/audiod_command.c +++ b/audiod_command.c @@ -1,25 +1,15 @@ /* - * Copyright (C) 2005-2006 Andre Noll + * Copyright (C) 2005-2008 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. + * Licensed under the GPL v2. For licencing details see COPYING. */ /** \file audiod_command.c commands for para_audiod */ -#include "para.h" +#include +#include +#include "para.h" #include "audiod.cmdline.h" #include "list.h" #include "close_on_fork.h" @@ -37,7 +27,7 @@ #include "audiod_command_list.h" /** iterate over the array of all audiod commands */ -#define FOR_EACH_COMMAND(c) for (c = 0; cmds[c].name; c++) +#define FOR_EACH_COMMAND(c) for (c = 0; audiod_cmds[c].name; c++) static int client_write(int fd, const char *buf) { @@ -80,7 +70,7 @@ static char *get_time_string(struct timeval *newest_stime) total = 0; out: return make_message( - "%s:%s%d:%02d [%d:%02d] (%d%%/%d:%02d)\n", + "%s: %s%d:%02d [%d:%02d] (%d%%/%d:%02d)\n", status_item_list[SI_PLAY_TIME], use_server_time? "~" : "", total / 60, @@ -98,7 +88,7 @@ __malloc static char *audiod_status_string(void) { const char *status = (audiod_status == AUDIOD_ON)? "on" : (audiod_status == AUDIOD_OFF)? "off": "sb"; - return make_message("%s:%s\n", status_item_list[SI_AUDIOD_STATUS], status); + return make_message("%s: %s\n", status_item_list[SI_AUDIOD_STATUS], status); } static struct timeval *wstime(void) @@ -130,7 +120,7 @@ __malloc static char *decoder_flags(void) flags[i] = flag; } flags[MAX_STREAM_SLOTS] = '\0'; - return make_message("%s:%s\n", status_item_list[SI_DECODER_FLAGS], + return make_message("%s: %s\n", status_item_list[SI_DECODER_FLAGS], flags); } @@ -141,8 +131,8 @@ static int dump_commands(int fd) ssize_t ret; FOR_EACH_COMMAND(i) { - tmp = make_message("%s%s\t%s\n", buf, cmds[i].name, - cmds[i].description); + tmp = make_message("%s%s\t%s\n", buf, audiod_cmds[i].name, + audiod_cmds[i].description); free(buf); buf = tmp; } @@ -168,16 +158,16 @@ int com_help(int fd, int argc, char **argv) goto out; } FOR_EACH_COMMAND(i) { - if (strcmp(cmds[i].name, argv[1])) + if (strcmp(audiod_cmds[i].name, argv[1])) continue; buf = make_message( "NAME\n\t%s -- %s\n" "SYNOPSIS\n\tpara_audioc %s\n" "DESCRIPTION\n%s\n", argv[1], - cmds[i].description, - cmds[i].synopsis, - cmds[i].help + audiod_cmds[i].description, + audiod_cmds[i].usage, + audiod_cmds[i].help ); ret = client_write(fd, buf); free(buf); @@ -247,7 +237,7 @@ int com_stat(int fd, __a_unused int argc, __a_unused char **argv) } if (mask & (1 << SI_AUDIOD_UPTIME)) { char *tmp, *us = uptime_str(); - tmp = make_message("%s:%s\n", + tmp = make_message("%s: %s\n", status_item_list[SI_AUDIOD_UPTIME], us); free(us); ret = client_write(fd, tmp); @@ -263,14 +253,13 @@ int com_stat(int fd, __a_unused int argc, __a_unused char **argv) free(s); } if (mask & (1 << SI_DECODER_FLAGS)) { - char *df =decoder_flags(); + char *df = decoder_flags(); ret = client_write(fd, df); if (ret < 0) goto out; free(df); } - - for (i = 0; i < NUM_STAT_ITEMS; i++) { + FOR_EACH_STATUS_ITEM(i) { char *tmp, *v; if (!((1 << i) & mask)) continue; @@ -290,8 +279,7 @@ out: static struct filter_node *find_filter_node(int slot_num, int format, int filternum) { - struct filter_node *fn; - int i, j; + int i; FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; @@ -301,14 +289,10 @@ static struct filter_node *find_filter_node(int slot_num, int format, int filter continue; if (format >= 0 && s->format != format) continue; - if (num_filters(i) < filternum) + if (num_filters(i) <= filternum) continue; /* success */ - j = 1; - list_for_each_entry(fn, &s->fc->filters, node) - if (filternum <= 0 || j++ == filternum) - break; - return fn; + return s->fc->filter_nodes + filternum; } return NULL; } @@ -350,7 +334,7 @@ err_out: return 1; } -int __noreturn com_term(int fd, __a_unused int argc, __a_unused char **argv) +__noreturn int com_term(int fd, __a_unused int argc, __a_unused char **argv) { close(fd); clean_exit(EXIT_SUCCESS, "terminating on user request"); @@ -406,11 +390,27 @@ static int check_perms(uid_t uid) return -E_UCRED_PERM; } +/** + * handle arriving connections on the local socket + * + * \param accept_fd the fd to call accept() on + * + * This is called whenever para_audiod's main task detects an incoming + * connection by the readability of \a accept_fd. This function reads the + * command sent by the peer, checks the connecting user's permissions by using + * unix socket credentials (if supported by the OS) and calls the corresponding + * command handler if permissions are OK. + * + * \return positive on success, negative on errors + * + * \sa para_accept(), recv_cred_buffer() + * */ int handle_connect(int accept_fd) { int i, argc, ret, clifd = -1; char *cmd = NULL, *p, *buf = para_calloc(MAXLINE), **argv = NULL; struct sockaddr_un unix_addr; + uid_t uid; ret = para_accept(accept_fd, &unix_addr, sizeof(struct sockaddr_un)); if (ret < 0) @@ -419,8 +419,9 @@ int handle_connect(int accept_fd) ret = recv_cred_buffer(clifd, buf, MAXLINE - 1); if (ret < 0) goto out; + uid = ret; PARA_INFO_LOG("connection from user %i, buf: %s\n", ret, buf); - ret = check_perms(ret); + ret = check_perms(uid); if (ret < 0) goto out; ret = -E_INVALID_AUDIOD_CMD; @@ -432,21 +433,21 @@ int handle_connect(int accept_fd) *p = '\0'; p++; } - for (i = 0; cmds[i].name; i++) { + for (i = 0; audiod_cmds[i].name; i++) { int j; - if (strcmp(cmds[i].name, cmd)) + if (strcmp(audiod_cmds[i].name, cmd)) continue; - if (cmds[i].handler) { + if (audiod_cmds[i].handler) { argc = split_args(buf, &argv, "\n"); PARA_INFO_LOG("argv[0]: %s, argc= %d\n", argv[0], argc); - ret = cmds[i].handler(clifd, argc, argv); + ret = audiod_cmds[i].handler(clifd, argc, argv); goto out; } for (j = 0; p[j]; j++) if (p[j] == '\n') p[j] = ' '; PARA_INFO_LOG("cmd: %s, options: %s\n", cmd, p); - ret = cmds[i].line_handler(clifd, p); + ret = audiod_cmds[i].line_handler(clifd, p); goto out; } ret = -E_INVALID_AUDIOD_CMD; @@ -455,14 +456,16 @@ out: free(buf); free(argv); if (clifd > 0 && ret < 0 && ret != -E_CLIENT_WRITE) { - char *tmp = make_message("%s\n", PARA_STRERROR(-ret)); + char *tmp = make_message("%s\n", para_strerror(-ret)); client_write(clifd, tmp); free(tmp); close(clifd); } return ret; } - +/** + * send the current audiod status to all connected stat clients + */ void audiod_status_dump(void) { struct timeval *t = wstime(); @@ -483,7 +486,7 @@ void audiod_status_dump(void) old = stat_task->stat_item_values[SI_AUDIOD_UPTIME]; if (!old || strcmp(old, new)) { free(old); - tmp = make_message("%s:%s\n", + tmp = make_message("%s: %s\n", status_item_list[SI_AUDIOD_UPTIME], new); stat_client_write(tmp, SI_AUDIOD_UPTIME); free(tmp); @@ -503,6 +506,7 @@ void audiod_status_dump(void) old = stat_task->stat_item_values[SI_DECODER_FLAGS]; new = decoder_flags(); if (!old || strcmp(old, new)) { + free(old); stat_client_write(new, SI_DECODER_FLAGS); stat_task->stat_item_values[SI_DECODER_FLAGS] = new; } else @@ -519,7 +523,7 @@ void dump_empty_status(void) { int i; - FOR_EACH_STAT_ITEM(i) { + FOR_EACH_STATUS_ITEM(i) { char *tmp = make_message("%s:\n", status_item_list[i]); stat_client_write(tmp, i); free(tmp);