|
Packit Service |
26469c |
/*
|
|
Packit Service |
26469c |
* proc.c - ACPI daemon proc filesystem interface
|
|
Packit Service |
26469c |
*
|
|
Packit Service |
26469c |
* Portions Copyright (C) 2000 Andrew Henroid
|
|
Packit Service |
26469c |
* Portions Copyright (C) 2001 Sun Microsystems
|
|
Packit Service |
26469c |
* Portions Copyright (C) 2004 Tim Hockin (thockin@hockin.org)
|
|
Packit Service |
26469c |
*
|
|
Packit Service |
26469c |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
26469c |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
26469c |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
26469c |
* (at your option) any later version.
|
|
Packit Service |
26469c |
*
|
|
Packit Service |
26469c |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
26469c |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
26469c |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
26469c |
* GNU General Public License for more details.
|
|
Packit Service |
26469c |
*
|
|
Packit Service |
26469c |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
26469c |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
26469c |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit Service |
26469c |
*/
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
#include <unistd.h>
|
|
Packit Service |
26469c |
#include <fcntl.h>
|
|
Packit Service |
26469c |
#include <stdio.h>
|
|
Packit Service |
26469c |
#include <stdlib.h>
|
|
Packit Service |
26469c |
#include <string.h>
|
|
Packit Service |
26469c |
#include <errno.h>
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
#include "acpid.h"
|
|
Packit Service |
26469c |
#include "log.h"
|
|
Packit Service |
26469c |
#include "event.h"
|
|
Packit Service |
26469c |
#include "connection_list.h"
|
|
Packit Service |
26469c |
#include "libc_compat.h"
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
#include "proc.h"
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
const char *eventfile = ACPID_EVENTFILE;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
static char *read_line(int fd);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
static void
|
|
Packit Service |
26469c |
process_proc(int fd)
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
char *event;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* read an event */
|
|
Packit Service |
26469c |
event = read_line(fd);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* if we're locked, don't process the event */
|
|
Packit Service |
26469c |
if (locked()) {
|
|
Packit Service |
26469c |
if (logevents && event != NULL) {
|
|
Packit Service |
26469c |
acpid_log(LOG_INFO,
|
|
Packit Service |
26469c |
"lockfile present, not processing "
|
|
Packit Service |
26469c |
"event \"%s\"", event);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
return;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* handle the event */
|
|
Packit Service |
26469c |
if (event) {
|
|
Packit Service |
26469c |
if (logevents) {
|
|
Packit Service |
26469c |
acpid_log(LOG_INFO,
|
|
Packit Service |
26469c |
"procfs received event \"%s\"", event);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
acpid_handle_event(event);
|
|
Packit Service |
26469c |
if (logevents) {
|
|
Packit Service |
26469c |
acpid_log(LOG_INFO,
|
|
Packit Service |
26469c |
"procfs completed event \"%s\"", event);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
} else if (errno == EPIPE) {
|
|
Packit Service |
26469c |
acpid_log(LOG_WARNING,
|
|
Packit Service |
26469c |
"events file connection closed");
|
|
Packit Service |
26469c |
exit(EXIT_FAILURE);
|
|
Packit Service |
26469c |
} else {
|
|
Packit Service |
26469c |
static int nerrs;
|
|
Packit Service |
26469c |
if (++nerrs >= ACPID_MAX_ERRS) {
|
|
Packit Service |
26469c |
acpid_log(LOG_ERR,
|
|
Packit Service |
26469c |
"too many errors reading "
|
|
Packit Service |
26469c |
"events file - aborting");
|
|
Packit Service |
26469c |
exit(EXIT_FAILURE);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
int
|
|
Packit Service |
26469c |
open_proc()
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
int fd;
|
|
Packit Service |
26469c |
struct connection c;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* O_CLOEXEC: Make sure scripts we exec() (in event.c) don't get our file
|
|
Packit Service |
26469c |
descriptors. */
|
|
Packit Service |
26469c |
fd = open(eventfile, O_RDONLY | O_CLOEXEC);
|
|
Packit Service |
26469c |
if (fd < 0) {
|
|
Packit Service |
26469c |
if (errno == ENOENT) {
|
|
Packit Service |
26469c |
acpid_log(LOG_DEBUG, "Deprecated %s was not found. "
|
|
Packit Service |
26469c |
"Trying netlink and the input layer...", eventfile);
|
|
Packit Service |
26469c |
} else {
|
|
Packit Service |
26469c |
acpid_log(LOG_ERR, "can't open %s: %s (%d)", eventfile,
|
|
Packit Service |
26469c |
strerror(errno), errno);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
return -1;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
acpid_log(LOG_DEBUG, "proc fs opened successfully");
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* add a connection to the list */
|
|
Packit Service |
26469c |
c.fd = fd;
|
|
Packit Service |
26469c |
c.process = process_proc;
|
|
Packit Service |
26469c |
c.pathname = NULL;
|
|
Packit Service |
26469c |
c.kybd = 0;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
if (add_connection(&c) < 0) {
|
|
Packit Service |
26469c |
close(fd);
|
|
Packit Service |
26469c |
acpid_log(LOG_ERR, "can't add connection for %s", eventfile);
|
|
Packit Service |
26469c |
return -1;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
return 0;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/*
|
|
Packit Service |
26469c |
* This depends on fixes in linux ACPI after 2.4.8
|
|
Packit Service |
26469c |
*/
|
|
Packit Service |
26469c |
#define BUFLEN 1024
|
|
Packit Service |
26469c |
static char *
|
|
Packit Service |
26469c |
read_line(int fd)
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
static char buf[BUFLEN];
|
|
Packit Service |
26469c |
int i = 0;
|
|
Packit Service |
26469c |
int r;
|
|
Packit Service |
26469c |
int searching = 1;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
while (searching) {
|
|
Packit Service |
26469c |
memset(buf+i, 0, BUFLEN-i);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* only go to BUFLEN-1 so there will always be a 0 at the end */
|
|
Packit Service |
26469c |
while (i < BUFLEN-1) {
|
|
Packit Service |
26469c |
r = TEMP_FAILURE_RETRY(read(fd, buf+i, 1));
|
|
Packit Service |
26469c |
if (r < 0) {
|
|
Packit Service |
26469c |
/* we should do something with the data */
|
|
Packit Service |
26469c |
acpid_log(LOG_ERR, "read(): %s",
|
|
Packit Service |
26469c |
strerror(errno));
|
|
Packit Service |
26469c |
return NULL;
|
|
Packit Service |
26469c |
} else if (r == 0) {
|
|
Packit Service |
26469c |
/* signal this in an almost standard way */
|
|
Packit Service |
26469c |
errno = EPIPE;
|
|
Packit Service |
26469c |
return NULL;
|
|
Packit Service |
26469c |
} else if (r == 1) {
|
|
Packit Service |
26469c |
/* scan for a newline */
|
|
Packit Service |
26469c |
if (buf[i] == '\n') {
|
|
Packit Service |
26469c |
searching = 0;
|
|
Packit Service |
26469c |
buf[i] = '\0';
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
i++;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
if (i >= BUFLEN - 1)
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
return buf;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
#if 0
|
|
Packit Service |
26469c |
/* This version leaks memory. The above version is simpler and leak-free. */
|
|
Packit Service |
26469c |
/* Downside is that the above version always uses 1k of RAM. */
|
|
Packit Service |
26469c |
/*
|
|
Packit Service |
26469c |
* This depends on fixes in linux ACPI after 2.4.8
|
|
Packit Service |
26469c |
*/
|
|
Packit Service |
26469c |
#define MAX_BUFLEN 1024
|
|
Packit Service |
26469c |
static char *
|
|
Packit Service |
26469c |
read_line(int fd)
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
static char *buf;
|
|
Packit Service |
26469c |
int buflen = 64;
|
|
Packit Service |
26469c |
int i = 0;
|
|
Packit Service |
26469c |
int r;
|
|
Packit Service |
26469c |
int searching = 1;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
while (searching) {
|
|
Packit Service |
26469c |
/* ??? This memory is leaked since it is never freed */
|
|
Packit Service |
26469c |
buf = realloc(buf, buflen);
|
|
Packit Service |
26469c |
if (!buf) {
|
|
Packit Service |
26469c |
acpid_log(LOG_ERR, "malloc(%d): %s",
|
|
Packit Service |
26469c |
buflen, strerror(errno));
|
|
Packit Service |
26469c |
return NULL;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
memset(buf+i, 0, buflen-i);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
while (i < buflen) {
|
|
Packit Service |
26469c |
r = read(fd, buf+i, 1);
|
|
Packit Service |
26469c |
if (r < 0 && errno != EINTR) {
|
|
Packit Service |
26469c |
/* we should do something with the data */
|
|
Packit Service |
26469c |
acpid_log(LOG_ERR, "read(): %s",
|
|
Packit Service |
26469c |
strerror(errno));
|
|
Packit Service |
26469c |
return NULL;
|
|
Packit Service |
26469c |
} else if (r == 0) {
|
|
Packit Service |
26469c |
/* signal this in an almost standard way */
|
|
Packit Service |
26469c |
errno = EPIPE;
|
|
Packit Service |
26469c |
return NULL;
|
|
Packit Service |
26469c |
} else if (r == 1) {
|
|
Packit Service |
26469c |
/* scan for a newline */
|
|
Packit Service |
26469c |
if (buf[i] == '\n') {
|
|
Packit Service |
26469c |
searching = 0;
|
|
Packit Service |
26469c |
buf[i] = '\0';
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
i++;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
if (buflen >= MAX_BUFLEN) {
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
buflen *= 2;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
return buf;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
#endif
|