degesch: "nickname" -> "nicks"

Now you can specify multiple nicknames to try.
This commit is contained in:
Přemysl Eric Janouch 2015-07-09 02:46:31 +02:00
parent 2b2da0beab
commit 5e7f9882dd
1 changed files with 59 additions and 13 deletions

View File

@ -1138,6 +1138,7 @@ struct server
struct str_map irc_buffer_map; ///< Maps IRC identifiers to buffers struct str_map irc_buffer_map; ///< Maps IRC identifiers to buffers
struct user *irc_user; ///< Our own user struct user *irc_user; ///< Our own user
int nick_counter; ///< Iterates "nicks" when registering
struct str irc_user_mode; ///< Our current user modes struct str irc_user_mode; ///< Our current user modes
char *irc_user_host; ///< Our current user@host char *irc_user_host; ///< Our current user@host
@ -1488,9 +1489,9 @@ config_validate_nonnegative
static struct config_schema g_config_server[] = static struct config_schema g_config_server[] =
{ {
{ .name = "nickname", { .name = "nicks",
.comment = "IRC nickname", .comment = "IRC nickname",
.type = CONFIG_ITEM_STRING, .type = CONFIG_ITEM_STRING_ARRAY,
.validate = config_validate_nonjunk_string }, .validate = config_validate_nonjunk_string },
{ .name = "username", { .name = "username",
.comment = "IRC user name", .comment = "IRC user name",
@ -4003,11 +4004,11 @@ static struct transport g_transport_tls =
static bool static bool
irc_autofill_user_info (struct server *s, struct error **e) irc_autofill_user_info (struct server *s, struct error **e)
{ {
const char *nickname = get_config_string (s->config, "nickname"); const char *nicks = get_config_string (s->config, "nicks");
const char *username = get_config_string (s->config, "username"); const char *username = get_config_string (s->config, "username");
const char *realname = get_config_string (s->config, "realname"); const char *realname = get_config_string (s->config, "realname");
if (nickname && username && realname) if (nicks && *nicks && username && *username && realname)
return true; return true;
// Read POSIX user info and fill the configuration if needed // Read POSIX user info and fill the configuration if needed
@ -4016,9 +4017,9 @@ irc_autofill_user_info (struct server *s, struct error **e)
FAIL ("cannot retrieve user information: %s", strerror (errno)); FAIL ("cannot retrieve user information: %s", strerror (errno));
// FIXME: set_config_strings() writes errors on its own // FIXME: set_config_strings() writes errors on its own
if (!nickname) if (!nicks || !*nicks)
set_config_string (s->config, "nickname", pwd->pw_name); set_config_string (s->config, "nicks", pwd->pw_name);
if (!username) if (!username || !*username)
set_config_string (s->config, "username", pwd->pw_name); set_config_string (s->config, "username", pwd->pw_name);
// Not all systems have the GECOS field but the vast majority does // Not all systems have the GECOS field but the vast majority does
@ -4037,16 +4038,33 @@ irc_autofill_user_info (struct server *s, struct error **e)
return true; return true;
} }
static char *
irc_fetch_next_nickname (struct server *s)
{
struct str_vector v;
str_vector_init (&v);
split_str_ignore_empty (get_config_string (s->config, "nicks"), ',', &v);
char *result = NULL;
if (s->nick_counter >= 0 && s->nick_counter < v.len)
result = str_vector_steal (&v, s->nick_counter++);
if (s->nick_counter >= v.len)
// Exhausted all nicknames
s->nick_counter = -1;
str_vector_free (&v);
return result;
}
static void static void
irc_register (struct server *s) irc_register (struct server *s)
{ {
// Fill in user information automatically if needed // Fill in user information automatically if needed
irc_autofill_user_info (s, NULL); irc_autofill_user_info (s, NULL);
const char *nickname = get_config_string (s->config, "nickname");
const char *username = get_config_string (s->config, "username"); const char *username = get_config_string (s->config, "username");
const char *realname = get_config_string (s->config, "realname"); const char *realname = get_config_string (s->config, "realname");
hard_assert (nickname && username && realname); hard_assert (username && realname);
// Start IRCv3.1 capability negotiation; // Start IRCv3.1 capability negotiation;
// at worst the server will ignore this or send a harmless error message // at worst the server will ignore this or send a harmless error message
@ -4056,7 +4074,15 @@ irc_register (struct server *s)
if (password) if (password)
irc_send (s, "PASS :%s", password); irc_send (s, "PASS :%s", password);
irc_send (s, "NICK %s", nickname); s->nick_counter = 0;
char *nickname = irc_fetch_next_nickname (s);
if (nickname)
irc_send (s, "NICK :%s", nickname);
else
log_server_error (s, s->buffer, "No nicks present in configuration");
free (nickname);
// IRC servers may ignore the last argument if it's empty // IRC servers may ignore the last argument if it's empty
irc_send (s, "USER %s 8 * :%s", username, *realname ? realname : " "); irc_send (s, "USER %s 8 * :%s", username, *realname ? realname : " ");
} }
@ -5647,6 +5673,28 @@ irc_handle_rpl_inviting (struct server *s, const struct irc_message *msg)
"You have invited #n to #S", nickname, channel_name); "You have invited #n to #S", nickname, channel_name);
} }
static void
irc_handle_err_nicknameinuse (struct server *s, const struct irc_message *msg)
{
if (msg->params.len < 2)
return;
log_server_error (s, s->buffer,
"Nickname is already in use: #S", msg->params.vector[1]);
// Only do this while we haven't successfully registered yet
if (s->state != IRC_CONNECTED)
return;
char *nickname = irc_fetch_next_nickname (s);
if (nickname)
{
log_server_status (s, s->buffer, "Retrying with #s...", nickname);
irc_send (s, "NICK :%s", nickname);
free (nickname);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void static void
@ -5848,9 +5896,7 @@ irc_process_numeric (struct server *s,
irc_handle_rpl_inviting (s, msg); buffer = NULL; break; irc_handle_rpl_inviting (s, msg); buffer = NULL; break;
case IRC_ERR_NICKNAMEINUSE: case IRC_ERR_NICKNAMEINUSE:
// TODO: if (state == IRC_CONNECTED), use a different nick; irc_handle_err_nicknameinuse (s, msg); buffer = NULL; break;
// either use a number suffix, or accept commas in "nickname" config
break;
case IRC_RPL_LIST: case IRC_RPL_LIST:
case IRC_RPL_WHOREPLY: case IRC_RPL_WHOREPLY: