static COMMAND_HELPER(command_help_find, struct command *head, struct command **out) { if (0 == CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; *out = command_find(head, CMD_ARGV[0]); if (NULL == *out && strncmp(CMD_ARGV[0], "ocd_", 4) == 0) *out = command_find(head, CMD_ARGV[0] + 4); if (NULL == *out) return ERROR_COMMAND_SYNTAX_ERROR; if (--CMD_ARGC == 0) return ERROR_OK; CMD_ARGV++; return CALL_COMMAND_HANDLER(command_help_find, (*out)->children, out); }
int main( int argc, char** argv ) { ctrl_subsystem_t* subsystem; ctrl_command_t* command; argv0 = argv[ 0 ]; ycfg_init(); if ( argc < 2 ) { print_usage(); return EXIT_FAILURE; } subsystem = subsystem_find( argv[ 1 ] ); if ( subsystem == NULL ) { print_usage(); return EXIT_FAILURE; } if ( argc < 3 ) { command = NULL; } else { command = command_find( subsystem, argv[ 2 ] ); } if ( command == NULL ) { print_subsystem_usage( subsystem ); return EXIT_FAILURE; } command->handler( argc - 3, &argv[ 3 ] ); return EXIT_SUCCESS; }
/* ************************************************************************* * * コマンド分岐関数 * ************************************************************************* */ void exec_command (char command, char *parameter, char *str) { switch (command) { case 'Q': command_quit(parameter); break; case 'C': command_check(parameter); break; case 'P': command_print(profile_data, atoi(parameter), str); break; case 'R': command_read(profile_data, parameter); break; case 'W': command_write(profile_data, parameter); break; case 'F': command_find(profile_data, parameter, str); break; case 'S': command_sort(profile_data, atoi(parameter), str); break; default: printf("Invalid command '%c' was found.\n", command); break; } }
/* SET <!group> <setting> <parameters> */ static void gs_cmd_set(sourceinfo_t *si, int parc, char *parv[]) { char *group; char *cmd; command_t *c; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET"); command_fail(si, fault_needmoreparams, _("Syntax: SET <!group> <setting> [parameters]")); return; } if (parv[0][0] == '!') group = parv[0], cmd = parv[1]; else if (parv[1][0] == '!') cmd = parv[0], group = parv[1]; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET"); command_fail(si, fault_badparams, _("Syntax: SET <!group> <setting> [parameters]")); return; } c = command_find(gs_set_cmdtree, cmd); if (c == NULL) { command_fail(si, fault_badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); return; } parv[1] = group; command_exec(si->service, si, c, parc - 1, parv + 1); }
struct command *register_command(struct command_context *context, struct command *parent, const struct command_registration *cr) { if (!context || !cr->name) return NULL; const char *name = cr->name; struct command **head = command_list_for_parent(context, parent); struct command *c = command_find(*head, name); if (NULL != c) { /* TODO: originally we treated attempting to register a cmd twice as an error * Sometimes we need this behaviour, such as with flash banks. * http://www.mail-archive.com/[email protected]/msg11152.html */ LOG_DEBUG("command '%s' is already registered in '%s' context", name, parent ? parent->name : "<global>"); return c; } c = command_new(context, parent, cr); if (NULL == c) return NULL; int retval = ERROR_OK; if (NULL != cr->jim_handler && NULL == parent) { retval = Jim_CreateCommand(context->interp, cr->name, cr->jim_handler, cr->jim_handler_data, NULL); } else if (NULL != cr->handler || NULL != parent) retval = register_command_handler(context, command_root(c)); if (ERROR_OK != retval) { unregister_command(context, parent, name); c = NULL; } return c; }
static void cs_cmd_clear(sourceinfo_t *si, int parc, char *parv[]) { char *chan; char *cmd; command_t *c; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "CLEAR"); command_fail(si, fault_needmoreparams, _("Syntax: CLEAR <#channel> <command> [parameters]")); return; } if (parv[0][0] == '#') chan = parv[0], cmd = parv[1]; else if (parv[1][0] == '#') cmd = parv[0], chan = parv[1]; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "CLEAR"); command_fail(si, fault_badparams, _("Syntax: CLEAR <#channel> <command> [parameters]")); return; } c = command_find(&cs_clear_cmds, cmd); if (c == NULL) { command_fail(si, fault_badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); return; } parv[1] = chan; command_exec(si->service, si, c, parc - 1, parv + 1); }
static void bs_cmd_set(sourceinfo_t *si, int parc, char *parv[]) { char *dest; char *cmd; command_t *c; if (parc < 3) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET"); command_fail(si, fault_needmoreparams, _("Syntax: SET <destination> <setting> <parameters>")); return; } dest = parv[0]; cmd = parv[1]; c = command_find(&bs_set_cmdtree, cmd); if (c == NULL) { command_fail(si, fault_badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); return; } parv[1] = dest; command_exec(si->service, si, c, parc - 1, parv + 1); }
static int command_exec_user(struct command_head_t *cmd_head, struct argv_kit_t *argv_kit) { int ret = -1; struct command_t *cmd = command_find(cmd_head, argv_kit->argv[0], 0); if (cmd) { cmd->exec(argv_kit->argc, argv_kit->argv); ret = 0; } return ret; }
static void cmd_statusbar(const char *data) { char *arg1, *arg2, *params, *oldcmd; void *free_arg; if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &arg1, &arg2, ¶ms)) return; /* backward compatibility layer */ oldcmd = NULL; if (*arg1 == '\0') { oldcmd = g_strdup("list"); } else if (g_ascii_strcasecmp(arg2, "enable") == 0) { oldcmd = g_strdup_printf("add -nodisable %s %s", arg1, params); } else if (g_ascii_strcasecmp(arg2, "disable") == 0) { oldcmd = g_strdup_printf("add -disable %s %s", arg1, params); } else if (g_ascii_strcasecmp(arg2, "reset") == 0) { oldcmd = g_strdup_printf("reset %s", arg1); } else if (g_ascii_strcasecmp(arg2, "type") == 0) { oldcmd = g_strdup_printf("add -type %s %s", params, arg1); } else if (g_ascii_strcasecmp(arg2, "placement") == 0) { oldcmd = g_strdup_printf("add -placement %s %s", params, arg1); } else if (g_ascii_strcasecmp(arg2, "position") == 0) { oldcmd = g_strdup_printf("add -position %s %s", params, arg1); } else if (g_ascii_strcasecmp(arg2, "visible") == 0) { oldcmd = g_strdup_printf("add -visible %s %s", params, arg1); } else if (g_ascii_strcasecmp(arg2, "add") == 0) { oldcmd = g_strdup_printf("additem %s %s", params, arg1); } else if (g_ascii_strcasecmp(arg2, "remove") == 0) { oldcmd = g_strdup_printf("removeitem %s %s", params, arg1); } else if (*arg2 == '\0') { oldcmd = g_strdup_printf("statusbar %s", arg1); if (command_find(oldcmd) == NULL) { g_free(oldcmd); oldcmd = g_strdup_printf("info %s", arg1); } else { g_free(oldcmd); oldcmd = NULL; } } cmd_params_free(free_arg); if (oldcmd) { command_runsub("statusbar", oldcmd, NULL, NULL); g_free(oldcmd); } else { command_runsub("statusbar", data, NULL, NULL); } return; }
static void ns_cmd_fdrop(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; mynick_t *mn; char *acc = parv[0]; if (!acc) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FDROP"); command_fail(si, fault_needmoreparams, _("Syntax: FDROP <account>")); return; } if (!(mu = myuser_find(acc))) { if (!nicksvs.no_nick_ownership) { mn = mynick_find(acc); if (mn != NULL && command_find(si->service->cmdtree, "FUNGROUP")) { command_fail(si, fault_nosuch_target, _("\2%s\2 is a grouped nick, use %s to remove it."), acc, "FUNGROUP"); return; } } command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), acc); return; } if (is_soper(mu)) { command_fail(si, fault_noprivs, _("The nickname \2%s\2 belongs to a services operator; it cannot be dropped."), acc); return; } if (mu->flags & MU_HOLD) { command_fail(si, fault_noprivs, _("The account \2%s\2 is held; it cannot be dropped."), acc); return; } wallops("%s dropped the account \2%s\2", get_oper_name(si), mu->name); snoop("FDROP: \2%s\2 by \2%s\2", mu->name, get_oper_name(si)); logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FDROP %s", mu->name); hook_call_user_drop(mu); command_success_nodata(si, _("The account \2%s\2 has been dropped."), mu->name); object_unref(mu); }
/** @brief Parse command and fill result in a way the specific command expects it * * - Some commands parse the raw string on their own * - Some commands expect every parameter in result.name * - Some commands use result.name and result.file[0].name (ASSIGN, RENAME) * - COPY may use 1 target file name and up to 4 source file names * * @param[in] cmdstr Raw command string * @param[in] len Length of command string * @param[out] result Filled with zero, one to two names */ static void parse_cmd (uint8_t *cmdstr, uint8_t len, nameinfo_t *result) { uint8_t cmdlen; result->num_files = 0; // Initialize # of secondary files result->cmd = command_find(cmdstr, &cmdlen); if (result->cmd == CMD_SYNTAX) return; // skip whitespace if any while(isspace(cmdstr[cmdlen])) ++cmdlen; // the position command is fully binary if (result->cmd == CMD_POSITION || result->cmd == CMD_TIME) { result->name = cmdstr + cmdlen; result->namelen = len - cmdlen; return; } // check for disk copy "Dt=s" or "Ct=s" if ((result->cmd == CMD_DUPLICATE || result->cmd == CMD_COPY) && cmdstr[cmdlen+1] == '=' && cmdstr[cmdlen+3] == 0 && isdigit(cmdstr[cmdlen]) && isdigit(cmdstr[cmdlen+2])) { result->drive = cmdstr[cmdlen ] & 15; // target drive result->file[0].drive = cmdstr[cmdlen+2] & 15; // source drive return; } if (result->cmd == CMD_ASSIGN || result->cmd == CMD_RENAME || result->cmd == CMD_COPY) { // Split cmdstr at '=' for file[0].name // and at ',' for more file names uint8_t i = 0; uint8_t *sep = (uint8_t*) strchr((char*) cmdstr, '='); while (sep && i < MAX_NAMEINFO_FILES) { *sep = 0; result->file[i].drive = parse_drive (sep+1, &result->file[i].name, &result->file[i].namelen, &result->file[i].drivename); sep = (uint8_t*) strchr((char*) result->file[i].name, ','); // Correct length of filename if comma separator found if (sep) result->file[i].namelen = sep - result->file[i].name; ++i; } result->num_files = i; } result->drive = parse_drive (cmdstr+cmdlen, &result->name, &result->namelen, &result->drivename); // set source drives to target drive if not specified for (uint8_t i=0 ; i < result->num_files ; ++i) { if (result->file[i].drive > 9) result->file[i].drive = result->drive; } }
/* split the line to command and arguments */ static char *line_get_command(const char *line, char **args, int aliases) { const char *ptr, *cmdargs; char *cmd, *checkcmd; g_return_val_if_fail(line != NULL, NULL); g_return_val_if_fail(args != NULL, NULL); cmd = checkcmd = NULL; *args = ""; cmdargs = NULL; ptr = line; do { ptr = strchr(ptr, ' '); if (ptr == NULL) { checkcmd = g_strdup(line); cmdargs = ""; } else { checkcmd = g_strndup(line, (int) (ptr-line)); while (*ptr == ' ') ptr++; cmdargs = ptr; } if (aliases ? !alias_find(checkcmd) : !command_find(checkcmd)) { /* not found, use the previous */ g_free(checkcmd); break; } /* found, check if it has subcommands */ g_free_not_null(cmd); if (!aliases) cmd = checkcmd; else { cmd = g_strdup(alias_find(checkcmd)); g_free(checkcmd); } *args = (char *) cmdargs; } while (ptr != NULL); if (cmd != NULL) ascii_strdown(cmd); return cmd; }
static int command_exec_sys(struct command_head_t *cmd_head, struct argv_kit_t *argv_kit) { struct command_t *cmd; char *cmd_name; int ret = 0; cmd_name = argv_kit->argv[0]; if (!command_is_help(cmd_name)) { cmd = command_find(cmd_head, cmd_name, 1); if (cmd) cmd->exec(argv_kit->argc, argv_kit->argv); else ret = -1; } else { command_sys_help(cmd_head); } return ret; }
/** @brief 执行命令 */ static void execute_cmd(char * line_buffer) { void * cmd; /* 立马按了回车键 */ if (!strlen(line_buffer)) return; // printf("执行命令:%s(%d个字节)。\n", line_buffer, max_size); cmd = command_find(line_buffer, true); if (!cmd) { printf("没有找到您输入的命令。\n"); return; } if (command_exec(cmd, line_buffer)) { printf("命令执行失败。\n"); } }
/* SET <setting> <parameters> */ static void os_cmd_set(sourceinfo_t *si, int parc, char *parv[]) { char *setting = parv[0]; command_t *c; if (setting == NULL) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET"); command_fail(si, fault_needmoreparams, _("Syntax: SET <setting> <parameters>")); return; } /* take the command through the hash table */ if ((c = command_find(os_set_cmdtree, setting))) { command_exec(si->service, si, c, parc - 1, parv + 1); } else { command_fail(si, fault_badparams, _("Invalid set command. Use \2/%s%s HELP SET\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->nick); } }
int command_doline(buffer_t* out, command_t* commands, const char* line) { uint8_t argc; char** argv = NULL; int error; command_t* command; if (NULL == commands || NULL == line) return EFAULT; argc = command_split(line, &argv); if (NULL == argv) return errno; if (!argc || NULL == (command = command_find(commands, argv[0]))) { command_sfree(&argv); command_report_error(out, commands, ENOCMD); return ENOCMD; } error = command_do(out, command, argc, argv); command_sfree(&argv); return error; }
void command_fail(int reason, irc_user_t *origin, const char *command) { command_t *cmd; cmd = command_find(command); switch(reason) { case CMD_BADPARAM: irc_notice(origin->nick, "Incorrect parameters for \2%s\2", cmd->name); irc_notice(origin->nick, "Syntax: %s", cmd->syntax); break; case CMD_NEEDSPARAM: irc_notice(origin->nick, "Insufficient parameters for \2%s\2", cmd->name); irc_notice(origin->nick, "Syntax: %s", cmd->syntax); break; case CMD_NOAUTH: irc_notice(origin->nick, "You are not authorised to use \2%s\2", cmd->name); break; } }
bool cmd_uid(struct client_command_context *cmd) { struct command *command; const char *cmd_name; /* UID <command> <args> */ cmd_name = imap_parser_read_word(cmd->parser); if (cmd_name == NULL) return FALSE; command = command_find(t_strconcat("UID ", cmd_name, NULL)); if (command == NULL) { client_send_tagline(cmd, t_strconcat( "BAD Unknown UID command ", cmd_name, NULL)); return TRUE; } cmd->name = p_strconcat(cmd->pool, "UID ", cmd_name, NULL); cmd->cmd_flags = command->flags; cmd->func = command->func; cmd->uid = TRUE; return cmd->func(cmd); }
static void command_loop(void) { struct Command apa = {{NULL, NULL}, "apa", 1}; struct Command banan = {{NULL, NULL}, "banan", 2}; struct Command cykel = {{NULL, NULL}, "cykel", 3}; command_add(&apa); command_add(&banan); command_add(&cykel); for (;;) { static char read_buffer[1024] = {0, }; static int buffer_position = 0; if (serial_data_buffered()) { char c = serial_read8(); switch (c) { case 0x0d: { read_buffer[buffer_position++] = '\0'; printf("\n"); struct Command* command = NULL; if ((command = command_find(read_buffer)) != NULL) { printf("Executing %d\n", command->x); } buffer_position = 0; break; } default: serial_write8(c); read_buffer[buffer_position++] = c; break; } } } }
GList *completion_get_options(const char *cmd, const char *option) { COMMAND_REC *rec; GList *list; char **tmp; int len; g_return_val_if_fail(cmd != NULL, NULL); g_return_val_if_fail(option != NULL, NULL); rec = command_find(cmd); if (rec == NULL || rec->options == NULL) return NULL; list = NULL; len = strlen(option); for (tmp = rec->options; *tmp != NULL; tmp++) { const char *optname = *tmp + iscmdtype(**tmp); if (len == 0 || g_strncasecmp(optname, option, len) == 0) list = g_list_append(list, g_strconcat("-", optname, NULL)); } return list; }
int main(int argc, char ** argv) { check(); // Передан файл базы как параметр if (argc == 2) { db_filename = argv[1]; } // Файл не передан, используется имя по умолчанию else if (argc == 1) { db_filename = "default.db"; } // Неправильное использование else { fprintf( stderr, "Usage: dictionary [words.db]\n"); exit( EXIT_WRONG_USAGE); } assert(NULL != db_filename); FILE * f = NULL; int code = access(db_filename, R_OK | W_OK); // Нет прав, не существует файл или что-нибудь ещё if (-1 == code) { // Нет файла, можно создавать if ( errno == ENOENT) { f = fopen(db_filename, "w+"); fprintf( stderr, "INFO: Файл не существовал и теперь создан.\n"); } else if ( errno == EACCES) { fprintf( stderr, "FATAL: Нет прав доступа к базе.\n"); exit( EXIT_WRONG_RIGHTS); } else { printf("errno = %d\n", errno); exit( EXIT_WTF); } } // Есть права и файл существует else { f = fopen(db_filename, "r+"); fprintf( stderr, "INFO: Существующий файл открыт для работы.\n"); } assert(NULL != f); fseek(f, 0, SEEK_END); int length = ftell(f); fprintf( stderr, "DEBUG: Длина файла: %d\n", length); if (length < HEADER_SIZE) { // Длина файла заведомо меньше размера header. Пишем новый. write_new_header(&header, f); } else { // Читаем read_header(&header, f); // Проверяем if (header.version != 1 || header.actual_words > header.total_words) { fprintf( stderr, "FATAL: База данных (%s), вероятно, испорчена. Возможно, стоит её удалить.\n", db_filename); WTF(); } } // Всё есть. Можно работать. printf("Введите help для справки, quit для выхода.\n"); int working = 1; while (working) { printf("> "); char str[6]; fgets(str, 6, stdin); remove_newline(str); if (strcmp(str, "help") == 0) { command_help(); } else if (strcmp(str, "quit") == 0 || strcmp(str, "exit") == 0 || strcmp(str, "bye") == 0) { save_database(f); exit( EXIT_SUCCESS); } else if (strcmp(str, "add") == 0) { command_add(f); } else if (strcmp(str, "find") == 0) { command_find(f); } else if (strcmp(str, "del") == 0 || strcmp(str, "rm") == 0) { command_remove(f); } else if (strcmp(str, "frag") == 0) { command_defragment(f); } else { fprintf( stderr, "ERROR: Неизвестная команда '%s'\n", str); } } /* Операции: 1. Добавить слово. Имя (128 байт), содержание (не ограничено) -> 2. Найти слово. Имя -> содержание 3. Удалить. Имя -> */ if (f != NULL) fclose(f); return EXIT_SUCCESS; }
/* * atheme.command * * XML inputs: * authcookie, account name, source ip, service name, command name, * parameters. * * XML outputs: * depends on command * * Side Effects: * command is executed */ static int xmlrpcmethod_command(void *conn, int parc, char *parv[]) { myuser_t *mu; service_t *svs; command_t *cmd; sourceinfo_t *si; int newparc; char *newparv[20]; struct httpddata *hd = ((connection_t *)conn)->userdata; int i; for (i = 0; i < parc; i++) { if (*parv[i] == '\0' || strchr(parv[i], '\r') || strchr(parv[i], '\n')) { xmlrpc_generic_error(fault_badparams, "Invalid parameters."); return 0; } } if (parc < 5) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } if (*parv[1] != '\0' && strlen(parv[0]) > 1) { if ((mu = myuser_find(parv[1])) == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Unknown user."); return 0; } if (authcookie_validate(parv[0], mu) == false) { xmlrpc_generic_error(fault_badauthcookie, "Invalid authcookie for this account."); return 0; } } else mu = NULL; /* try literal service name first, then user-configured nickname. */ svs = service_find(parv[3]); if ((svs == NULL && (svs = service_find_nick(parv[3])) == NULL) || svs->commands == NULL) { slog(LG_DEBUG, "xmlrpcmethod_command(): invalid service %s", parv[3]); xmlrpc_generic_error(fault_nosuch_source, "Invalid service name."); return 0; } cmd = command_find(svs->commands, parv[4]); if (cmd == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Invalid command name."); return 0; } memset(newparv, '\0', sizeof newparv); newparc = parc - 5; if (newparc > 20) newparc = 20; if (newparc > 0) memcpy(newparv, parv + 5, newparc * sizeof(parv[0])); si = sourceinfo_create(); si->smu = mu; si->service = svs; si->sourcedesc = parv[2][0] != '\0' ? parv[2] : NULL; si->connection = conn; si->v = &xmlrpc_vtable; si->force_language = language_find("en"); command_exec(svs, si, cmd, newparc, newparv); /* XXX: needs to be fixed up for restartable commands... */ if (!hd->sent_reply) { if (hd->replybuf != NULL) xmlrpc_send_string(hd->replybuf); else xmlrpc_generic_error(fault_unimplemented, "Command did not return a result."); } object_unref(si); return 0; }
static void ns_cmd_sendpass(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; char *name = parv[0]; char *newpass = NULL; char *key; metadata_t *md; enum specialoperation op = op_none; bool ismarked = false; char cmdtext[NICKLEN + 20]; hook_user_needforce_t needforce_hdata; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS"); command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>")); return; } if (parc > 1) { if (!strcasecmp(parv[1], "FORCE")) op = op_force; else if (!strcasecmp(parv[1], "CLEAR")) op = op_clear; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SENDPASS"); command_fail(si, fault_badparams, _("Syntax: SENDPASS <account> [FORCE|CLEAR]")); return; } } if (!(mu = myuser_find_by_nick(name))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), name); return; } if (is_soper(mu) && !has_priv(si, PRIV_ADMIN)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (is SOPER)", name); command_fail(si, fault_badparams, _("\2%s\2 belongs to a services operator; you need %s privilege to send the password."), name, PRIV_ADMIN); return; } if (mu->flags & MU_WAITAUTH) { command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name); return; } if ((md = metadata_find(mu, "private:mark:setter"))) { ismarked = true; if (op == op_none) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked by %s."), entity(mu)->name, md->value); if (has_priv(si, PRIV_MARK)) { snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name); command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext); } return; } else if (!has_priv(si, PRIV_MARK)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK); return; } } needforce_hdata.si = si; needforce_hdata.mu = mu; needforce_hdata.allowed = 1; hook_call_user_needforce(&needforce_hdata); if (!needforce_hdata.allowed) { ismarked = true; if (op == op_none) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked)", entity(mu)->name); command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked."), entity(mu)->name); if (has_priv(si, PRIV_MARK)) { snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name); command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext); } return; } else if (!has_priv(si, PRIV_MARK)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked)", entity(mu)->name); command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK); return; } } if (op == op_clear) { if (metadata_find(mu, "private:setpass:key")) { metadata_delete(mu, "private:setpass:key"); metadata_delete(mu, "private:sendpass:sender"); metadata_delete(mu, "private:sendpass:timestamp"); logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name); command_success_nodata(si, _("The password change key for \2%s\2 has been cleared."), entity(mu)->name); } else command_fail(si, fault_nochange, _("\2%s\2 did not have a password change key outstanding."), entity(mu)->name); return; } if (MOWGLI_LIST_LENGTH(&mu->logins) > 0) { command_fail(si, fault_noprivs, _("This operation cannot be performed on %s, because someone is logged in to it."), entity(mu)->name); return; } if (metadata_find(mu, "private:freeze:freezer")) { command_fail(si, fault_noprivs, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname); return; } if (command_find(si->service->commands, "SETPASS")) { if (metadata_find(mu, "private:setpass:key")) { command_fail(si, fault_alreadyexists, _("\2%s\2 already has a password change key outstanding."), entity(mu)->name); command_fail(si, fault_alreadyexists, _("Use SENDPASS %s CLEAR to clear it so that a new one can be sent."), entity(mu)->name); return; } if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); if (md) command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); else command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name); } logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name); key = random_string(12); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key)) { command_fail(si, fault_emailfail, _("Email send failed.")); free(key); return; } metadata_add(mu, "private:setpass:key", crypt_string(key, gen_salt())); free(key); command_success_nodata(si, _("The password change key for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); } else { if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); if (md) command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); else command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name); } logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2", name); newpass = random_string(12); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SENDPASS, mu->email, newpass)) { command_fail(si, fault_emailfail, _("Email send failed.")); free(newpass); return; } set_password(mu, newpass); free(newpass); command_success_nodata(si, _("The password for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); if (mu->flags & MU_NOPASSWORD) { mu->flags &= ~MU_NOPASSWORD; command_success_nodata(si, _("The \2%s\2 flag has been removed for account \2%s\2."), "NOPASSWORD", entity(mu)->name); } } }
static bool client_command_input(struct client_command_context *cmd) { struct client *client = cmd->client; struct command *command; if (cmd->func != NULL) { /* command is being executed - continue it */ if (command_exec(cmd)) { /* command execution was finished */ client_command_free(&cmd); client_add_missing_io(client); return TRUE; } return client_handle_unfinished_cmd(cmd); } if (cmd->tag == NULL) { cmd->tag = imap_parser_read_word(cmd->parser); if (cmd->tag == NULL) return FALSE; /* need more data */ cmd->tag = p_strdup(cmd->pool, cmd->tag); } if (cmd->name == NULL) { cmd->name = imap_parser_read_word(cmd->parser); if (cmd->name == NULL) return FALSE; /* need more data */ /* UID commands are a special case. better to handle them here. */ if (!cmd->uid && strcasecmp(cmd->name, "UID") == 0) { cmd->uid = TRUE; cmd->name = imap_parser_read_word(cmd->parser); if (cmd->name == NULL) return FALSE; /* need more data */ } cmd->name = !cmd->uid ? p_strdup(cmd->pool, cmd->name) : p_strconcat(cmd->pool, "UID ", cmd->name, NULL); imap_refresh_proctitle(); } client->input_skip_line = TRUE; if (cmd->name[0] == '\0') { /* command not given - cmd->func is already NULL. */ } else if ((command = command_find(cmd->name)) != NULL) { cmd->func = command->func; cmd->cmd_flags = command->flags; if (client_command_is_ambiguous(cmd)) { /* do nothing until existing commands are finished */ i_assert(cmd->state == CLIENT_COMMAND_STATE_WAIT_INPUT); cmd->state = CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; io_remove(&client->io); return FALSE; } } if (cmd->func == NULL) { /* unknown command */ client_send_command_error(cmd, "Unknown command."); cmd->param_error = TRUE; client_command_free(&cmd); return TRUE; } else { i_assert(!client->disconnected); return client_command_input(cmd); } }
static void ns_cmd_drop(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; mynick_t *mn; char *acc = parv[0]; char *pass = parv[1]; if (!acc || !pass) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "DROP"); command_fail(si, fault_needmoreparams, _("Syntax: DROP <account> <password>")); return; } if (!(mu = myuser_find(acc))) { if (!nicksvs.no_nick_ownership) { mn = mynick_find(acc); if (mn != NULL && command_find(si->service->cmdtree, "UNGROUP")) { command_fail(si, fault_nosuch_target, _("\2%s\2 is a grouped nick, use %s to remove it."), acc, "UNGROUP"); return; } } command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), acc); return; } if (metadata_find(mu, "private:freeze:freezer")) { command_fail(si, fault_authfail, nicksvs.no_nick_ownership ? "You cannot login as \2%s\2 because the account has been frozen." : "You cannot identify to \2%s\2 because the nickname has been frozen.", mu->name); return; } if (!verify_password(mu, pass)) { command_fail(si, fault_authfail, _("Authentication failed. Invalid password for \2%s\2."), mu->name); bad_password(si, mu); return; } if (!nicksvs.no_nick_ownership && LIST_LENGTH(&mu->nicks) > 1 && command_find(si->service->cmdtree, "UNGROUP")) { command_fail(si, fault_noprivs, _("Account \2%s\2 has %d other nick(s) grouped to it, remove those first."), mu->name, LIST_LENGTH(&mu->nicks) - 1); return; } if (is_soper(mu)) { command_fail(si, fault_noprivs, _("The nickname \2%s\2 belongs to a services operator; it cannot be dropped."), acc); return; } if (mu->flags & MU_HOLD) { command_fail(si, fault_noprivs, _("The account \2%s\2 is held; it cannot be dropped."), acc); return; } snoop("DROP: \2%s\2 by \2%s\2", mu->name, get_source_name(si)); command_add_flood(si, FLOOD_MODERATE); logcommand(si, CMDLOG_REGISTER, "DROP %s", mu->name); hook_call_user_drop(mu); command_success_nodata(si, _("The account \2%s\2 has been dropped."), mu->name); object_unref(mu); }
struct command *command_find_in_parent(struct command *parent, const char *name) { return command_find(parent->children, name); }
struct command *command_find_in_context(struct command_context *cmd_ctx, const char *name) { return command_find(cmd_ctx->commands, name); }
/* * Add timestamp in qlogentry. */ static const char * qlog_add_timestamp(qlogentry *entry, char *buf, size_t size) { int cmd, i; char *p; /* TSLEN: "[HH:MM:SS]\0" == 11 */ #define TSLEN 11 char stamp[TSLEN]; /* attach tag only if we know what we're doing */ p = nextword(entry->text); if (p == NULL) { return entry->text; } /* Next find out what command it was. */ i = pos(p, ' '); if (i != -1 && i < TSLEN) { char tmp[18]; strncpy(tmp, p, i); tmp[i] = '\0'; cmd = command_find(tmp); } else { return entry->text; } /* Is this something we can handle? */ if (cmd != CMD_PRIVMSG && cmd != CMD_NOTICE && cmd != CMD_QUIT && cmd != CMD_PART && cmd != CMD_KICK && cmd != CMD_KILL) { return entry->text; } /* * p now points to command. The next parameter is target, which can be * either channel or user. Since channel name may contain a colon (':'), * we need to skip it (and the command). */ p = nextword(p); if (p == NULL) { return entry->text; } p = nextword(p); if (p == NULL) { return entry->text; } switch (cfg.timestamp) { case TS_BEGINNING: { char rep; p = strchr(p, (int) ':'); if (p != NULL) { if (p[1] == '\0') { p = NULL; } else if (p[1] == '\1') { p = strchr(p, (int) ' '); } } /* * Confused? Don't break already broken things any * further. */ if (p == NULL) { return entry->text; } rep = *p; *p = '\0'; /* ugly, but makes life easier */ strftime(stamp, TSLEN, "[%H:%M:%S]", localtime(&entry->timestamp)); snprintf(buf, size, "%s%c%s %s", entry->text, rep, stamp, p + 1); buf[size - 1] = '\0'; *p = rep; return buf; } case TS_END: { int add_one; int len; len = strlen(entry->text); if (entry->text[len - 1] == '\1') { entry->text[len - 1] = '\0'; add_one = 1; } else { add_one = 0; } strftime(stamp, TSLEN, "[%H:%M:%S]", localtime(&entry->timestamp)); snprintf(buf, size, "%s %s%s", entry->text, stamp, add_one == 1 ? "\1" : ""); buf[size - 1] = '\0'; return buf; } default: return entry->text; } } /* static const char *qlog_add_timestamp(qlogentry *entry, char *buf,
static void ns_cmd_register(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; mynick_t *mn = NULL; mowgli_node_t *n; const char *account; const char *pass; const char *email; char lau[BUFSIZE], lao[BUFSIZE]; hook_user_register_check_t hdata; hook_user_req_t req; if (si->smu) { command_fail(si, fault_already_authed, _("You are already logged in as \2%s\2."), entity(si->smu)->name); if (si->su != NULL && !mynick_find(si->su->nick) && command_find(si->service->commands, "GROUP")) command_fail(si, fault_already_authed, _("Use %s to register %s to your account."), "GROUP", si->su->nick); return; } if (nicksvs.no_nick_ownership || si->su == NULL) account = parv[0], pass = parv[1], email = parv[2]; else account = si->su->nick, pass = parv[0], email = parv[1]; if (!account || !pass || !email) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REGISTER"); if (nicksvs.no_nick_ownership || si->su == NULL) command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <account> <password> <email>")); else command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <password> <email>")); return; } if (strlen(pass) >= PASSLEN) { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "REGISTER"); command_fail(si, fault_badparams, _("Registration passwords may not be longer than \2%d\2 characters."), PASSLEN - 1); return; } if (!nicksvs.no_nick_ownership && si->su == NULL && user_find_named(account)) { command_fail(si, fault_noprivs, _("A user matching this account is already on IRC.")); return; } if (!nicksvs.no_nick_ownership && IsDigit(*account)) { command_fail(si, fault_badparams, _("For security reasons, you can't register your UID.")); command_fail(si, fault_badparams, _("Please change to a real nickname, and try again.")); return; } if (nicksvs.no_nick_ownership || si->su == NULL) { if (strchr(account, ' ') || strchr(account, '\n') || strchr(account, '\r') || account[0] == '=' || account[0] == '#' || account[0] == '@' || account[0] == '+' || account[0] == '%' || account[0] == '!' || strchr(account, ',')) { command_fail(si, fault_badparams, _("The account name \2%s\2 is invalid."), account); return; } } if (strlen(account) >= NICKLEN) { command_fail(si, fault_badparams, _("The account name \2%s\2 is invalid."), account); return; } if ((si->su != NULL && !strcasecmp(pass, si->su->nick)) || !strcasecmp(pass, account)) { command_fail(si, fault_badparams, _("You cannot use your nickname as a password.")); if (nicksvs.no_nick_ownership || si->su == NULL) command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <account> <password> <email>")); else command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <password> <email>")); return; } /* make sure it isn't registered already */ if (nicksvs.no_nick_ownership ? myuser_find(account) != NULL : mynick_find(account) != NULL) { command_fail(si, fault_alreadyexists, _("\2%s\2 is already registered."), account); return; } if ((unsigned int)(CURRTIME - ratelimit_firsttime) > config_options.ratelimit_period) ratelimit_count = 0, ratelimit_firsttime = CURRTIME; /* Still do flood priv checking because the user may be in the ircop operclass */ if (ratelimit_count > config_options.ratelimit_uses && !has_priv(si, PRIV_FLOOD)) { command_fail(si, fault_toomany, _("The system is currently too busy to process your registration, please try again later.")); slog(LG_INFO, "NICKSERV:REGISTER:THROTTLED: \2%s\2 by \2%s\2", account, si->su != NULL ? si->su->nick : get_source_name(si)); return; } hdata.si = si; hdata.account = account; hdata.email = email; hdata.password = pass; hdata.approved = 0; hook_call_user_can_register(&hdata); if (hdata.approved != 0) return; if (!nicksvs.no_nick_ownership) { hook_call_nick_can_register(&hdata); if (hdata.approved != 0) return; } if (!validemail(email)) { command_fail(si, fault_badparams, _("\2%s\2 is not a valid email address."), email); return; } if (!email_within_limits(email)) { command_fail(si, fault_toomany, _("\2%s\2 has too many accounts registered."), email); return; } mu = myuser_add(account, auth_module_loaded ? "*" : pass, email, config_options.defuflags | MU_NOBURSTLOGIN | (auth_module_loaded ? MU_CRYPTPASS : 0)); mu->registered = CURRTIME; mu->lastlogin = CURRTIME; if (!nicksvs.no_nick_ownership) { mn = mynick_add(mu, entity(mu)->name); mn->registered = CURRTIME; mn->lastseen = CURRTIME; } if (config_options.ratelimit_uses && config_options.ratelimit_period) ratelimit_count++; if (auth_module_loaded) { if (!verify_password(mu, pass)) { command_fail(si, fault_authfail, _("Invalid password for \2%s\2."), entity(mu)->name); bad_password(si, mu); object_unref(mu); return; } } if (me.auth == AUTH_EMAIL) { char *key = random_string(12); mu->flags |= MU_WAITAUTH; metadata_add(mu, "private:verify:register:key", key); metadata_add(mu, "private:verify:register:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_REGISTER, mu->email, key)) { command_fail(si, fault_emailfail, _("Sending email failed, sorry! Registration aborted.")); object_unref(mu); free(key); return; } command_success_nodata(si, _("An email containing nickname activation instructions has been sent to \2%s\2."), mu->email); command_success_nodata(si, _("If you do not complete registration within one day, your nickname will expire.")); free(key); } if (si->su != NULL) { si->su->myuser = mu; n = mowgli_node_create(); mowgli_node_add(si->su, n, &mu->logins); if (!(mu->flags & MU_WAITAUTH)) /* only grant ircd registered status if it's verified */ ircd_on_login(si->su, mu, NULL); } command_add_flood(si, FLOOD_MODERATE); if (!nicksvs.no_nick_ownership && si->su != NULL) logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2 to \2%s\2", account, email); else logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2 to \2%s\2 by \2%s\2", account, email, si->su != NULL ? si->su->nick : get_source_name(si)); if (is_soper(mu)) { wallops("%s registered the nick \2%s\2 and gained services operator privileges.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "SOPER: \2%s\2 as \2%s\2", get_oper_name(si), entity(mu)->name); } command_success_nodata(si, _("\2%s\2 is now registered to \2%s\2, with the password \2%s\2."), entity(mu)->name, mu->email, pass); hook_call_user_register(mu); if (si->su != NULL) { snprintf(lau, BUFSIZE, "%s@%s", si->su->user, si->su->vhost); metadata_add(mu, "private:host:vhost", lau); snprintf(lao, BUFSIZE, "%s@%s", si->su->user, si->su->host); metadata_add(mu, "private:host:actual", lao); } if (!(mu->flags & MU_WAITAUTH)) { req.si = si; req.mu = mu; req.mn = mn; hook_call_user_verify_register(&req); } }
/* * atheme.command * * XML inputs: * authcookie, account name, source ip, service name, command name, * parameters. * * XML outputs: * depends on command * * Side Effects: * command is executed */ static int xmlrpcmethod_command(void *conn, int parc, char *parv[]) { myuser_t *mu; service_t *svs; command_t *cmd; sourceinfo_t si; int newparc; char *newparv[20]; struct httpddata *hd = ((connection_t *)conn)->userdata; int i; for (i = 0; i < parc; i++) { if (strchr(parv[i], '\r') || strchr(parv[i], '\n')) { xmlrpc_generic_error(fault_badparams, "Invalid parameters."); return 0; } } if (parc < 5) { xmlrpc_generic_error(fault_needmoreparams, "Insufficient parameters."); return 0; } if (*parv[1] != '\0' && strlen(parv[0]) > 1) { if ((mu = myuser_find(parv[1])) == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Unknown user."); return 0; } if (authcookie_validate(parv[0], mu) == false) { xmlrpc_generic_error(fault_badauthcookie, "Invalid authcookie for this account."); return 0; } } else mu = NULL; svs = service_find_nick(parv[3]); if (svs == NULL || svs->cmdtree == NULL) { slog(LG_DEBUG, "xmlrpcmethod_command(): invalid service %s", parv[3]); xmlrpc_generic_error(fault_nosuch_source, "Invalid service name."); return 0; } cmd = command_find(svs->cmdtree, parv[4]); if (cmd == NULL) { xmlrpc_generic_error(fault_nosuch_source, "Invalid command name."); return 0; } memset(newparv, '\0', sizeof newparv); newparc = parc - 5; if (newparc > 20) newparc = 20; if (newparc > 0) memcpy(newparv, parv + 5, newparc * sizeof(parv[0])); memset(&si, '\0', sizeof si); si.smu = mu; si.service = svs; si.sourcedesc = parv[2][0] != '\0' ? parv[2] : NULL; si.connection = conn; si.v = &xmlrpc_vtable; command_exec(svs, &si, cmd, newparc, newparv); if (!hd->sent_reply) { if (hd->replybuf != NULL) xmlrpc_send_string(hd->replybuf); else xmlrpc_generic_error(fault_unimplemented, "Command did not return a result."); } return 0; }