home *** CD-ROM | disk | FTP | other *** search
- /*
- $Id: upsd.c,v 1.3 1991/05/06 19:10:34 marc Exp marc $
-
- 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 Boucher.
- Internet: marc@PostImage.COM Telephone: +1 514 489-8989
-
- */
- #include <fcntl.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/signal.h>
- #include <sys/utsname.h>
- #include <utmp.h>
-
- #include <sys/peek.h>
-
- #define INTERVAL 20 /* Time in seconds between checks */
-
- #define PORTADDR 0x201
-
- #define UPSF_LINEFAIL (1<<6)
- #define UPSF_LOWBATT (1<<7)
-
- #define CONSOLE "/dev/console"
- #define LOGFILE "/usr/adm/upslog"
- #define ISSUEPOWER "/etc/issue.linefail"
-
- void SendMsg(str, line)
- char *str, *line;
- {
- FILE *linefil;
-
- linefil=fopen(line, "w");
- if(linefil) {
- time_t ti;
- struct utsname unam;
- char tibuf[40];
-
- uname(&unam);
- time(&ti);
- cftime(tibuf, "%a %b %e %T %Y", &ti);
- fprintf(linefil, "\n\007Broadcast Message from UPS daemon on %s [ %s ]...\n%s\n\n", unam.nodename, tibuf, str);
- fclose(linefil);
- }
- }
-
- void Broadcast(str)
- char *str;
- {
- struct utmp *uptr, *getutent();
- int console=0;
-
- setutent();
- while(uptr=getutent()) {
- if((uptr->ut_type==USER_PROCESS)&&(strncmp(uptr->ut_user, "uu", 2))) {
- char line[32];
-
- sprintf(line, "/dev/%s", uptr->ut_line);
- if(!strcmp(line, CONSOLE)) console=1;
- SendMsg(str, line);
- }
- }
- endutent();
- if(!console) SendMsg(str, CONSOLE);
- }
-
- void LogString(class, str)
- char class;
- char *str;
- {
- char *datimebuf[255];
- time_t ti;
- FILE *logfil;
-
- time(&ti);
- cftime(datimebuf, "%D %T", &ti);
-
- logfil=fopen(LOGFILE, "a");
-
- if(logfil) {
- fprintf(logfil, "%c/%d %s - %s\n", class, getpid(), datimebuf, str);
- fclose(logfil);
- }
- }
-
- void LineFail()
- {
- FILE *issuepower;
-
- LogString('F', "Line Fail");
- Broadcast("POWER FAILURE DETECTED: SYSTEM WILL SHUTDOWN IF UPS BATTERY BECOMES LOW");
- system("/etc/init.d/cron stop");
- issuepower=fopen(ISSUEPOWER, "w");
- if(!issuepower) LogString('E', "Can't open /etc/issue.linefail for writing");
- else {
- fprintf(issuepower, "\nLogins have been disabled by the UPS daemon because of power failure.\n");
- fclose(issuepower);
- }
- }
-
- void EndLineFail()
- {
-
- LogString('F', "Line Normal");
- Broadcast("GOOD NEWS: POWER HAS BEEN RESTORED.");
- system("/etc/init.d/cron start");
- unlink(ISSUEPOWER);
- }
-
- void LowBattery()
- {
- LogString('L', "Low Battery");
- Broadcast("UPS BATTERY IS LOW!!! SYSTEM GOING DOWN IN 40 SECONDS. LOGOUT NOW!");
- sleep(40);
- Broadcast("UPS BATTERY IS LOW!!! SYSTEM GOING DOWN IMMEDIATELY!");
- LogString('L', "System going down");
- sync();
- unlink(ISSUEPOWER);
- close(0); close(1); close(2);
- open("/dev/console", O_RDWR);
- open("/dev/console", O_RDWR);
- open("/dev/console", O_RDWR);
- sync();
- execlp("/etc/init", "init", "0", 0);
- LogString('E', "Can't exec /etc/init!!!");
- sync();
- exit(1);
- }
-
- main()
- {
- int peekfd;
- struct peek_t pd;
- int linefail=0;
-
- if(fork()) exit(0);
-
- setpgrp();
-
- chdir("/");
-
- signal(SIGHUP, SIG_IGN);
- signal(SIGINT, SIG_IGN);
-
- pd.port=PORTADDR;
-
- peekfd=open("/dev/peek", O_RDONLY);
- if(peekfd==-1) {
- LogString('E', "Can't open /dev/peek");
- exit(1);
- }
-
- for(;;) {
- if (ioctl(peekfd,PEEKIN,&pd)==-1) {
- LogString('E', "ioctl() error");
- exit(1);
- }
-
- if(pd.data&UPSF_LINEFAIL) {
- if(linefail) {
- linefail=0;
- EndLineFail();
- }
- } else if(!linefail) {
- linefail=1;
- LineFail();
- }
-
- if(!(pd.data&UPSF_LOWBATT)) LowBattery(); /* Never returns */
-
- sleep(INTERVAL);
- }
- /* Not reached */
- }
-