/*
- * Copyright (C) 2005-2006 Andre Noll <noll@mathematik.tu-darmstadt.de>
+ * Copyright (C) 2005-2007 Andre Noll <maan@systemlinux.org>
*
- * 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 <sys/types.h>
+#include <dirent.h>
+#include "para.h"
#include "audiod.cmdline.h"
#include "list.h"
#include "close_on_fork.h"
#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)
{
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;
}
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);
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");
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)
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;
*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;
}
return ret;
}
-
+/**
+ * send the current audiod status to all connected stat clients
+ */
void audiod_status_dump(void)
{
struct timeval *t = wstime();
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