/*****************************************************************************\
* $Id: ipmipower_util.c,v 1.37 2010-02-08 22:02:31 chu11 Exp $
*****************************************************************************
* Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
* Copyright (C) 2003-2007 The Regents of the University of California.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Albert Chu <chu11@llnl.gov>
* UCRL-CODE-155698
*
* This file is part of Ipmipower, a remote power control utility.
* For details, see http://www.llnl.gov/linux/.
*
* Ipmipower is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* Ipmipower 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 Ipmipower. If not, see <http://www.gnu.org/licenses/>.
\*****************************************************************************/
#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#if STDC_HEADERS
#include <string.h>
#include <stdarg.h>
#endif /* STDC_HEADERS */
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else /* !TIME_WITH_SYS_TIME */
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else /* !HAVE_SYS_TIME_H */
#include <time.h>
#endif /* !HAVE_SYS_TIME_H */
#endif /* !TIME_WITH_SYS_TIME */
#include <sys/poll.h>
#include <assert.h>
#include <errno.h>
#include "ipmipower_util.h"
#include "ipmipower_error.h"
#include "freeipmi-portability.h"
#include "cbuf.h"
extern struct ipmipower_arguments cmd_args;
char *
ipmipower_power_cmd_to_string (ipmipower_power_cmd_t cmd)
{
assert (IPMIPOWER_POWER_CMD_VALID (cmd));
switch (cmd)
{
case IPMIPOWER_POWER_CMD_POWER_OFF:
return ("off");
case IPMIPOWER_POWER_CMD_POWER_ON:
return ("on");
case IPMIPOWER_POWER_CMD_POWER_CYCLE:
return ("cycle");
case IPMIPOWER_POWER_CMD_POWER_RESET:
return ("reset");
case IPMIPOWER_POWER_CMD_POWER_STATUS:
return ("status");
case IPMIPOWER_POWER_CMD_PULSE_DIAGNOSTIC_INTERRUPT:
return ("diagnostic interrupt");
case IPMIPOWER_POWER_CMD_SOFT_SHUTDOWN_OS:
return ("soft shutdown os");
case IPMIPOWER_POWER_CMD_IDENTIFY_ON:
return ("identify on");
case IPMIPOWER_POWER_CMD_IDENTIFY_OFF:
return ("identify off");
case IPMIPOWER_POWER_CMD_IDENTIFY_STATUS:
return ("identify status");
default:
IPMIPOWER_ERROR (("ipmipower_power_cmd_to_string: invalid power cmd type: %d", cmd));
exit (EXIT_FAILURE);
}
return (NULL); /* NOT REACHED */
}
int
ipmipower_power_cmd_check_privilege (ipmipower_power_cmd_t cmd,
char *errbuf,
unsigned int errbuflen)
{
int rv = -1;
assert (IPMIPOWER_POWER_CMD_VALID (cmd));
assert (errbuf);
assert (errbuflen);
assert (cmd_args.oem_power_type == IPMIPOWER_OEM_POWER_TYPE_NONE);
if (cmd_args.common_args.privilege_level == IPMI_PRIVILEGE_LEVEL_USER
&& IPMIPOWER_POWER_CMD_REQUIRES_OPERATOR_PRIVILEGE_LEVEL (cmd))
{
char *power_cmd_str;
power_cmd_str = ipmipower_power_cmd_to_string (cmd);
snprintf (errbuf,
errbuflen,
"'%s' requires atleast operator privilege",
power_cmd_str);
rv = 0;
goto cleanup;
}
rv = 1;
cleanup:
return (rv);
}
int
ipmipower_poll (struct pollfd *ufds, unsigned int nfds, int timeout)
{
int n;
struct timeval tv, tv_orig;
struct timeval start, end, delta;
/* prep for EINTR handling */
if (timeout >= 0)
{
/* poll uses timeout in milliseconds */
tv_orig.tv_sec = (long)timeout/1000;
tv_orig.tv_usec = (timeout % 1000) * 1000;
if (gettimeofday(&start, NULL) < 0)
{
IPMIPOWER_ERROR (("gettimeofday: %s", strerror (errno)));
exit (EXIT_FAILURE);
}
}
else
{
tv_orig.tv_sec = 0;
tv_orig.tv_usec = 0;
}
/* repeat poll if interrupted */
do
{
n = poll(ufds, nfds, timeout);
/* unrecov error */
if (n < 0 && errno != EINTR)
{
IPMIPOWER_ERROR (("poll: %s", strerror (errno)));
exit (EXIT_FAILURE);
}
if (n < 0 && timeout >= 0) /* EINTR - adjust timeout */
{
if (gettimeofday(&end, NULL) < 0)
{
IPMIPOWER_ERROR (("gettimeofday: %s", strerror (errno)));
exit (EXIT_FAILURE);
}
timersub(&end, &start, &delta); /* delta = end-start */
timersub(&tv_orig, &delta, &tv); /* tv = tvsave-delta */
timeout = (tv.tv_sec * 1000) + (tv.tv_usec/1000);
}
} while (n < 0);
return n;
}
void
ipmipower_cbuf_printf(cbuf_t cbuf, const char *fmt, ...)
{
char buf[IPMIPOWER_OUTPUT_BUFLEN];
va_list ap;
int written, dropped;
int len;
va_start(ap, fmt);
/* overflow ignored */
len = vsnprintf (buf, IPMIPOWER_OUTPUT_BUFLEN, fmt, ap);
written = cbuf_write (cbuf, buf, len, &dropped);
if (written < 0)
{
IPMIPOWER_ERROR (("cbuf_write: %s", strerror (errno)));
exit (EXIT_FAILURE);
}
va_end(ap);
}
int
ipmipower_cbuf_peek_and_drop (cbuf_t buf, void *buffer, int len)
{
int rv, r_len, dropped = 0;
assert (buf);
assert (buffer);
assert (len > 0);
if ((r_len = cbuf_peek (buf, buffer, len)) < 0)
{
IPMIPOWER_ERROR (("cbuf_peek: %s", strerror (errno)));
exit (EXIT_FAILURE);
}
/* Nothing there */
if (!r_len)
return (0);
if ((dropped = cbuf_drop (buf, len)) < 0)
{
IPMIPOWER_ERROR (("cbuf_drop: %s", strerror (errno)));
exit (EXIT_FAILURE);
}
if (dropped != r_len)
{
IPMIPOWER_ERROR (("cbuf_drop: dropped incorrect bytes: %d", dropped));
exit (EXIT_FAILURE);
}
if ((rv = cbuf_drop (buf, -1)) < 0)
{
IPMIPOWER_ERROR (("cbuf_drop: %s", strerror (errno)));
exit (EXIT_FAILURE);
}
if (rv > 0)
IPMIPOWER_DEBUG (("cbuf_drop dropped data: %d", rv));
return (r_len);
}