|
Packit Service |
26469c |
/*
|
|
Packit Service |
26469c |
* acpi_listen.c - ACPI client for acpid's UNIX socket
|
|
Packit Service |
26469c |
*
|
|
Packit Service |
26469c |
* Portions Copyright (C) 2003 Sun Microsystems (thockin@sun.com)
|
|
Packit Service |
26469c |
* Some parts (C) 2003 - Gismo / Luca Capello <luca.pca.it> http://luca.pca.it
|
|
Packit Service |
26469c |
* 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 <sys/types.h>
|
|
Packit Service |
26469c |
#include <sys/stat.h>
|
|
Packit Service |
26469c |
#include <fcntl.h>
|
|
Packit Service |
26469c |
#include <signal.h>
|
|
Packit Service |
26469c |
#include <unistd.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 |
#include <ctype.h>
|
|
Packit Service |
26469c |
#include <getopt.h>
|
|
Packit Service |
26469c |
#include <time.h>
|
|
Packit Service |
26469c |
#include <poll.h>
|
|
Packit Service |
26469c |
#include <grp.h>
|
|
Packit Service |
26469c |
#include <signal.h>
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
#include "acpid.h"
|
|
Packit Service |
26469c |
#include "ud_socket.h"
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
#include "libc_compat.h"
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
static int handle_cmdline(int *argc, char ***argv);
|
|
Packit Service |
26469c |
static char *read_line(int fd);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
const char *progname;
|
|
Packit Service |
26469c |
const char *socketfile = ACPID_SOCKETFILE;
|
|
Packit Service |
26469c |
static int max_events;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
static void
|
|
Packit Service |
26469c |
time_expired(int signum __attribute__((unused)))
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
exit(EXIT_SUCCESS);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
int
|
|
Packit Service |
26469c |
main(int argc, char **argv)
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
int sock_fd;
|
|
Packit Service |
26469c |
int ret;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* handle an alarm */
|
|
Packit Service |
26469c |
signal(SIGALRM, time_expired);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* learn who we really are */
|
|
Packit Service |
26469c |
progname = (const char *)strrchr(argv[0], '/');
|
|
Packit Service |
26469c |
progname = progname ? (progname + 1) : argv[0];
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* handle the commandline */
|
|
Packit Service |
26469c |
handle_cmdline(&argc, &argv);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* open the socket */
|
|
Packit Service |
26469c |
sock_fd = ud_connect(socketfile);
|
|
Packit Service |
26469c |
if (sock_fd < 0) {
|
|
Packit Service |
26469c |
fprintf(stderr, "%s: can't open socket %s: %s\n",
|
|
Packit Service |
26469c |
progname, socketfile, strerror(errno));
|
|
Packit Service |
26469c |
exit(EXIT_FAILURE);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
/* set stdout to be line buffered */
|
|
Packit Service |
26469c |
setvbuf(stdout, NULL, _IOLBF, 0);
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* main loop */
|
|
Packit Service |
26469c |
ret = 0;
|
|
Packit Service |
26469c |
while (1) {
|
|
Packit Service |
26469c |
char *event;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/* read and handle an event */
|
|
Packit Service |
26469c |
event = read_line(sock_fd);
|
|
Packit Service |
26469c |
if (event) {
|
|
Packit Service |
26469c |
fprintf(stdout, "%s\n", event);
|
|
Packit Service |
26469c |
} else if (errno == EPIPE) {
|
|
Packit Service |
26469c |
fprintf(stderr, "connection closed\n");
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
} else {
|
|
Packit Service |
26469c |
static int nerrs;
|
|
Packit Service |
26469c |
if (++nerrs >= ACPID_MAX_ERRS) {
|
|
Packit Service |
26469c |
fprintf(stderr, "too many errors - aborting\n");
|
|
Packit Service |
26469c |
ret = 1;
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
if (max_events > 0 && --max_events == 0) {
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
return ret;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
static struct option opts[] = {
|
|
Packit Service |
26469c |
{"count", 0, 0, 'c'},
|
|
Packit Service |
26469c |
{"socketfile", 1, 0, 's'},
|
|
Packit Service |
26469c |
{"time", 0, 0, 't'},
|
|
Packit Service |
26469c |
{"version", 0, 0, 'v'},
|
|
Packit Service |
26469c |
{"help", 0, 0, 'h'},
|
|
Packit Service |
26469c |
{NULL, 0, 0, 0},
|
|
Packit Service |
26469c |
};
|
|
Packit Service |
26469c |
static const char *opts_help[] = {
|
|
Packit Service |
26469c |
"Set the maximum number of events.", /* count */
|
|
Packit Service |
26469c |
"Use the specified socket file.", /* socketfile */
|
|
Packit Service |
26469c |
"Listen for the specified time (in seconds).",/* time */
|
|
Packit Service |
26469c |
"Print version information.", /* version */
|
|
Packit Service |
26469c |
"Print this message.", /* help */
|
|
Packit Service |
26469c |
};
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
static void
|
|
Packit Service |
26469c |
usage(FILE *fp)
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
struct option *opt;
|
|
Packit Service |
26469c |
const char **hlp;
|
|
Packit Service |
26469c |
int max, size;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
fprintf(fp, "Usage: %s [OPTIONS]\n", progname);
|
|
Packit Service |
26469c |
max = 0;
|
|
Packit Service |
26469c |
for (opt = opts; opt->name; opt++) {
|
|
Packit Service |
26469c |
size = strlen(opt->name);
|
|
Packit Service |
26469c |
if (size > max)
|
|
Packit Service |
26469c |
max = size;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
for (opt = opts, hlp = opts_help; opt->name; opt++, hlp++) {
|
|
Packit Service |
26469c |
fprintf(fp, " -%c, --%s", opt->val, opt->name);
|
|
Packit Service |
26469c |
size = strlen(opt->name);
|
|
Packit Service |
26469c |
for (; size < max; size++)
|
|
Packit Service |
26469c |
fprintf(fp, " ");
|
|
Packit Service |
26469c |
fprintf(fp, " %s\n", *hlp);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
/*
|
|
Packit Service |
26469c |
* Parse command line arguments
|
|
Packit Service |
26469c |
*/
|
|
Packit Service |
26469c |
static int
|
|
Packit Service |
26469c |
handle_cmdline(int *argc, char ***argv)
|
|
Packit Service |
26469c |
{
|
|
Packit Service |
26469c |
for (;;) {
|
|
Packit Service |
26469c |
int i;
|
|
Packit Service |
26469c |
i = getopt_long(*argc, *argv, "c:s:t:vh", opts, NULL);
|
|
Packit Service |
26469c |
if (i == -1) {
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
switch (i) {
|
|
Packit Service |
26469c |
case 'c':
|
|
Packit Service |
26469c |
if (!isdigit(optarg[0])) {
|
|
Packit Service |
26469c |
usage(stderr);
|
|
Packit Service |
26469c |
exit(EXIT_FAILURE);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
max_events = atoi(optarg);
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
case 's':
|
|
Packit Service |
26469c |
socketfile = optarg;
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
case 't':
|
|
Packit Service |
26469c |
if (!isdigit(optarg[0])) {
|
|
Packit Service |
26469c |
usage(stderr);
|
|
Packit Service |
26469c |
exit(EXIT_FAILURE);
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
alarm(atoi(optarg));
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
case 'v':
|
|
Packit Service |
26469c |
printf(PACKAGE "-" VERSION "\n");
|
|
Packit Service |
26469c |
exit(EXIT_SUCCESS);
|
|
Packit Service |
26469c |
case 'h':
|
|
Packit Service |
26469c |
usage(stdout);
|
|
Packit Service |
26469c |
exit(EXIT_SUCCESS);
|
|
Packit Service |
26469c |
default:
|
|
Packit Service |
26469c |
usage(stderr);
|
|
Packit Service |
26469c |
exit(EXIT_FAILURE);
|
|
Packit Service |
26469c |
break;
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
}
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
*argc -= optind;
|
|
Packit Service |
26469c |
*argv += optind;
|
|
Packit Service |
26469c |
|
|
Packit Service |
26469c |
return 0;
|
|
Packit Service |
26469c |
}
|
|
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 |
buf = realloc(buf, buflen);
|
|
Packit Service |
26469c |
if (!buf) {
|
|
Packit Service |
26469c |
fprintf(stderr, "ERR: malloc(%d): %s\n",
|
|
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 = 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 |
fprintf(stderr, "ERR: read(): %s\n",
|
|
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 |
}
|