📄 env.c
字号:
/* shell variable functions:
* Used to load or retrieve shell variable information from the
* shell variable table.
*
* General notice:
* This code is part of a boot-monitor package developed as a generic base
* platform for embedded system designs. As such, it is likely to be
* distributed to various projects beyond the control of the original
* author. Please notify the author of any enhancements made or bugs found
* so that all may benefit from the changes. In addition, notification back
* to the author will allow the new user to pick up changes that may have
* been made by other users after this version of the code was distributed.
*
* Note1: the majority of this code was edited with 4-space tabs.
* Note2: as more and more contributions are accepted, the term "author"
* is becoming a mis-representation of credit.
*
* Original author: Ed Sutter
* Email: esutter@lucent.com
* Phone: 908-582-2351
*/
#include <stdarg.h>
#include "config.h"
#if INCLUDE_SHELLVARS
#include "tfs.h"
#include "tfsprivate.h"
#include "ether.h"
#include "genlib.h"
#include "stddefs.h"
#include "cli.h"
#include "version.h"
#include "boardinfo.h"
#include "ee.h"
#ifdef TARGET_ENV_SETUP
extern void TARGET_ENV_SETUP(void);
#endif
#ifndef PROMPT
#define PROMPT "uMON>"
#endif
int shell_print(void);
int envToExec(char *);
void clearenv(void);
/* Structure used for the shell variables: */
struct s_shell {
char *val; /* Value stored in shell variable */
char *name; /* Name of shell variable */
int vsize; /* Size of storage allocated for value */
struct s_shell *next;
};
struct s_shell *shell_vars;
/* If no malloc, then use locally defined env_alloc() and env_free()...
*/
#if INCLUDE_MALLOC
#define env_alloc malloc
#define env_free free
#else
#define ENV_ALLOC_TOT 48
#define ENV_ALLOC_SIZE (sizeof(struct s_shell)+8)
struct env_space {
int inuse;
char space[ENV_ALLOC_SIZE];
} envSpace[ENV_ALLOC_TOT];
char *
env_alloc(int size)
{
int i;
if (size > ENV_ALLOC_SIZE)
return(0);
for(i=0;i<ENV_ALLOC_TOT;i++) {
if (envSpace[i].inuse == 0) {
envSpace[i].inuse = 1;
memset(envSpace[i].space,0,ENV_ALLOC_SIZE);
return(envSpace[i].space);
}
}
return(0);
}
void
env_free(char *space)
{
int i;
for(i=0;i<ENV_ALLOC_TOT;i++) {
if (envSpace[i].space == space) {
envSpace[i].inuse = 0;
break;
}
}
return;
}
#endif
/*
* Set()
*
* Syntax:
* set var clears the variable 'var'
* set var value assign "value" to variable 'var'
* set -a var value AND 'var' with 'value'
* set -o var value OR 'var' with 'value'
* set -i var [value] increment 'var' by 'value' (or 1 if no value)
* set -d var [value] decrement 'var' by 'value' (or 1 if no value)
* set -x result of -i/-d is in hex
*/
char *SetHelp[] = {
"Shell variable operations",
#if INCLUDE_EE
"-[ab:cdef:iox] [varname[=expression]] [value]",
#else
"-[ab:cdef:iox] [varname] [value]",
#endif
#if INCLUDE_VERBOSEHELP
" -a AND var with value",
" -b set console baudrate",
" -c clear the environment",
" -d decrease var by value (or 1)",
" -e build an environ string",
" -f{file} create script from environment",
" -i increase var by value (or 1)",
" -o OR var with value",
" -x result is hex (else decimal)",
#endif
0,
};
#define SET_NOOP 0
#define SET_INCR 1
#define SET_DECR 2
#define SET_OR 3
#define SET_AND 4
int
Set(int argc,char *argv[])
{
char *file, *envp, buf[128];
int opt, decimal, setop, i;
setop = SET_NOOP;
file = (char *)0;
envp = (char *)0;
decimal = 1;
while((opt=getopt(argc,argv,"ab:cde:f:iox")) != -1) {
switch(opt) {
case 'a': /* logical and */
setop = SET_AND;
decimal = 0;
break;
case 'b':
ChangeConsoleBaudrate(atoi(optarg));
return(CMD_SUCCESS);
case 'c': /* clear environment */
clearenv();
break;
case 'd': /* decrement */
setop = SET_DECR;
break;
case 'e':
envp = getenvp();
break;
#if INCLUDE_TFS
case 'f': /* build script from environment */
envToExec(optarg);
return(0);
#endif
case 'i': /* increment */
setop = SET_INCR;
break;
case 'o': /* logical or */
setop = SET_OR;
decimal = 0;
break;
case 'x':
decimal = 0;
break;
default:
return(CMD_PARAM_ERROR);
}
}
if (!shell_vars) {
printf("No memory allocated for environment.\n");
return(CMD_FAILURE);
}
if (setop != SET_NOOP) { /* Do some operation on a shell variable */
char *varval, buf[32];
unsigned long value, opval;
/* For -i & -d, if value is not specified, then assume 1. */
if (argc == optind+1) {
if ((setop == SET_INCR) || (setop == SET_DECR))
opval = 1;
else
return(CMD_PARAM_ERROR);
}
else if (argc == optind+2)
opval = strtoul(argv[optind+1],0,0);
else
return(CMD_PARAM_ERROR);
varval = getenv(argv[optind]);
if (!varval) {
printf("%s: not found\n", argv[optind]);
return(CMD_FAILURE);
}
value = strtoul(varval,(char **)0,0);
switch(setop) {
case SET_INCR:
value += opval;
break;
case SET_DECR:
value -= opval;
break;
case SET_AND:
value &= opval;
break;
case SET_OR:
value |= opval;
break;
}
if (decimal)
sprintf(buf,"%ld",value);
else
sprintf(buf,"0x%lx",value);
setenv(argv[optind],buf);
}
else if (argc == optind) { /* display all variables */
shell_print();
}
else if (argc == (optind+1)) { /* run EE or clear one var or set envp */
#if INCLUDE_EE
switch(setEE(argv[optind])) {
case 1:
return(CMD_SUCCESS);
case -1:
return(CMD_FAILURE);
}
#endif
if (envp)
shell_sprintf(argv[optind],"0x%lx",(ulong)envp);
else
setenv(argv[optind],0);
}
else if (argc >= (optind+2)) { /* Set a specific variable */
buf[0] = 0;
for(i=optind+1;i<argc;i++) {
if ((strlen(buf) + strlen(argv[i]) + 2) >= sizeof(buf)) {
printf("String too large\n");
break;
}
strcat(buf,argv[i]);
if (i != (argc-1))
strcat(buf," ");
}
setenv(argv[optind],buf);
}
else
return(CMD_PARAM_ERROR);
//printf("Ethaddr=%s\n",getenv("ETHERADD"));
return(CMD_SUCCESS);
}
/* Shell variable support routines...
* The basic scheme is to malloc in the space needed for the variable
* name and the value of that variable. For each variable that
* exists there is one s_shell structure that is in the linked list.
* As shell variables are removed, their corresonding s_shell structure
* is NOT removed, but the data pointed to within the structure is
* freed. This keeps the linked list implementation extremely simple
* but maintains the versatility gained by using malloc for the
* variables instead of some limted set of static arrays.
*/
/* shell_alloc():
* First scan through the entire list to see if the requested
* shell variable name already exists in the list; if it does,
* then just use the same s_shell entry but change the value.
* Also, if the new value fits in the same space as the older value,
* then just use the same memory space (don't do the free/malloc).
* If it doesn't, then scan through the list again. If there
* is one that has no variable assigned to it (name = 0), then
* use it for the new allocation. If all s_shell structures do
* have valid entries, then malloc a new s_shell structure and then
* place the new shell variable data in that structure.
*/
static int
shell_alloc(char *name,char *value)
{
int namelen, valuelen;
struct s_shell *sp;
sp = shell_vars;
namelen = strlen(name);
valuelen = strlen(value);
while(1) {
if (sp->name == (char *)0) {
if (sp->next != (struct s_shell *)0) {
sp = sp->next;
continue;
}
else
break;
}
if (strcmp(sp->name,name) == 0) {
if (sp->vsize < valuelen+1) { /* If new value is smaller */
env_free(sp->val); /* than the old value, then */
sp->val = env_alloc(valuelen+1);/* don't re-allocate any */
if (!sp->val) /* memory, just copy into */
return(-1); /* the space used by the */
sp->vsize = valuelen+1; /* previous value. */
}
strcpy(sp->val,value);
return(0);
}
if (sp->next == (struct s_shell *)0)
break;
sp = sp->next;
}
sp = shell_vars;
while(1) {
if (sp->name == (char *)0) {
sp->name = env_alloc(namelen+1);
if (!sp->name)
return(-1);
strcpy(sp->name,name);
sp->val = env_alloc(valuelen+1);
if (!sp->val)
return(-1);
sp->vsize = valuelen+1;
strcpy(sp->val,value);
return(0);
}
if (sp->next != (struct s_shell *)0)
sp = sp->next;
else {
sp->next = (struct s_shell *)env_alloc(sizeof(struct s_shell));
if (!sp->next)
return(-1);
sp = sp->next;
sp->name = env_alloc(namelen+1);
if (!sp->name)
return(-1);
strcpy(sp->name,name);
sp->val = env_alloc(valuelen+1);
if (!sp->val)
return(-1);
sp->vsize = valuelen+1;
strcpy(sp->val,value);
sp->next = (struct s_shell *)0;
return(0);
}
}
}
/* shell_dealloc():
* Remove the requested shell variable from the list. Return 0 if
* the variable was removed successfully, otherwise return -1.
*/
static int
shell_dealloc(char *name)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -