Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

plugins.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou 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.
 *
 *  lebiniou 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
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "plugins.h"
#include "brandom.h"
#include "constants.h"
#include "biniou.h"


Plugins_t *
Plugins_new(const char *path)
{
  Plugins_t *p = NULL;

  if (NULL == path)
    path = ".";

  p = xcalloc(1, sizeof(Plugins_t));

  p->path = strdup(path);
  p->plugins = NULL;
  p->size = 0;
  p->selected_idx = 0;
  p->selected = NULL;

  return p;
}


void
Plugins_delete(Plugins_t *p)
{
  short i;

  for (i = 0; i < p->size; i++)
    Plugin_delete(p->plugins[i]);
  xfree(p->plugins);
  xfree(p->path);
  xfree(p);
}


void
Plugins_init(Plugins_t *ps)
{
  short i;

  if (libbiniou_verbose)
    printf("[+] Initializing %d plugin%c\n", ps->size, (ps->size == 1) ? ' ' : 's');
  for (i = 0; i < ps->size; i++) {
    Plugin_t *p = ps->plugins[i];
    u_short t;

    Plugin_init(p);
        
    /* re-adjust on-boot B_DISABLED plugins */
    for (t = 0; t < MAX_TYPES; t++)
      if (*p->options & (1 << t))
      if (*p->options & BEQ_DISABLED)
        if (pTypes[t].count > 0) /* XXX should not need this test */
          pTypes[t].count--;
  }
}


/*
 * Check if a directory is a plugin directory.
 * Convention is that you MUST name your .so and directory
 * with your plugin name. eg: you have a plugin called Foo.
 * It MUST be in /path/to/plugins/Foo/
 * This directory MUST contain /path/to/plugins/Foo/Foo.so
 */
static int
isPluginDir(const char *dir, const char *name)
{
  struct stat istics;
  int rc = -1;
  char *soname = NULL;

  if (name[0] == '.')
    return 0;

  /* XXX hardcoded main */
  soname = g_strdup_printf("%s/main/%s/%s.so", dir, name, name);
      
  rc = stat(soname, &istics);
  g_free(soname);
  if (rc == -1)
    return 0;

  return ((rc == 0) && S_ISREG(istics.st_mode));
}


void
Plugins_select(Plugins_t *ps, const Plugin_t *p)
{
  short i;

  for (i = 0; i < ps->size; i++) {
    if (ps->plugins[i] == p) {
      ps->selected_idx = i;
      ps->selected = (Plugin_t *)p;
      return;
    }
  }

  xerror("Plugins_select failed");
}


static int
Plugins_compare(const void *_p0, const void *_p1)
{
  const Plugin_t **p0, **p1;

  p0 = (const Plugin_t **)(_p0);
  p1 = (const Plugin_t **)(_p1);

  return strcasecmp((*p0)->dname, (*p1)->dname);
}


void
Plugins_load(Plugins_t *ps)
{
  DIR *da_dir;
  struct dirent *da_ent;
  int i;
  gchar *blah;

  /* XXX hardcoded main */
  blah = g_strdup_printf("%s/main", ps->path);
  if (libbiniou_verbose)
    printf("[i] Loading plugins from %s\n", blah);

  if ((da_dir = opendir(blah)) == NULL)
    xperror("opendir");

  g_free(blah);
  while ((da_ent = readdir(da_dir)) != NULL)
    if (isPluginDir(ps->path, da_ent->d_name))
      ps->size++;
  
  if (!ps->size)
    xerror("Won't do anything without a plugin, stupid\n");
  ps->plugins = xcalloc(ps->size, sizeof(Plugin_t *));

  rewinddir(da_dir);
  i = 0;

  while ((da_ent = readdir(da_dir)) != NULL) {
    Plugin_t *p;
    u_char t;
    int j;
    const char *name = da_ent->d_name;

    if (!isPluginDir(ps->path, name))
      continue;

    /* load the plugin */
    p = ps->plugins[i] = Plugin_new(ps->path, name, PL_MAIN);
    if (libbiniou_verbose) {
      if (NULL != p->desc)
      printf("        %s\n", p->desc);
      else
      printf("!!! FIXME: %s has no description\n", name);
    }

    for (j = 0; j < i; j++)
      if (p->id == ps->plugins[j]->id)
      xerror("Duplicated plugin id: %li\n", p->id);

    /* plugin types stuff */
    for (t = 0; t < MAX_TYPES; t++)
      if (*p->options & (1 << t)) {
#ifdef XDEBUG
      printf("[T] Has type %s\n", pTypes[t].name);
#endif
      if (!(*p->options & BEQ_NORANDOM))
        pTypes[t].count++;
      }
#ifdef XDEBUG
    printf("\n");
#endif
    i++;
  }
  closedir(da_dir);

  /* sort the plugins array */
  qsort((void *)ps->plugins, (size_t)ps->size,
      (size_t)sizeof(Plugin_t *), &Plugins_compare);

  if (libbiniou_verbose)
    printf("[+] Loaded %d plugin%c\n", ps->size, (ps->size == 1 ? ' ' : 's'));

  Plugins_select(ps, ps->plugins[0]);
}


Plugin_t *
Plugins_find(const u_long id)
{
  short i;

  for (i = 0; i < plugins->size; i++)
    if (plugins->plugins[i]->id == id)
      return plugins->plugins[i];

  return NULL;
}


Plugin_t *
Plugins_get_random(const enum PluginOptions feat)
{
  int i;
  u_short rand = 0;

  /* check if we can select at random or not */
  for (i = 0; i < MAX_TYPES; i++)
    if (pTypes[i].count && ((1 << i) & feat))
      break;
  
  if (i == MAX_TYPES) {
    /* TODO option_to_string */
    /* printf("[!] Failed to find plugin with feature %d\n", feat); */
    return NULL;
  }
  // else printf("pTypes[%d].count= %d\n", i, pTypes[i].count);

  do {
    rand = b_rand_int_range(0, plugins->size);
  } while (!(*plugins->plugins[rand]->options & feat)
         || (*plugins->plugins[rand]->options & BEQ_NORANDOM)
         || (*plugins->plugins[rand]->options & BEQ_DISABLED));

  return plugins->plugins[rand];
}


void
Plugins_next()
{
  do {
    if (++plugins->selected_idx == plugins->size)
      plugins->selected_idx = 0;
    plugins->selected = plugins->plugins[plugins->selected_idx];
  } while (*plugins->selected->options & BEQ_DISABLED);
}


void
Plugins_prev()
{
  do {
    if (--plugins->selected_idx == -1)
      plugins->selected_idx = plugins->size-1;
    plugins->selected = plugins->plugins[plugins->selected_idx];
  } while (*plugins->selected->options & BEQ_DISABLED);
}


void
Plugins_next_n(const u_short n)
{
  u_short i;

  for (i = 0; i < n; i++)
    Plugins_next();
}


void
Plugins_prev_n(const u_short n)
{
  u_short i;

  for (i = 0; i < n; i++)
    Plugins_prev();
}


void
Plugins_change_run_callback(const u_long id, void (*run)(struct Context_s *))
{
  Plugin_t *p = NULL;

  p = Plugins_find(id);

  if (p != NULL)
    p->run = run;
}


void
Plugins_reload_selected(Plugins_t *plugins)
{
  Plugin_reload(plugins->selected);
}

Generated by  Doxygen 1.6.0   Back to index