📄 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 "config.h"#include "tfs.h"#include "tfsprivate.h"#include "ether.h"#include "genlib.h"#include "stddefs.h"#include "cli.h"#ifndef PROMPT#define PROMPT "uMON>"#endifint shell_print(void);int envToExec(char *);/* 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;/* * 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", "-[adF:iox] [varname] [value]", " -a AND var with value", " -d decrease var by value (or 1)", " -i increase var by value (or 1)", " -o OR var with value", " -x result is hex (else decimal)", 0,};#define SET_NOOP 0#define SET_INCR 1#define SET_DECR 2#define SET_OR 3#define SET_AND 4intSet(int argc,char *argv[]){ char *buf, *file; int i, opt, decimal, setop; setop = SET_NOOP; file = (char *)0; decimal = 1; while((opt=getopt(argc,argv,"adiox")) != -1) { switch(opt) { case 'a': /* logical and */ setop = SET_AND; decimal = 0; break; case 'd': /* decrement */ setop = SET_DECR; break; 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) { /* clear one variable */ setenv(argv[optind],0); } else if (argc == optind + 2) { /* Set a specific variable */ setenv(argv[optind],argv[optind+1]); } else if (argc >= optind + 2) { /* Concatenate multiple args into one. */ int len = 0; for(i=optind+1;i<argc;i++) len += strlen(argv[i]); buf = malloc(len+argc+8); *buf = 0; for(i=optind+1;i<argc;i++) { strcat(buf,argv[i]); if (i+1 != argc) strcat(buf," "); } setenv(argv[optind],buf); free(buf); } 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. */intshell_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 */ free(sp->val); /* than the old value, then */ sp->val = malloc(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 = malloc(namelen+1); if (!sp->name) return(-1); strcpy(sp->name,name); sp->val = malloc(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 *)malloc(sizeof(struct s_shell)); if (!sp->next) return(-1); sp = sp->next; sp->name = malloc(namelen+1); if (!sp->name) return(-1); strcpy(sp->name,name); sp->val = malloc(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. */intshell_dealloc(name)char *name;{ struct s_shell *sp; sp = shell_vars; while(1) { if (sp->name == (char *)0) { if (sp->next == (struct s_shell *)0) return(-1); else { sp = sp->next; continue; } } if (strcmp(name,sp->name) == 0) { free(sp->name); free(sp->val); sp->name = (char *)0; sp->val = (char *)0; return(0); } if (sp->next == (struct s_shell *)0) return(-1); else sp = sp->next; }}/* ConsoleBaudEnvSet(): * Called by ShellVarInit() and mstat() to load/reload the CONSOLEBAUD * shell variable based on the content of the global variable * "ConsoleBaudRate". */voidConsoleBaudEnvSet(void){ char buf[16]; sprintf(buf,"%d",ConsoleBaudRate); setenv("CONSOLEBAUD",buf);}/* ShellVarInit(); * Setup the shell_vars pointer appropriately for additional * shell variable assignments that will be made through shell_alloc(). */intShellVarInit(){ char buf[16]; shell_vars = (struct s_shell *)malloc(sizeof(struct s_shell)); if (!shell_vars) { printf("No memory for environment initialization\n"); return(-1); } shell_vars->next = (struct s_shell *)0; shell_vars->name = (char *)0; setenv("PROMPT",PROMPT); sprintf(buf,"0x%lx",APPLICATION_RAMSTART); setenv("APPRAMBASE",buf); sprintf(buf,"0x%lx",BOOTROM_BASE); setenv("BOOTROMBASE",buf); setenv("PLATFORM",PLATFORM_NAME); ConsoleBaudEnvSet(); MonitorBuiltEnvSet(); return(0);}/* shell_get: * Return the pointer to the value entry if the shell variable * name is currently set; otherwise, return a null pointer. */char *getenv(char *name){ register struct s_shell *sp; sp = shell_vars; while(sp) { if (sp->name != (char *)0) { if (strcmp(sp->name,name) == 0) return(sp->val); } sp = sp->next; } return((char *)0);}/* setenv: * Interface to shell_dealloc() and shell_alloc(). */intsetenv(char *name,char *value){ if (!shell_vars) return(-1); if ((value == (char *)0) || (*value == 0)) return(shell_dealloc(name)); else return(shell_alloc(name,value));}/* shell_print(): * Print out all of the current shell variables and their values. */intshell_print(void){ register struct s_shell *sp; sp = shell_vars; while(1) { if (sp->name != (char *)0) { printf("%16s = ", sp->name); puts(sp->val); /* sp->val may overflow printf, so use puts */ putchar('\n'); } if (sp->next != (struct s_shell *)0) sp = sp->next; else break; } return(0);}/* shell_sprintf(): * Simple way to turn a printf-like formatted string into a shell variable. */intshell_sprintf(char *varname,char *format,long arg1,long arg2,long arg3, long arg4,long arg5,long arg6,long arg7,long arg8,long arg9, long arg10,long arg11,long arg12){ int len; char buf[80]; len = sprintf(buf,format,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9, arg10,arg11,arg12); setenv(varname,buf); return(len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -