Main Page | Class List | File List | Class Members | File Members

acpi_listen.c

Go to the documentation of this file.
00001 /*
00002  *  acpi_listen.c - ACPI client for acpid's UNIX socket
00003  *
00004  *  Portions Copyright (C) 2003 Sun Microsystems (thockin@sun.com)
00005  *  Some parts (C) 2003 - Gismo / Luca Capello <luca.pca.it> http://luca.pca.it
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <fcntl.h>
00025 #include <signal.h>
00026 #include <unistd.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <errno.h>
00031 #include <ctype.h>
00032 #include <getopt.h>
00033 #include <time.h>
00034 #include <sys/poll.h>
00035 #include <grp.h>
00036 #include <signal.h>
00037 
00038 #include "acpid.h"
00039 #include "ud_socket.h"
00040 
00041 static int handle_cmdline(int *argc, char ***argv);
00042 static char *read_line(int fd);
00043 
00044 static const char *progname;
00045 static const char *socketfile = ACPI_SOCKETFILE;
00046 static int max_events;
00047 
00048 static void
00049 time_expired(int signum)
00050 {
00051         exit(EXIT_SUCCESS);
00052 }
00053 
00054 int
00055 main(int argc, char **argv)
00056 {
00057         int sock_fd;
00058         int ret;
00059 
00060         /* handle an alarm */
00061         signal(SIGALRM, time_expired);
00062 
00063         /* learn who we really are */
00064         progname = (const char *)strrchr(argv[0], '/');
00065         progname = progname ? (progname + 1) : argv[0];
00066 
00067         /* handle the commandline  */
00068         handle_cmdline(&argc, &argv);
00069 
00070         /* open the socket */
00071         sock_fd = ud_connect(socketfile);
00072         if (sock_fd < 0) {
00073                 fprintf(stderr, "%s: can't open socket %s: %s\n",
00074                         progname, socketfile, strerror(errno));
00075                 exit(EXIT_FAILURE);
00076         }
00077         fcntl(sock_fd, F_SETFD, FD_CLOEXEC);
00078 
00079         /* set stdout to be line buffered */
00080         setvbuf(stdout, NULL, _IOLBF, 0);
00081 
00082         /* main loop */
00083         ret = 0;
00084         while (1) {
00085                 char *event;
00086 
00087                 /* read and handle an event */
00088                 event = read_line(sock_fd);
00089                 if (event) {
00090                         fprintf(stdout, "%s\n", event);
00091                 } else if (errno == EPIPE) {
00092                         fprintf(stderr, "connection closed\n");
00093                         break;
00094                 } else {
00095                         static int nerrs;
00096                         if (++nerrs >= ACPI_MAX_ERRS) {
00097                                 fprintf(stderr, "too many errors - aborting\n");
00098                                 ret = 1;
00099                                 break;
00100                         }
00101                 }
00102 
00103                 if (max_events > 0 && --max_events == 0) {
00104                         break;
00105                 }
00106         }
00107 
00108         return ret;
00109 }
00110 
00111 static struct option opts[] = {
00112         {"count", 0, 0, 'c'},
00113         {"socketfile", 1, 0, 's'},
00114         {"time", 0, 0, 't'},
00115         {"version", 0, 0, 'v'},
00116         {"help", 0, 0, 'h'},
00117         {NULL, 0, 0, 0},
00118 };
00119 static const char *opts_help[] = {
00120         "Set the maximum number of events.",    /* count */
00121         "Use the specified socket file.",       /* socketfile */
00122         "Listen for the specified time (in seconds).",/* time */
00123         "Print version information.",           /* version */
00124         "Print this message.",                  /* help */
00125 };
00126 
00127 static void
00128 usage(FILE *fp)
00129 {
00130         struct option *opt;
00131         const char **hlp;
00132         int max, size;
00133 
00134         fprintf(fp, "Usage: %s [OPTIONS]\n", progname);
00135         max = 0;
00136         for (opt = opts; opt->name; opt++) {
00137                 size = strlen(opt->name);
00138                 if (size > max)
00139                         max = size;
00140         }
00141         for (opt = opts, hlp = opts_help; opt->name; opt++, hlp++) {
00142                 fprintf(fp, "  -%c, --%s", opt->val, opt->name);
00143                 size = strlen(opt->name);
00144                 for (; size < max; size++)
00145                         fprintf(fp, " ");
00146                 fprintf(fp, "  %s\n", *hlp);
00147         }
00148 }
00149 
00150 /*
00151  * Parse command line arguments
00152  */
00153 static int
00154 handle_cmdline(int *argc, char ***argv)
00155 {
00156         for (;;) {
00157                 int i;
00158                 i = getopt_long(*argc, *argv, "c:s:t:vh", opts, NULL);
00159                 if (i == -1) {
00160                         break;
00161                 }
00162                 switch (i) {
00163                 case 'c':
00164                         if (!isdigit(optarg[0])) {
00165                                 usage(stderr);
00166                                 exit(EXIT_FAILURE);
00167                         }
00168                         max_events = atoi(optarg);
00169                         break;
00170                 case 's':
00171                         socketfile = optarg;
00172                         break;
00173                 case 't':
00174                         if (!isdigit(optarg[0])) {
00175                                 usage(stderr);
00176                                 exit(EXIT_FAILURE);
00177                         }
00178                         alarm(atoi(optarg));
00179                         break;
00180                 case 'v':
00181                         printf(PACKAGE "-" VERSION "\n");
00182                         exit(EXIT_SUCCESS);
00183                 case 'h':
00184                         usage(stdout);
00185                         exit(EXIT_SUCCESS);
00186                 default:
00187                         usage(stderr);
00188                         exit(EXIT_FAILURE);
00189                         break;
00190                 }
00191         }
00192 
00193         *argc -= optind;
00194         *argv += optind;
00195 
00196         return 0;
00197 }
00198 
00199 #define MAX_BUFLEN      1024
00200 static char *
00201 read_line(int fd)
00202 {
00203         static char *buf;
00204         int buflen = 64;
00205         int i = 0;
00206         int r;
00207         int searching = 1;
00208 
00209         while (searching) {
00210                 buf = realloc(buf, buflen);
00211                 if (!buf) {
00212                         fprintf(stderr, "ERR: malloc(%d): %s\n",
00213                                 buflen, strerror(errno));
00214                         return NULL;
00215                 }
00216                 memset(buf+i, 0, buflen-i);
00217 
00218                 while (i < buflen) {
00219                         r = read(fd, buf+i, 1);
00220                         if (r < 0 && errno != EINTR) {
00221                                 /* we should do something with the data */
00222                                 fprintf(stderr, "ERR: read(): %s\n",
00223                                         strerror(errno));
00224                                 return NULL;
00225                         } else if (r == 0) {
00226                                 /* signal this in an almost standard way */
00227                                 errno = EPIPE;
00228                                 return NULL;
00229                         } else if (r == 1) {
00230                                 /* scan for a newline */
00231                                 if (buf[i] == '\n') {
00232                                         searching = 0;
00233                                         buf[i] = '\0';
00234                                         break;
00235                                 }
00236                                 i++;
00237                         }
00238                 }
00239                 if (buflen >= MAX_BUFLEN) {
00240                         break;
00241                 }
00242                 buflen *= 2;
00243         }
00244 
00245         return buf;
00246 }

© sourcejam.com 2005-2008