From owner-FreeBSD-users-jp@jp.freebsd.org  Fri Feb 20 18:17:15 1998
Received: by jaz.jp.freebsd.org (8.8.8+3.0Wbeta7/8.7.3) id SAA10906
	Fri, 20 Feb 1998 18:17:15 +0900 (JST)
Received: by jaz.jp.freebsd.org (8.8.8+3.0Wbeta7/8.7.3) with SMTP id SAA10892
	for <FreeBSD-users-jp@jp.freebsd.org>; Fri, 20 Feb 1998 18:16:55 +0900 (JST)
Received: from tkudo by rdc.tohoku-epco.co.jp (SMI-8.6/SMI-SVR4)
	id SAA11213; Fri, 20 Feb 1998 18:16:26 +0900
Message-Id: <199802200916.SAA11213@rdc.tohoku-epco.co.jp>
X-Sender: tkudo@192.168.1.1
X-Mailer: Macintosh Eudora Pro Version 3.1.1-Jr1
In-Reply-To: <199802191127.UAA03636@rishiri.bsys.tsukuba.ac.jp>
Mime-Version: 1.0
Content-Type: text/plain; charset="ISO-2022-JP"
Content-Transfer-Encoding: 7bit
Date: Fri, 20 Feb 1998 18:14:45 +0900
To: FreeBSD-users-jp@jp.freebsd.org
From: Takashi Kudo <tkudo@rdc.tohoku-epco.co.jp>
Reply-To: FreeBSD-users-jp@jp.freebsd.org
Precedence: bulk
X-Distribute: distribute [version 2.1 (Alpha) patchlevel=24]
X-Sequence: FreeBSD-users-jp 24854
Subject: [FreeBSD-users-jp 24854] Re:How to use UPS (not APC)
Errors-To: owner-FreeBSD-users-jp@jp.freebsd.org
Sender: owner-FreeBSD-users-jp@jp.freebsd.org

At 20:27 +0900 98.2.19, Yoshihiko OHTA wrote:
[FreeBSD-users-jp 24805] $B$KBP$9$k%3%a%s%H$G$9!#(J

$B9)F#!wElKLEENO$G$9!#(J

>   $B$H$$$&$o$1$G!"$I$J$?$+(J
>
>   o $B>e5-(J UPS $B$G(J FreeBSD $B$r<+F0%7%c%C%H%@%&%s$G$-$k$h$&$K$5$l$?J}(J
>     $B$$$i$C$7$c$$$^$;$s$+!)(J
>   o APC UPS $B$N%$%s%?!<%U%'!<%9?.9f$N;EMM$r65$($F$$$?$@$1$^$;$s$+!)(J
>   o $B;qNA$5$($"$k$J$i!">e5-(J UPS $BMQ$K(J upsd $B$r2~B$$7$F$"$2$F$b$$$$(J
>     $B$h!"$H$$$&4qFC$JJ}$$$i$C$7$c$$$^$;$s$G$7$g$&$+!)(J

$BF1$8@=IJ$G$O$"$j$^$;$s$,!$%5%s%1%sEE5$$N(JUPS$B$r;H$C$F$$$^$9!#(J
$B%"%i!<%`=PNO$N;EMM$H!$(JUPS$B$NDd;_?.9f$N;EMM$,!$6vA3$K$bA4$/F1$8$@$C$?(J
$B$N$G!$;d$,;H$C$F$$$k(Jupsd$B$N%=!<%9$rE:IU$7$^$9!#(J
[FreeBSD-users-jp 23215]$B$NNS$5$s$,8x3+$7$F$$$k%=!<%9$r;d$N(JUPS$BMQ$K(J
$B=q$-49$($?$b$N$G$9!#NS$5$s$"$j$,$H$&$4$6$$$^$7$?!#(J

$BE,Ev$J%G%#%l%/%H%j$G(J"gcc upsd.c"$B$H$d$l$P!$(Ja.out$B$H$$$&<B9T%U%!%$%k$,(J
$B=PMh$k$N$G!$E,Ev$J%G%#%l%/%H%j$K(Jupsd$B$H$$$&L>A0$G%3%T!<$7$^$9!#(J
$B$"$H$O!$(Jrc.local$B$K(J
hogehoge/upsd /dev/cuaa0
$B$rDI5-$7$^$9!#(J/dev/cuaa0$B$N$H$3$m$O!$(JUPS$B$,@\B3$5$l$?%7%j%"%k%]!<%H(J
$B$G$9!#!J(Jcuaa0$B$O!$(JCOM1$B!K(J
$B$^$?!$(J
/etc/rc.shutdown
$B$H$$$&!$%7%'%k%9%/%j%W%H$K%7%c%C%H%@%&%s=hM}$r=q$$$F$*$-$^$9!#(J
$BDdEE(J && Battery Low$B$G!$(J/etc/rc.shutdown$B$,<B9T$5$l$^$9!#(J

>   $B$^$?!"$3$N%a!<%+$+$i%$%s%?!<%U%'!<%9%1!<%V%k$rGc$&$H(J 10,000 $B1_(J
> $B$b$7$^$9!#%a!<%k$GLd$$9g$o$;$?$H$3$m!"(J

$B<+:n$9$l$P(J2,000$B1_$/$i$$$G=PMh$k$G$7$g$&!#%=!<%9%U%!%$%k$K7k@~?^$,(J
$B=q$$$F$"$j$^$9!#(JUPS$B$bDd;_$5$;$?$1$l$P!$JLES%?%$%^!<$J$I$,I,MW$G$9!#(J
$B;d$O(JUPS$B$NDd;_$O$7$F$$$^$;$s!#%5%s%1%sEE5$$N(JUPS$B$O!$(JBattery Low$B$N8e!$(J
$BEECS$NEE05$,5,DjCM$r2<2s$k$H<+F0E*$K(JUPS$B$O;_$^$k$N$G!$NI$7$H$7$F$$$^$9!#(J

$B:G8e$K!$;d$N(Jupsd$B$,8mF0:n$7$F%U%!%$%k$rHt$P$7$F$b!$;d$O@UG$$b$F$^$;$s!#(J
$B$4<+J,$N%j%9%/$G;H$C$F2<$5$$!#(J
$B0l1~!$(JFreeBSD(98)2.2.1R-RELEASE$B$GF0:n3NG':Q$_$G$9!#(J

$BElKLEENO(J($B3t(J)$B8&5f3+H/%;%s%?!<(J
$B9)F#!!5.;J(J

/* UPS auto shutdown daemon upsd.c

  Wire Connection

  PC Serial port (DB-25)            UPS MUE1011-GL
   4 RTS ----+----+
             |    |  R=10kOhm
             |    R
             R    |          +-----7 GND OF UPS STOP
             |    |          |
   8 DCD ----+-------------------- 1 LOW BATTERY
                  |          |
   7 GND --------------------+---- 5 SIGNAL GROUND
                  |
   5 CTS ---------+--------------- 3 POWER FAIL

  20 DTR ------------------------- 6 UPS STOP
*/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <unistd.h>
#include <varargs.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/ttycom.h>
#include <sys/time.h>

#define	TURN_UPS_OFF	0	/* Yes : 1 , No : 0 */

int status;
char *scr = "/etc/rc.shutdown";
char *idf = "/var/run/upsd.pid";

void upsterm();
void upsdown(int);

int main(int argc, char *argv[]) {
  FILE *fd;
  struct timeval tp;
  struct timezone tzp;
  long powerdowntime, standuptime=60;
  int pd, zero=0, low=0, pow=1, lineok, batteryok;

  /* check arguments */
  switch(argc) {
  case  4:
    scr = argv[3];
  case  3:
    standuptime = atol(argv[2]);
  case  2:
    break;
  default:
    fprintf(stderr, "usage: %s <device> [wait [script]]\n", argv[0]);
    exit(1);
  }

  /* check if script exists */
  if (!(fd = fopen(scr, "r"))) {
    fprintf(stderr, "fopen: %s: %s\n", scr, sys_errlist[errno]);
    exit(1);
  }
  fclose(fd);

  /* check if upsd is already running */
  if (fd = fopen(idf, "r")) {
    fprintf(stderr, "fopen: %s: File already exists\n", idf);
    exit(1);
  }

  /* become a daemon */
  switch(fork()) {
  case -1:
    /* error */
    fprintf(stderr, "fork: %s\n", sys_errlist[errno]);
    exit(1);
  case  0:
    /* child */
    break;
  default:
    /* parent */
    exit(0);
  }

  /* save the pid */
  if (!(fd = fopen(idf, "w"))) {
    fprintf(stderr, "fopen: %s: %s\n", idf, sys_errlist[errno]);
    exit(1);
  }
  fprintf(fd, "%d\n", (int)getpid());
  fclose(fd);

  /* open monitor device */
  if ((pd = open(argv[1], O_RDWR | O_NDELAY)) < 0) {
    fprintf(stderr, "open: %s: %s\n", argv[1], sys_errlist[errno]);
    exit(1);
  }

  /* daemon is alive */
  openlog("upsd", LOG_PID, LOG_DAEMON);
  syslog(LOG_INFO, "daemon started");

  /* signal reaction */
  (void)signal(SIGTERM, upsterm);

  /* monitor device */
  while (1) {
    /* clear bits */
    if (ioctl(pd, TIOCMSET, &zero) < 0) {
      fprintf(stderr, "ioctl: %s\n", sys_errlist[errno]);
      exit(1);
    }

    /* set RTS monitor powerfail and low battery */
    status = TIOCM_RTS;
    if (ioctl(pd, TIOCMSET, &status) < 0) {
      fprintf(stderr, "ioctl: %s\n", sys_errlist[errno]);
      exit(1);
    }
    usleep(1000); /* wait for RTS stable */

    /* get device status */
    if (ioctl(pd, TIOCMGET, &status) < 0) {
      fprintf(stderr, "ioctl: %s\n", sys_errlist[errno]);
      exit(1);
    }

    /* determin status */
    lineok = status & TIOCM_CTS;
    batteryok = status & TIOCM_CD;

    /* power down */
    if (!lineok) {
      if (pow) {
	syslog(LOG_CRIT, "line failure");
	gettimeofday(&tp,&tzp);
	powerdowntime = tp.tv_sec;
	pow = 0;

	/* down ups */
	if (low) {
	  upsdown(pd);
	}
      }
      else {
	gettimeofday(&tp,&tzp);
	if ((tp.tv_sec-powerdowntime) > standuptime) {
	  upsdown(pd);
	}
      }

    /* power up */
    } else {
      if (!pow) {
	syslog(LOG_CRIT, "line ok");
	pow = 1;
      }
    }

    /* battery ok */
    if (batteryok) {
      if (low) {
	syslog(LOG_CRIT, "battery ok");
	low = 0;
      }

    /* battery low */
    } else {
      if (!low) {
	syslog(LOG_ALERT, "battery low");
	low = 1;

	/* down ups */
	if (!pow) {
	  upsdown(pd);
	}
      }
    }

    sleep(1);
  }

  /* not reached */
  return 0;

}

void upsterm() {
  /* log termination message */
  syslog(LOG_INFO, "daemon terminated");

  /* remove pid file */
  unlink(idf);

  exit(0);
}

void upsdown(int pd) {
  /* log shutdown message */
  syslog(LOG_ALERT, "system is going down");

  /* remove pid file */
  unlink(idf);

  /* save our filesystem */
  system("/bin/sync");
  system("/bin/sync");
  system("/bin/sync");

#if TURN_UPS_OFF
  /* shutdown ups */
  status = TIOCM_DTR;
  if (ioctl(pd, TIOCMSET, &status) < 0) {
    fprintf(stderr, "ioctl: %s\n", sys_errlist[errno]);
    exit(1);
  }
  sleep(1);  /* wait shutdown signal period */
#endif

  /* run shutdown script */
  system(scr);
  exit(0); /* exit to keep DTR set */
}


