MINI SHELL

Server : Apache/2.2.2 (Fedora)
System : Linux App1.pathumtani.go.th 2.6.20-1.2320.fc5smp #1 SMP Tue Jun 12 19:40:16 EDT 2007 i686
User : apache ( 48)
PHP Version : 5.2.9
Disable Function : NONE
Directory :  /usr/local/src/apcupsd-3.14.10/src/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //usr/local/src/apcupsd-3.14.10/src/device.c
/*
 * apcdevice.c
 *
 * Generic device handling
 *
 * Written by Riccardo Fachetti 2000 from Kern's design
 */

/*
 * Copyright (C) 2000-2004 Kern Sibbald
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General
 * Public License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 */

/*    
 * This is a sort of helper routine between apcupsd core and the drivers.
 * The raw calls into the drivers are through function pointers in the 
 * ups device structure, and are #defined to the following:
 *
 *    device_open(ups)
 *    device_setup(ups)
 *    device_close(ups)
 *    device_kill_power(ups)
 *    device_shutdown(ups)
 *    device_read_static_data(ups)
 *    device_read_volatile_data(ups)
 *    device_get_capabilities(ups) 
 *    device_check_state(ups)
 *    device_program_eeprom(ups)
 *    device_entry_point(ups, command, data)
 * 
 * see include/apc_drivers.h for more details on each routine.
 */

#include "apc.h"

/* Forward referenced function */
static int device_wait_time(UPSINFO *ups);

/*********************************************************************/
void setup_device(UPSINFO *ups)
{
   /*
    * Marko Sakari Asplund <Marko.Asplund@cern.ch>
    *    prevents double init of UPS device 9/25/98
    */
   if (ups->is_dev_setup())
      return;

   ups->set_dev_setup();

   device_open(ups);

   /* If create_lockfile fails there's no need to delete_lockfile. */
   if ((ups->fd != -1) && create_lockfile(ups) == LCKERROR) {
      device_close(ups);
      Error_abort0("Unable to create UPS lock file.\n"
                   "  If apcupsd or apctest is already running,\n"
                   "  please stop it and run this program again.\n");
   }

   device_setup(ups);
   device_get_capabilities(ups);
}

/*********************************************************************/
void initiate_hibernate(UPSINFO *ups)
{
   FILE *pwdf;
   int killcount;

   if (ups->mode.type == DUMB_UPS) {
      /* Make sure we are on battery */
      for (killcount = 0; killcount < 3; killcount++)
         device_read_volatile_data(ups);
   }

   /*
    * ****FIXME*****  This big if is BROKEN in the
    *                 case that there is no real power failure.
    *
    * We really need to find out if we are on batteries
    * and if not, delete the PWRFAIL file.  Note, the code
    * above only tests UPS_onbatt flag for dumb UPSes.
    */

   pwdf = fopen(ups->pwrfailpath, "r");
   if ((pwdf == NULL && ups->mode.type != DUMB_UPS) ||
       (pwdf == NULL && ups->is_onbatt() && ups->mode.type == DUMB_UPS)) {

      /*                                                  
       * At this point, we really should not be attempting
       * a kill power since either the powerfail file is
       * not defined, or we are not on batteries.
       */

      /* Now complain */
      log_event(ups, LOG_WARNING,
         "Cannot find %s file.\n Killpower requested in "
           "non-power fail condition or bug.\n Killpower request "
           "ignored at %s:%d\n", ups->pwrfailpath, __FILE__, __LINE__);
      Error_abort3(
         "Cannot find %s file.\n Killpower requested in "
           "non-power fail condition or bug.\n Killpower request "
           "ignored at %s:%d\n", ups->pwrfailpath, __FILE__, __LINE__);
   } else {
      /* We are on batteries, so do the kill_power */
      if (ups->upsclass.type == SHAREMASTER) {
         log_event(ups, LOG_WARNING,
            "Waiting 30 seconds for slave(s) to shutdown.");
         sleep(30);
      }

      /* close the powerfail file */
      if (pwdf)
         fclose(pwdf);

      log_event(ups, LOG_WARNING, "Attempting to kill the UPS power!");

      if (ups->upsclass.type == SHARESLAVE) {
         sleep(10);
         log_event(ups, LOG_WARNING, "Waiting For ShareUPS Master to shutdown");
         sleep(60);
         log_event(ups, LOG_WARNING, "Failed to have power killed by Master!");

         /*
          * ***FIXME*** this really should not do a reboot here,
          * but rather a halt or nothing -- KES
          */
         /* generate_event(ups, CMDDOREBOOT); */

         log_event(ups, LOG_WARNING, "Perform CPU-reset or power-off");
         return;
      } else {
         /* it must be a SmartUPS or BackUPS */
         device_kill_power(ups);
      }
   }
}

/*********************************************************************/
void initiate_shutdown(UPSINFO *ups)
{
   log_event(ups, LOG_WARNING, "Attempting to shutdown the UPS!");
   device_shutdown(ups);
}

/*
 * After the device is initialized, we come here
 * to read all the information we can about the UPS.
 */
void prep_device(UPSINFO *ups)
{
   device_read_static_data(ups);

   /* If no UPS name found, use hostname, or "default" */
   if (ups->upsname[0] == 0) {     /* no name given */
      gethostname(ups->upsname, sizeof(ups->upsname) - 1);
      if (ups->upsname[0] == 0)    /* error */
         astrncpy(ups->upsname, "default", sizeof(ups->upsname));
   }
}

/* Called once every 5 seconds to read all UPS info */
int fillUPS(UPSINFO *ups)
{
   device_read_volatile_data(ups);

   return 0;
}

/* NOTE! This is the starting point for a separate process (thread). */
void do_device(UPSINFO *ups)
{
   /* get all data so apcaccess is happy */
   fillUPS(ups);

   while(1)
   {
      /* compute appropriate wait time */
      ups->wait_time = device_wait_time(ups);

      Dmsg2(70, "Before do_action: 0x%x (OB:%d).\n",
         ups->Status, ups->is_onbatt());

      /* take event actions */
      do_action(ups);

      Dmsg2(70, "Before fillUPS: 0x%x (OB:%d).\n",
         ups->Status, ups->is_onbatt());

      /* Get all info available from UPS by asking it questions */
      fillUPS(ups);

      Dmsg2(70, "Before do_action: 0x%x (OB:%d).\n",
         ups->Status, ups->is_onbatt());

      /* take event actions */
      do_action(ups);

      Dmsg2(70, "Before do_reports: 0x%x (OB:%d).\n",
         ups->Status, ups->is_onbatt());

      do_reports(ups);

      /* compute appropriate wait time */
      ups->wait_time = device_wait_time(ups);

      Dmsg2(70, "Before device_check_state: 0x%x (OB:%d).\n",
         ups->Status, ups->is_onbatt());

      /*
       * Check the UPS to see if has changed state.
       * This routine waits a reasonable time to prevent
       * consuming too much CPU time.
       */
      device_check_state(ups);
   }
}

/* 
 * Each device handler when called at device_check_state() waits
 * a specified time for the next event. In general, we want this
 * to be as long as possible (i.e. about a minute) to prevent
 * excessive "polling" because when device_check_state() returns,
 * repoll the UPS (fillUPS). 
 * This routine attempts to determine a reasonable "sleep" time
 * for the device.
 */
static int device_wait_time(UPSINFO *ups)
{
   int wait_time;

   if (ups->is_fastpoll() || !ups->is_battpresent())
      wait_time = TIMER_FAST;
   else if (ups->is_commlost())
      wait_time = TIMER_FAST*5;
   else
      wait_time = ups->polltime;    /* normally 60 seconds */

   /* Make sure we do data and stats when asked */
   if (ups->datatime && ups->datatime < wait_time)
      wait_time = ups->datatime;

   if (ups->stattime && ups->stattime < wait_time)
      wait_time = ups->stattime;

   /* Sanity check */
   if (wait_time < TIMER_FAST)
      wait_time = TIMER_FAST;

   return wait_time;
}

Anon7 - 2021