+/*
+Some hooks you can call from modpython.py to interact with the
+service. These emb_* functions are available as _svc.* in python. */
+
+struct _tuple_dict_extra {
+ PyObject* data;
+ size_t* extra;
+};
+
+static void pyobj_release_tuple(PyObject* tuple, size_t n) {
+ size_t i;
+
+ if (tuple == NULL)
+ return;
+
+ for (i = 0; i < n; ++i)
+ Py_XDECREF(PyTuple_GET_ITEM(tuple, i));
+
+ Py_XDECREF(tuple);
+}
+
+static int _dict_iter_fill_tuple(char const* key, UNUSED_ARG(void* data), void* extra) {
+ PyObject* tmp;
+ struct _tuple_dict_extra* real_extra = (struct _tuple_dict_extra*)extra;
+
+ if ((tmp = PyString_FromString(key)) == NULL)
+ return 1;
+
+ if (PyTuple_SetItem(real_extra->data, *(int*)real_extra->extra, tmp)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
+
+ *real_extra->extra = *real_extra->extra + 1;
+ return 0;
+}
+
+static PyObject*
+pyobj_from_dict_t(dict_t d) {
+ PyObject* retval;
+ size_t n = 0;
+ struct _tuple_dict_extra extra;
+
+ if ((retval = PyTuple_New(dict_size(d))) == NULL)
+ return NULL;
+
+ extra.extra = &n;
+ extra.data = retval;
+
+ if (dict_foreach(d, _dict_iter_fill_tuple, (void*)&extra) != NULL) {
+ pyobj_release_tuple(retval, n);
+ return NULL;
+ }
+
+ return retval;
+}
+
+/* get a tuple with all users in it */
+static PyObject*
+emb_get_users(UNUSED_ARG(PyObject *self), PyObject *args) {
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ return pyobj_from_dict_t(clients);
+}
+
+/* get a tuple with all channels in it */
+static PyObject*
+emb_get_channels(UNUSED_ARG(PyObject* self), PyObject* args) {
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ return pyobj_from_dict_t(channels);
+}
+
+static PyObject*
+emb_get_servers(UNUSED_ARG(PyObject* self), PyObject* args) {
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ return pyobj_from_dict_t(servers);
+}
+
+static PyObject*
+emb_get_accounts(UNUSED_ARG(PyObject* self), PyObject* args) {
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ return pyobj_from_dict_t(nickserv_handle_dict);
+}