home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3294 / upsd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  4.3 KB  |  196 lines

  1. /*
  2.  $Id: upsd.c,v 1.3 1991/05/06 19:10:34 marc Exp marc $
  3.  
  4. Yet another ups daemon. This one's good for people without a serial port to
  5. spare. (The hardware interface uses the game port)
  6.  
  7. This code is being released because of the numerous requests I have received
  8. for it. I am placing it in the public domain. It's probably filled with local
  9. dependencies and will require some adaptation to your site.
  10.  
  11. On powerloss, it stops cron, disables logins (by creating /etc/issue.linefail-
  12. when this file exists, our custom login program displays its contents and
  13. aborts the login attempt) and broadcasts a message to all logged in users
  14. (except those whose names start with "uu" [uucp logins]; again, a local
  15. assumption). The system is brought down only when the low battery condition
  16. is detected. If power returns before the battery becomes low, cron
  17. is restarted, /etc/issue.linefail removed and the users are notified.
  18.  
  19. Brian E. Litzinger's peek driver must be installed in your kernel and available
  20. as /dev/peek. You can get it by anonymous FTP from
  21.     svin02.info.win.tue.nl:/pub/sysvX86/peek.tar.z
  22.  
  23. If you can't FTP, email me.
  24.  
  25. Marc Boucher.
  26. Internet: marc@PostImage.COM Telephone: +1 514 489-8989
  27.  
  28. */
  29. #include <fcntl.h>
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <sys/signal.h>
  33. #include <sys/utsname.h>
  34. #include <utmp.h>
  35.  
  36. #include <sys/peek.h>
  37.  
  38. #define    INTERVAL    20    /* Time in seconds between checks */
  39.  
  40. #define PORTADDR    0x201
  41.  
  42. #define    UPSF_LINEFAIL    (1<<6)
  43. #define    UPSF_LOWBATT    (1<<7)
  44.  
  45. #define    CONSOLE        "/dev/console"
  46. #define    LOGFILE        "/usr/adm/upslog"
  47. #define    ISSUEPOWER    "/etc/issue.linefail"
  48.  
  49. void SendMsg(str, line)
  50. char *str, *line;
  51. {
  52.     FILE *linefil;
  53.  
  54.     linefil=fopen(line, "w");
  55.     if(linefil) {
  56.         time_t ti;
  57.         struct utsname unam;
  58.         char tibuf[40];
  59.  
  60.         uname(&unam);
  61.         time(&ti);
  62.         cftime(tibuf, "%a %b %e %T %Y", &ti);
  63.         fprintf(linefil, "\n\007Broadcast Message from UPS daemon on %s [ %s ]...\n%s\n\n", unam.nodename, tibuf, str);
  64.         fclose(linefil);
  65.     }
  66. }
  67.  
  68. void Broadcast(str)
  69. char *str;
  70. {
  71.     struct utmp *uptr, *getutent();
  72.     int console=0;
  73.  
  74.     setutent();
  75.     while(uptr=getutent()) {
  76.         if((uptr->ut_type==USER_PROCESS)&&(strncmp(uptr->ut_user, "uu", 2))) {
  77.             char line[32];
  78.  
  79.             sprintf(line, "/dev/%s", uptr->ut_line);
  80.             if(!strcmp(line, CONSOLE)) console=1;
  81.             SendMsg(str, line);
  82.         }
  83.     }
  84.     endutent();
  85.     if(!console) SendMsg(str, CONSOLE);
  86. }
  87.  
  88. void LogString(class, str)
  89. char class;
  90. char *str;
  91. {
  92.     char *datimebuf[255];
  93.     time_t ti;
  94.     FILE *logfil;
  95.  
  96.     time(&ti);
  97.     cftime(datimebuf, "%D %T", &ti);
  98.  
  99.     logfil=fopen(LOGFILE, "a");
  100.  
  101.     if(logfil) {
  102.         fprintf(logfil, "%c/%d %s - %s\n", class, getpid(), datimebuf, str);
  103.         fclose(logfil);
  104.     }
  105. }
  106.  
  107. void LineFail()
  108. {
  109.     FILE *issuepower;
  110.  
  111.     LogString('F', "Line Fail");
  112.     Broadcast("POWER FAILURE DETECTED: SYSTEM WILL SHUTDOWN IF UPS BATTERY BECOMES LOW");
  113.     system("/etc/init.d/cron stop");
  114.     issuepower=fopen(ISSUEPOWER, "w");
  115.     if(!issuepower) LogString('E', "Can't open /etc/issue.linefail for writing");
  116.     else {
  117.         fprintf(issuepower, "\nLogins have been disabled by the UPS daemon because of power failure.\n");
  118.         fclose(issuepower);
  119.     }
  120. }
  121.  
  122. void EndLineFail()
  123. {
  124.  
  125.     LogString('F', "Line Normal");
  126.     Broadcast("GOOD NEWS: POWER HAS BEEN RESTORED.");
  127.     system("/etc/init.d/cron start");
  128.     unlink(ISSUEPOWER);
  129. }
  130.  
  131. void LowBattery()
  132. {
  133.     LogString('L', "Low Battery");
  134.     Broadcast("UPS BATTERY IS LOW!!! SYSTEM GOING DOWN IN 40 SECONDS. LOGOUT NOW!");
  135.     sleep(40);
  136.     Broadcast("UPS BATTERY IS LOW!!! SYSTEM GOING DOWN IMMEDIATELY!");
  137.     LogString('L', "System going down");
  138.     sync();
  139.     unlink(ISSUEPOWER);
  140.     close(0); close(1); close(2);
  141.     open("/dev/console", O_RDWR);
  142.     open("/dev/console", O_RDWR);
  143.     open("/dev/console", O_RDWR);
  144.     sync();
  145.     execlp("/etc/init", "init", "0", 0);
  146.     LogString('E', "Can't exec /etc/init!!!");
  147.     sync();
  148.     exit(1);
  149. }
  150.  
  151. main()
  152. {
  153.     int peekfd;
  154.     struct peek_t pd;
  155.     int linefail=0;
  156.  
  157.     if(fork()) exit(0);
  158.  
  159.     setpgrp();
  160.  
  161.     chdir("/");
  162.  
  163.     signal(SIGHUP, SIG_IGN);
  164.     signal(SIGINT, SIG_IGN);
  165.  
  166.     pd.port=PORTADDR;
  167.  
  168.     peekfd=open("/dev/peek", O_RDONLY);
  169.     if(peekfd==-1) {
  170.         LogString('E', "Can't open /dev/peek");
  171.         exit(1);
  172.     }
  173.  
  174.     for(;;) {
  175.         if (ioctl(peekfd,PEEKIN,&pd)==-1) {
  176.             LogString('E', "ioctl() error");
  177.             exit(1);
  178.         }
  179.  
  180.         if(pd.data&UPSF_LINEFAIL) {
  181.             if(linefail) {
  182.                 linefail=0;
  183.                 EndLineFail();
  184.             }
  185.         } else if(!linefail) {
  186.             linefail=1;
  187.             LineFail();
  188.         }
  189.  
  190.         if(!(pd.data&UPSF_LOWBATT)) LowBattery(); /* Never returns */
  191.  
  192.         sleep(INTERVAL);
  193.     }
  194.     /* Not reached */
  195. }
  196.