#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stropts.h>
#include <signal.h>
#include <sys/stat.h>
#include <poll.h>
#include "misc.h"
#include "msgs.h"
#include "extern.h"
#include <sac.h>
#include "adm.h"
#include "structs.h"
struct sactab *
findpm(tag)
register char *tag;
{
register struct sactab *sp;
for (sp = Sactab; sp; sp = sp->sc_next) {
if (!strcmp(tag, sp->sc_tag))
return(sp);
}
return(NULL);
}
void
sigpoll()
{
struct pollfd fds;
struct admcmd cmd;
register struct admcmd *ap = &cmd;
struct admack ack;
register struct admack *ak = &ack;
register struct sactab *sp;
struct sacmsg sacmsg;
char **data;
char *p;
register int i;
int ret;
sigset_t cset;
sigset_t tset;
# ifdef DEBUG
debug("in sigpoll");
# endif
fds.fd = Cfd;
fds.events = POLLIN;
fds.revents = 0;
if (poll(&fds, 1, 0) < 0)
error(E_POLL, EXIT);
switch (fds.revents) {
case POLLIN:
if (read(Cfd, ap, sizeof(struct admcmd)) < 0) {
error(E_READ, EXIT);
}
switch (ap->ac_mtype) {
case AC_START:
# ifdef DEBUG
(void) sprintf(Scratch, "Got AC_START for <%s>", ap->ac_tag);
log(Scratch);
# endif
if ((sp = findpm(ap->ac_tag)) == NULL) {
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_NOPM;
ak->ak_size = 0;
sendack(ak);
break;
}
switch (sp->sc_sstate) {
case UNKNOWN:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_RECOVER;
ak->ak_size = 0;
sendack(ak);
break;
case FAILED:
case NOTRUNNING:
sp->sc_rscnt = 0;
if (ret = startpm(sp)) {
ak->ak_pid = ap->ac_pid;
if (ret == -1)
ak->ak_resp = AK_PMLOCK;
else
ak->ak_resp = AK_REQFAIL;
ak->ak_size = 0;
sendack(ak);
break;
}
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
sendack(ak);
break;
case ENABLED:
case DISABLED:
case STARTING:
case STOPPING:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_PMRUN;
ak->ak_size = 0;
sendack(ak);
break;
}
break;
case AC_KILL:
# ifdef DEBUG
(void) sprintf(Scratch, "Got AC_KILL for <%s>", ap->ac_tag);
log(Scratch);
# endif
if ((sp = findpm(ap->ac_tag)) == NULL) {
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_NOPM;
ak->ak_size = 0;
sendack(ak);
break;
}
switch (sp->sc_sstate) {
case UNKNOWN:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_RECOVER;
ak->ak_size = 0;
sendack(ak);
break;
case NOTRUNNING:
case FAILED:
case STOPPING:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_PMNOTRUN;
ak->ak_size = 0;
sendack(ak);
break;
case STARTING:
case ENABLED:
case DISABLED:
(void) sigprocmask(SIG_SETMASK, NULL, &cset);
tset = cset;
(void) sigaddset(&tset, SIGALRM);
(void) sigaddset(&tset, SIGCLD);
(void) sigprocmask(SIG_SETMASK, &tset, NULL);
if (sendsig(sp, SIGTERM)) {
(void) sprintf(Scratch, "could not send SIGTERM to <%s>", sp->sc_tag);
log(Scratch);
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_NOCONTACT;
ak->ak_size = 0;
sendack(ak);
(void) sigprocmask(SIG_SETMASK, &cset, NULL);
break;
}
sp->sc_lstate = NOTRUNNING;
sp->sc_sstate = NOTRUNNING;
sp->sc_pstate = STOPPING;
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
sendack(ak);
(void) sprintf(Scratch, "terminating <%s>", sp->sc_tag);
log(Scratch);
(void) sigprocmask(SIG_SETMASK, &cset, NULL);
break;
}
break;
case AC_ENABLE:
# ifdef DEBUG
(void) sprintf(Scratch, "Got AC_ENABLE for <%s>", ap->ac_tag);
log(Scratch);
# endif
if ((sp = findpm(ap->ac_tag)) == NULL) {
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_NOPM;
ak->ak_size = 0;
sendack(ak);
break;
}
switch (sp->sc_sstate) {
case UNKNOWN:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_RECOVER;
ak->ak_size = 0;
sendack(ak);
break;
case NOTRUNNING:
case FAILED:
case STOPPING:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_PMNOTRUN;
ak->ak_size = 0;
sendack(ak);
break;
case STARTING:
case DISABLED:
sacmsg.sc_type = SC_ENABLE;
sacmsg.sc_size = 0;
sp->sc_sstate = ENABLED;
sp->sc_lstate = ENABLED;
sendpmmsg(sp, &sacmsg);
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
sendack(ak);
break;
case ENABLED:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
sendack(ak);
break;
}
break;
case AC_DISABLE:
# ifdef DEBUG
(void) sprintf(Scratch, "Got AC_DISABLE for <%s>", ap->ac_tag);
log(Scratch);
# endif
if ((sp = findpm(ap->ac_tag)) == NULL) {
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_NOPM;
ak->ak_size = 0;
sendack(ak);
break;
}
switch (sp->sc_sstate) {
case UNKNOWN:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_RECOVER;
ak->ak_size = 0;
sendack(ak);
break;
case NOTRUNNING:
case FAILED:
case STOPPING:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_PMNOTRUN;
ak->ak_size = 0;
sendack(ak);
break;
case STARTING:
case ENABLED:
sacmsg.sc_type = SC_DISABLE;
sacmsg.sc_size = 0;
sp->sc_sstate = DISABLED;
sp->sc_lstate = DISABLED;
sendpmmsg(sp, &sacmsg);
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
sendack(ak);
break;
case DISABLED:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
sendack(ak);
break;
}
break;
case AC_STATUS:
# ifdef DEBUG
log("Got AC_STATUS");
# endif
data = dump_table();
if ((data == NULL) && (Nentries > 0)) {
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_REQFAIL;
ak->ak_size = 0;
sendack(ak);
break;
}
ak->ak_size = 0;
for (i = 0; i < Nentries; ++i)
ak->ak_size += strlen(data[i]);
# ifdef DEBUG
(void) sprintf(Scratch, "ak_size is %d", ak->ak_size);
debug(Scratch);
# endif
if ((p = malloc((unsigned) (ak->ak_size + 1))) == NULL) {
error(E_MALLOC, CONT);
for (i = 0; i < Nentries; ++i)
free(data[i]);
free((char *) data);
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_REQFAIL;
ak->ak_size = 0;
sendack(ak);
break;
}
*p = '\0';
for (i = 0; i < Nentries; ++i) {
(void) strcat(p, data[i]);
free(data[i]);
}
# ifdef DEBUG
debug(p);
# endif
if (data)
free((char *) data);
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
sendack(ak);
if (ak->ak_size)
if (write(Cfd, p, (unsigned) ak->ak_size) != ak->ak_size)
log("could not send info");
free(p);
break;
case AC_SACREAD:
# ifdef DEBUG
log("Got AC_SACREAD");
# endif
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
read_table(TRUE);
sendack(ak);
break;
case AC_PMREAD:
# ifdef DEBUG
(void) sprintf(Scratch, "Got AC_PMREAD for <%s>", ap->ac_tag);
log(Scratch);
# endif
if ((sp = findpm(ap->ac_tag)) == NULL) {
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_NOPM;
ak->ak_size = 0;
sendack(ak);
break;
}
switch (sp->sc_sstate) {
case UNKNOWN:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_RECOVER;
ak->ak_size = 0;
sendack(ak);
break;
case NOTRUNNING:
case FAILED:
case STOPPING:
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_PMNOTRUN;
ak->ak_size = 0;
sendack(ak);
break;
case STARTING:
case ENABLED:
case DISABLED:
sacmsg.sc_type = SC_READDB;
sacmsg.sc_size = 0;
sendpmmsg(sp, &sacmsg);
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_ACK;
ak->ak_size = 0;
sendack(ak);
break;
}
break;
default:
(void) sprintf(Scratch, "Got unknown message for <%s>", ap->ac_tag);
log(Scratch);
ak->ak_pid = ap->ac_pid;
ak->ak_resp = AK_UNKNOWN;
ak->ak_size = 0;
sendack(ak);
break;
}
break;
default:
error(E_POLL, EXIT);
}
}
void
sendack(ap)
struct admack *ap;
{
# ifdef DEBUG
debug("in sendack");
# endif
if (write(Cfd, ap, sizeof(struct admack)) != sizeof(struct admack))
log("Could not send ack");
}
void
sendpmmsg(sp, sm)
register struct sactab *sp;
register struct sacmsg *sm;
{
char buf[SIZE];
# ifdef DEBUG
debug("in sendpmmsg");
# endif
if (write(sp->sc_fd, sm, sizeof(struct sacmsg)) != sizeof(struct sacmsg)) {
(void) sprintf(buf, "message to <%s> failed", sp->sc_tag);
log(buf);
}
}
int
sendsig(struct sactab *sp, int signo)
{
pid_t pid;
pid_t checklock();
# ifdef DEBUG
(void) sprintf(Scratch, "in sendsig - sending signo %d to %s", signo, sp->sc_tag);
debug(Scratch);
# endif
if (pid = checklock(sp)) {
if (kill(pid, signo) < 0) {
# ifdef DEBUG
debug("in sendsig - kill failed");
# endif
return(-1);
}
else
return(0);
}
else {
# ifdef DEBUG
debug("in sendsig - checklock failed");
# endif
return(-1);
}
}
pid_t
checklock(sp)
register struct sactab *sp;
{
int fd;
char buf[SIZE];
int ret;
# ifdef DEBUG
debug("in checklock");
# endif
(void) sprintf(Scratch, "%s/%s/_pid", HOME, sp->sc_tag);
fd = open(Scratch, O_RDONLY);
if (fd < 0) {
(void) sprintf(Scratch, "can not open _pid file for <%s>", sp->sc_tag);
log(Scratch);
return((pid_t)0);
}
if (lockf(fd, F_TEST, 0) < 0) {
if ((ret = read(fd, buf, SIZE - 1)) < 0) {
(void) close(fd);
return((pid_t)0);
}
(void) close(fd);
buf[ret] = '\0';
return((pid_t)atol(buf));
}
(void) close(fd);
return((pid_t)0);
}