diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-07-23 15:03:01 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-07-23 15:03:01 +0200 | 
| commit | 777af8a8761d05c30588abec7444b143fe7393f0 (patch) | |
| tree | 5a135c37eaa9ac94772819a28ce5beedd18e5c4a /src/ipmishell.c | |
| parent | c3445516ecd58e97de483cf4b7fafcc1104890d7 (diff) | |
| parent | b32d92e890caac903491116e9d817aa780c0323b (diff) | |
Merge tag 'upstream/1.8.14'
Upstream version 1.8.14
Diffstat (limited to 'src/ipmishell.c')
| -rw-r--r-- | src/ipmishell.c | 510 | 
1 files changed, 510 insertions, 0 deletions
| diff --git a/src/ipmishell.c b/src/ipmishell.c new file mode 100644 index 0000000..4eebcd8 --- /dev/null +++ b/src/ipmishell.c @@ -0,0 +1,510 @@ +/* + * 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->session->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->session->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->session->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->session->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->session->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"); +					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; +} | 
