--- Makefile.in +++ Makefile.in 2006-02-07 16:29:20.000000000 +0100 @@ -28,7 +28,7 @@ detectups: detectups.c - $(CC) $(LFLAGS) $(LIBS) detectups.c -o detectups + $(CC) $(LFLAGS) $(CFLAGS) $(LIBS) detectups.c -o detectups powerd: powerd.h config.h $(OBJS) $(CC) $(LFLAGS) $(LIBS) $(OBJS) -o $@ --- config.h +++ config.h 2006-02-07 16:31:03.000000000 +0100 @@ -8,7 +8,12 @@ /* You shouldnt (and it wont work unless you have modified init) change * this file - this is what init uses to know the power status. */ -#define PWRSTAT "/etc/powerstatus" +#define PWRSTAT "/var/run/powerstatus" +#if defined(linux) +# include +# define NEWINIT +# define INIT_REQ_SLEEP 5 +#endif /* Define this if you want to develop on powerd. This will cause powerd to --- powerd.c +++ powerd.c 2006-02-07 17:18:38.000000000 +0100 @@ -27,7 +27,6 @@ #include "powerd.h" - static Client *clients; static Listen *listens; @@ -73,7 +72,10 @@ int i; #endif char *me=argv[0]; + char *base = basename(me); + char *pidf = NULL; int delay = 16; + int n; if (argc<1 || (argc >1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))) { printf("powerd %s by: James Brents (DaSyonic)\n\n", ver); @@ -92,10 +94,36 @@ setsid(); if ((root = getuid())) { - fprintf(stderr, "%s: need to have root privlidges.", me); + fprintf(stderr, "%s: need to have root privliges\n", me); } else if (touser != NULL) { if (seteuid(user = uname2id(touser)) == -1) - fprintf(stderr, "%s is not a valid username.", touser); + fprintf(stderr, "%s is not a valid username: %s\n", touser, strerror(errno)); + } + + if ((pidf = (char*)malloc(strlen(_PATH_VARRUN)+strlen(base)+1+3+1)) == NULL) { + fprintf(stderr, "%s: can create pid file: %s\n", me, strerror(errno)); + } else { + pidf = strcpy(pidf, _PATH_VARRUN); + pidf = strcat(pidf, base); + pidf = strcat(pidf, ".pid"); + + if ((n = open(pidf, O_WRONLY|O_CREAT|O_TRUNC)) == -1) { + fprintf(stderr, "%s: can create pid file: %s\n", me, strerror(errno)); + } else { + snprintf(logbuffer, sizeof(logbuffer)-1, "%d", (int)getpid()); + write(n, logbuffer, strlen(logbuffer)); + close(n); + } + } + + if ((n = open("/dev/null", O_RDWR)) == -1) { + fprintf(stderr, "%s: can not open /dev/null.", me); + } else { + (void)dup2(n, 0); + (void)dup2(n, 1); + (void)dup2(n, 2); + (void)close(n); + errno=0; } break; @@ -116,6 +144,8 @@ monitorups(delay); else if (mode == 1) bindport(); + if (pidf) + (void)unlink(pidf); exit(0); } @@ -194,9 +224,12 @@ /* log to the syslog */ void log(int type, int facility, const char *entry, ...) { + va_list ap; + va_start(ap, entry); openlog("powerd", LOG_CONS | LOG_PID, facility); - syslog(type, entry); + vsyslog(type, entry, ap); closelog(); + va_end(ap); } /* Borrowed from Apache @@ -220,12 +253,39 @@ */ void notifyinit(int status) { unsigned int file; +#ifdef NEWINIT + struct init_request req; + int success = 0; + void (*save_sigalrm)(); +#endif errno = 0; if (touser != NULL) seteuid(root); +#ifdef NEWINIT + /* Fill out the request struct. */ + memset(&req, 0, sizeof(req)); + req.magic = INIT_MAGIC; + req.sleeptime = INIT_REQ_SLEEP; + req.cmd = (status == FAIL) ? INIT_CMD_POWERFAIL : INIT_CMD_POWEROK; + + /* Open the fifo (with timeout) */ + save_sigalrm = signal(SIGALRM, alarm_handler); + alarm(3); + if ((file = open(INIT_FIFO, O_WRONLY, 0644)) >= 0) { + if (write(file, &req, sizeof(req)) == sizeof(req)) + success = 1; + close(file); + } + alarm(0); + (void)signal(SIGALRM, save_sigalrm); + + if (!success) { + /* The old method ... */ +#endif + if ((file = open(PWRSTAT, O_CREAT | O_WRONLY, 0644)) == -1) { fprintf(stderr, "Cant open %s: %s\n", PWRSTAT, strerror(errno)); exit(-1); @@ -237,6 +297,10 @@ #else bsdshutdown(status); #endif + +#ifdef NEWINIT + } +#endif if (touser != NULL) seteuid(user); @@ -259,7 +323,8 @@ * connections */ int bindport() { - int len, addr_len, newfd, sin_size, numbytes; + socklen_t len, sin_size; + int newfd, numbytes; struct sockaddr_in serveraddr, remoteaddr; struct timeval mytv; FileDescriptor *list; @@ -289,7 +354,7 @@ exit(-1); } - len = sizeof(serveraddr); + len = (socklen_t)sizeof(serveraddr); if (getsockname(serverfd, (struct sockaddr *)&serveraddr, &len)) { fprintf(stderr, "getsockname()\n"); @@ -301,8 +366,6 @@ if ((touser != NULL) && (listenport < 1024)) seteuid(user); - addr_len = sizeof(struct sockaddr); - // printf("Im here\n"); while (1) { errno = 0; @@ -321,7 +384,7 @@ if (FD_ISSET(serverfd, &readfds)) { FileDescriptor *tmp; - sin_size = sizeof(struct sockaddr_in); + sin_size = (socklen_t)sizeof(struct sockaddr_in); if ((newfd=accept(serverfd, (struct sockaddr *)&remoteaddr, &sin_size)) == -1) { perror("accept"); @@ -540,6 +603,15 @@ mypower = (mypower == 1) ? 0 : 1; } +#ifdef NEWINIT +/* alarm handler for communication with init */ +/* static */ void alarm_handler (int sig) +{ + printf("Writing to init FIFO %s timed out\n", INIT_FIFO); + sleep(1); +} +#endif + /* Open and parse the configuration file */ void openconfig(int *delay) { --- powerd.h.in +++ powerd.h.in 2006-02-07 17:07:39.000000000 +0100 @@ -60,6 +60,7 @@ /*********** If you do, Please send patches. **********/ #include #include +#include #include #include #include @@ -77,6 +78,11 @@ #include #include #include +#include +#include +#ifndef _PATH_VARRUN +# define _PATH_VARRUN "/var/run/" +#endif #define CONNECTED 0x01 #define SENTNOTICE 0x02 @@ -122,7 +128,8 @@ Listen *listen; }; -void log(int type, int facility, const char *entry, ...); +void mylog(int type, int facility, const char *entry, ...); +#define log(args...) mylog(args) uid_t uname2id(char *name); void notifyinit(int status); void monitorups(int delay); @@ -139,6 +146,7 @@ void auth(FileDescriptor *fd, char *password); void quit_sig(int sig); void debughelp(int sig); +/* static */ void alarm_handler(int sig); int notifyclients(int status); void getrid(FileDescriptor *fd, int i); void bsdshutdown(int status);