Index: irc_im.c
===================================================================
--- irc_im.c	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ irc_im.c	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -1014,5 +1014,5 @@
 	if (!(acc = account_get(ic->irc->b, value))) {
 		return SET_INVALID;
-	} else if (!acc->prpl->chat_join) {
+	} else if (!acc->prpl->chat_join && acc->prpl != &protocol_missing) {
 		irc_rootmsg(ic->irc, "Named chatrooms not supported on that account.");
 		return SET_INVALID;
Index: protocols/Makefile
===================================================================
--- protocols/Makefile	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ protocols/Makefile	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -13,5 +13,5 @@
 
 # [SH] Program variables
-objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o unknown.o 
+objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o
 
 
Index: protocols/account.c
===================================================================
--- protocols/account.c	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ protocols/account.c	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -75,4 +75,9 @@
 	s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | ACC_SET_LOCKABLE;
 	set_setstr(&a->set, "username", user);
+
+	if (prpl == &protocol_missing) {
+		s = set_add(&a->set, "server", NULL, set_eval_account, a);
+		s->flags |= SET_NOSAVE | SET_HIDDEN | ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
+	}
 
 	/* Hardcode some more clever tag guesses. */
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ protocols/nogaim.c	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -160,5 +160,4 @@
 GList *protocols = NULL;
 GList *disabled_protocols = NULL;
-static struct prpl *unknown_prpl;
 
 void register_protocol(struct prpl *p)
@@ -190,12 +189,4 @@
 	GList *gl = g_list_find_custom(protocols, name, proto_name_cmp);
 	return gl ? gl->data: NULL;
-}
-
-struct prpl *make_unknown_protocol(const char *name)
-{
-	struct prpl *ret = g_memdup(unknown_prpl, sizeof(struct prpl));
-	ret->name = g_strdup(name);
-	register_protocol(ret);
-	return ret;
 }
 
@@ -250,7 +241,4 @@
 	extern void twitter_initmodule();
 	extern void purple_initmodule();
-	extern void unknown_prpl_initmodule();
-
-	unknown_prpl_initmodule(&unknown_prpl);
 
 #ifdef WITH_MSN
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ protocols/nogaim.h	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -159,7 +159,4 @@
 	/* The protocol is not suitable for OTR, see OPT_NOOTR */
 	PRPL_OPT_NOOTR = 1 << 12,
-
-	/* This prpl is a placeholder for a missing protocol */
-	PRPL_OPT_UNKNOWN_PROTOCOL = 1 << 13,
 } prpl_options_t;
 
@@ -324,5 +321,4 @@
 G_MODULE_EXPORT struct prpl *find_protocol(const char *name);
 G_MODULE_EXPORT gboolean is_protocol_disabled(const char *name);
-G_MODULE_EXPORT struct prpl *make_unknown_protocol(const char *name);
 G_MODULE_EXPORT char *explain_unknown_protocol(const char *name);
 /* When registering a new protocol, you should allocate space for a new prpl
Index: otocols/unknown.c
===================================================================
--- protocols/unknown.c	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ 	(revision )
@@ -1,75 +1,0 @@
-/********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2016 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
-  Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#define BITLBEE_CORE
-#include "nogaim.h"
-
-/* Displays an error when trying to connect this account */
-static void unknown_prpl_login(account_t *acc)
-{
-	struct im_connection *ic = imcb_new(acc);
-	char *msg;
-
-	imcb_error(ic, "Unknown protocol");
-
-	msg = explain_unknown_protocol(acc->prpl->name);
-	imcb_error(ic, "%s", msg);
-	g_free(msg);
-
-	imc_logout(ic, FALSE);
-}
-
-/* Required, no-op */
-static void unknown_prpl_logout(struct im_connection *ic)
-{
-}
-
-/* Needed to ensure the server setting is preserved */
-static void unknown_prpl_init(account_t *acc)
-{
-	set_t *s;
-
-	s = set_add(&acc->set, "server", NULL, set_eval_account, acc);
-	s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK;
-}
-
-/* Needed to silence warnings about named groupchats not supported */
-struct groupchat *unknown_prpl_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password,
-                                         set_t **sets)
-{
-	return NULL;
-}
-
-void unknown_prpl_initmodule(struct prpl **prpl)
-{
-	struct prpl *ret = g_new0(struct prpl, 1);
-
-	ret->name = "unknown";
-	ret->options = PRPL_OPT_UNKNOWN_PROTOCOL | PRPL_OPT_NOOTR;
-	ret->login = unknown_prpl_login;
-	ret->logout = unknown_prpl_logout;
-	ret->init = unknown_prpl_init;
-	ret->chat_join = unknown_prpl_chat_join;
-	*prpl = ret;
-}
-
Index: root_commands.c
===================================================================
--- root_commands.c	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ root_commands.c	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -498,5 +498,5 @@
 
 		for (a = irc->b->accounts; a; a = a->next) {
-			char *con;
+			char *con = NULL, *protocol = NULL;
 
 			if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) {
@@ -510,5 +510,12 @@
 			}
 
-			irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con);
+			if (a->prpl == &protocol_missing) {
+				protocol = g_strdup_printf("%s (missing!)", set_getstr(&a->set, "_protocol_name"));
+			} else {
+				protocol = g_strdup(a->prpl->name);
+			}
+
+			irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, protocol, a->user, con);
+			g_free(protocol);
 
 			i++;
@@ -524,5 +531,5 @@
 
 			for (a = irc->b->accounts; a; a = a->next) {
-				if (!a->ic && a->auto_connect) {
+				if (!a->ic && a->auto_connect && a->prpl != &protocol_missing) {
 					if (strcmp(a->pass, PASSWORD_PENDING) == 0) {
 						irc_rootmsg(irc, "Enter password for account %s "
@@ -584,4 +591,10 @@
 			irc_rootmsg(irc, "Enter password for account %s "
 			            "first (use /OPER)", a->tag);
+		} else if (a->prpl == &protocol_missing) {
+			char *proto = set_getstr(&a->set, "_protocol_name");
+			char *msg = explain_unknown_protocol(proto);
+			irc_rootmsg(irc, "Unknown protocol `%s'", proto);
+			irc_rootmsg(irc, msg);
+			g_free(msg);
 		} else {
 			account_on(irc->b, a);
Index: storage.c
===================================================================
--- storage.c	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ storage.c	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -32,4 +32,8 @@
 
 static GList *storage_backends = NULL;
+
+const struct prpl protocol_missing = {
+	.name = "_unknown",
+};
 
 void register_storage_backend(storage_t *backend)
Index: storage.h
===================================================================
--- storage.h	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ storage.h	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -63,3 +63,5 @@
 G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate);
 
+extern const struct prpl protocol_missing;
+
 #endif /* __STORAGE_H__ */
Index: storage_xml.c
===================================================================
--- storage_xml.c	(revision 11d4123fe9a4d88d475bee6c623fb80af8fdbb0b)
+++ storage_xml.c	(revision 5a8afc3f24a5308799d3960cab5726228345022d)
@@ -60,5 +60,5 @@
 }
 
-static void handle_settings(struct xt_node *node, set_t **head, gboolean add_unknowns)
+static void handle_settings(struct xt_node *node, set_t **head)
 {
 	struct xt_node *c;
@@ -70,11 +70,4 @@
 
 		if (!name) {
-			continue;
-		}
-
-		if (add_unknowns && !set_find(head, name)) {
-			s = set_add(head, name, NULL, NULL, NULL);
-			s->flags |= ACC_SET_ONLINE_ONLY;
-			s->value = g_strdup(c->text);
 			continue;
 		}
@@ -93,4 +86,23 @@
 			}
 		}
+	}
+}
+
+/* Use for unsupported/not-found protocols. Save settings as-is but don't allow changes. */
+static void handle_settings_raw(struct xt_node *node, set_t **head)
+{
+	struct xt_node *c;
+
+	for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) {
+		char *name = xt_find_attr(c, "name");
+
+		if (!name) {
+			continue;
+		}
+
+		set_t *s = set_add(head, name, NULL, NULL, NULL);
+		set_setstr(head, name, c->text);
+		s->flags |= SET_HIDDEN |
+		            ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
 	}
 }
@@ -106,5 +118,4 @@
 	account_t *acc;
 	struct xt_node *c;
-	gboolean is_unknown = FALSE;
 
 	handle = xt_find_attr(node, "handle");
@@ -120,7 +131,6 @@
 		if (!prpl) {
 			irc_rootmsg(xd->irc, "Warning: Protocol not found: `%s'", protocol);
-			prpl = make_unknown_protocol(protocol);
-		}
-		is_unknown = (prpl->options & PRPL_OPT_UNKNOWN_PROTOCOL) != 0;
+			prpl = (struct prpl*) &protocol_missing;
+		}
 		local = protocol_account_islocal(protocol);
 	}
@@ -158,9 +168,18 @@
 		acc->flags |= ACC_FLAG_LOCKED;
 	}
+	if (prpl == &protocol_missing) {
+		set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL);
+		s->flags |= SET_HIDDEN | SET_NOSAVE |
+			    ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
+	}
 
 	g_free(pass_cr);
 	g_free(password);
 
-	handle_settings(node, &acc->set, is_unknown);
+	if (prpl == &protocol_missing) {
+		handle_settings_raw(node, &acc->set);
+	} else {
+		handle_settings(node, &acc->set);
+	}
 
 	for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) {
@@ -201,5 +220,5 @@
 	}
 
-	handle_settings(node, &ic->set, FALSE);
+	handle_settings(node, &ic->set);
 
 	return XT_HANDLED;
@@ -279,5 +298,5 @@
 	}
 
-	handle_settings(node, &xd->irc->b->set, FALSE);
+	handle_settings(node, &xd->irc->b->set);
 
 error:
@@ -351,5 +370,9 @@
 
 		cur = xt_new_node("account", NULL, NULL);
-		xt_add_attr(cur, "protocol", acc->prpl->name);
+		if (acc->prpl == &protocol_missing) {
+			xt_add_attr(cur, "protocol", set_getstr(&acc->set, "_protocol_name"));
+		} else {
+			xt_add_attr(cur, "protocol", acc->prpl->name);
+		}
 		xt_add_attr(cur, "handle", acc->user);
 		xt_add_attr(cur, "password", pass_b64);
