/*
Copyright (C) 2001 Ulric Eriksson <ulric@siag.nu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdarg.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/socket.h>
#define CFG ETCDIR "/dwatch.conf"
#define TIMEOUT 5
static int foreground = 1;
static int debuglevel = 0;
static int verboselevel = 0;
static char *cfg = CFG;
static int timeout = TIMEOUT;
static void debug(char *fmt, ...)
{
char b[4096];
va_list ap;
va_start(ap, fmt);
vsnprintf(b, sizeof b, fmt, ap);
if (foreground) {
fprintf(stderr, "%s\n", b);
} else {
openlog("pen", LOG_CONS, LOG_USER);
syslog(LOG_DEBUG, "%s\n", b);
closelog();
}
va_end(ap);
}
static void error(char *fmt, ...)
{
char b[4096];
va_list ap;
va_start(ap, fmt);
vsnprintf(b, sizeof b, fmt, ap);
if (foreground) {
fprintf(stderr, "%s\n", b);
} else {
openlog("pen", LOG_CONS, LOG_USER);
syslog(LOG_ERR, "%s\n", b);
closelog();
}
va_end(ap);
exit(1);
}
static void usage(void)
{
printf("usage:\n"
" dwatch [-d] [-f conf]\n"
"\n"
" -d debugging on\n"
" -v verbose\n"
" -f conf alternate configuration file [%s]\n",
CFG);
exit(0);
}
static void options(int argc, char **argv)
{
int c;
while ((c = getopt(argc, argv, "f:dv")) != EOF) {
switch (c) {
case 'd':
debuglevel++;
break;
case 'f':
cfg = optarg;
break;
case 'v':
verboselevel++;
break;
default:
usage();
break;
}
}
}
static int try_process(char *p)
{
FILE *fp;
char b[1024];
if (debuglevel) debug("Scanning for process '%s'", p);
fp = popen(PS, "r");
if (fp == NULL) error("Can't run ps");
while (fgets(b, sizeof b, fp)) {
if (strstr(b, p)) {
pclose(fp);
return 0;
}
}
pclose(fp);
return -1;
}
static void tcp_alarm(int dummy)
{
;
}
static int try_tcp(char *p)
{
struct sockaddr_in serv_addr;
int upfd;
char *addr = strtok(p, ":"), *port = strtok(NULL, ":");
struct hostent *h = gethostbyname(addr);
struct in_addr a;
struct servent *s = getservbyname(port, "tcp");
int po;
if (h == NULL) {
if ((a.s_addr = inet_addr(addr)) == -1) {
error("unknown or invalid address [%s]\n", addr);
}
} else {
memcpy(&a, h->h_addr, h->h_length);
}
if (s == NULL) {
po = atoi(port);
} else {
po = ntohs(s->s_port);
}
if (debuglevel) debug("Connecting to %s", p);
upfd = socket(AF_INET, SOCK_STREAM, 0);
if (upfd < 0) error("Error opening socket");
memset(&serv_addr, 0, sizeof serv_addr);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = a.s_addr;
if (debuglevel) debug("Port '%s' = %d", port, po);
serv_addr.sin_port = htons(po);
signal(SIGALRM, tcp_alarm);
alarm(timeout);
if (connect(upfd, (struct sockaddr *) &serv_addr,
sizeof serv_addr) == -1) {
if (debuglevel) debug("Connect failed");
close(upfd);
return -1;
}
if (debuglevel) debug("Successful connect");
close(upfd);
return 0;
}
int main(int argc, char **argv)
{
char b[1024], directive[1024], argument[1024], command[1024];
int n;
FILE *fp;
options(argc, argv);
fp = fopen(cfg, "r");
if (fp == NULL) error("Can't open configuration file '%s'", cfg);
while (fgets(b, sizeof b, fp)) {
if (b[0] == '#') continue;
n = sscanf(b, "%s \"%[^\"]\" %[^\n]",
directive, argument, command);
if (n != 3) {
if (debuglevel) debug("Bogus conf line '%s'", b);
continue;
}
if (debuglevel) {
debug("directive: '%s'", directive);
debug("argument: '%s'", argument);
debug("command: '%s'", command);
}
switch (directive[0]) {
case 'P':
if (try_process(argument)) {
if (debuglevel) debug("Running '%s'", command);
if (verboselevel) {
printf("No process '%s'; running '%s'\n",
argument, command);
}
system(command);
sleep(10);
}
break;
case 'T':
if (try_tcp(argument)) {
if (debuglevel) debug("Running '%s'", command);
if (verboselevel) {
printf("No listener on %s, running '%s'\n",
argument, command);
}
system(command);
sleep(10);
}
break;
default:
error("Bogus directive '%s'", directive);
break;
}
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1