예제 #1
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
/* the actual shutdown procedure */
static void doshutdown(void)
{
    int	ret;

    /* this should probably go away at some point */
    upslogx(LOG_CRIT, "Executing automatic power-fail shutdown");
    wall("Executing automatic power-fail shutdown\n");

    do_notify(NULL, NOTIFY_SHUTDOWN);

    sleep(finaldelay);

    /* in the pipe model, we let the parent do this for us */
    if (use_pipe) {
        char	ch;

        ch = 1;
        ret = write(pipefd[1], &ch, 1);
    } else {
        /* one process model = we do all the work here */

        if (geteuid() != 0)
            upslogx(LOG_WARNING, "Not root, shutdown may fail");

        set_pdflag();

        ret = system(shutdowncmd);

        if (ret != 0)
            upslogx(LOG_ERR, "Unable to call shutdown command: %s",
                    shutdowncmd);
    }

    exit(EXIT_SUCCESS);
}
예제 #2
0
파일: tripplite_usb.c 프로젝트: AlexLov/nut
/*!@brief Report a USB comm failure, and reconnect if necessary
 * 
 * @param[in] res	Result code from libusb/libhid call
 * @param[in] msg	Error message to display
 */
void usb_comm_fail(int res, const char *msg)
{
	static int try = 0;

	switch(res) {
		case -EBUSY:
			upslogx(LOG_WARNING, "%s: Device claimed by another process", msg);
			fatalx(EXIT_FAILURE, "Terminating: EBUSY");
			break;

		default:
			upslogx(LOG_WARNING, "%s: Device detached? (error %d: %s)", msg, res, usb_strerror());

			upslogx(LOG_NOTICE, "Reconnect attempt #%d", ++try);
			hd = NULL;
			reconnect_ups();

			if(hd) {
				upslogx(LOG_NOTICE, "Successfully reconnected");
				try = 0;
				upsdrv_initinfo();
			} else {
				if(try > MAX_RECONNECT_TRIES) {
					fatalx(EXIT_FAILURE, "Too many unsuccessful reconnection attempts");
				}
			}
			break;
	}
예제 #3
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
/* exit with success only if it exists and is proper */
static int check_pdflag(void)
{
    int	ret;

    ret = pdflag_status();

    if (ret == -1) {
        upslogx(LOG_ERR, "POWERDOWNFLAG (%s) does not contain "
                "the upsmon magic string", powerdownflag);
        return EXIT_FAILURE;
    }

    if (ret == 0) {
        /* not there - this is not a shutdown event */
        upslogx(LOG_ERR, "Power down flag is not set");
        return EXIT_FAILURE;
    }

    if (ret != 1) {
        upslogx(LOG_ERR, "Programming error: pdflag_status returned %d",
                ret);
        return EXIT_FAILURE;
    }

    /* only thing left - must be time for a shutdown */
    upslogx(LOG_INFO, "Power down flag is set");
    return EXIT_SUCCESS;
}
예제 #4
0
파일: libusb.c 프로젝트: alfh/nut
/*
 * Error handler for usb_get/set_* functions. Return value > 0 success,
 * 0 unknown or temporary failure (ignored), < 0 permanent failure (reconnect)
 */
static int libusb_strerror(const int ret, const char *desc)
{
	if (ret > 0) {
		return ret;
	}

	switch(ret)
	{
	case -EBUSY:	/* Device or resource busy */
	case -EPERM:	/* Operation not permitted */
	case -ENODEV:	/* No such device */
	case -EACCES:	/* Permission denied */
	case -EIO:	/* I/O error */
	case -ENXIO:	/* No such device or address */
	case -ENOENT:	/* No such file or directory */
	case -EPIPE:	/* Broken pipe */
	case -ENOSYS:	/* Function not implemented */
		upslogx(LOG_DEBUG, "%s: %s", desc, usb_strerror());
		return ret;

	case -ETIMEDOUT:	/* Connection timed out */
		upsdebugx(2, "%s: Connection timed out", desc);
		return 0;

	case -EOVERFLOW:	/* Value too large for defined data type */
	case -EPROTO:	/* Protocol error */
		upsdebugx(2, "%s: %s", desc, usb_strerror());
		return 0;

	default:	/* Undetermined, log only */
		upslogx(LOG_DEBUG, "%s: %s", desc, usb_strerror());
		return 0;
	}
}
예제 #5
0
파일: upssched.c 프로젝트: AlexLov/nut
static void log_unknown(int numarg, char **arg)
{
	int	i;

	upslogx(LOG_INFO, "Unknown command on socket: ");

	for (i = 0; i < numarg; i++)
		upslogx(LOG_INFO, "arg %d: %s", i, arg[i]);
}
예제 #6
0
파일: upssched.c 프로젝트: AlexLov/nut
static void parse_at(const char *ntype, const char *un, const char *cmd,
		const char *ca1, const char *ca2)
{
	/* complain both ways in case we don't have a tty */

	if (!cmdscript) {
		printf("CMDSCRIPT must be set before any ATs in the config file!\n");
		fatalx(EXIT_FAILURE, "CMDSCRIPT must be set before any ATs in the config file!");
	}

	if (!pipefn) {
		printf("PIPEFN must be set before any ATs in the config file!\n");
		fatalx(EXIT_FAILURE, "PIPEFN must be set before any ATs in the config file!");
	}

	if (!lockfn) {
		printf("LOCKFN must be set before any ATs in the config file!\n");
		fatalx(EXIT_FAILURE, "LOCKFN must be set before any ATs in the config file!");
	}

	/* check upsname: does this apply to us? */
	if (strcmp(upsname, un) != 0)
		if (strcmp(un, "*") != 0)
			return;		/* not for us, and not the wildcard */

	/* see if the current notify type matches the one from the .conf */
	if (strcasecmp(notify_type, ntype) != 0)
		return;

	/* if command is valid, send it to the daemon (which may start it) */

	if (!strcmp(cmd, "START-TIMER")) {
		sendcmd("START", ca1, ca2);
		return;
	}

	if (!strcmp(cmd, "CANCEL-TIMER")) {
		sendcmd("CANCEL", ca1, ca2);
		return;
	}

	if (!strcmp(cmd, "EXECUTE")) {
		if (ca1 == '\0') {
			upslogx(LOG_ERR, "Empty EXECUTE command argument");
			return;
		}

		if (verbose)
			upslogx(LOG_INFO, "Executing command: %s", ca1);

		exec_cmd(ca1);
		return;
	}

	upslogx(LOG_ERR, "Invalid command: %s", cmd);
}
예제 #7
0
파일: rhino.c 프로젝트: AlexLov/nut
static int instcmd(const char *cmdname, const char *extra)
{

	int ret = 0;
	
	if (!strcasecmp(cmdname, "shutdown.stayoff"))
	  {
	    /* shutdown now (one way) */
	    /* send_command( CMD_SHUT ); */
	    sendshut();
	    return STAT_INSTCMD_HANDLED;
	  }

	if (!strcasecmp(cmdname, "load.on"))
	  {
	    /* liga Saida */
	    ret = send_command( 3 );
	    if ( ret < 1 )
	      upslogx(LOG_ERR, "send_command 3 failed");
	    return STAT_INSTCMD_HANDLED;
	  }

	if (!strcasecmp(cmdname, "load.off"))
	  {
	    /* desliga Saida */
	    ret = send_command( 4 );
	    if ( ret < 1 )
	      upslogx(LOG_ERR, "send_command 4 failed");
	    return STAT_INSTCMD_HANDLED;
	  }

	if (!strcasecmp(cmdname, "bypass.start"))
	  {
	    /* liga Bypass */
	    ret = send_command( 5 );
	    if ( ret < 1 )
	      upslogx(LOG_ERR, "send_command 5 failed");
	    return STAT_INSTCMD_HANDLED;
	  }

	if (!strcasecmp(cmdname, "bypass.stop"))
	  {
	    /* desliga Bypass */
	    ret = send_command( 6 );
	    if ( ret < 1 )
	      upslogx(LOG_ERR, "send_command 6 failed");
	    return STAT_INSTCMD_HANDLED;
	  }


	upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
	return STAT_INSTCMD_UNKNOWN;

}
예제 #8
0
파일: conf.c 프로젝트: baruch/nut
/* called after SIGHUP */
void conf_reload(void)
{
    upstype_t	*upstmp, *upsnext;

    upslogx(LOG_INFO, "SIGHUP: reloading configuration");

    /* see if we can access upsd.conf before blowing away the config */
    if (!check_file("upsd.conf"))
        return;

    /* reset retain flags on all known UPS entries */
    upstmp = firstups;
    while (upstmp) {
        upstmp->retain = 0;
        upstmp = upstmp->next;
    }

    /* reload from ups.conf */
    read_upsconf();
    upsconf_add(1);			/* 1 = reloading */

    /* now reread upsd.conf */
    load_upsdconf(1);		/* 1 = reloading */

    /* now delete all UPS entries that didn't get reloaded */

    upstmp = firstups;

    while (upstmp) {
        /* upstmp may be deleted during this pass */
        upsnext = upstmp->next;

        if (upstmp->retain == 0)
            delete_ups(upstmp);

        upstmp = upsnext;
    }

    /* did they actually delete the last UPS? */
    if (firstups == NULL)
        upslogx(LOG_WARNING, "Warning: no UPSes currently defined!");

    /* and also make sure upsd.users can be read... */
    if (!check_file("upsd.users"))
        return;

    /* delete all users */
    user_flush();

    /* and finally reread from upsd.users */
    user_load();
}
예제 #9
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static void set_notifyflag(const char *ntype, char *flags)
{
    int	i, pos;
    char	*ptr, *tmp;

    /* find ntype */

    pos = -1;
    for (i = 0; notifylist[i].name != NULL; i++) {
        if (!strcasecmp(notifylist[i].name, ntype)) {
            pos = i;
            break;
        }
    }

    if (pos == -1) {
        upslogx(LOG_WARNING, "Warning: invalid notify type [%s]", ntype);
        return;
    }

    ptr = flags;

    /* zero existing flags */
    notifylist[pos].flags = 0;

    while (ptr) {
        int	newflag;

        tmp = strchr(ptr, '+');
        if (tmp)
            *tmp++ = '\0';

        newflag = 0;

        if (!strcmp(ptr, "SYSLOG"))
            newflag = NOTIFY_SYSLOG;
        if (!strcmp(ptr, "WALL"))
            newflag = NOTIFY_WALL;
        if (!strcmp(ptr, "EXEC"))
            newflag = NOTIFY_EXEC;
        if (!strcmp(ptr, "IGNORE"))
            newflag = NOTIFY_IGNORE;

        if (newflag)
            notifylist[pos].flags |= newflag;
        else
            upslogx(LOG_WARNING, "Invalid notify flag: [%s]", ptr);

        ptr = tmp;
    }
}
예제 #10
0
파일: conf.c 프로젝트: baruch/nut
/* change the configuration of an existing UPS (used during reloads) */
static void ups_update(const char *fn, const char *name, const char *desc)
{
    upstype_t	*temp;

    temp = get_ups_ptr(name);

    if (!temp) {
        upslogx(LOG_ERR, "UPS %s disappeared during reload", name);
        return;
    }

    /* paranoia */
    if (!temp->fn) {
        upslogx(LOG_ERR, "UPS %s had a NULL filename!", name);

        /* let's give it something quick to use later */
        temp->fn = xstrdup("");
    }

    /* when the filename changes, force a reconnect */
    if (strcmp(temp->fn, fn) != 0) {

        upslogx(LOG_NOTICE, "Redefined UPS [%s]", name);

        /* release all data */
        sstate_infofree(temp);
        sstate_cmdfree(temp);
        pconf_finish(&temp->sock_ctx);

        close(temp->sock_fd);
        temp->sock_fd = -1;
        temp->dumpdone = 0;

        /* now redefine the filename and wrap up */
        free(temp->fn);
        temp->fn = xstrdup(fn);
    }

    /* update the description */

    free(temp->desc);

    if (desc)
        temp->desc = xstrdup(desc);
    else
        temp->desc = NULL;

    /* always set this on reload */
    temp->retain = 1;
}
예제 #11
0
파일: conf.c 프로젝트: baruch/nut
/* add valid UPSes from ups.conf to the internal structures */
void upsconf_add(int reloading)
{
    ups_t	*tmp = upstable, *next;
    char	statefn[SMALLBUF];

    if (!tmp) {
        upslogx(LOG_WARNING, "Warning: no UPS definitions in ups.conf");
        return;
    }

    while (tmp) {

        /* save for later, since we delete as we go along */
        next = tmp->next;

        /* this should always be set, but better safe than sorry */
        if (!tmp->upsname) {
            tmp = tmp->next;
            continue;
        }

        /* don't accept an entry that's missing items */
        if ((!tmp->driver) || (!tmp->port)) {
            upslogx(LOG_WARNING, "Warning: ignoring incomplete configuration for UPS [%s]\n",
                    tmp->upsname);
        } else {
            snprintf(statefn, sizeof(statefn), "%s-%s",
                     tmp->driver, tmp->upsname);

            /* if a UPS exists, update it, else add it as new */
            if ((reloading) && (get_ups_ptr(tmp->upsname) != NULL))
                ups_update(statefn, tmp->upsname, tmp->desc);
            else
                ups_create(statefn, tmp->upsname, tmp->desc);
        }

        /* free tmp's resources */

        free(tmp->driver);
        free(tmp->port);
        free(tmp->desc);
        free(tmp->upsname);
        free(tmp);

        tmp = next;
    }

    /* upstable should be completely gone by this point */
    upstable = NULL;
}
예제 #12
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
/* see what the status of the UPS is and handle any changes */
static void pollups(utype_t *ups)
{
    char	status[SMALLBUF];

    /* try a reconnect here */
    if (!flag_isset(ups->status, ST_CONNECTED))
        if (try_connect(ups) != 1)
            return;

    if (upscli_ssl(&ups->conn) == 1)
        upsdebugx(2, "%s: %s [SSL]", __func__, ups->sys);
    else
        upsdebugx(2, "%s: %s", __func__, ups->sys);

    set_alarm();

    if (get_var(ups, "status", status, sizeof(status)) == 0) {
        clear_alarm();
        parse_status(ups, status);
        return;
    }

    /* fallthrough: no communications */
    clear_alarm();

    /* try to make some of these a little friendlier */

    switch (upscli_upserror(&ups->conn)) {

    case UPSCLI_ERR_UNKNOWNUPS:
        upslogx(LOG_ERR, "Poll UPS [%s] failed - [%s] "
                "does not exist on server %s",
                ups->sys, ups->upsname,	ups->hostname);

        break;
    default:
        upslogx(LOG_ERR, "Poll UPS [%s] failed - %s",
                ups->sys, upscli_strerror(&ups->conn));
        break;
    }

    /* throw COMMBAD or NOCOMM as conditions may warrant */
    ups_is_gone(ups);

    /* if upsclient lost the connection, clean up things on our side */
    if (upscli_fd(&ups->conn) == -1) {
        drop_connection(ups);
        return;
    }
}
예제 #13
0
파일: blazer.c 프로젝트: balooloo/nut
void upsdrv_updateinfo(void)
{
    static int	retry = 0;

    if (blazer_status(command[proto].status)) {

        if (retry < MAXTRIES) {
            upsdebugx(1, "Communications with UPS lost: status read failed!");
            retry++;
        } else if (retry == MAXTRIES) {
            upslogx(LOG_WARNING, "Communications with UPS lost: status read failed!");
            retry++;
        } else {
            dstate_datastale();
        }

        return;
    }

    if (getval("runtimecal")) {
        time_t	now;

        time(&now);

        if (online) {	/* OL */
            batt.runt.est += batt.runt.nom * difftime(now, lastpoll) / batt.chrg.time;
            if (batt.runt.est > batt.runt.nom) {
                batt.runt.est = batt.runt.nom;
            }
        } else {	/* OB */
            batt.runt.est -= load.eff * difftime(now, lastpoll);
            if (batt.runt.est < 0) {
                batt.runt.est = 0;
            }
        }

        dstate_setinfo("battery.charge", "%.0f", 100 * batt.runt.est / batt.runt.nom);
        dstate_setinfo("battery.runtime", "%.0f", batt.runt.est / load.eff);

        lastpoll = now;
    }

    if (retry > MAXTRIES) {
        upslogx(LOG_NOTICE, "Communications with UPS re-established");
    }

    retry = 0;

    dstate_dataok();
}
예제 #14
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static void reload_conf(void)
{
    utype_t	*tmp, *next;

    upslogx(LOG_INFO, "Reloading configuration");

    /* sanity check */
    if (!check_file(configfile)) {
        reload_flag = 0;
        return;
    }

    /* flip through ups list, clear retain value */
    tmp = firstups;

    while (tmp) {
        tmp->retain = 0;
        tmp = tmp->next;
    }

    /* reset paranoia checker */
    totalpv = 0;

    /* reread upsmon.conf */
    loadconfig();

    /* go through the utype_t struct again */
    tmp = firstups;

    while (tmp) {
        next = tmp->next;

        /* !retain means it wasn't in the .conf this time around */
        if (tmp->retain == 0)
            delete_ups(tmp);

        tmp = next;
    }

    /* see if the user just blew off a foot */
    if (totalpv < minsupplies) {
        upslogx(LOG_CRIT, "Fatal error: total power value (%d) less "
                "than MINSUPPLIES (%d)", totalpv, minsupplies);

        fatalx(EXIT_FAILURE, "Impossible power configuation, unable to continue");
    }

    /* finally clear the flag */
    reload_flag = 0;
}
예제 #15
0
파일: upssched.c 프로젝트: AlexLov/nut
static void checktimers(void)
{
	ttype_t	*tmp, *tmpnext;
	time_t	now;
	static	int	emptyctr = 0;

	/* if the queue is empty we might be ready to exit */
	if (!thead) {

		emptyctr++;

		/* wait a little while in case someone wants us again */
		if (emptyctr < EMPTY_WAIT)
			return;

		if (verbose)
			upslogx(LOG_INFO, "Timer queue empty, exiting");

#ifdef UPSSCHED_RACE_TEST
		upslogx(LOG_INFO, "triggering race: sleeping 15 sec before exit");
		sleep(15);
#endif

		unlink(pipefn);
		exit(EXIT_SUCCESS);
	}

	emptyctr = 0;

	/* flip through LL, look for activity */
	tmp = thead;

	time(&now);
	while (tmp) {
		tmpnext = tmp->next;

		if (now >= tmp->etime) {
			if (verbose)
				upslogx(LOG_INFO, "Event: %s ", tmp->name);

			exec_cmd(tmp->name);

			/* delete from queue */
			removetimer(tmp);
		}

		tmp = tmpnext;
	}
}
예제 #16
0
파일: conf.c 프로젝트: baruch/nut
void load_upsdconf(int reloading)
{
    char	fn[SMALLBUF];
    PCONF_CTX_t	ctx;

    snprintf(fn, sizeof(fn), "%s/upsd.conf", confpath());

    check_perms(fn);

    pconf_init(&ctx, upsd_conf_err);

    if (!pconf_file_begin(&ctx, fn)) {
        pconf_finish(&ctx);

        if (!reloading)
            fatalx(EXIT_FAILURE, "%s", ctx.errmsg);

        upslogx(LOG_ERR, "Reload failed: %s", ctx.errmsg);
        return;
    }

    while (pconf_file_next(&ctx)) {
        if (pconf_parse_error(&ctx)) {
            upslogx(LOG_ERR, "Parse error: %s:%d: %s",
                    fn, ctx.linenum, ctx.errmsg);
            continue;
        }

        if (ctx.numargs < 1)
            continue;

        if (!parse_upsd_conf_args(ctx.numargs, ctx.arglist)) {
            unsigned int	i;
            char	errmsg[SMALLBUF];

            snprintf(errmsg, sizeof(errmsg),
                     "upsd.conf: invalid directive");

            for (i = 0; i < ctx.numargs; i++)
                snprintfcat(errmsg, sizeof(errmsg), " %s",
                            ctx.arglist[i]);

            upslogx(LOG_WARNING, "%s", errmsg);
        }

    }

    pconf_finish(&ctx);
}
예제 #17
0
파일: tripplitesu.c 프로젝트: AlexLov/nut
static int setvar(const char *varname, const char *val)
{

	if (!strcasecmp(varname, "ups.id")) {
		set_identification(val);
		get_identification();
		return STAT_SET_HANDLED;
	}
	if (!strcasecmp(varname, "input.transfer.low")) {
		set_transfer_voltage_low(atoi(val));
		get_transfer_voltage_low();
		return STAT_SET_HANDLED;
	}
	if (!strcasecmp(varname, "input.transfer.high")) {
		set_transfer_voltage_high(atoi(val));
		get_transfer_voltage_high();
		return STAT_SET_HANDLED;
	}
	if (!strcasecmp(varname, "input.sensitivity")) {
		set_sensitivity(val);
		get_sensitivity();
		return STAT_SET_HANDLED;
	}

	upslogx(LOG_NOTICE, "setvar: unknown var [%s]", varname);
	return STAT_SET_UNKNOWN;
}
예제 #18
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static int is_ups_critical(utype_t *ups)
{
    time_t	now;

    /* FSD = the master is forcing a shutdown */
    if (flag_isset(ups->status, ST_FSD))
        return 1;

    /* not OB or not LB = not critical yet */
    if ((!flag_isset(ups->status, ST_ONBATT)) ||
            (!flag_isset(ups->status, ST_LOWBATT)))
        return 0;

    /* must be OB+LB now */

    /* if we're a master, declare it critical so we set FSD on it */
    if (flag_isset(ups->status, ST_MASTER))
        return 1;

    /* must be a slave now */

    /* FSD isn't set, so the master hasn't seen it yet */

    time(&now);

    /* give the master up to HOSTSYNC seconds before shutting down */
    if ((now - ups->lastnoncrit) > hostsync) {
        upslogx(LOG_WARNING, "Giving up on the master for UPS [%s]",
                ups->sys);
        return 1;
    }

    /* there's still time left */
    return 0;
}
예제 #19
0
파일: conf.c 프로젝트: baruch/nut
/* add another UPS for monitoring from ups.conf */
static void ups_create(const char *fn, const char *name, const char *desc)
{
    upstype_t	*temp;

    for (temp = firstups; temp != NULL; temp = temp->next) {
        if (!strcasecmp(temp->name, name)) {
            upslogx(LOG_ERR, "UPS name [%s] is already in use!", name);
            return;
        }
    }

    /* grab some memory and add the info */
    temp = xcalloc(1, sizeof(*temp));
    temp->fn = xstrdup(fn);
    temp->name = xstrdup(name);

    if (desc) {
        temp->desc = xstrdup(desc);
    }

    temp->stale = 1;
    temp->retain = 1;
    temp->sock_fd = sstate_connect(temp);

    /* preload this to the current time to avoid false staleness */
    clock_monotonic(&temp->last_heard);

    temp->next = firstups;
    firstups = temp;
    num_ups++;
}
예제 #20
0
파일: upssched.c 프로젝트: AlexLov/nut
static void conn_del(conn_t *target)
{
	conn_t	*tmp, *last = NULL;

	tmp = connhead;

	while (tmp) {
		if (tmp == target) {

			if (last)
				last->next = tmp->next;
			else
				connhead = tmp->next;

			pconf_finish(&tmp->ctx);

			free(tmp);
			return;
		}

		last = tmp;
		tmp = tmp->next;
	}

	upslogx(LOG_ERR, "Tried to delete a bogus state connection");
}
예제 #21
0
파일: blazer.c 프로젝트: balooloo/nut
void upsdrv_shutdown(void)
{
    int	retry;

    /* Stop pending shutdowns */
    for (retry = 1; retry <= MAXTRIES; retry++) {

        if (blazer_instcmd("shutdown.stop", NULL) != STAT_INSTCMD_HANDLED) {
            continue;
        }

        break;

    }

    if (retry > MAXTRIES) {
        upslogx(LOG_NOTICE, "No shutdown pending");
    }

    /* Shutdown */
    for (retry = 1; retry <= MAXTRIES; retry++) {

        if (blazer_instcmd("shutdown.return", NULL) != STAT_INSTCMD_HANDLED) {
            continue;
        }

        fatalx(EXIT_SUCCESS, "Shutting down in %d seconds", offdelay);

    }

    fatalx(EXIT_FAILURE, "Shutdown failed!");
}
예제 #22
0
파일: blazer.c 프로젝트: balooloo/nut
/*
 * The battery voltage will quickly return to at least the nominal value after
 * discharging them. For overlapping battery.voltage.low/high ranges therefor
 * choose the one with the highest multiplier.
 */
static double blazer_packs(const char *ptr, char **endptr)
{
    const double packs[] = {
        120, 100, 80, 60, 48, 36, 30, 24, 18, 12, 8, 6, 4, 3, 2, 1, 0.5, -1
    };

    const char	*val;
    int		i;

    val = dstate_getinfo("battery.voltage.nominal");

    batt.volt.nom = strtod(val ? val : ptr, endptr);

    for (i = 0; packs[i] > 0; i++) {

        if (packs[i] * batt.volt.act > 1.2 * batt.volt.nom) {
            continue;
        }

        if (packs[i] * batt.volt.act < 0.8 * batt.volt.nom) {
            upslogx(LOG_INFO, "Can't autodetect number of battery packs [%.0f/%.2f]", batt.volt.nom, batt.volt.act);
            break;
        }

        batt.packs = packs[i];
        break;
    }

    return batt.volt.nom;
}
예제 #23
0
/* close ttys and become a daemon */
void background(void)
{
	int	pid;

	if ((pid = fork()) < 0)
		fatal_with_errno(EXIT_FAILURE, "Unable to enter background");

	xbit_set(&upslog_flags, UPSLOG_SYSLOG);
	xbit_clear(&upslog_flags, UPSLOG_STDERR);

	close(0);
	close(1);
	close(2);

	if (pid != 0)
		_exit(EXIT_SUCCESS);		/* parent */

	/* child */

	/* make fds 0-2 point somewhere defined */
	if (open("/dev/null", O_RDWR) != 0)
		fatal_with_errno(EXIT_FAILURE, "open /dev/null");

	if (dup(0) == -1)
		fatal_with_errno(EXIT_FAILURE, "dup");

	if (dup(0) == -1)
		fatal_with_errno(EXIT_FAILURE, "dup");

#ifdef HAVE_SETSID
	setsid();		/* make a new session to dodge signals */
#endif

	upslogx(LOG_INFO, "Startup successful");
}
예제 #24
0
파일: upsconf.c 프로젝트: AlexLov/nut
/* open the ups.conf, parse it, and call back do_upsconf_args() */
void read_upsconf(void)
{
	char	fn[SMALLBUF];
	PCONF_CTX_t	ctx;

	ups_section = NULL;
	snprintf(fn, sizeof(fn), "%s/ups.conf", confpath());

	pconf_init(&ctx, upsconf_err);

	if (!pconf_file_begin(&ctx, fn))
		fatalx(EXIT_FAILURE, "Can't open %s: %s", fn, ctx.errmsg);

	while (pconf_file_next(&ctx)) {
		if (pconf_parse_error(&ctx)) {
			upslogx(LOG_ERR, "Parse error: %s:%d: %s",
				fn, ctx.linenum, ctx.errmsg);
			continue;
		}

		conf_args(ctx.numargs, ctx.arglist);
	}

	pconf_finish(&ctx);

	free(ups_section);
}
예제 #25
0
파일: state.c 프로젝트: balooloo/nut
int state_setaux(st_tree_t *root, const char *var, const char *auxs)
{
	st_tree_t	*sttmp;
	int	aux;

	/* find the tree node for var */
	sttmp = state_tree_find(root, var);

	if (!sttmp) {
		upslogx(LOG_ERR, "state_addenum: base variable (%s) "
			"does not exist", var);
		return -1;	/* failed */
	}

	aux = strtol(auxs, (char **) NULL, 10);

	/* silently ignore matches */
	if (sttmp->aux == aux) {
		return 0;
	}

	sttmp->aux = aux;

	return 1;
}
예제 #26
0
파일: upscode2.c 프로젝트: alicaccs/nut
static int upsc_getvalue(const char *cmd, const char *param,
			const char *resp, const char *nutvar, char *ret)
{
	char var[UPSC_BUFLEN];
	char val[UPSC_BUFLEN];

	upsdebugx(2, "Request value: %s %s", cmd, param ? param : "\"\"");
	upscsend(cmd);
	if (param)
		upscsend(param);
	upscrecv(var);
	upscrecv(val);
	upsdebugx(2, "Got value: %s %s", var, val);
	if (strcmp(var, resp)) {
		upslogx(LOG_ERR, "Bad response to %s %s: %s %s",
			cmd, param ? param : "\"\"", var, val);
		return 0;
	}
	else {
		if (nutvar)
			dstate_setinfo(nutvar, "%s", val);
		if (ret)
			strcpy(ret, val);
	}
	return 1;
}
예제 #27
0
파일: upscode2.c 프로젝트: alicaccs/nut
void upsdrv_initinfo(void)
{
	if (!upsc_commandlist()) {
		upslogx(LOG_ERR, "No contact with UPS, delaying init.");
		status = UPSC_STAT_NOTINIT;
		return;
	} else {
		status = 0;
	}

	upsc_getbaseinfo();
	if (can_upda) {
		upsc_flush_input();
		upscsend("UPDA");
	}
	if (can_upid) {
		upsc_getvalue("UPID", NULL, "ACID", "ups.id", NULL);
	}
	if (can_uppm) {
		check_uppm();
	}

	/* make sure we have some sensible defaults */
	setvar("ups.delay.shutdown", "10");
	setvar("ups.delay.reboot", "60");

	upsh.instcmd = instcmd;
	upsh.setvar = setvar;
}
예제 #28
0
파일: upssched.c 프로젝트: AlexLov/nut
static void removetimer(ttype_t *tfind)
{
	ttype_t	*tmp, *last;

	last = NULL;
	tmp = thead;

	while (tmp) {
		if (tmp == tfind) {	/* found it */
			if (last == NULL)	/* deleting first */
				thead = tmp->next;
			else
				last->next = tmp->next;

			free(tmp->name);
			free(tmp);
			return;
		}

		last = tmp;
		tmp = tmp->next;
	}

	/* this one should never happen */

	upslogx(LOG_ERR, "removetimer: failed to locate target at %p", (void *)tfind);
}
예제 #29
0
파일: upscode2.c 프로젝트: alicaccs/nut
/* get limits and parameters */
static int upsc_getparams(const char *cmd, const simple_t *table)
{
	char var[UPSC_BUFLEN];
	char val[UPSC_BUFLEN];
	int first = 1;

	upsc_flush_input();

	upscsend(cmd);
	buffer_empty = 0;
	while (!buffer_empty) {
		upscrecv(var);
		if (strlen(var) == 0) {
			if (first)
				upscrecv(var);
			if (strlen(var) == 0) {
				ser_comm_fail("Empty string from UPS for %s!",
					cmd);
				break;
			}
		}
		first = 0;
		upscrecv(val);
		if (strlen(val) == 0) {
			ser_comm_fail("Empty value from UPS for %s %s!", cmd, var);
			break;
		}
		upsdebugx(2, "Parameter %s %s", var, val);
		if (!upsc_simple(table, var, val))
			upslogx(LOG_ERR, "Unknown response to %s: %s %s",
				cmd, var, val);
	}
	return buffer_empty;
}
예제 #30
0
파일: powerpanel.c 프로젝트: alicaccs/nut
void upsdrv_initups(void)
{
	char	*version;

	version = getval("protocol");
	upsfd = ser_open(device_path);

	ser_set_rts(upsfd, 0);

	/*
	 * Try to autodetect which UPS is connected.
	 */
	for (mode = 0; subdriver[mode] != NULL; mode++) {

		if ((version != NULL) && strcasecmp(version, subdriver[mode]->version)) {
			continue;
		}

		ser_set_dtr(upsfd, 1);
		usleep(10000);

		if (subdriver[mode]->initups() > 0) {
			upslogx(LOG_INFO, "CyberPower UPS with %s protocol on %s detected", subdriver[mode]->version, device_path);
			return;
		}

		ser_set_dtr(upsfd, 0);
		usleep(10000);
	}

	fatalx(EXIT_FAILURE, "CyberPower UPS not found on %s", device_path);
}