1
/* upscommon.c - functions used in more than one model support module
3
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include "upscommon.h"
26
#include <sys/ioctl.h>
28
#include <sys/socket.h>
35
#define shmget(a,b,c) (-1)
36
#define shmctl(a,b,c) /* nop */
46
int upsfd, shmid = -1, upsc_debug = 0;
47
static int statefd = -1;
48
char statefn[SIZE_OF_STATEFN], *upsport, *pidfn = NULL;
49
char initfn[SIZE_OF_STATEFN];
51
static char sock_fn[SIZE_OF_STATEFN];
52
static int sock_fd = -1;
53
static fd_set sock_rfds;
54
static int sock_maxfd;
57
static itype *shared_info = NULL;
58
static size_t info_size = 0;
59
static itype *info_mtime = NULL;
60
int infoused = 0, infomax = 0;
62
struct ups_handler upsh;
66
/* main sets this, and nobody else does */
67
/* TODO: remove when all old style drivers are dead */
70
/* need to pick a sane default. maybe this should be set by open_serial */
71
unsigned int upssend_delay = 0;
72
char upssend_endchar = '\0';
74
int flag_timeoutfailure = 0;
76
/* signal handler for SIGALRM when opening a serial port */
77
void openfail(int sig)
79
fatal("Fatal error: serial port open timed out");
82
/* try whatever method(s) are available to lock the port for our use */
83
void lockport (int upsfd, const char *port)
85
if (do_lock_port == 0) {
86
upslogx(LOG_INFO, "Serial port locking disabled.");
91
if (upsport) /* already locked? */
94
/* save for later in case we need it at shutdown */
95
upsport = xstrdup(xbasename(port));
98
int res = uu_lock(upsport);
101
fatalx("Can't uu_lock %s: %s", upsport,
104
#elif defined(HAVE_FLOCK)
105
if (flock(upsfd, LOCK_EX | LOCK_NB) != 0)
106
fatalx("%s is locked by another process", port);
107
#elif defined(HAVE_LOCKF)
108
lseek(upsfd, 0L, SEEK_SET);
109
if (lockf(upsfd, F_TLOCK, 0L))
110
fatalx("%s is locked by another process", port);
114
/* explain in full detail what's wrong when the open fails */
115
static void open_error(const char *port)
120
/* see if port even exists first - typo check */
121
if (stat(port, &fs)) {
122
upslogx(LOG_NOTICE, "Can't stat() %s - did you specify a nonexistent /dev file?",
124
fatal("Unable to open %s", port);
127
user = getpwuid(getuid());
129
upslogx(LOG_NOTICE, "This program is currently running as %s (UID %d)",
130
user->pw_name, (int)user->pw_uid);
132
user = getpwuid(fs.st_uid);
134
upslogx(LOG_NOTICE, "%s is owned by user %s (UID %d), mode %04o", port,
135
user->pw_name, (int)user->pw_uid,
136
(int)(fs.st_mode & 07777));
138
upslogx(LOG_NOTICE, "Change the port name, or fix the permissions or ownership"
139
" of %s and try again.", port);
141
fatal("Unable to open %s", port);
144
/* open the port, but don't touch the tty details (except CLOCAL and speed) */
145
void open_serial_simple(const char *port, speed_t speed, int flags)
149
signal(SIGALRM, openfail);
152
if ((upsfd = open(port, O_RDWR | O_NONBLOCK)) == -1)
157
lockport(upsfd, port);
159
tcgetattr(upsfd, &tio);
160
tio.c_cflag |= CLOCAL;
162
#ifndef HAVE_CFSETISPEED
163
#error This system lacks cfsetispeed() and has no other means to set the speed
165
cfsetispeed(&tio, speed);
166
cfsetospeed(&tio, speed);
168
tcsetattr(upsfd, TCSANOW, &tio);
170
/* set "normal" flags - cable power, or whatever */
171
if (ioctl(upsfd, TIOCMSET, &flags))
175
/* open a serial port and setup the flags properly at a given speed */
176
void open_serial(const char *port, speed_t speed)
181
/* open port for normal use */
183
signal (SIGALRM, openfail);
186
upsfd = open (port, O_RDWR | O_NOCTTY | O_EXCL | O_NONBLOCK);
192
fcarg = fcntl(upsfd, F_GETFL, 0);
193
if (fcarg < 0 || fcntl(upsfd, F_SETFL, fcarg & ~O_NONBLOCK) < 0)
194
fatal("Unable to clear O_NONBLOCK 2 %s", port);
196
signal (SIGALRM, SIG_IGN);
198
lockport (upsfd, port);
200
tcgetattr (upsfd, &tio);
201
tio.c_cflag = CS8 | CLOCAL | CREAD;
202
tio.c_iflag = IGNPAR;
208
#ifdef HAVE_CFSETISPEED
209
cfsetispeed (&tio, speed);
210
cfsetospeed (&tio, speed);
212
#error This system lacks cfsetispeed() and has no other means to set the speed
215
tcflush (upsfd, TCIFLUSH);
216
tcsetattr (upsfd, TCSANOW, &tio);
219
/* put a notice in the syslog */
220
void notice (const char *msg)
222
upslogx(LOG_NOTICE, "Notice: %s", msg);
225
/* function for erasing "timeout"-conditions */
226
void nolongertimeout(void)
228
/* if override enabled, then return without changing anything */
229
if (flag_timeoutfailure == -1)
232
if (flag_timeoutfailure == 1)
233
upslogx(LOG_NOTICE, "Serial port read ok again");
235
flag_timeoutfailure = 0;
239
/* signal handler for SIGALRM when trying to read */
240
void timeout(int sig)
245
sa.sa_handler = SIG_DFL;
246
sigemptyset (&sigmask);
247
sa.sa_mask = sigmask;
249
sigaction (SIGALRM, &sa, NULL);
251
/* if override enabled, then return without changing anything */
252
if (flag_timeoutfailure == -1)
255
if (flag_timeoutfailure == 0)
256
upslogx(LOG_NOTICE, "Serial port read timed out");
258
flag_timeoutfailure = 1;
262
/* wait for an answer in the form <data><endchar> and store in buf */
263
int upsrecv (char *buf, int buflen, char endchar, const char *ignchars)
265
char recvbuf[512], *ptr, in;
270
strcpy (recvbuf, "");
272
sa.sa_handler = timeout;
273
sigemptyset (&sigmask);
274
sa.sa_mask = sigmask;
276
sigaction (SIGALRM, &sa, NULL);
284
ret = read (upsfd, &in, 1);
289
signal (SIGALRM, SIG_IGN);
290
strlcpy (buf, recvbuf, buflen);
291
if (upsc_debug > 0) {
293
printf("upsrecv: read %d bytes [", cnt);
294
for (i = 0; i < cnt; ++i)
295
printf(isprint((unsigned char)buf[i]) ? "%c" : "\\%03o",
302
if (strchr(ignchars, in) == NULL) {
304
*ptr = 0; /* tie off end */
312
signal (SIGALRM, SIG_IGN);
313
strlcpy (buf, recvbuf, buflen);
317
/* keep from overrunning the buffer - lame hack */
318
if (cnt > (sizeof(recvbuf) - 4)) {
319
notice ("UPS is spewing wildly");
324
return (-1); /* not reached */
327
/* read buflen chars and store in buf */
328
int upsrecvchars (char *buf, int buflen)
335
sa.sa_handler = timeout;
336
sigemptyset (&sigmask);
337
sa.sa_mask = sigmask;
339
sigaction (SIGALRM, &sa, NULL);
346
ret=read(upsfd,bufptr,count);
352
signal (SIGALRM, SIG_IGN);
357
signal (SIGALRM, SIG_IGN);
361
/* send a single byte to the UPS */
362
int upssendchar (char data)
364
if (upsc_debug > 0) {
365
printf ("upssendchar: sending [");
366
printf (isprint((unsigned char)data) ? "%c" : "\\%03o", data);
370
tcflush (upsfd, TCIFLUSH);
371
return (write (upsfd, &data, 1));
374
int upssend(const char *fmt, ...)
382
if (vsnprintf(buf, sizeof(buf), fmt, ap) >= sizeof(buf))
387
tcflush(upsfd, TCIFLUSH);
389
for (p = buf; *p; p++) {
390
if (upsc_debug > 0) {
391
/* printf ("upssendchar: sending [");
392
* printf (isprint(data) ? "%c" : "\\%03o", data);
396
if (write(upsfd, p, 1) != 1)
399
usleep(upssend_delay);
402
if (upssend_endchar) {
403
if (write(upsfd, &upssend_endchar, 1) != 1)
406
usleep(upssend_delay);
413
/* read in any pending characters. If expected is set then
414
* just drop them, otherwise log an error unles they are
417
void upsflushin (int expected, int debugit, const char *ignchars)
420
struct timeval timeout;
427
left = 250; /* somewhat smaller than buffer */
430
FD_SET(upsfd, &readfds);
435
while ((rc = select(upsfd+1,
444
printf ("upsflushin: read char ");
445
printf(isprint(in) ? "%c" : "\\%03o",
449
(strchr(ignchars, in) == NULL)) {
450
/* log the excess characters */
453
*ptr = 0; /* tie of string */
456
sprintf(ptr, "\\%03o", in);
460
/* check if buffer full - if so moan */
463
"Unexpected UPS jabber [%s]",
471
/* check for error returns from select */
473
upslogx(LOG_NOTICE, "select() on input flush returned error");
478
"Unexpected UPS output [%s]",
485
/* get data from the UPS and install it in the data array */
486
void installinfo (int infotype, char reqchar, char endchar, const char *ignchars)
490
pos = findinfo(info, infomax, 0, infotype);
492
if (pos == -1) /* not found, probably not supported */
495
upssendchar (reqchar);
496
upsrecv (info[pos].value, sizeof(info[pos].value), endchar, ignchars);
499
/* store data into the array */
500
void setinfo(int infotype, const char *fmt, ...)
505
pos = findinfo(info, infomax, 0, infotype);
507
if (pos == -1) { /* not found, probably debugging? */
508
upslogx(LOG_ERR, "setinfo: can't find type %i", infotype);
513
if (vsnprintf(info[pos].value, sizeof(info[pos].value), fmt, ap) >= sizeof(info[pos].value))
518
/* set a flag on an existing member of the array */
519
void setflag (int infotype, int newflags)
523
pos = findinfo(info, infomax, 0, infotype);
525
if (pos == -1) { /* not found, probably debugging? */
526
upslogx(LOG_ERR, "setflag: can't find type %i", infotype);
530
info[pos].flags = newflags;
533
/* find data of a given type in the info array */
534
char *getdata (int infotype)
538
for (i = 0; i < infomax; i++)
539
if (info[i].type == infotype)
540
return (info[i].value);
547
/* create state file with a pointer to the SHM struct */
548
static void writeshminfo(itype *writeinfo)
550
if (writeinfo[0].type != INFO_SHMID)
551
fatalx("shouldn't be here");
554
int ret = write(statefd, writeinfo, sizeof(itype));
555
if (ret == sizeof(itype))
559
/* ssfd < 0 || ret < 0 */
560
fatal("Can't write shminfo to %s", statefn);
562
#endif /* HAVE_SHMAT */
569
/* if data is stale, don't write it so the information ages */
570
if (flag_timeoutfailure == 1)
573
if (info[0].type == INFO_SHMID)
574
fatalx("info[0].type == INFO_SHMID in a shm segment");
576
snprintf(info_mtime->value, VALSIZE, "%ld", time(NULL));
580
lock.l_type = F_WRLCK;
581
lock.l_whence = SEEK_SET;
583
/* try to get the lock for up to 250 ms */
584
while (fcntl(statefd, F_SETLK, &lock) == -1) {
588
upslogx(LOG_WARNING, "Could not lock data for writing");
595
memcpy(shared_info, info, info_size);
598
struct shmid_ds shmbuf;
600
/* this updates the ctime that upsd wants to see */
601
shmctl (shmid, IPC_STAT, &shmbuf);
602
shmctl (shmid, IPC_SET, &shmbuf);
605
if (lseek(statefd, 0, SEEK_SET))
606
fatal("lseek statefd");
607
if (write(statefd, info, info_size) != info_size)
608
fatal("Can't write to %s", statefn);
609
#endif /* HAVE_MMAP */
614
lock.l_type = F_UNLCK;
615
lock.l_whence = SEEK_SET;
617
ret = fcntl(statefd, F_SETLK, &lock);
620
upslog(LOG_INFO, "Error while unlocking UPS data");
623
static void create_socket(void)
625
struct sockaddr_un sa;
628
snprintf(sock_fn, sizeof(sock_fn), "%s.sock", statefn);
630
memset(&sa, '\0', sizeof(sa));
631
sa.sun_family = AF_UNIX;
632
if (strlcpy(sa.sun_path, sock_fn, sizeof(sa.sun_path)) >= sizeof(sa.sun_path))
633
fatalx("sockfile path too long: %s", sock_fn);
635
/* sa.sun_len = strlen(sock_fn); */ /* not portable */
637
if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
639
if (bind(sock_fd, (struct sockaddr *) &sa, sizeof(sa)))
640
fatal("bind %s", sock_fn);
641
if (listen(sock_fd, 5))
642
fatal("listen %s", sock_fn);
644
if ((ret = fcntl(sock_fd, F_GETFL, 0)) == -1)
646
if (fcntl(sock_fd, F_SETFL, ret | O_NDELAY) == -1)
650
FD_SET(sock_fd, &sock_rfds);
651
sock_maxfd = sock_fd + 1;
654
/* try to create the state file before entering the background */
655
static void test_writeinfo(void)
660
/* upsd needs to be able to write to the file in mmap mode */
662
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
665
mode = S_IRUSR | S_IWUSR | S_IRGRP;
668
/* TODO: remove when all old style drivers are dead */
669
/* for now - instead of adding info_ready to all the old drivers */
672
snprintf(initfn, sizeof(initfn), "%s.init", statefn);
677
/* OK, this is the end of the line for the old drivers...
679
* this is a place only old drivers get to, so it's the
680
* perfect place to warn the user of the impending doom
683
upslogx(LOG_WARNING, "*** Warning: old style driver detected ***");
684
upslogx(LOG_WARNING, "*** This driver will be removed from the tree in the next version ***");
685
upslogx(LOG_WARNING, "*** See the FAQ for more information ***");
691
statefd = open(fn, O_RDWR | O_CREAT | O_NOCTTY, mode);
695
upslog(LOG_NOTICE, "Can't open %s", fn);
697
if (tmperr == EACCES) {
699
user = getpwuid(getuid());
702
upslogx(LOG_NOTICE, "This program is currently running as %s (UID %d)",
703
user ? user->pw_name : "(UNKNOWN)", user->pw_uid);
709
/* rename from <fn>.init to <fn> when it's ready to be used */
710
void info_ready(void)
714
if (use_init_fn != 1) {
715
upslogx(LOG_ERR, "Programming error: info_ready() called without use_init_fn set");
719
ret = rename(initfn, statefn);
722
fatal("rename %s to %s", initfn, statefn);
725
static void cleanup(void)
732
/* just in case this lingers... */
744
/* mark for deletion after total detachment */
746
shmctl (shmid, IPC_RMID, NULL);
747
shmdt ((char *) info); /* detach */
749
#endif /* HAVE_SHMAT */
758
upslogx(LOG_INFO, "Signal %d: Shutting down", sig);
762
/* install handler for sigterm */
763
void catch_sigterm(void)
768
sa.sa_handler = sigdie;
769
sigemptyset (&sigmask);
770
sa.sa_mask = sigmask;
772
sigaction (SIGTERM, &sa, NULL);
775
/* clean up the local info storage for future use */
776
static void info_init()
780
/* initialize the array */
781
for (i = 0; i < infomax; i++)
782
info[i].type = INFO_UNUSED;
784
info[0].type = INFO_MEMBERS;
785
snprintf(info[0].value, VALSIZE, "%i", infomax);
788
info[1].type = INFO_MTIME;
789
snprintf(info[1].value, VALSIZE, "%ld", time(NULL));
792
info_mtime = &info[1];
799
/* create a shared memory struct for our info */
800
static int shm_create(void)
802
key_t shmkey = IPC_PRIVATE;
805
/* get some shared memory */
806
shmid = shmget(shmkey, sizeof(itype) * infomax, IPC_MODE);
809
upslog(LOG_ERR, "shmget");
811
return 0; /* failed */
814
/* got a good ID, so attach to it */
815
shared_info = (itype *) shmat(shmid, 0, 0);
817
if (shared_info == (itype *) (-1)) {
818
upslog(LOG_ERR, "shmat");
820
return 0; /* failed */
823
shminfo.type = INFO_SHMID;
824
snprintf(shminfo.value, sizeof(shminfo.value), "%d", shmid);
826
/* create state file with pointer to shm struct */
827
writeshminfo(&shminfo);
829
/* use the same mtime number in both places */
835
#endif /* HAVE_SHMAT */
837
/* start the state file, and possibly the shared memory struct too */
838
void create_info(int numinfo, int shmok)
841
info_size = infomax * sizeof(itype);
843
info = xcalloc(1, info_size);
845
/* make sure we clean up when exiting */
847
signal(SIGINT, sigdie);
848
signal(SIGQUIT, sigdie);
852
/* see if the state file can be created */
857
/* SHM failures fall through and try normal mode */
858
if ((shmok) && (shm_create()))
864
if (ftruncate(statefd, info_size))
867
if ((shared_info = (itype *) mmap(NULL, info_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NOSYNC, statefd, 0)) == MAP_FAILED)
868
fatal("mmap fd=%d size=%u", statefd, info_size);
869
#else /* HAVE_MMAP */
871
shared_info = xcalloc(1, info_size);
873
#endif /* HAVE_MMAP */
875
/* clean out some space for later */
879
/* add a member to the info struct */
880
void addinfo (int type, const char *value, int flags, int auxdata)
884
for (i = 0; i < infomax; i++) {
885
if (info[i].type == INFO_UNUSED) { /* found open spot */
888
strlcpy(info[i].value, value, sizeof(info[i].value));
889
info[i].flags = flags;
890
info[i].auxdata = auxdata;
895
upslogx(LOG_ERR, "Unable to add new member to info array!");
900
/* add a new ENUM info entry and do other related housekeeping */
901
void addenum (int basetype, const char *value)
905
/* first find the basetype in the struct */
906
for (i = 0; i < infomax; i++)
907
if (info[i].type == basetype) {
909
/* add the enum value, then increment the enum count */
910
addinfo (INFO_ENUM, value, 0, basetype);
915
upslogx(LOG_ERR, "Unable to add enumerated type for base 0x%04x", basetype);
920
void createmsgq(void)
922
/* init handlers early */
923
memset (&upsh, '\0', sizeof(upsh));
930
struct sockaddr_un sa;
931
struct client_conn *next;
936
static struct client_conn *client_conn = NULL;
938
void close_client_conn(struct client_conn *cc)
940
struct client_conn *t1, *t2;
942
upsdebugx(1, "closing client_conn %p fd=%d", cc, cc->fd);
944
for (t1 = client_conn, t2 = NULL; t1; t2 = t1, t1 = t1->next)
952
if (cc == client_conn)
953
client_conn = cc->next;
956
FD_CLR(cc->fd, &sock_rfds);
958
if (cc->fd + 1 == sock_maxfd) {
961
for (t1 = client_conn; t1; t1 = t1->next) {
966
sock_maxfd = maxfd + 1;
972
/* get a message if one's waiting in the queue */
973
int getupsmsg(int wait)
979
struct client_conn *cc;
981
memcpy(&rfds, &sock_rfds, sizeof(rfds));
983
start_time = time(NULL);
986
upsdebugx(3, "select loop maxfd=%d", sock_maxfd);
990
ret = select(sock_maxfd, &rfds, NULL, NULL, &tv);
1001
for (cc = client_conn; cc; cc = cc->next) {
1002
if (FD_ISSET(cc->fd, &rfds)) {
1003
switch ((ret = read(cc->fd, (char *) &cc->msg, sizeof(cc->msg) - cc->msg_len))) {
1006
if (errno == 0 || errno == EINTR || errno == EAGAIN) /* try again the next time around */
1009
upsdebug(1, "read %d bytes from fd %d", ret, cc->fd);
1010
close_client_conn(cc);
1013
upsdebugx(1, "read %d bytes from fd %d", ret, cc->fd);
1016
upsdebugx(1, "msg_len=%d", cc->msg_len);
1018
if (cc->msg_len != sizeof(cc->msg)) /* buffer not full yet */
1021
if (cc->msg.dlen >= UPSMSG_MAXLEN) {
1022
upslogx(LOG_ERR, "client sent bad data - possible buffer overflow");
1023
close_client_conn(cc);
1027
switch (cc->msg.cmdtype) {
1030
upsh.setvar(cc->msg.auxcmd, cc->msg.dlen, cc->msg.data);
1032
upslogx(LOG_INFO, "No handler for SET command");
1034
case UPSMSG_INSTCMD:
1036
upsh.instcmd(cc->msg.auxcmd, cc->msg.dlen, cc->msg.data);
1038
upslogx(LOG_INFO, "No handler for INSTCMD command");
1041
upslogx(LOG_INFO, "Unknown msgcmd 0x%04x", cc->msg.cmdtype);
1046
upsdebugx(1, "finished message");
1051
if (FD_ISSET(sock_fd, &rfds)) {
1054
cc = xcalloc(1, sizeof(struct client_conn));
1055
sa_len = sizeof(cc->sa);
1057
if ((cc->fd = accept(sock_fd, (struct sockaddr *) &cc->sa, &sa_len)) != -1) {
1058
upsdebugx(1, "accept sock_fd fd=%d", cc->fd);
1060
cc->next = client_conn;
1063
FD_SET(cc->fd, &sock_rfds);
1064
if (cc->fd >= sock_maxfd)
1065
sock_maxfd = cc->fd + 1;
1067
upslog(LOG_NOTICE, "accept sock_fd");
1071
} while (start_time + wait < time(NULL));
1076
/* add these functions back when a driver is capable of testing them.
1077
void sendupsmsg(struct client_conn *cc, const msgtype *msg)
1079
if (write(cc->fd, msg, sizeof(msgtype)) != sizeof(msgtype)) {
1080
upslog(LOG_NOTICE, "write failed");
1081
close_client_conn(cc);
1085
void msgreply(struct client_conn *cc, int reptype)
1089
msg.cmdtype = reptype;
1094
sendupsmsg(cc, &msg);
1098
/* modify in - strip all trailing instances of <sep> */
1099
void rtrim(char *in, char sep)
1103
p = &in[strlen(in) - 1];
1113
/* try to unlock the port using any methods that are available */
1114
void unlockport (int upsfd, const char *port)
1119
if (!upsport) /* not already locked? */
1122
res = uu_unlock(upsport);
1124
/* free up allocated memory */
1128
fatalx("Can't uu_unlock %s: %s", upsport, uu_lockerr(res));
1130
#elif defined(HAVE_FLOCK)
1131
if (flock(upsfd, LOCK_UN) != 0)
1132
fatalx("can't unlock %s!", port);
1133
#elif defined(HAVE_LOCKF)
1134
lseek(upsfd, 0L, SEEK_SET);
1135
if (lockf(upsfd, F_ULOCK, 0L))
1136
fatalx("can't unlock %s!", port);
1140
/* close the state fd - used by the exiting parent */
1141
void close_statefd(void)