[alt.sources] UPS daemon with gameport hardware interface

marc@PostImage.COM (Marc Boucher) (05/07/91)

Yet another ups daemon. This one's good for people without a serial port to
spare. (The hardware interface uses the game port)

This code is being released because of the numerous requests I have received
for it. I am placing it in the public domain. It's probably filled with local
dependencies and will require some adaptation to your site.

On powerloss, it stops cron, disables logins (by creating /etc/issue.linefail-
when this file exists, our custom login program displays its contents and
aborts the login attempt) and broadcasts a message to all logged in users
(except those whose names start with "uu" [uucp logins]; again, a local
assumption). The system is brought down only when the low battery condition
is detected. If power returns before the battery becomes low, cron
is restarted, /etc/issue.linefail removed and the users are notified.

Brian E. Litzinger's peek driver must be installed in your kernel and available
as /dev/peek. You can get it by anonymous FTP from
	svin02.info.win.tue.nl:/pub/sysvX86/peek.tar.z

If you can't FTP, email me.

-Marc.       
                                                       
-- 
Marc Boucher                   Internet: marc@PostImage.COM      BIX: mboucher
Dir., Informatique             Telephone: (514) 489-8989         FAX: 489-0242
(H) PostImage Inc.             6265 St-Jacques O., Montreal QC Canada H4B 1T8


#!/bin/sh
# This is a shell archive (shar 3.20)
# made 05/06/1991 19:14 UTC by marc@Cactus
# Source directory /usr3/home/marc/upsd
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1136 -rw-r--r-- README
#   2009 -rw------- CABLE
#    223 -rw-r--r-- Makefile
#   4411 -rw-r--r-- upsd.c
#    286 -rwxr--r-- upsd.init
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= README ==============
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
XYet another ups daemon. This one's good for people without a serial port to
Xspare. (The hardware interface uses the game port)
X
XThis code is being released because of the numerous requests I have received
Xfor it. I am placing it in the public domain. It's probably filled with local
Xdependencies and will require some adaptation to your site.
X
XOn powerloss, it stops cron, disables logins (by creating /etc/issue.linefail-
Xwhen this file exists, our custom login program displays its contents and
Xaborts the login attempt) and broadcasts a message to all logged in users
X(except those whose names start with "uu" [uucp logins]; again, a local
Xassumption). The system is brought down only when the low battery condition
Xis detected. If power returns before the battery becomes low, cron
Xis restarted, /etc/issue.linefail removed and the users are notified.
X
XBrian E. Litzinger's peek driver must be installed in your kernel and available
Xas /dev/peek. You can get it by anonymous FTP from
X	svin02.info.win.tue.nl:/pub/sysvX86/peek.tar.z
X
XIf you can't FTP, email me.
X
XMarc Boucher.
XInternet: marc@PostImage.COM Telephone: +1 514 489-8989
SHAR_EOF
$TOUCH -am 0506151391 README &&
chmod 0644 README ||
echo "restore of README failed"
set `wc -c README`;Wc_c=$1
if test "$Wc_c" != "1136"; then
	echo original size 1136, current size $Wc_c
fi
# ============= CABLE ==============
echo "x - extracting CABLE (Text)"
sed 's/^X//' << 'SHAR_EOF' > CABLE &&
X
XThe following cable will link any standard PC joystick port to
Xany American Power Conversion UPS computer interface. This has been tested 
Xon an APC 520ES model UPS and on two different joystick cards. If your
Xjoystick card has two ports, you can use either without reconfiguring
Xthe software.  The joystick buttons used for monitoring the UPS
Xare those of the primary joystick.  If you wish to keep using a primary 
Xjoystick on your system and still use this software, you will need to
Xmodify the cable and software appropriately (i.e. wire buttons 6 and 7
Xinstead, figure out new port values for line fail and low battery).
X
X
X                 UPS -> PC-Type Joystick port interface
X                 --------------------------------------
X
X
XIBM PC Standard Joystick port        American Power Conversion UPS
X-----------------------------        -----------------------------
X   DB-15 connector(male)                DB-9 connector (male)      
X
X      PIN #    DESC          Wiring         PIN #    DESC
X       1       + 5VDC                        1    hi=RS-232C shutdown input
X       2       BUTTON 4 --------\            2    hi=RS-232C fail
X       3       POSITION 0        \---------- 3    closed=line fail
X       4       GROUND ---------------------- 4    switch common
X       5       N/C                +--------- 5    closed=low battery
X       6       POSITION 1        /           6    N/C
X       7       BUTTON 5 --------+            7    N/C
X       8       + 5VDC                        8    N/C
X       9       + 5VDC                        9    chassis ground
X       10      BUTTON 6
X       11      POSITION 2
X       12      GROUND
X       13      POSITION 3
X       14      BUTTON 7
X       15      GROUND
X
XNote: Due to the lack of output signals on the joystick port, the UPS
X      input that allows the UPS to shut down to conserve its batteries is
X      not supported.  One possibility involves the use of the PC speaker 
X      and some external circuitry...  any takers ?   - pascal@CAM.ORG
X
X
X
SHAR_EOF
$TOUCH -am 0506151491 CABLE &&
chmod 0600 CABLE ||
echo "restore of CABLE failed"
set `wc -c CABLE`;Wc_c=$1
if test "$Wc_c" != "2009"; then
	echo original size 2009, current size $Wc_c
fi
# ============= Makefile ==============
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X
XINSTBIN=/usr/local/etc/upsd
X
Xupsd: upsd.c
X	cc -O -s -o upsd upsd.c -lc_s
X	mcs -d upsd
X
Xinstall: upsd
X	-mv -f $(INSTBIN) $(INSTBIN)-
X	rm -f $(INSTBIN)-
X	cp upsd $(INSTBIN)
X	chmod 100 $(INSTBIN)
X
Xclean:
X	rm -f *.o upsd core
SHAR_EOF
$TOUCH -am 1215193690 Makefile &&
chmod 0644 Makefile ||
echo "restore of Makefile failed"
set `wc -c Makefile`;Wc_c=$1
if test "$Wc_c" != "223"; then
	echo original size 223, current size $Wc_c
fi
# ============= upsd.c ==============
echo "x - extracting upsd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > upsd.c &&
X/*
X $Id: upsd.c,v 1.3 1991/05/06 19:10:34 marc Exp marc $
X
XYet another ups daemon. This one's good for people without a serial port to
Xspare. (The hardware interface uses the game port)
X
XThis code is being released because of the numerous requests I have received
Xfor it. I am placing it in the public domain. It's probably filled with local
Xdependencies and will require some adaptation to your site.
X
XOn powerloss, it stops cron, disables logins (by creating /etc/issue.linefail-
Xwhen this file exists, our custom login program displays its contents and
Xaborts the login attempt) and broadcasts a message to all logged in users
X(except those whose names start with "uu" [uucp logins]; again, a local
Xassumption). The system is brought down only when the low battery condition
Xis detected. If power returns before the battery becomes low, cron
Xis restarted, /etc/issue.linefail removed and the users are notified.
X
XBrian E. Litzinger's peek driver must be installed in your kernel and available
Xas /dev/peek. You can get it by anonymous FTP from
X	svin02.info.win.tue.nl:/pub/sysvX86/peek.tar.z
X
XIf you can't FTP, email me.
X
XMarc Boucher.
XInternet: marc@PostImage.COM Telephone: +1 514 489-8989
X
X*/
X#include <fcntl.h>
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/signal.h>
X#include <sys/utsname.h>
X#include <utmp.h>
X
X#include <sys/peek.h>
X
X#define	INTERVAL	20	/* Time in seconds between checks */
X
X#define PORTADDR	0x201
X
X#define	UPSF_LINEFAIL	(1<<6)
X#define	UPSF_LOWBATT	(1<<7)
X
X#define	CONSOLE		"/dev/console"
X#define	LOGFILE		"/usr/adm/upslog"
X#define	ISSUEPOWER	"/etc/issue.linefail"
X
Xvoid SendMsg(str, line)
Xchar *str, *line;
X{
X	FILE *linefil;
X
X	linefil=fopen(line, "w");
X	if(linefil) {
X		time_t ti;
X		struct utsname unam;
X		char tibuf[40];
X
X		uname(&unam);
X		time(&ti);
X		cftime(tibuf, "%a %b %e %T %Y", &ti);
X		fprintf(linefil, "\n\007Broadcast Message from UPS daemon on %s [ %s ]...\n%s\n\n", unam.nodename, tibuf, str);
X		fclose(linefil);
X	}
X}
X
Xvoid Broadcast(str)
Xchar *str;
X{
X	struct utmp *uptr, *getutent();
X	int console=0;
X
X	setutent();
X	while(uptr=getutent()) {
X		if((uptr->ut_type==USER_PROCESS)&&(strncmp(uptr->ut_user, "uu", 2))) {
X			char line[32];
X
X			sprintf(line, "/dev/%s", uptr->ut_line);
X			if(!strcmp(line, CONSOLE)) console=1;
X			SendMsg(str, line);
X		}
X	}
X	endutent();
X	if(!console) SendMsg(str, CONSOLE);
X}
X
Xvoid LogString(class, str)
Xchar class;
Xchar *str;
X{
X	char *datimebuf[255];
X	time_t ti;
X	FILE *logfil;
X
X	time(&ti);
X	cftime(datimebuf, "%D %T", &ti);
X
X	logfil=fopen(LOGFILE, "a");
X
X	if(logfil) {
X		fprintf(logfil, "%c/%d %s - %s\n", class, getpid(), datimebuf, str);
X		fclose(logfil);
X	}
X}
X
Xvoid LineFail()
X{
X	FILE *issuepower;
X
X	LogString('F', "Line Fail");
X	Broadcast("POWER FAILURE DETECTED: SYSTEM WILL SHUTDOWN IF UPS BATTERY BECOMES LOW");
X	system("/etc/init.d/cron stop");
X	issuepower=fopen(ISSUEPOWER, "w");
X	if(!issuepower) LogString('E', "Can't open /etc/issue.linefail for writing");
X	else {
X		fprintf(issuepower, "\nLogins have been disabled by the UPS daemon because of power failure.\n");
X		fclose(issuepower);
X	}
X}
X
Xvoid EndLineFail()
X{
X
X	LogString('F', "Line Normal");
X	Broadcast("GOOD NEWS: POWER HAS BEEN RESTORED.");
X	system("/etc/init.d/cron start");
X	unlink(ISSUEPOWER);
X}
X
Xvoid LowBattery()
X{
X	LogString('L', "Low Battery");
X	Broadcast("UPS BATTERY IS LOW!!! SYSTEM GOING DOWN IN 40 SECONDS. LOGOUT NOW!");
X	sleep(40);
X	Broadcast("UPS BATTERY IS LOW!!! SYSTEM GOING DOWN IMMEDIATELY!");
X	LogString('L', "System going down");
X	sync();
X	unlink(ISSUEPOWER);
X	close(0); close(1); close(2);
X	open("/dev/console", O_RDWR);
X	open("/dev/console", O_RDWR);
X	open("/dev/console", O_RDWR);
X	sync();
X	execlp("/etc/init", "init", "0", 0);
X	LogString('E', "Can't exec /etc/init!!!");
X	sync();
X	exit(1);
X}
X
Xmain()
X{
X	int peekfd;
X	struct peek_t pd;
X	int linefail=0;
X
X	if(fork()) exit(0);
X
X	setpgrp();
X
X	chdir("/");
X
X	signal(SIGHUP, SIG_IGN);
X	signal(SIGINT, SIG_IGN);
X
X	pd.port=PORTADDR;
X
X	peekfd=open("/dev/peek", O_RDONLY);
X	if(peekfd==-1) {
X		LogString('E', "Can't open /dev/peek");
X		exit(1);
X	}
X
X	for(;;) {
X		if (ioctl(peekfd,PEEKIN,&pd)==-1) {
X			LogString('E', "ioctl() error");
X			exit(1);
X		}
X
X		if(pd.data&UPSF_LINEFAIL) {
X			if(linefail) {
X				linefail=0;
X				EndLineFail();
X			}
X		} else if(!linefail) {
X			linefail=1;
X			LineFail();
X		}
X
X		if(!(pd.data&UPSF_LOWBATT)) LowBattery(); /* Never returns */
X
X		sleep(INTERVAL);
X	}
X	/* Not reached */
X}
SHAR_EOF
$TOUCH -am 0506151291 upsd.c &&
chmod 0644 upsd.c ||
echo "restore of upsd.c failed"
set `wc -c upsd.c`;Wc_c=$1
if test "$Wc_c" != "4411"; then
	echo original size 4411, current size $Wc_c
fi
# ============= upsd.init ==============
echo "x - extracting upsd.init (Text)"
sed 's/^X//' << 'SHAR_EOF' > upsd.init &&
Xcase $1 in
X'start')
X	( cd /usr/local/etc ; PATH=.:$PATH ; upsd </dev/console >/dev/console 2>&1 )
X	;;
X'stop')
X	pid=`/bin/ps -e | grep upsd | sed -e 's/^  *//' -e 's/ .*//'`
X	if [ "${pid}" != "" ]
X	then
X		/bin/kill ${pid}
X	fi
X	;;
X*)
X	echo "usage: /etc/init.d/upsd {start|stop}"
X	;;
Xesac
SHAR_EOF
$TOUCH -am 0506144791 upsd.init &&
chmod 0744 upsd.init ||
echo "restore of upsd.init failed"
set `wc -c upsd.init`;Wc_c=$1
if test "$Wc_c" != "286"; then
	echo original size 286, current size $Wc_c
fi
exit 0