If this function gets called we already read a whole * command, arguments are in the client argv/argc fields. * processCommand() execute the command or prepare the * server for a bulk read from the client. * * If C_OK is returned the client is still alive and valid and * other operations can be performed by the caller. Otherwise * if C_ERR is returned the client was destroyed (i.e. after QU
| 3958 | * other operations can be performed by the caller. Otherwise |
| 3959 | * if C_ERR is returned the client was destroyed (i.e. after QUIT). */ |
| 3960 | int processCommand(client *c) { |
| 3961 | if (!server.lua_timedout) { |
| 3962 | /* Both EXEC and EVAL call call() directly so there should be |
| 3963 | * no way in_exec or in_eval or propagate_in_transaction is 1. |
| 3964 | * That is unless lua_timedout, in which case client may run |
| 3965 | * some commands. */ |
| 3966 | serverAssert(!server.propagate_in_transaction); |
| 3967 | serverAssert(!server.in_exec); |
| 3968 | serverAssert(!server.in_eval); |
| 3969 | } |
| 3970 | |
| 3971 | moduleCallCommandFilters(c); |
| 3972 | |
| 3973 | /* The QUIT command is handled separately. Normal command procs will |
| 3974 | * go through checking for replication and QUIT will cause trouble |
| 3975 | * when FORCE_REPLICATION is enabled and would be implemented in |
| 3976 | * a regular command proc. */ |
| 3977 | if (!strcasecmp(c->argv[0]->ptr,"quit")) { |
| 3978 | addReply(c,shared.ok); |
| 3979 | c->flags |= CLIENT_CLOSE_AFTER_REPLY; |
| 3980 | return C_ERR; |
| 3981 | } |
| 3982 | |
| 3983 | /* Now lookup the command and check ASAP about trivial error conditions |
| 3984 | * such as wrong arity, bad command name and so forth. */ |
| 3985 | c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr); |
| 3986 | if (!c->cmd) { |
| 3987 | sds args = sdsempty(); |
| 3988 | int i; |
| 3989 | for (i=1; i < c->argc && sdslen(args) < 128; i++) |
| 3990 | args = sdscatprintf(args, "`%.*s`, ", 128-(int)sdslen(args), (char*)c->argv[i]->ptr); |
| 3991 | rejectCommandFormat(c,"unknown command `%s`, with args beginning with: %s", |
| 3992 | (char*)c->argv[0]->ptr, args); |
| 3993 | sdsfree(args); |
| 3994 | return C_OK; |
| 3995 | } else if ((c->cmd->arity > 0 && c->cmd->arity != c->argc) || |
| 3996 | (c->argc < -c->cmd->arity)) { |
| 3997 | rejectCommandFormat(c,"wrong number of arguments for '%s' command", |
| 3998 | c->cmd->name); |
| 3999 | return C_OK; |
| 4000 | } |
| 4001 | |
| 4002 | int is_read_command = (c->cmd->flags & CMD_READONLY) || |
| 4003 | (c->cmd->proc == execCommand && (c->mstate.cmd_flags & CMD_READONLY)); |
| 4004 | int is_write_command = (c->cmd->flags & CMD_WRITE) || |
| 4005 | (c->cmd->proc == execCommand && (c->mstate.cmd_flags & CMD_WRITE)); |
| 4006 | int is_denyoom_command = (c->cmd->flags & CMD_DENYOOM) || |
| 4007 | (c->cmd->proc == execCommand && (c->mstate.cmd_flags & CMD_DENYOOM)); |
| 4008 | int is_denystale_command = !(c->cmd->flags & CMD_STALE) || |
| 4009 | (c->cmd->proc == execCommand && (c->mstate.cmd_inv_flags & CMD_STALE)); |
| 4010 | int is_denyloading_command = !(c->cmd->flags & CMD_LOADING) || |
| 4011 | (c->cmd->proc == execCommand && (c->mstate.cmd_inv_flags & CMD_LOADING)); |
| 4012 | int is_may_replicate_command = (c->cmd->flags & (CMD_WRITE | CMD_MAY_REPLICATE)) || |
| 4013 | (c->cmd->proc == execCommand && (c->mstate.cmd_flags & (CMD_WRITE | CMD_MAY_REPLICATE))); |
| 4014 | |
| 4015 | if (authRequired(c)) { |
| 4016 | /* AUTH and HELLO and no auth commands are valid even in |
| 4017 | * non-authenticated state. */ |
no test coverage detected