about summary refs log tree commit diff stats
path: root/src/command/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/command/command.c')
-rw-r--r--src/command/command.c411
1 files changed, 320 insertions, 91 deletions
diff --git a/src/command/command.c b/src/command/command.c
index 1ac87374..906f2708 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -137,6 +137,11 @@ GHashTable *commands = NULL;
 #define CMD_TAG_UI          "ui"
 #define CMD_TAG_PLUGINS     "plugins"
 
+#define CMD_MAINFUNC(func)  func,
+#define CMD_NOMAINFUNC      NULL,
+#define CMD_SUBFUNCS(...)   { __VA_ARGS__, { NULL, NULL } },
+#define CMD_NOSUBFUNCS      { { NULL, NULL } },
+
 #define CMD_NOTAGS          { { NULL },
 #define CMD_TAGS(...)       { { __VA_ARGS__, NULL },
 #define CMD_SYN(...)        { __VA_ARGS__, NULL },
@@ -152,7 +157,9 @@ GHashTable *commands = NULL;
 static struct cmd_t command_defs[] =
 {
     { "/help",
-        cmd_help, parse_args, 0, 2, NULL,
+        parse_args, 0, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_help)
         CMD_NOTAGS
         CMD_SYN(
             "/help [<area>|<command>]")
@@ -173,7 +180,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/about",
-        cmd_about, parse_args, 0, 0, NULL,
+        parse_args, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_about)
         CMD_NOTAGS
         CMD_SYN(
             "/about")
@@ -184,7 +193,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/connect",
-        cmd_connect, parse_args, 0, 7, NULL,
+        parse_args, 0, 7, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_connect)
         CMD_TAGS(
             CMD_TAG_CONNECTION)
         CMD_SYN(
@@ -211,7 +222,15 @@ static struct cmd_t command_defs[] =
         },
 
     { "/tls",
-        cmd_tls, parse_args, 1, 3, NULL,
+        parse_args, 1, 3, NULL,
+        CMD_SUBFUNCS(
+            { "certpath",   cmd_tls_certpath },
+            { "trust",      cmd_tls_trust },
+            { "trusted",    cmd_tls_trusted },
+            { "revoke",     cmd_tls_revoke },
+            { "show",       cmd_tls_show },
+            { "cert",       cmd_tls_cert })
+        CMD_NOMAINFUNC
         CMD_TAGS(
             CMD_TAG_CONNECTION,
             CMD_TAG_UI)
@@ -246,7 +265,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/disconnect",
-        cmd_disconnect, parse_args, 0, 0, NULL,
+        parse_args, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_disconnect)
         CMD_TAGS(
             CMD_TAG_CONNECTION)
         CMD_SYN(
@@ -258,7 +279,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/msg",
-        cmd_msg, parse_args_with_freetext, 1, 2, NULL,
+        parse_args_with_freetext, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_msg)
         CMD_TAGS(
             CMD_TAG_CHAT)
         CMD_SYN(
@@ -281,7 +304,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/roster",
-        cmd_roster, parse_args_with_freetext, 0, 4, NULL,
+        parse_args_with_freetext, 0, 4, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_roster)
         CMD_TAGS(
             CMD_TAG_ROSTER,
             CMD_TAG_UI)
@@ -399,7 +424,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/group",
-        cmd_group, parse_args_with_freetext, 0, 3, NULL,
+        parse_args_with_freetext, 0, 3, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_group)
         CMD_TAGS(
             CMD_TAG_ROSTER,
             CMD_TAG_UI)
@@ -424,7 +451,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/info",
-        cmd_info, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_info)
         CMD_TAGS(
             CMD_TAG_ROSTER,
             CMD_TAG_CHAT,
@@ -445,7 +474,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/caps",
-        cmd_caps, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_caps)
         CMD_TAGS(
             CMD_TAG_DISCOVERY,
             CMD_TAG_CHAT,
@@ -466,7 +497,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/software",
-        cmd_software, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_software)
         CMD_TAGS(
             CMD_TAG_DISCOVERY,
             CMD_TAG_CHAT,
@@ -488,7 +521,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/status",
-        cmd_status, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_status)
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_GROUPCHAT)
@@ -507,7 +542,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/resource",
-        cmd_resource, parse_args, 1, 2, &cons_resource_setting,
+        parse_args, 1, 2, &cons_resource_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_resource)
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_UI)
@@ -527,7 +564,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/join",
-        cmd_join, parse_args, 0, 5, NULL,
+        parse_args, 0, 5, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_join)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -552,7 +591,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/leave",
-        cmd_leave, parse_args, 0, 0, NULL,
+        parse_args, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_leave)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -564,7 +605,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/invite",
-        cmd_invite, parse_args_with_freetext, 1, 2, NULL,
+        parse_args_with_freetext, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_invite)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -578,7 +621,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/invites",
-        cmd_invites, parse_args_with_freetext, 0, 0, NULL,
+        parse_args_with_freetext, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_invites)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -590,7 +635,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/decline",
-        cmd_decline, parse_args_with_freetext, 1, 1, NULL,
+        parse_args_with_freetext, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_decline)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -603,7 +650,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/room",
-        cmd_room, parse_args, 1, 1, NULL,
+        parse_args, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_room)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -618,7 +667,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/kick",
-        cmd_kick, parse_args_with_freetext, 1, 2, NULL,
+        parse_args_with_freetext, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_kick)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -632,7 +683,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/ban",
-        cmd_ban, parse_args_with_freetext, 1, 2, NULL,
+        parse_args_with_freetext, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_ban)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -646,7 +699,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/subject",
-        cmd_subject, parse_args_with_freetext, 0, 2, NULL,
+        parse_args_with_freetext, 0, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_subject)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -667,7 +722,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/affiliation",
-        cmd_affiliation, parse_args_with_freetext, 1, 4, NULL,
+        parse_args_with_freetext, 1, 4, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_affiliation)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -683,7 +740,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/role",
-        cmd_role, parse_args_with_freetext, 1, 4, NULL,
+        parse_args_with_freetext, 1, 4, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_role)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -699,7 +758,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/occupants",
-        cmd_occupants, parse_args, 1, 3, cons_occupants_setting,
+        parse_args, 1, 3, cons_occupants_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_occupants)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT,
             CMD_TAG_UI)
@@ -721,7 +782,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/form",
-        cmd_form, parse_args, 1, 2, NULL,
+        parse_args, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_form)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -740,7 +803,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/rooms",
-        cmd_rooms, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_rooms)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -755,7 +820,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/bookmark",
-        cmd_bookmark, parse_args, 0, 8, NULL,
+        parse_args, 0, 8, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_bookmark)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -781,7 +848,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/disco",
-        cmd_disco, parse_args, 1, 2, NULL,
+        parse_args, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_disco)
         CMD_TAGS(
             CMD_TAG_DISCOVERY)
         CMD_SYN(
@@ -801,7 +870,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/sendfile",
-        cmd_sendfile, parse_args_with_freetext, 1, 1, NULL,
+        parse_args_with_freetext, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_sendfile)
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_GROUPCHAT)
@@ -817,7 +888,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/lastactivity",
-        cmd_lastactivity, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_lastactivity)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -837,7 +910,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/nick",
-        cmd_nick, parse_args_with_freetext, 1, 1, NULL,
+        parse_args_with_freetext, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_nick)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -850,7 +925,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/win",
-        cmd_win, parse_args, 1, 1, NULL,
+        parse_args, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_win)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -881,7 +958,14 @@ static struct cmd_t command_defs[] =
     },
 
     { "/wins",
-        cmd_wins, parse_args, 0, 3, NULL,
+        parse_args, 0, 3, NULL,
+        CMD_SUBFUNCS(
+            { "unread",     cmd_wins_unread },
+            { "tidy",       cmd_wins_tidy },
+            { "prune",      cmd_wins_prune },
+            { "swap",       cmd_wins_swap },
+            { "autotidy",   cmd_wins_autotidy })
+        CMD_MAINFUNC(cmd_wins)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -904,7 +988,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/sub",
-        cmd_sub, parse_args, 1, 2, NULL,
+        parse_args, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_sub)
         CMD_TAGS(
             CMD_TAG_ROSTER)
         CMD_SYN(
@@ -932,7 +1018,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/tiny",
-        cmd_tiny, parse_args, 1, 1, NULL,
+        parse_args, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_tiny)
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_GROUPCHAT)
@@ -947,7 +1035,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/who",
-        cmd_who, parse_args, 0, 2, NULL,
+        parse_args, 0, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_who)
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_GROUPCHAT,
@@ -978,7 +1068,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/close",
-        cmd_close, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_close)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1006,7 +1098,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/clear",
-        cmd_clear, parse_args, 0, 0, NULL,
+        parse_args, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_clear)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1018,7 +1112,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/quit",
-        cmd_quit, parse_args, 0, 0, NULL,
+        parse_args, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_quit)
         CMD_NOTAGS
         CMD_SYN(
             "/quit")
@@ -1029,7 +1125,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/privileges",
-        cmd_privileges, parse_args, 1, 1, &cons_privileges_setting,
+        parse_args, 1, 1, &cons_privileges_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_privileges)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT,
             CMD_TAG_UI)
@@ -1043,7 +1141,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/charset",
-        cmd_charset, parse_args, 0, 0, NULL,
+        parse_args, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_charset)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1055,7 +1155,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/beep",
-        cmd_beep, parse_args, 1, 1, &cons_beep_setting,
+        parse_args, 1, 1, &cons_beep_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_beep)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1070,7 +1172,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/console",
-        cmd_console, parse_args, 2, 2, &cons_console_setting,
+        parse_args, 2, 2, &cons_console_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_console)
         CMD_TAGS(
             CMD_TAG_UI,
             CMD_TAG_CHAT,
@@ -1096,7 +1200,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/encwarn",
-        cmd_encwarn, parse_args, 1, 1, &cons_encwarn_setting,
+        parse_args, 1, 1, &cons_encwarn_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_encwarn)
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_UI)
@@ -1110,7 +1216,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/presence",
-        cmd_presence, parse_args, 1, 1, &cons_presence_setting,
+        parse_args, 1, 1, &cons_presence_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_presence)
         CMD_TAGS(
             CMD_TAG_UI,
             CMD_TAG_CHAT)
@@ -1124,7 +1232,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/wrap",
-        cmd_wrap, parse_args, 1, 1, &cons_wrap_setting,
+        parse_args, 1, 1, &cons_wrap_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_wrap)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1137,7 +1247,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/time",
-        cmd_time, parse_args, 1, 3, &cons_time_setting,
+        parse_args, 1, 3, &cons_time_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_time)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1177,7 +1289,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/inpblock",
-        cmd_inpblock, parse_args, 2, 2, &cons_inpblock_setting,
+        parse_args, 2, 2, &cons_inpblock_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_inpblock)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1192,7 +1306,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/notify",
-        cmd_notify, parse_args_with_freetext, 0, 4, NULL,
+        parse_args_with_freetext, 0, 4, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_notify)
         CMD_TAGS(
             CMD_TAG_UI,
             CMD_TAG_CHAT,
@@ -1261,7 +1377,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/flash",
-        cmd_flash, parse_args, 1, 1, &cons_flash_setting,
+        parse_args, 1, 1, &cons_flash_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_flash)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1275,7 +1393,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/tray",
-        cmd_tray, parse_args, 1, 1, &cons_tray_setting,
+        parse_args, 1, 1, &cons_tray_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_tray)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1288,7 +1408,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/intype",
-        cmd_intype, parse_args, 1, 1, &cons_intype_setting,
+        parse_args, 1, 1, &cons_intype_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_intype)
         CMD_TAGS(
             CMD_TAG_UI,
             CMD_TAG_CHAT)
@@ -1302,7 +1424,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/splash",
-        cmd_splash, parse_args, 1, 1, &cons_splash_setting,
+        parse_args, 1, 1, &cons_splash_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_splash)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1315,7 +1439,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/autoconnect",
-        cmd_autoconnect, parse_args, 1, 2, &cons_autoconnect_setting,
+        parse_args, 1, 2, &cons_autoconnect_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_autoconnect)
         CMD_TAGS(
             CMD_TAG_CONNECTION)
         CMD_SYN(
@@ -1333,7 +1459,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/vercheck",
-        cmd_vercheck, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_vercheck)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1346,7 +1474,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/titlebar",
-        cmd_titlebar, parse_args, 2, 2, &cons_titlebar_setting,
+        parse_args, 2, 2, &cons_titlebar_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_titlebar)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1361,7 +1491,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/alias",
-        cmd_alias, parse_args_with_freetext, 1, 3, NULL,
+        parse_args_with_freetext, 1, 3, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_alias)
         CMD_NOTAGS
         CMD_SYN(
             "/alias list",
@@ -1382,7 +1514,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/chlog",
-        cmd_chlog, parse_args, 1, 1, &cons_chlog_setting,
+        parse_args, 1, 1, &cons_chlog_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_chlog)
         CMD_TAGS(
             CMD_TAG_CHAT)
         CMD_SYN(
@@ -1398,7 +1532,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/grlog",
-        cmd_grlog, parse_args, 1, 1, &cons_grlog_setting,
+        parse_args, 1, 1, &cons_grlog_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_grlog)
         CMD_TAGS(
             CMD_TAG_GROUPCHAT)
         CMD_SYN(
@@ -1412,7 +1548,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/states",
-        cmd_states, parse_args, 1, 1, &cons_states_setting,
+        parse_args, 1, 1, &cons_states_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_states)
         CMD_TAGS(
             CMD_TAG_CHAT)
         CMD_SYN(
@@ -1425,7 +1563,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/pgp",
-        cmd_pgp, parse_args, 1, 3, NULL,
+        parse_args, 1, 3, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_pgp)
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_UI)
@@ -1460,7 +1600,23 @@ static struct cmd_t command_defs[] =
     },
 
     { "/otr",
-        cmd_otr, parse_args, 1, 3, NULL,
+        parse_args, 1, 3, NULL,
+        CMD_SUBFUNCS(
+            { "char",       cmd_otr_char },
+            { "log",        cmd_otr_log },
+            { "libver",     cmd_otr_libver },
+            { "policy",     cmd_otr_policy },
+            { "gen",        cmd_otr_gen },
+            { "myfp",       cmd_otr_myfp },
+            { "theirfp",    cmd_otr_theirfp },
+            { "start",      cmd_otr_start },
+            { "end",        cmd_otr_end },
+            { "trust",      cmd_otr_trust },
+            { "untrust",    cmd_otr_untrust },
+            { "secret",     cmd_otr_secret },
+            { "question",   cmd_otr_question },
+            { "answer",     cmd_otr_answer })
+        CMD_NOMAINFUNC
         CMD_TAGS(
             CMD_TAG_CHAT,
             CMD_TAG_UI)
@@ -1513,7 +1669,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/outtype",
-        cmd_outtype, parse_args, 1, 1, &cons_outtype_setting,
+        parse_args, 1, 1, &cons_outtype_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_outtype)
         CMD_TAGS(
             CMD_TAG_CHAT)
         CMD_SYN(
@@ -1526,7 +1684,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/gone",
-        cmd_gone, parse_args, 1, 1, &cons_gone_setting,
+        parse_args, 1, 1, &cons_gone_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_gone)
         CMD_TAGS(
             CMD_TAG_CHAT)
         CMD_SYN(
@@ -1540,7 +1700,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/history",
-        cmd_history, parse_args, 1, 1, &cons_history_setting,
+        parse_args, 1, 1, &cons_history_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_history)
         CMD_TAGS(
             CMD_TAG_UI,
             CMD_TAG_CHAT)
@@ -1555,7 +1717,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/log",
-        cmd_log, parse_args, 1, 2, &cons_log_setting,
+        parse_args, 1, 2, &cons_log_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_log)
         CMD_NOTAGS
         CMD_SYN(
             "/log where",
@@ -1573,7 +1737,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/carbons",
-        cmd_carbons, parse_args, 1, 1, &cons_carbons_setting,
+        parse_args, 1, 1, &cons_carbons_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_carbons)
         CMD_TAGS(
             CMD_TAG_CHAT)
         CMD_SYN(
@@ -1587,7 +1753,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/receipts",
-        cmd_receipts, parse_args, 2, 2, &cons_receipts_setting,
+        parse_args, 2, 2, &cons_receipts_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_receipts)
         CMD_TAGS(
             CMD_TAG_CHAT)
         CMD_SYN(
@@ -1602,7 +1770,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/reconnect",
-        cmd_reconnect, parse_args, 1, 1, &cons_reconnect_setting,
+        parse_args, 1, 1, &cons_reconnect_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_reconnect)
         CMD_TAGS(
             CMD_TAG_CONNECTION)
         CMD_SYN(
@@ -1615,7 +1785,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/autoping",
-        cmd_autoping, parse_args, 2, 2, &cons_autoping_setting,
+        parse_args, 2, 2, &cons_autoping_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_autoping)
         CMD_TAGS(
             CMD_TAG_CONNECTION)
         CMD_SYN(
@@ -1630,7 +1802,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/ping",
-        cmd_ping, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_ping)
         CMD_TAGS(
             CMD_TAG_CONNECTION)
         CMD_SYN(
@@ -1644,7 +1818,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/autoaway",
-        cmd_autoaway, parse_args_with_freetext, 2, 3, &cons_autoaway_setting,
+        parse_args_with_freetext, 2, 3, &cons_autoaway_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_autoaway)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -1675,7 +1851,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/priority",
-        cmd_priority, parse_args, 1, 1, NULL,
+        parse_args, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_priority)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -1689,7 +1867,19 @@ static struct cmd_t command_defs[] =
     },
 
     { "/account",
-        cmd_account, parse_args, 0, 4, NULL,
+        parse_args, 0, 4, NULL,
+        CMD_SUBFUNCS(
+            { "list",       cmd_account_list },
+            { "show",       cmd_account_show },
+            { "add",        cmd_account_add },
+            { "remove",     cmd_account_remove },
+            { "enable",     cmd_account_enable },
+            { "disable",    cmd_account_disable },
+            { "rename",     cmd_account_rename },
+            { "default",    cmd_account_default },
+            { "set",        cmd_account_set },
+            { "clear",      cmd_account_clear })
+        CMD_MAINFUNC(cmd_account)
         CMD_TAGS(
             CMD_TAG_CONNECTION
             CMD_TAG_PRESENCE,
@@ -1780,7 +1970,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/plugins",
-        cmd_plugins, parse_args, 0, 2, NULL,
+        parse_args, 0, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_plugins)
         CMD_NOTAGS
         CMD_SYN(
             "/plugins",
@@ -1794,7 +1986,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/prefs",
-        cmd_prefs, parse_args, 0, 1, NULL,
+        parse_args, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_prefs)
         CMD_NOTAGS
         CMD_SYN(
             "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp]")
@@ -1814,7 +2008,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/theme",
-        cmd_theme, parse_args, 1, 2, &cons_theme_setting,
+        parse_args, 1, 2, &cons_theme_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_theme)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1835,7 +2031,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/statuses",
-        cmd_statuses, parse_args, 2, 2, &cons_statuses_setting,
+        parse_args, 2, 2, &cons_statuses_setting,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_statuses)
         CMD_TAGS(
             CMD_TAG_UI,
             CMD_TAG_CHAT,
@@ -1859,7 +2057,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/xmlconsole",
-        cmd_xmlconsole, parse_args, 0, 0, NULL,
+        parse_args, 0, 0, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_xmlconsole)
         CMD_TAGS(
             CMD_TAG_UI)
         CMD_SYN(
@@ -1871,7 +2071,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/away",
-        cmd_away, parse_args_with_freetext, 0, 1, NULL,
+        parse_args_with_freetext, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_away)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -1886,7 +2088,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/chat",
-        cmd_chat, parse_args_with_freetext, 0, 1, NULL,
+        parse_args_with_freetext, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_chat)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -1901,7 +2105,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/dnd",
-        cmd_dnd, parse_args_with_freetext, 0, 1, NULL,
+        parse_args_with_freetext, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_dnd)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -1916,7 +2122,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/online",
-        cmd_online, parse_args_with_freetext, 0, 1, NULL,
+        parse_args_with_freetext, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_online)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -1931,7 +2139,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/xa",
-        cmd_xa, parse_args_with_freetext, 0, 1, NULL,
+        parse_args_with_freetext, 0, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_xa)
         CMD_TAGS(
             CMD_TAG_PRESENCE)
         CMD_SYN(
@@ -1946,7 +2156,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/script",
-        cmd_script, parse_args, 1, 2, NULL,
+        parse_args, 1, 2, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_script)
         CMD_NOTAGS
         CMD_SYN(
             "/script run <script>",
@@ -1966,7 +2178,9 @@ static struct cmd_t command_defs[] =
     },
 
     { "/export",
-        cmd_export, parse_args, 1, 1, NULL,
+        parse_args, 1, 1, NULL,
+        CMD_NOSUBFUNCS
+        CMD_MAINFUNC(cmd_export)
         CMD_NOTAGS
         CMD_SYN(
             "/export <filepath>")
@@ -3073,11 +3287,26 @@ _cmd_execute(ProfWin *window, const char *const command, const char *const inp)
         if (result == FALSE) {
             ui_invalid_command_usage(cmd->cmd, cmd->setting_func);
             return TRUE;
-        } else {
-            gboolean result = cmd->func(window, command, args);
-            g_strfreev(args);
-            return result;
         }
+        if (args[0] && cmd->sub_funcs) {
+            int i = 0;
+            while (cmd->sub_funcs[i][0]) {
+                if (g_strcmp0(args[0], (char*)cmd->sub_funcs[i][0]) == 0) {
+                    gboolean (*func)(ProfWin *window, const char *const command, gchar **args) = cmd->sub_funcs[i][1];
+                    gboolean result = func(window, command, args);
+                    g_strfreev(args);
+                    return result;
+                }
+                i++;
+            }
+        }
+        if (!cmd->func) {
+            ui_invalid_command_usage(cmd->cmd, cmd->setting_func);
+            return TRUE;
+        }
+        gboolean result = cmd->func(window, command, args);
+        g_strfreev(args);
+        return result;
     } else if (plugins_run_command(inp)) {
         return TRUE;
     } else {