aft.c: Check for osl errors in com_add_callback().
[paraslash.git] / command.c
index 175b496ca799820bc5d891676f71970d31ba7cc9..e8f6948437aac8c0f03b538381afc5ea20b55fe4 100644 (file)
--- a/command.c
+++ b/command.c
 #include "signal.h"
 #include "version.h"
 
+typedef int server_command_handler_t(struct command_context *);
+static server_command_handler_t SERVER_COMMAND_HANDLERS;
+server_command_handler_t AFS_COMMAND_HANDLERS;
+
+/* Defines one command of para_server. */
+struct server_command {
+       /* The name of the command. */
+       const char *name;
+       /* Pointer to the function that handles the command. */
+       server_command_handler_t *handler;
+       /* The privileges a user must have to execute this command. */
+       unsigned int perms;
+       /* One-line description of the command. */
+       const char *description;
+       /* Summary of the command line options. */
+       const char *usage;
+       /* The long help text. */
+       const char *help;
+};
+
 static struct server_command afs_cmds[] = {DEFINE_AFS_CMD_ARRAY};
 static struct server_command server_cmds[] = {DEFINE_SERVER_CMD_ARRAY};
 
@@ -151,7 +171,7 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman
        const char *subcmds[] = {"add", "delete", "allow", "deny", "on", "off", NULL};
 
        scd->sender_num = -1;
-       if (argc < 2)
+       if (argc < 3)
                return -E_COMMAND_SYNTAX;
        for (i = 0; senders[i].name; i++)
                if (!strcmp(senders[i].name, argv[1]))
@@ -405,9 +425,10 @@ static int com_version(struct command_context *cc)
        char *msg;
        size_t len;
 
-       if (cc->argc != 1)
-               return -E_COMMAND_SYNTAX;
-       len = xasprintf(&msg, "%s", version_text("server"));
+       if (cc->argc > 1 && strcmp(cc->argv[1], "-v") == 0)
+               len = xasprintf(&msg, "%s", version_text("server"));
+       else
+               len = xasprintf(&msg, "%s\n", version_single_line("server"));
        return send_sb(&cc->scc, msg, len, SBD_OUTPUT, false);
 }
 
@@ -834,22 +855,23 @@ out:
 
 #define HANDSHAKE_BUFSIZE 4096
 
-static int parse_sb_command(struct command_context *cc, struct iovec *iov)
+static int run_command(struct command_context *cc, struct iovec *iov,
+               const char *peername)
 {
        int ret, i;
        char *p, *end;
+       struct server_command *cmd;
 
-       ret = -E_BAD_CMD;
        if (iov->iov_base == NULL || iov->iov_len == 0)
-               goto out;
+               return -E_BAD_CMD;
        p = iov->iov_base;
        p[iov->iov_len - 1] = '\0'; /* just to be sure */
-       cc->cmd = get_cmd_ptr(p, NULL);
-       if (!cc->cmd)
-               goto out;
-       ret = check_perms(cc->u->perms, cc->cmd);
+       cmd = get_cmd_ptr(p, NULL);
+       if (!cmd)
+               return -E_BAD_CMD;
+       ret = check_perms(cc->u->perms, cmd);
        if (ret < 0)
-               goto out;
+               return ret;
        end = iov->iov_base + iov->iov_len;
        for (i = 0; p < end; i++)
                p += strlen(p) + 1;
@@ -860,9 +882,15 @@ static int parse_sb_command(struct command_context *cc, struct iovec *iov)
                p += strlen(p) + 1;
        }
        cc->argv[cc->argc] = NULL;
-       ret = cc->argc;
-out:
-       free(iov->iov_base);
+       PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name,
+               cc->u->name, peername);
+       ret = cmd->handler(cc);
+       free_argv(cc->argv);
+       mutex_lock(mmd_mutex);
+       mmd->num_commands++;
+       if (ret >= 0 && (cmd->perms & AFS_WRITE))
+               mmd->events++;
+       mutex_unlock(mmd_mutex);
        return ret;
 }
 
@@ -983,17 +1011,10 @@ __noreturn void handle_connect(int fd, const char *peername)
        ret = recv_sb(&cc->scc, SBD_COMMAND, MAX_COMMAND_LEN, &iov);
        if (ret < 0)
                goto net_err;
-       ret = parse_sb_command(cc, &iov);
+       ret = run_command(cc, &iov, peername);
+       free(iov.iov_base);
        if (ret < 0)
                goto err_out;
-       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:
@@ -1005,8 +1026,6 @@ out:
        free(buf);
        free(command);
        mutex_lock(mmd_mutex);
-       if (cc->cmd && (cc->cmd->perms & AFS_WRITE) && ret >= 0)
-               mmd->events++;
        mmd->active_connections--;
        mutex_unlock(mmd_mutex);
        if (ret >= 0) {