Command handlers should not know about this implementation detail.
This commit also changes parse_sb_command() to not only parse the
command line but to actually run the command in case the caller has
sufficient permissions. The function is renamed to run_command()
to reflect this change.
We use the opportunity to clean up the allocation and freeing of
the command buffer and the argument vector. Both are now freed in
the same function they were allocated, which is considered good
programming practice.
#define HANDSHAKE_BUFSIZE 4096
#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;
{
int ret, i;
char *p, *end;
+ struct server_command *cmd;
if (iov->iov_base == NULL || iov->iov_len == 0)
if (iov->iov_base == NULL || iov->iov_len == 0)
p = iov->iov_base;
p[iov->iov_len - 1] = '\0'; /* just to be sure */
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);
end = iov->iov_base + iov->iov_len;
for (i = 0; p < end; i++)
p += strlen(p) + 1;
end = iov->iov_base + iov->iov_len;
for (i = 0; p < end; i++)
p += strlen(p) + 1;
p += strlen(p) + 1;
}
cc->argv[cc->argc] = NULL;
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);
ret = recv_sb(&cc->scc, SBD_COMMAND, MAX_COMMAND_LEN, &iov);
if (ret < 0)
goto net_err;
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;
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:
if (ret >= 0)
goto out;
err_out:
free(buf);
free(command);
mutex_lock(mmd_mutex);
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) {
mmd->active_connections--;
mutex_unlock(mmd_mutex);
if (ret >= 0) {
int argc;
/** Argument vector. */
char **argv;
int argc;
/** Argument vector. */
char **argv;
- /** The command being executed. */
- const struct server_command *cmd;
/** File descriptor and crypto keys. */
struct stream_cipher_context scc;
};
/** File descriptor and crypto keys. */
struct stream_cipher_context scc;
};