Blame acpi_listen.c

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
}