degesch: "nickname" -> "nicks"
Now you can specify multiple nicknames to try.
This commit is contained in:
parent
2b2da0beab
commit
5e7f9882dd
72
degesch.c
72
degesch.c
@ -1138,6 +1138,7 @@ struct server
|
||||
struct str_map irc_buffer_map; ///< Maps IRC identifiers to buffers
|
||||
|
||||
struct user *irc_user; ///< Our own user
|
||||
int nick_counter; ///< Iterates "nicks" when registering
|
||||
struct str irc_user_mode; ///< Our current user modes
|
||||
char *irc_user_host; ///< Our current user@host
|
||||
|
||||
@ -1488,9 +1489,9 @@ config_validate_nonnegative
|
||||
|
||||
static struct config_schema g_config_server[] =
|
||||
{
|
||||
{ .name = "nickname",
|
||||
{ .name = "nicks",
|
||||
.comment = "IRC nickname",
|
||||
.type = CONFIG_ITEM_STRING,
|
||||
.type = CONFIG_ITEM_STRING_ARRAY,
|
||||
.validate = config_validate_nonjunk_string },
|
||||
{ .name = "username",
|
||||
.comment = "IRC user name",
|
||||
@ -4003,11 +4004,11 @@ static struct transport g_transport_tls =
|
||||
static bool
|
||||
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 *realname = get_config_string (s->config, "realname");
|
||||
|
||||
if (nickname && username && realname)
|
||||
if (nicks && *nicks && username && *username && realname)
|
||||
return true;
|
||||
|
||||
// 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));
|
||||
|
||||
// FIXME: set_config_strings() writes errors on its own
|
||||
if (!nickname)
|
||||
set_config_string (s->config, "nickname", pwd->pw_name);
|
||||
if (!username)
|
||||
if (!nicks || !*nicks)
|
||||
set_config_string (s->config, "nicks", pwd->pw_name);
|
||||
if (!username || !*username)
|
||||
set_config_string (s->config, "username", pwd->pw_name);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
irc_register (struct server *s)
|
||||
{
|
||||
// Fill in user information automatically if needed
|
||||
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 *realname = get_config_string (s->config, "realname");
|
||||
hard_assert (nickname && username && realname);
|
||||
hard_assert (username && realname);
|
||||
|
||||
// Start IRCv3.1 capability negotiation;
|
||||
// at worst the server will ignore this or send a harmless error message
|
||||
@ -4056,7 +4074,15 @@ irc_register (struct server *s)
|
||||
if (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_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);
|
||||
}
|
||||
|
||||
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
|
||||
@ -5848,9 +5896,7 @@ irc_process_numeric (struct server *s,
|
||||
irc_handle_rpl_inviting (s, msg); buffer = NULL; break;
|
||||
|
||||
case IRC_ERR_NICKNAMEINUSE:
|
||||
// TODO: if (state == IRC_CONNECTED), use a different nick;
|
||||
// either use a number suffix, or accept commas in "nickname" config
|
||||
break;
|
||||
irc_handle_err_nicknameinuse (s, msg); buffer = NULL; break;
|
||||
|
||||
case IRC_RPL_LIST:
|
||||
case IRC_RPL_WHOREPLY:
|
||||
|
Loading…
Reference in New Issue
Block a user