This is funcs.c in view mode; [Download] [Up]
/*
** f u n c s . c
**
** functions for UPS monitor daemon
**
** Arthur W. Neilson III
** art@pilikia.pegasus.com
** Sat Mar 30 1991
*/
#include <sys/ioctl.h>
#include "common.h"
/*
** g e t v a r s
**
** retrieve environment variables
*/
void
getvars()
{
char *s, *getenv();
if ((s = getenv(UPSPORT)) != NULL)
ups_port = s;
if ((s = getenv(UPSSHUT)) != NULL)
ups_shut = s;
if ((s = getenv(UPSLOG)) != NULL)
ups_log = s;
if ((s = getenv(UPSFAIL)) != NULL)
ups_fail = s;
if ((s = getenv(UPSREST)) != NULL)
ups_rest = s;
if ((s = getenv(UPSTIME)) != NULL)
ups_time = atoi(s);
}
/*
** g e t o p t i o n s
**
** retrieve and process command line options
*/
void
getoptions(ac, av)
int ac;
char *av[];
{
int c;
void version();
void usage();
extern char *optarg;
extern int optind, opterr;
/* display program version */
version(av[0]);
/* parse the command line */
while ((c = getopt(ac, av, "d:c:l:f:r:t:")) != EOF)
switch (c) {
case 'd': /* device option */
ups_port = optarg;
break;
case 'c': /* command option */
ups_shut = optarg;
break;
case 'l': /* logfile option */
ups_log = optarg;
break;
case 'f': /* failure option */
ups_fail = optarg;
break;
case 'r': /* restore option */
ups_rest = optarg;
break;
case 't': /* time option */
ups_time = atoi(optarg);
break;
case '\?': /* illegal option */
usage(av[0]);
exit(1);
}
}
/*
** c h k o p t i o n s
**
** check runtime options
** with various sanity tests
*/
void
chkoptions()
{
struct stat st;
char *p, buf[64];
/* UPS port must exist */
if (stat(ups_port, &st) == ERR) {
perror(ups_port);
exit(1);
}
/* and must be character special */
if ((st.st_mode & S_IFMT) != S_IFCHR) {
fprintf(stderr, "%s not character special\n", ups_port);
exit(1);
}
/* get command name out of shutdown command */
strcpy(buf, ups_shut);
if ((p = strtok(buf, " ")) == NULL)
p = buf;
/* shutdown command must exist */
if (stat(p, &st) == ERR) {
perror(ups_shut);
exit(1);
}
/* and must be a regular file */
if ((st.st_mode & S_IFMT) != S_IFREG) {
fprintf(stderr, "%s not regular\n", ups_port);
exit(1);
}
/* delay time must be > 0 and <= MAX_TIME */
if (ups_time < 1 || ups_time > MAX_TIME) {
fprintf(stderr, "time must be between 1 and %d\n", MAX_TIME);
exit(1);
}
}
/*
** m k d a e m o n
**
** create daemon process
*/
void
mkdaemon()
{
char c;
int stat;
unsigned int modembits;
unsigned int oldbits;
void sigcatch();
void writelog();
void writeall();
void shutdown();
writelog(START_MSG);
if (!fork()) {
/* close standard files */
close(0); /* stdin */
close(1); /* stdout */
close(2); /* stderr */
setpgrp(); /* disassociate from terminal */
/* ignore interrupts */
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
/* catch termination signal */
signal(SIGTERM, sigcatch);
/* and shutdown on alarm */
signal(SIGALRM, shutdown);
/* open log file for append */
if ((log_fd = open(ups_log, LOG_FLAGS, LOG_PERMS)) == ERR) {
perror("could not open log file");
exit(1);
}
/* and advisory lock it */
/*
if (lockf(log_fd, F_TLOCK, 0L) == ERR) {
perror("could not open lock file");
exit(1);
}
*/
writelog(START_MSG);
ups_fd = open(ups_port,O_RDONLY,0);
if (stat<0) {
perror("cant open port");
exit(1);
}
/* get old bits first time */
stat = ioctl(ups_fd,TIOCMGET,&oldbits);
while (1) {
stat = ioctl(ups_fd,TIOCMGET,&modembits);
if (modembits!=oldbits) {
if (state==UPS_LINE) {
state = UPS_BATTERY;
} else {
state = UPS_LINE;
}
switch(state) {
case UPS_LINE :
writelog(ONLINE_MSG);
writeall(ups_rest);
alarm(0);
break;
case UPS_BATTERY :
writelog(BATTERY_MSG);
writeall(ups_fail);
alarm(ups_time * SECS_PER_MIN/4);
break;
}
oldbits = modembits;
}
sleep(interval);
}
close(log_fd);
close(ups_fd);
} else {
printf("process forked\n");
}
}
/*
** s i g c a t c h
**
** catch termination signal
*/
void
sigcatch()
{
writelog(TERM_MSG);
close(log_fd);
close(ups_fd);
exit(1);
}
/*
** w r i t e l o g
**
** write message to the UPS log file
*/
void
writelog(msg)
char *msg;
{
time_t ticks;
char *p, *ct;
char msg_buf[80];
char *strrchr();
time(&ticks);
ct = ctime(&ticks);
/* find newline in buffer */
if ((p = strrchr(ct, '\n')) != NULL)
*p = NULL; /* and zap it */
sprintf(msg_buf, "%s -- %s\n", ct, msg);
write(log_fd, msg_buf, strlen(msg_buf));
}
/*
** w r i t e a l l
**
** write to all users
*/
void
writeall(fn)
char *fn;
{
struct stat st;
void attach();
/* message file must exist */
if (stat(fn, &st) == ERR)
return;
/* and must be a regular file */
if ((st.st_mode & S_IFMT) != S_IFREG)
return;
if (!fork()) {
attach(CONSOLE);
/* write message file to users */
execlp(WALL, WALL, fn, NULL);
}
}
/*
** s h u t d o w n
**
** shutdown the system
*/
void
shutdown()
{
void attach();
writelog(SHUTDOWN_MSG);
close(ups_log);
close(ups_port);
if (!fork()) {
attach(CONSOLE);
chdir(ROOT);
/* execute shutdown command */
execlp(SH, SH, ups_shut, NULL);
}
}
/*
** a t t a c h
**
** attach standard i/o to a device
*/
void
attach(dev)
char *dev;
{
int fd;
/* close standard files */
close(0); /* stdin */
close(1); /* stdout */
close(2); /* stderr */
/* attach stdin to named device */
if ((fd = open(dev, O_RDWR)) == ERR)
exit(1);
dup(fd); /* and stdout */
dup(fd); /* and stderr */
}
/*
** b a s e n a m e
**
** remove absolute path from filename
**
*/
char *
basename(s)
char *s;
{
register char *p;
/* point to char after last '/' */
if ((p = strrchr(s, '/')) != NULL)
return (++p);
return (s);
}
/*
** v e r s i o n
**
** display program version
*/
void
version(s)
char *s;
{
char *basename();
/* display version in foreground */
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
fprintf(stderr, "%s release %s version %d.%d patchlevel %d\n",
basename(s), RELEASE_DATE, RELEASE, REVISION,
PATCHLEVEL);
}
/*
** u s a g e
**
** display program usage
*/
void
usage(s)
char *s;
{
char *basename();
fprintf(stderr, "usage: %s [-d tty][-c cmd][-l file][-f file][-r file][-t min]\n", basename(s));
fprintf(stderr, "\t-d tty\t\tpathname of UPS device\n");
fprintf(stderr, "\t-c cmd\t\tpathname of shutdown command\n");
fprintf(stderr, "\t-l file\t\tpathname of UPS log file\n");
fprintf(stderr, "\t-f file\t\tpathname of UPS fail message file\n");
fprintf(stderr, "\t-r file\t\tpathname of UPS restore message file\n");
fprintf(stderr, "\t-t min\t\tdelay time in minutes\n");
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.