mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
There are lots of feature test macros like _POSIX_SOURCE, _BSD_SOURCE, etc. chaotically placed at the beginning of multiple files without apparent reason, sometime purely erroneously. This commit removes them all for the sake of cleaner code. No new warnings are added due to that at least for gcc 5.4 on Linux with glibc 2.23.
515 lines
13 KiB
C
515 lines
13 KiB
C
/*
|
|
* Copyright (c) 2003, 2004 Sun Microsystems, Inc. All Rights Reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistribution of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* Redistribution in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* Neither the name of Sun Microsystems, Inc. or the names of
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* This software is provided "AS IS," without a warranty of any kind.
|
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
|
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
|
|
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
|
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
|
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
|
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
|
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
|
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include <ipmitool/helper.h>
|
|
#include <ipmitool/log.h>
|
|
#include <ipmitool/ipmi.h>
|
|
#include <ipmitool/ipmi_intf.h>
|
|
#include <ipmitool/ipmi_session.h>
|
|
#include <ipmitool/ipmi_main.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#define EXEC_BUF_SIZE 2048
|
|
#define EXEC_ARG_SIZE 64
|
|
#define MAX_PORT 65535
|
|
|
|
extern const struct valstr ipmi_privlvl_vals[];
|
|
extern const struct valstr ipmi_authtype_session_vals[];
|
|
|
|
#ifdef HAVE_READLINE
|
|
|
|
/* avoid warnings errors due to non-ANSI type declarations in readline.h */
|
|
#define _FUNCTION_DEF
|
|
#define USE_VARARGS
|
|
#define PREFER_STDARG
|
|
|
|
#include <readline/readline.h>
|
|
#include <readline/history.h>
|
|
#define RL_PROMPT "ipmitool> "
|
|
#define RL_TIMEOUT 30
|
|
|
|
static struct ipmi_intf * shell_intf;
|
|
|
|
/* This function attempts to keep lan sessions active
|
|
* so they do not time out waiting for user input. The
|
|
* readline timeout is set to 1 second but lan session
|
|
* timeout is ~60 seconds.
|
|
*/
|
|
static int rl_event_keepalive(void)
|
|
{
|
|
static int internal_timer = 0;
|
|
|
|
if (shell_intf == NULL)
|
|
return -1;
|
|
if (shell_intf->keepalive == NULL)
|
|
return 0;
|
|
#if defined (RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0402
|
|
if (internal_timer++ < RL_TIMEOUT)
|
|
#else
|
|
/* In readline < 4.2 keyboard timeout hardcoded to 0.1 second */
|
|
if (internal_timer++ < RL_TIMEOUT * 10)
|
|
#endif
|
|
return 0;
|
|
|
|
internal_timer = 0;
|
|
shell_intf->keepalive(shell_intf);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
char *ptr, *pbuf, **ap, *__argv[EXEC_ARG_SIZE];
|
|
int __argc, rc=0;
|
|
|
|
rl_readline_name = "ipmitool";
|
|
|
|
/* this essentially disables command completion
|
|
* until its implemented right, otherwise we get
|
|
* the current directory contents... */
|
|
rl_bind_key('\t', rl_insert);
|
|
|
|
if (intf->keepalive) {
|
|
/* hook to keep lan sessions active */
|
|
shell_intf = intf;
|
|
rl_event_hook = rl_event_keepalive;
|
|
#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0402
|
|
/* There is a bug in readline 4.2 and later (at least on FreeBSD and NetBSD):
|
|
* timeout equal or greater than 1 second causes an infinite loop. */
|
|
rl_set_keyboard_input_timeout(1000 * 1000 - 1);
|
|
#endif
|
|
}
|
|
|
|
while ((pbuf = (char *)readline(RL_PROMPT)) != NULL) {
|
|
if (strlen(pbuf) == 0) {
|
|
free(pbuf);
|
|
pbuf = NULL;
|
|
continue;
|
|
}
|
|
if (strncmp(pbuf, "quit", 4) == 0 ||
|
|
strncmp(pbuf, "exit", 4) == 0) {
|
|
free(pbuf);
|
|
pbuf = NULL;
|
|
return 0;
|
|
}
|
|
if (strncmp(pbuf, "help", 4) == 0 ||
|
|
strncmp(pbuf, "?", 1) == 0) {
|
|
ipmi_cmd_print(intf->cmdlist);
|
|
free(pbuf);
|
|
pbuf = NULL;
|
|
continue;
|
|
}
|
|
|
|
/* for the all-important up arrow :) */
|
|
add_history(pbuf);
|
|
|
|
/* change "" and '' with spaces in the middle to ~ */
|
|
ptr = pbuf;
|
|
while (*ptr != '\0') {
|
|
if (*ptr == '"') {
|
|
ptr++;
|
|
while (*ptr != '"' && *ptr != '\0') {
|
|
if (isspace((int)*ptr))
|
|
*ptr = '~';
|
|
ptr++;
|
|
}
|
|
}
|
|
if (*ptr == '\'') {
|
|
ptr++;
|
|
while (*ptr != '\'' && *ptr != '\0') {
|
|
if (isspace((int)*ptr))
|
|
*ptr = '~';
|
|
ptr++;
|
|
}
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
__argc = 0;
|
|
ap = __argv;
|
|
|
|
for (*ap = strtok(pbuf, " \t");
|
|
*ap != NULL;
|
|
*ap = strtok(NULL, " \t")) {
|
|
__argc++;
|
|
|
|
ptr = *ap;
|
|
if (*ptr == '\'') {
|
|
memmove(ptr, ptr+1, strlen(ptr));
|
|
while (*ptr != '\'' && *ptr != '\0') {
|
|
if (*ptr == '~')
|
|
*ptr = ' ';
|
|
ptr++;
|
|
}
|
|
*ptr = '\0';
|
|
}
|
|
if (*ptr == '"') {
|
|
memmove(ptr, ptr+1, strlen(ptr));
|
|
while (*ptr != '"' && *ptr != '\0') {
|
|
if (*ptr == '~')
|
|
*ptr = ' ';
|
|
ptr++;
|
|
}
|
|
*ptr = '\0';
|
|
}
|
|
|
|
if (**ap != '\0') {
|
|
if (++ap >= &__argv[EXEC_ARG_SIZE])
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (__argc && __argv[0])
|
|
rc = ipmi_cmd_run(intf,
|
|
__argv[0],
|
|
__argc-1,
|
|
&(__argv[1]));
|
|
|
|
free(pbuf);
|
|
pbuf = NULL;
|
|
}
|
|
printf("\n");
|
|
return rc;
|
|
}
|
|
|
|
#else /* HAVE_READLINE */
|
|
|
|
int
|
|
ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
lprintf(LOG_ERR, "Compiled without readline, shell is disabled");
|
|
return -1;
|
|
}
|
|
|
|
#endif /* HAVE_READLINE */
|
|
|
|
int ipmi_echo_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<argc; i++) {
|
|
printf("%s ", argv[i]);
|
|
}
|
|
printf("\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
ipmi_set_usage(void)
|
|
{
|
|
lprintf(LOG_NOTICE, "Usage: set <option> <value>\n");
|
|
lprintf(LOG_NOTICE, "Options are:");
|
|
lprintf(LOG_NOTICE, " hostname <host> Session hostname");
|
|
lprintf(LOG_NOTICE, " username <user> Session username");
|
|
lprintf(LOG_NOTICE, " password <pass> Session password");
|
|
lprintf(LOG_NOTICE, " privlvl <level> Session privilege level force");
|
|
lprintf(LOG_NOTICE, " authtype <type> Authentication type force");
|
|
lprintf(LOG_NOTICE, " localaddr <addr> Local IPMB address");
|
|
lprintf(LOG_NOTICE, " targetaddr <addr> Remote target IPMB address");
|
|
lprintf(LOG_NOTICE, " port <port> Remote RMCP port");
|
|
lprintf(LOG_NOTICE, " csv [level] enable output in comma separated format");
|
|
lprintf(LOG_NOTICE, " verbose [level] Verbose level");
|
|
lprintf(LOG_NOTICE, "");
|
|
}
|
|
|
|
int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
|
|
ipmi_set_usage();
|
|
return -1;
|
|
}
|
|
|
|
/* these options can have no arguments */
|
|
if (strncmp(argv[0], "verbose", 7) == 0) {
|
|
if (argc > 1) {
|
|
if (str2int(argv[1], &verbose) != 0) {
|
|
lprintf(LOG_ERR,
|
|
"Given verbose '%s' argument is invalid.",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
} else {
|
|
verbose = verbose + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
if (strncmp(argv[0], "csv", 3) == 0) {
|
|
if (argc > 1) {
|
|
if (str2int(argv[1], &csv_output) != 0) {
|
|
lprintf(LOG_ERR,
|
|
"Given csv '%s' argument is invalid.",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
} else {
|
|
csv_output = 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* the rest need an argument */
|
|
if (argc == 1) {
|
|
ipmi_set_usage();
|
|
return -1;
|
|
}
|
|
|
|
if (strncmp(argv[0], "host", 4) == 0 ||
|
|
strncmp(argv[0], "hostname", 8) == 0) {
|
|
ipmi_intf_session_set_hostname(intf, argv[1]);
|
|
if (intf->session == NULL) {
|
|
lprintf(LOG_ERR, "Failed to set session hostname.");
|
|
return (-1);
|
|
}
|
|
printf("Set session hostname to %s\n",
|
|
intf->ssn_params.hostname);
|
|
}
|
|
else if (strncmp(argv[0], "user", 4) == 0 ||
|
|
strncmp(argv[0], "username", 8) == 0) {
|
|
ipmi_intf_session_set_username(intf, argv[1]);
|
|
if (intf->session == NULL) {
|
|
lprintf(LOG_ERR, "Failed to set session username.");
|
|
return (-1);
|
|
}
|
|
printf("Set session username to %s\n",
|
|
intf->ssn_params.username);
|
|
}
|
|
else if (strncmp(argv[0], "pass", 4) == 0 ||
|
|
strncmp(argv[0], "password", 8) == 0) {
|
|
ipmi_intf_session_set_password(intf, argv[1]);
|
|
if (intf->session == NULL) {
|
|
lprintf(LOG_ERR, "Failed to set session password.");
|
|
return (-1);
|
|
}
|
|
printf("Set session password\n");
|
|
}
|
|
else if (strncmp(argv[0], "authtype", 8) == 0) {
|
|
int authtype;
|
|
authtype = str2val(argv[1], ipmi_authtype_session_vals);
|
|
if (authtype == 0xFF) {
|
|
lprintf(LOG_ERR, "Invalid authtype: %s",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
ipmi_intf_session_set_authtype(intf, authtype);
|
|
if (intf->session == NULL) {
|
|
lprintf(LOG_ERR, "Failed to set session authtype.");
|
|
return (-1);
|
|
}
|
|
printf("Set session authtype to %s\n",
|
|
val2str(intf->ssn_params.authtype_set,
|
|
ipmi_authtype_session_vals));
|
|
}
|
|
else if (strncmp(argv[0], "privlvl", 7) == 0) {
|
|
int privlvl;
|
|
privlvl = str2val(argv[1], ipmi_privlvl_vals);
|
|
if (privlvl == 0xFF) {
|
|
lprintf(LOG_ERR, "Invalid privilege level: %s",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
ipmi_intf_session_set_privlvl(intf, privlvl);
|
|
if (intf->session == NULL) {
|
|
lprintf(LOG_ERR,
|
|
"Failed to set session privilege level.");
|
|
return (-1);
|
|
}
|
|
printf("Set session privilege level to %s\n",
|
|
val2str(intf->ssn_params.privlvl,
|
|
ipmi_privlvl_vals));
|
|
}
|
|
else if (strncmp(argv[0], "port", 4) == 0) {
|
|
int port = 0;
|
|
if (str2int(argv[1], &port) != 0 || port > MAX_PORT) {
|
|
lprintf(LOG_ERR, "Given port '%s' is invalid.",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
ipmi_intf_session_set_port(intf, port);
|
|
if (intf->session == NULL) {
|
|
lprintf(LOG_ERR, "Failed to set session port.");
|
|
return (-1);
|
|
}
|
|
printf("Set session port to %d\n", intf->ssn_params.port);
|
|
}
|
|
else if (strncmp(argv[0], "localaddr", 9) == 0) {
|
|
uint8_t my_addr = 0;
|
|
if (str2uchar(argv[1], &my_addr) != 0) {
|
|
lprintf(LOG_ERR, "Given localaddr '%s' is invalid.",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
intf->my_addr = my_addr;
|
|
printf("Set local IPMB address to 0x%02x\n", intf->my_addr);
|
|
}
|
|
else if (strncmp(argv[0], "targetaddr", 10) == 0) {
|
|
uint8_t target_addr = 0;
|
|
if (str2uchar(argv[1], &target_addr) != 0) {
|
|
lprintf(LOG_ERR, "Given targetaddr '%s' is invalid.",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
intf->target_addr = target_addr;
|
|
printf("Set remote IPMB address to 0x%02x\n", intf->target_addr);
|
|
}
|
|
else {
|
|
ipmi_set_usage();
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
FILE * fp;
|
|
char buf[EXEC_BUF_SIZE];
|
|
char * ptr, * tok, * ret, * tmp;
|
|
int __argc, i, r;
|
|
char * __argv[EXEC_ARG_SIZE];
|
|
int rc=0;
|
|
|
|
if (argc < 1) {
|
|
lprintf(LOG_ERR, "Usage: exec <filename>");
|
|
return -1;
|
|
}
|
|
|
|
fp = ipmi_open_file_read(argv[0]);
|
|
if (fp == NULL)
|
|
return -1;
|
|
|
|
while (feof(fp) == 0) {
|
|
ret = fgets(buf, EXEC_BUF_SIZE, fp);
|
|
if (ret == NULL)
|
|
continue;
|
|
|
|
/* clip off optional comment tail indicated by # */
|
|
ptr = strchr(buf, '#');
|
|
if (ptr)
|
|
*ptr = '\0';
|
|
else
|
|
ptr = buf + strlen(buf);
|
|
|
|
/* change "" and '' with spaces in the middle to ~ */
|
|
ptr = buf;
|
|
while (*ptr != '\0') {
|
|
if (*ptr == '"') {
|
|
ptr++;
|
|
while (*ptr != '"' && *ptr != '\0') {
|
|
if (isspace((int)*ptr))
|
|
*ptr = '~';
|
|
ptr++;
|
|
}
|
|
}
|
|
if (*ptr == '\'') {
|
|
ptr++;
|
|
while (*ptr != '\'' && *ptr != '\0') {
|
|
if (isspace((int)*ptr))
|
|
*ptr = '~';
|
|
ptr++;
|
|
}
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
/* clip off trailing and leading whitespace */
|
|
ptr--;
|
|
while (isspace((int)*ptr) && ptr >= buf)
|
|
*ptr-- = '\0';
|
|
ptr = buf;
|
|
while (isspace((int)*ptr))
|
|
ptr++;
|
|
if (strlen(ptr) == 0)
|
|
continue;
|
|
|
|
/* parse it and make argument list */
|
|
__argc = 0;
|
|
for (tok = strtok(ptr, " "); tok != NULL; tok = strtok(NULL, " ")) {
|
|
if (__argc < EXEC_ARG_SIZE) {
|
|
__argv[__argc++] = strdup(tok);
|
|
if (__argv[__argc-1] == NULL) {
|
|
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
if (fp) {
|
|
fclose(fp);
|
|
fp = NULL;
|
|
}
|
|
return -1;
|
|
}
|
|
tmp = __argv[__argc-1];
|
|
if (*tmp == '\'') {
|
|
memmove(tmp, tmp+1, strlen(tmp));
|
|
while (*tmp != '\'' && *tmp != '\0') {
|
|
if (*tmp == '~')
|
|
*tmp = ' ';
|
|
tmp++;
|
|
}
|
|
*tmp = '\0';
|
|
}
|
|
if (*tmp == '"') {
|
|
memmove(tmp, tmp+1, strlen(tmp));
|
|
while (*tmp != '"' && *tmp != '\0') {
|
|
if (*tmp == '~')
|
|
*tmp = ' ';
|
|
tmp++;
|
|
}
|
|
*tmp = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
/* now run the command, save the result if not successful */
|
|
r = ipmi_cmd_run(intf, __argv[0], __argc-1, &(__argv[1]));
|
|
if (r != 0)
|
|
rc = r;
|
|
|
|
/* free argument list */
|
|
for (i=0; i<__argc; i++) {
|
|
if (__argv[i] != NULL) {
|
|
free(__argv[i]);
|
|
__argv[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
return rc;
|
|
}
|