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

driver.c

#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <acpid/driver.h>
#include <sys/wait.h>

int acpi_channel_create(lua_State *L)
{
      lua_pushinteger(L, 1);
      lua_gettable(L, -3);

      const char *name = lua_tostring(L, -1);
      const struct acpi_driver_ops *ops = acpi_driver_find(name);
      lua_pop(L, 1);

      if (ops == NULL)
            return -1;

      lua_pushinteger(L, 2);
      lua_gettable(L, -3);

      struct acpi_channel *channel = malloc(sizeof(struct acpi_channel));
      int ret = (*ops->create)(channel, L);
      lua_pop(L, 1);

      if (ret)
            return -1;

      lua_pushlightuserdata(L, channel);

      return 0;
}

void acpi_channel_register(struct acpi_channel *channel, const struct acpi_channel_ops *ops)
{
      channel->ops = ops;
}

void acpi_channel_watch(struct acpi_channel *channel, struct acpi_channel_descriptor *cds, int fd, int events)
{
      cds->channel = channel;

      cds->fd = fd;
      cds->events = events;
}

static int printL(lua_State *L)
{
      printf(">>> ");
      for (int i = 1; i < lua_gettop(L); ++i)
            printf("%s, ", lua_tostring(L, i));
      printf("%s\n", lua_tostring(L, lua_gettop(L)));

      return 0;
}

static int execL(lua_State *L)
{
      if (lua_gettop(L) > 12)
            return 0;

      const char *args[12] = { lua_tostring(L, 1) };
      for (int i = 1; i < 12; ++i)
            args[i] = lua_tostring(L, i + 1);

      pid_t pid = fork();
      switch (pid) {
      case -1:
            exit(1);
      case 0:
            execvp(lua_tostring(L, 1), args);
            break;
      default:
            waitpid(pid, NULL, 0);
      }

      return 0;
}

int acpi_channel_event(struct acpi_channel *channel, lua_State *L, const char *hid, unsigned long event, unsigned long data)
{
      /* Send a dbus event */
      acpi_dbus_event(hid, event, data);

      /* Setup en basic Lua environment */
      lua_pushcclosure(L, execL, 0);
      lua_setfield(L, LUA_GLOBALSINDEX, "exec");

      lua_pushcclosure(L, printL, 0);
      lua_setfield(L, LUA_GLOBALSINDEX, "print");

      /* First we let the channel handler process the event. */
      lua_pushlightuserdata(L, channel);
      lua_gettable(L, LUA_REGISTRYINDEX);

      lua_pushstring(L, hid);
      lua_pushinteger(L, event);
      lua_pushinteger(L, data);

      /* TODO: For now we ignore the return values. */
      lua_pcall(L, 3, 0, 0);

      /* Now we pass the arguments to all script functions. If a function     
       * returns something else than nil, we abort the processing. */
      lua_getfield(L, LUA_GLOBALSINDEX, "script");
      for (int i = 1; i < 100; ++i) {
            lua_pushinteger(L, i);
            lua_gettable(L, -2);

            if (lua_type(L, -1) == LUA_TFUNCTION) {
                  lua_pushstring(L, hid);
                  lua_pushinteger(L, event);
                  lua_pushinteger(L, data);

                  if (lua_pcall(L, 3, 1, 0) || lua_type(L, -1)) {
                        printf("script[%02d] processing aborted: %s\n", i, lua_tostring(L, -1));
                        lua_pop(L, 1);
                        break;
                  }
            }

            lua_pop(L, 1);
      }
}



/*
 *    ACPI Driver
 */

static const struct acpi_driver *drivers[4];
static unsigned char num;


void acpi_driver_register(const struct acpi_driver *driver)
{
      drivers[num++] = driver;
}

const struct acpi_driver_ops *acpi_driver_find(const char *name)
{
      for (int i = 0; i < num; ++i) {
            if (strcmp(drivers[i]->name, name) == 0)
                  return &drivers[i]->ops;
      }

      return NULL;
}


Generated by  Doxygen 1.6.0   Back to index