~rcr/rirc

c677d85e88b1397d0eaa9b99ad3acf531f64aa3f — Richard Robbins 14 days ago 17d4f63
add -m/--mode flag
M README.md => README.md +1 -0
@@ 68,6 68,7 @@ Server options:
  -w, --pass=PASS           Connect to SERVER using PASS
  -u, --username=USERNAME   Connect to SERVER using USERNAME
  -r, --realname=REALNAME   Connect to SERVER using REALNAME
  -m, --mode=MODE           Connect to SERVER with user MODE
  -n, --nicks=NICKS         Comma separated list of nicks to use for SERVER
  -c, --chans=CHANNELS      Comma separated list of channels to join for SERVER


M docs/rirc.1 => docs/rirc.1 +3 -0
@@ 33,6 33,9 @@ Connect to \fIserver\fP using \fIusername\fP
.BI "-r, --realname=" realname
Connect to \fIserver\fP using \fIrealname\fP
.TP
.BI "-m, --mode=" mode
Connect to \fIserver\fP with user \fImode\fP
.TP
.BI "-n, --nicks=" nicks
Comma separated list of \fInicks\fP to use for \fIserver\fP
.TP

M src/components/server.c => src/components/server.c +16 -6
@@ 28,18 28,27 @@ HANDLED_005
#undef X

struct server*
server(const char *host, const char *port, const char *pass, const char *user, const char *real)
server(
	const char *host,
	const char *port,
	const char *pass,
	const char *username,
	const char *realname,
	const char *mode)
{
	struct server *s;

	if ((s = calloc(1, sizeof(*s))) == NULL)
		fatal("calloc: %s", strerror(errno));

	s->host = strdup(host);
	s->port = strdup(port);
	s->pass = pass ? strdup(pass) : NULL;
	s->username = strdup(user);
	s->realname = strdup(real);
	s->host     = strdup(host);
	s->port     = strdup(port);
	s->username = strdup(username);
	s->realname = strdup(realname);

	s->pass = (pass ? strdup(pass) : NULL);
	s->mode = (mode ? strdup(mode) : NULL);

	s->casemapping = CASEMAPPING_RFC1459;
	s->mode_str.type = MODE_STR_USERMODE;
	ircv3_caps(&(s->ircv3_caps));


@@ 149,6 158,7 @@ server_free(struct server *s)
	free((void *)s->pass);
	free((void *)s->username);
	free((void *)s->realname);
	free((void *)s->mode);
	free((void *)s->nick);
	free((void *)s->nicks.base);
	free((void *)s->nicks.set);

M src/components/server.h => src/components/server.h +3 -1
@@ 17,6 17,7 @@ struct server
	const char *username;
	const char *realname;
	const char *nick;
	const char *mode;
	enum casemapping casemapping;
	struct {
		size_t next;


@@ 58,7 59,8 @@ struct server* server(
	const char*,  /* port */
	const char*,  /* pass */
	const char*,  /* username */
	const char*); /* realname */
	const char*,  /* realname */
	const char*); /* mode */

struct server* server_list_add(struct server_list*, struct server*);
struct server* server_list_del(struct server_list*, struct server*);

M src/handlers/irc_recv.c => src/handlers/irc_recv.c +8 -5
@@ 313,16 313,19 @@ irc_numeric_001(struct server *s, struct irc_message *m)

	s->registered = 1;

	do {
		if (c->type == CHANNEL_T_CHANNEL && !c->parted)
			sendf(s, "JOIN %s", c->name);
	} while ((c = c->next) != s->channel);

	if (irc_message_split(m, &params, &trailing))
		newlinef(s->channel, 0, FROM_INFO, "%s", trailing);

	server_info(s, "You are known as %s", s->nick);

	if (s->mode)
		sendf(s, "MODE %s +%s", s->nick, s->mode);

	do {
		if (c->type == CHANNEL_T_CHANNEL && !c->parted)
			sendf(s, "JOIN %s", c->name);
	} while ((c = c->next) != s->channel);

	return 0;
}


M src/rirc.c => src/rirc.c +13 -2
@@ 71,6 71,7 @@ static const char *const rirc_help =
"\n  -w, --pass=PASS           Connect to SERVER using PASS"
"\n  -u, --username=USERNAME   Connect to SERVER using USERNAME"
"\n  -r, --realname=REALNAME   Connect to SERVER using REALNAME"
"\n  -m, --mode=MODE           Connect to SERVER with user MODE"
"\n  -n, --nicks=NICKS         Comma separated list of nicks to use for SERVER"
"\n  -c, --chans=CHANNELS      Comma separated list of channels to join for SERVER"
"\n"


@@ 99,6 100,7 @@ rirc_opt_str(char c)
		case 'c': return "-c/--chans";
		case 'u': return "-u/--username";
		case 'r': return "-r/--realname";
		case 'm': return "-m/--mode";
		case '4': return "--ipv4";
		case '6': return "--ipv6";
		case 'x': return "--tls-disable";


@@ 136,6 138,7 @@ rirc_parse_args(int argc, char **argv)
		const char *pass;
		const char *username;
		const char *realname;
		const char *mode;
		const char *nicks;
		const char *chans;
		int ipv;


@@ 150,6 153,7 @@ rirc_parse_args(int argc, char **argv)
		{"pass",        required_argument, 0, 'w'},
		{"username",    required_argument, 0, 'u'},
		{"realname",    required_argument, 0, 'r'},
		{"mode",        required_argument, 0, 'm'},
		{"nicks",       required_argument, 0, 'n'},
		{"chans",       required_argument, 0, 'c'},
		{"help",        no_argument,       0, 'h'},


@@ 163,7 167,7 @@ rirc_parse_args(int argc, char **argv)

	opterr = 0;

	while (0 < (opt_c = getopt_long(argc, argv, ":s:p:w:r:u:n:c:hv", long_opts, &opt_i))) {
	while (0 < (opt_c = getopt_long(argc, argv, ":s:p:w:u:r:m:n:c:hv", long_opts, &opt_i))) {

		switch (opt_c) {



@@ 184,6 188,7 @@ rirc_parse_args(int argc, char **argv)
				cli_servers[n_servers - 1].pass     = NULL;
				cli_servers[n_servers - 1].username = default_username;
				cli_servers[n_servers - 1].realname = default_realname;
				cli_servers[n_servers - 1].mode     = NULL;
				cli_servers[n_servers - 1].nicks    = default_nicks;
				cli_servers[n_servers - 1].chans    = NULL;
				cli_servers[n_servers - 1].ipv      = IO_IPV_UNSPEC;


@@ 221,6 226,11 @@ rirc_parse_args(int argc, char **argv)
				cli_servers[n_servers - 1].realname = optarg;
				break;

			case 'm': /* Connect with user mode */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].mode = optarg;
				break;

			case 'n': /* Comma separated list of nicks to use */
				CHECK_SERVER_OPTARG(opt_c, 1);
				cli_servers[n_servers - 1].nicks = optarg;


@@ 307,7 317,8 @@ rirc_parse_args(int argc, char **argv)
			cli_servers[i].port,
			cli_servers[i].pass,
			cli_servers[i].username,
			cli_servers[i].realname
			cli_servers[i].realname,
			cli_servers[i].mode
		);

		cli_servers[i].s->connection = connection(

M src/state.c => src/state.c +8 -2
@@ 635,6 635,7 @@ command(struct channel *c, char *buf)
			const char *pass     = NULL;
			const char *username = default_username;
			const char *realname = default_realname;
			const char *mode     = NULL;
			const char *nicks    = default_nicks;
			const char *chans    = NULL;
			int ipv      = IO_IPV_UNSPEC;


@@ 666,6 667,11 @@ command(struct channel *c, char *buf)
						action(action_error, "connect: '-r/--realname' requires an argument");
						return;
					}
				} else if (!strcmp(str, "-m") || !strcmp(str, "--mode")) {
					if (!(mode = irc_strsep(&buf))) {
						action(action_error, "connect: '-m/--mode' requires an argument");
						return;
					}
				} else if (!strcmp(str, "-n") || !strcmp(str, "--nicks")) {
					if (!(nicks = irc_strsep(&buf))) {
						action(action_error, "connect: '-n/--nicks' requires an argument");


@@ 705,7 711,7 @@ command(struct channel *c, char *buf)
			if (port == NULL)
				port = (tls == IO_TLS_ENABLED) ? "6697" : "6667";

			s = server(host, port, pass, username, realname);
			s = server(host, port, pass, username, realname, mode);

			if (nicks && server_set_nicks(s, nicks)) {
				action(action_error, "connect: invalid -n/--nicks: '%s'", nicks);


@@ 971,7 977,7 @@ io_cb_cxed(const void *cb_obj)
	if ((ret = io_sendf(s->connection, "NICK %s", s->nick)))
		newlinef(s->channel, 0, FROM_ERROR, "sendf fail: %s", io_err(ret));

	if ((ret = io_sendf(s->connection, "USER %s 8 * :%s", s->username, s->realname)))
	if ((ret = io_sendf(s->connection, "USER %s 0 * :%s", s->username, s->realname)))
		newlinef(s->channel, 0, FROM_ERROR, "sendf fail: %s", io_err(ret));

	draw(DRAW_STATUS);

M test/components/server.c => test/components/server.c +9 -9
@@ 44,13 44,13 @@ test_server_list(void)

	memset(&servers, 0, sizeof(servers));

	s1 = server("host1", "port1", NULL, "", "");
	s2 = server("host1", "port1", "foo1", "", ""); /* duplicate host, port (s1) */
	s3 = server("host1", "port2", "foo2", "", ""); /* duplicate host (s1), different port */
	s4 = server("host2", "port1", "foo3", "", ""); /* duplicate port (s1), different host */
	s5 = server("host2", "port2", NULL, "", "");   /* duplicate host (s4), duplicate port (s3) */
	s6 = server("host1", "port2", NULL, "", "");   /* duplicate host, port (s4) */
	s7 = server("host2", "port1", NULL, "", "");   /* duplicate host, port (s5) */
	s1 = server("host1", "port1",   NULL, "real", "user", "abc");
	s2 = server("host1", "port1", "foo1", "real", "user", "abc"); /* duplicate host, port (s1) */
	s3 = server("host1", "port2", "foo2", "real", "user", "abc"); /* duplicate host (s1), different port */
	s4 = server("host2", "port1", "foo3", "real", "user", NULL);  /* duplicate port (s1), different host */
	s5 = server("host2", "port2",   NULL, "real", "user", NULL);  /* duplicate host (s4), duplicate port (s3) */
	s6 = server("host1", "port2",   NULL, "real", "user", NULL);  /* duplicate host, port (s4) */
	s7 = server("host2", "port1",   NULL, "real", "user", NULL);  /* duplicate host, port (s5) */

	/* Test add */
	assert_ptr_eq(server_list_add(&servers, s1), NULL);


@@ 117,7 117,7 @@ test_server_set_chans(void)
	struct channel *c;
	struct server *s;

	s = server("host1", "port", NULL, "", "");
	s = server("host1", "port", NULL, "real", "user", NULL);
	assert_eq(s->clist.count, 1);

	/* empty values, invalid formats */


@@ 162,7 162,7 @@ test_server_set_chans(void)
static void
test_server_set_nicks(void)
{
	struct server *s = server("host", "port", NULL, "", "");
	struct server *s = server("host", "port", NULL, "real", "user", NULL);

	server_nicks_next(s);
	assert_strncmp(s->nick, "rirc", 4);

M test/handlers/irc_ctcp.c => test/handlers/irc_ctcp.c +1 -1
@@ 483,7 483,7 @@ test_recv_ctcp_response_version(void)
static int
test_init(void)
{
	s = server("h1", "p1", NULL, "u1", "r1");
	s = server("h1", "p1", NULL, "u1", "r1", NULL);

	c_chan = channel("chan", CHANNEL_T_CHANNEL);
	c_priv = channel("nick", CHANNEL_T_PRIVMSG);

M test/handlers/irc_recv.c => test/handlers/irc_recv.c +62 -83
@@ 44,8 44,6 @@ static struct server *s;
static void
test_irc_generic(void)
{
	server_reset(s);

	#define CHECK_IRC_GENERIC(M, C, F, RET, LINE_N) \
	do { \
		mock_reset_io(); \


@@ 92,8 90,6 @@ test_irc_generic(void)
static void
test_irc_generic_error(void)
{
	server_reset(s);

	char m1[] = "COMMAND arg1 arg2 :trailing arg";

	mock_reset_io();


@@ 108,8 104,6 @@ test_irc_generic_error(void)
static void
test_irc_generic_ignore(void)
{
	server_reset(s);

	char m1[] = "COMMAND arg1 arg2 :trailing arg";

	mock_reset_io();


@@ 123,8 117,6 @@ test_irc_generic_ignore(void)
static void
test_irc_generic_info(void)
{
	server_reset(s);

	char m1[] = "COMMAND arg1 arg2 :trailing arg";

	mock_reset_io();


@@ 139,8 131,6 @@ test_irc_generic_info(void)
static void
test_irc_generic_unknown(void)
{
	server_reset(s);

	char m1[] = "COMMAND arg1 arg2 :trailing arg";

	mock_reset_io();


@@ 153,6 143,66 @@ test_irc_generic_unknown(void)
}

static void
test_irc_numeric_001(void)
{
	/* 001 :<Welcome message> */

	/* test registered */
	mock_reset_io();
	mock_reset_state();

	assert_eq(s->registered, 0);

	CHECK_RECV("001 me", 0, 1, 3);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "You are known as me");
	assert_strcmp(mock_send[0], "JOIN #c1");
	assert_strcmp(mock_send[1], "JOIN #c2");
	assert_strcmp(mock_send[2], "JOIN #c3");

	assert_eq(s->registered, 1);

	/* test welcome message */
	mock_reset_io();
	mock_reset_state();

	CHECK_RECV("001 me :welcome message", 0, 2, 3);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "welcome message");
	assert_strcmp(mock_line[1], "You are known as me");
	assert_strcmp(mock_send[0], "JOIN #c1");
	assert_strcmp(mock_send[1], "JOIN #c2");
	assert_strcmp(mock_send[2], "JOIN #c3");

	/* test user modes */
	mock_reset_io();
	mock_reset_state();

	s->mode = strdup("abc");

	CHECK_RECV("001 me", 0, 1, 4);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "You are known as me");
	assert_strcmp(mock_send[0], "MODE me +abc");
	assert_strcmp(mock_send[1], "JOIN #c1");
	assert_strcmp(mock_send[2], "JOIN #c2");
	assert_strcmp(mock_send[3], "JOIN #c3");

	/* test parted channels aren't auto joined */
	mock_reset_io();
	mock_reset_state();

	c2->parted = 1;

	CHECK_RECV("001 me", 0, 1, 3);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "You are known as me");
	assert_strcmp(mock_send[0], "MODE me +abc");
	assert_strcmp(mock_send[1], "JOIN #c1");
	assert_strcmp(mock_send[2], "JOIN #c3");
}

static void
test_irc_numeric_353(void)
{
	/* 353 <nick> <type> <channel> 1*(<modes><nick>) */


@@ 162,9 212,6 @@ test_irc_numeric_353(void)
	struct user *u3;
	struct user *u4;

	channel_reset(c1);
	server_reset(s);

	/* test errors */
	CHECK_RECV("353 me", 1, 1, 0);
	assert_strcmp(mock_chan[0], "host");


@@ 239,8 286,6 @@ test_irc_numeric_401(void)
{
	/* <nick> :No such nick/channel */

	server_reset(s);

	/* test errors */
	CHECK_RECV("401 me", 1, 1, 0);
	assert_strcmp(mock_chan[0], "host");


@@ 277,8 322,6 @@ test_irc_numeric_403(void)
{
	/* <chan> :No such channel */

	server_reset(s);

	/* test errors */
	CHECK_RECV("403 me", 1, 1, 0);
	assert_strcmp(mock_chan[0], "host");


@@ 313,8 356,6 @@ test_irc_numeric_403(void)
static void
test_recv(void)
{
	server_reset(s);

	/* test unhandled command type */
	CHECK_RECV("UNHANDLED", 0, 1, 0);
	assert_strcmp(mock_chan[0], "host");


@@ 326,8 367,6 @@ test_recv_error(void)
{
	/* ERROR :<message> */

	server_reset(s);

	CHECK_RECV("ERROR", 1, 1, 0);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "ERROR: message is null");


@@ 349,9 388,6 @@ test_recv_invite(void)
{
	/* :nick!user@host INVITE <nick> <channel> */

	channel_reset(c1);
	server_reset(s);

	CHECK_RECV("INVITE nick channel", 1, 1, 0);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "INVITE: sender's nick is null");


@@ 380,10 416,6 @@ test_recv_join(void)
	/* :nick!user@host JOIN <channel>
	 * :nick!user@host JOIN <channel> <account> :<realname> */

	channel_reset(c1);
	channel_reset(c2);
	server_reset(s);

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c2->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);



@@ 443,15 475,6 @@ test_recv_kick(void)
{
	/* :nick!user@host KICK <channel> <user> [:message] */

	channel_reset(c1);
	channel_reset(c2);
	channel_reset(c3);
	server_reset(s);

	c1->parted = 0;
	c2->parted = 0;
	c3->parted = 0;

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick2", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick3", MODE_EMPTY), USER_ERR_NONE);


@@ 527,11 550,6 @@ test_recv_nick(void)
{
	/* :nick!user@host NICK <nick> */

	channel_reset(c1);
	channel_reset(c2);
	channel_reset(c3);
	server_reset(s);

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick2", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c3->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);


@@ 585,8 603,6 @@ test_recv_notice(void)
static void
test_recv_numeric(void)
{
	server_reset(s);

	CHECK_RECV(":hostname 0 * arg :trailing arg", 1, 1, 0);
	assert_strcmp(mock_line[0], "NUMERIC: '0' invalid");



@@ 625,15 641,6 @@ test_recv_part(void)
{
	/* :nick!user@host PART <channel> [:message] */

	channel_reset(c1);
	channel_reset(c2);
	channel_reset(c3);
	server_reset(s);

	c1->parted = 0;
	c2->parted = 0;
	c3->parted = 0;

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick2", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick3", MODE_EMPTY), USER_ERR_NONE);


@@ 703,8 710,6 @@ test_recv_ping(void)
{
	/* PING <server> */

	server_reset(s);

	CHECK_RECV("PING", 1, 1, 0);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "PING: server is null");


@@ 718,8 723,6 @@ test_recv_pong(void)
{
	/* PONG <server> [<server2>] */

	server_reset(s);

	CHECK_RECV("PONG", 0, 0, 0);
	CHECK_RECV("PONG s1", 0, 0, 0);
	CHECK_RECV("PONG s1 s2", 0, 0, 0);


@@ 736,11 739,6 @@ test_recv_quit(void)
{
	/* :nick!user@host QUIT [:message] */

	channel_reset(c1);
	channel_reset(c2);
	channel_reset(c3);
	server_reset(s);

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick2", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick3", MODE_EMPTY), USER_ERR_NONE);


@@ 794,9 792,6 @@ test_recv_topic(void)
{
	/* :nick!user@host TOPIC <channel> [:topic] */

	channel_reset(c1);
	server_reset(s);

	CHECK_RECV("TOPIC #c1 message", 1, 1, 0);
	assert_strcmp(mock_chan[0], "host");
	assert_strcmp(mock_line[0], "TOPIC: sender's nick is null");


@@ 832,8 827,6 @@ test_recv_ircv3_cap(void)
{
	/* Full IRCv3 CAP coverage in test/handlers/ircv3.c */

	server_reset(s);

	s->registered = 1;

	CHECK_RECV("CAP * LS :cap-1 cap-2 cap-3", 0, 1, 0);


@@ 846,11 839,6 @@ test_recv_ircv3_account(void)
{
	/* :nick!user@host ACCOUNT <account> */

	channel_reset(c1);
	channel_reset(c2);
	channel_reset(c3);
	server_reset(s);

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick2", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c3->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);


@@ 892,11 880,6 @@ test_recv_ircv3_away(void)
{
	/* :nick!user@host AWAY [:message] */

	channel_reset(c1);
	channel_reset(c2);
	channel_reset(c3);
	server_reset(s);

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick2", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c3->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);


@@ 935,11 918,6 @@ test_recv_ircv3_chghost(void)
{
	/* :nick!user@host CHGHOST new_user new_host */

	channel_reset(c1);
	channel_reset(c2);
	channel_reset(c3);
	server_reset(s);

	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c1->users), CASEMAPPING_RFC1459, "nick2", MODE_EMPTY), USER_ERR_NONE);
	assert_eq(user_list_add(&(c3->users), CASEMAPPING_RFC1459, "nick1", MODE_EMPTY), USER_ERR_NONE);


@@ 975,7 953,7 @@ test_recv_ircv3_chghost(void)
static int
test_init(void)
{
	s = server("host", "port", NULL, "user", "real");
	s = server("host", "port", NULL, "user", "real", NULL);

	c1 = channel("#c1", CHANNEL_T_CHANNEL);
	c2 = channel("#c2", CHANNEL_T_CHANNEL);


@@ 1018,6 996,7 @@ main(void)
		TESTCASE(test_irc_generic_ignore),
		TESTCASE(test_irc_generic_info),
		TESTCASE(test_irc_generic_unknown),
		TESTCASE(test_irc_numeric_001),
		TESTCASE(test_irc_numeric_353),
		TESTCASE(test_irc_numeric_401),
		TESTCASE(test_irc_numeric_403),

M test/handlers/irc_send.c => test/handlers/irc_send.c +1 -1
@@ 465,7 465,7 @@ test_send_ircv3_cap_list(void)
static int
test_init(void)
{
	s = server("h1", "p1", NULL, "u1", "r1");
	s = server("h1", "p1", NULL, "u1", "r1", NULL);

	c_serv = s->channel;


M test/handlers/ircv3.c => test/handlers/ircv3.c +1 -1
@@ 598,7 598,7 @@ test_ircv3_cap_req_send(void)
static int
test_init(void)
{
	if (!(s = server("host", "post", NULL, "user", "real")))
	if (!(s = server("host", "post", NULL, "user", "real", NULL)))
		return -1;

	return 0;

M test/state.c => test/state.c +21 -6
@@ 77,8 77,8 @@ test_command_close(void)
	c3 = channel("#c3", CHANNEL_T_CHANNEL);
	c4 = channel("#c4", CHANNEL_T_CHANNEL);
	c5 = channel("#c5", CHANNEL_T_CHANNEL);
	s1 = server("host1", "port1", NULL, "user1", "real1");
	s2 = server("host2", "port2", NULL, "user2", "real2");
	s1 = server("host1", "port1", NULL, "user1", "real1", NULL);
	s2 = server("host2", "port2", NULL, "user2", "real2", NULL);

	if (!s1 || !s2 || !c1 || !c2 || !c3 || !c4 || !c5)
		test_abort("Failed to create servers and channels");


@@ 211,6 211,16 @@ test_command_connect(void)
	assert_strcmp(current_channel()->name, "host-1");
	INP_C(0x0A);

	INP_COMMAND(":connect host -m");
	assert_strcmp(action_message(), "connect: '-m/--mode' requires an argument");
	assert_strcmp(current_channel()->name, "host-1");
	INP_C(0x0A);

	INP_COMMAND(":connect host --mode");
	assert_strcmp(action_message(), "connect: '-m/--mode' requires an argument");
	assert_strcmp(current_channel()->name, "host-1");
	INP_C(0x0A);

	INP_COMMAND(":connect host -n");
	assert_strcmp(action_message(), "connect: '-n/--nicks' requires an argument");
	assert_strcmp(current_channel()->name, "host-1");


@@ 274,8 284,10 @@ test_command_connect(void)

	assert_strcmp(s->host, "host-2");
	assert_strcmp(s->port, "6697");
	assert_ptr_null(s->pass);
	assert_strcmp(s->username, "username");
	assert_strcmp(s->realname, "realname");
	assert_ptr_null(s->mode);
	assert_strcmp(s->nicks.set[0], "n1");
	assert_strcmp(s->nicks.set[1], "n2");
	assert_strcmp(s->nicks.set[2], "n3");


@@ 286,6 298,7 @@ test_command_connect(void)
		" --pass abcdef"
		" --username xxx"
		" --realname yyy"
		" --mode zzz"
		" --nicks x0,y1,z2"
		" --chans #a1,b2,#c3"
		" --ipv4"


@@ 303,8 316,10 @@ test_command_connect(void)

	assert_strcmp(s->host, "host-3");
	assert_strcmp(s->port, "1234");
	assert_strcmp(s->pass, "abcdef");
	assert_strcmp(s->username, "xxx");
	assert_strcmp(s->realname, "yyy");
	assert_strcmp(s->mode, "zzz");
	assert_strcmp(s->nicks.set[0], "x0");
	assert_strcmp(s->nicks.set[1], "y1");
	assert_strcmp(s->nicks.set[2], "z2");


@@ 330,7 345,7 @@ test_command_disconnect(void)
	/* clear error */
	INP_C(0x0A);

	if (!(s = server("host", "port", NULL, "user", "real")))
	if (!(s = server("host", "port", NULL, "user", "real", NULL)))
		test_abort("Failed test setup");

	if (server_list_add(state_server_list(), s))


@@ 422,9 437,9 @@ test_state(void)
	assert_ptr_null(buffer_head(&current_channel()->buffer));

	/* Test adding servers */
	struct server *s1 = server("h1", "p1", NULL, "u1", "r1");
	struct server *s2 = server("h2", "p2", NULL, "u2", "r2");
	struct server *s3 = server("h3", "p3", NULL, "u3", "r3");
	struct server *s1 = server("h1", "p1", NULL, "u1", "r1", NULL);
	struct server *s2 = server("h2", "p2", NULL, "u2", "r2", NULL);
	struct server *s3 = server("h3", "p3", NULL, "u3", "r3", NULL);

	assert_ptr_eq(server_list_add(state_server_list(), s1), NULL);
	assert_ptr_eq(server_list_add(state_server_list(), s2), NULL);