#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 {
*/
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;
- ret = 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)
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;
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;
}
}
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;
}
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, "--")) {
}
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;
}
---
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
---
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
---
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]
---
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...
---
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
#include "fd.h"
#include "ipc.h"
#include "portable_io.h"
+#include "command.h"
static struct osl_table *audio_file_table;
static char *status_items;
/*
* 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;
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, "--")) {
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;
}
/** 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;
};
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;
}
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;
}
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:
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) {
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, "--")) {
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)
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;
}
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,
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, "--")) {
}
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;
}
}
/* 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, "--")) {
}
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;
}
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, "--")) {
}
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;
}
/**
* 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
*
* \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 */
#include "afh.h"
#include "afs.h"
#include "ipc.h"
+#include "command.h"
static struct osl_table *attribute_table;
static int greatest_att_bitnum;
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, "--")) {
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;
}
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 {
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;
}
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;
}
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;
}
#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.
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, "--")) {
}
// 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,
}
}
-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. */
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,
* \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)
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;
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 */
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) \
{ \
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,
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};
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;
}
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;
}
}
/* 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++) {
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"
}
/* 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"
);
#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;
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, "--")) {
}
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;
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;
}
/* 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,
}
/* 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;
}
/* 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()) {
}
/* 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++;
}
/* 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())
}
/* 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 */
}
/* 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;
*/
__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);
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;
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
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);
/** \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.
*/
/** 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. */