/* * Copyright © 2005-2006 Atheme Development Group * Rights to this code are documented in doc/pod/license.pod. * * Services binary tree manipulation. (add_service, del_service, et al.) */ static char const rcsid[] = "$Id: servtree.C,v 1.6 2007/09/04 11:13:26 pippijn Exp $"; #include "atheme.h" #include service_map services; service_t *fcmd_agent = NULL; static void dummy_handler (sourceinfo_t *si, int parc, char **parv) { } void servtree_init (void) { #if 0 service_heap = BlockHeapCreate (sizeof (service_t), 12); #endif } static void me_me_init (void) { if (me.numeric) init_uid (); me.me = server_add (me.name, 0, NULL, me.numeric ? me.numeric : NULL, me.desc); } service_t * add_service (char const * const name, char const * const user, char const * const host, char const * const real, void (*handler) (sourceinfo_t *si, int parc, char *parv[]), cmdvec &cmdtree) { service_t *sptr; user_t *u; if (me.me == NULL) me_me_init (); if (name == NULL) { slog (LG_INFO, "add_service(): Bad error! We were given a NULL pointer for service name!"); return NULL; } if ((sptr = find_service (name))) { slog (LG_DEBUG, "add_service(): Service `%s' already exists.", name); return NULL; } sptr = new service_t; sptr->name = sstrdup (name); sptr->user = sstrdup (user); sptr->host = sstrdup (host); sptr->real = sstrdup (real); /* Display name, either or @ */ sptr->disp = service_name (name); if (me.numeric && *me.numeric) sptr->uid = sstrdup (uid_get ()); sptr->handler = handler; sptr->notice_handler = dummy_handler; sptr->cmdtree = &cmdtree; if (me.connected) { u = user_find_named (name); if (u != NULL) { phandler->skill (me.name, u->nick, "Nick taken by service"); user_delete (u); } } sptr->me = user_add (name, user, host, NULL, NULL, ircd->uses_uid ? sptr->uid : NULL, real, me.me, NOW); sptr->me->flags |= UF_IRCOP; if (me.connected) { phandler->introduce_nick (sptr->me); /* if the snoop channel already exists, join it now */ if (config_options.chan != NULL && channel_find (config_options.chan) != NULL) join (config_options.chan, name); } services[sptr->name] = sptr; return sptr; } void del_service (service_t *sptr) { services.erase (sptr->name); phandler->quit_sts (sptr->me, "Service unloaded."); user_delete (sptr->me); sptr->me = NULL; sptr->handler = NULL; sfree (sptr->disp); /* service_name() does a salloc() */ sfree (sptr->name); sfree (sptr->user); sfree (sptr->host); sfree (sptr->real); sfree (sptr->uid); delete sptr; } service_t * find_service (char const * const name) { service_t *sptr; service_map::iterator sit; user_t *u; char *p; char name2[NICKLEN]; p = strchr (name, '@'); if (p != NULL) { /* Make sure it's for us, not for a jupe -- jilles */ if (irccasecmp (p + 1, me.name)) return NULL; strlcpy (name2, name, sizeof name2); p = strchr (name2, '@'); if (p != NULL) *p = '\0'; sit = services.find (name2); if (sit != services.end ()) return sit->second; foreach (service_pair &sp, services) { sptr = sp.second; if (sptr->me != NULL && !strcasecmp (name2, sptr->user)) return sptr; } } else { sit = services.find (name); if (sit != services.end ()) return sit->second; if (ircd->uses_uid) { /* yuck yuck -- but quite efficient -- jilles */ u = user_find (name); if (u != NULL && u->server == me.me) return (sit = services.find (u->nick)) == services.end () ? NULL : sit->second; } } return NULL; } char * service_name (char const * const name) { char *buf = salloc (BUFSIZE); snprintf (buf, BUFSIZE, "%s%s%s", name, (config_options.secure) ? "@" : "", (config_options.secure) ? me.name : ""); return buf; }