1 | /************************************************************************** |
---|
2 | * |
---|
3 | * Copyright (c) 2013 Alcatel-Lucent |
---|
4 | * |
---|
5 | * Alcatel Lucent licenses this file to You under the Apache License, |
---|
6 | * Version 2.0 (the "License"); you may not use this file except in |
---|
7 | * compliance with the License. A copy of the License is contained the |
---|
8 | * file LICENSE at the top level of this repository. |
---|
9 | * You may also obtain a copy of the License at: |
---|
10 | * |
---|
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
---|
12 | * |
---|
13 | * Unless required by applicable law or agreed to in writing, software |
---|
14 | * distributed under the License is distributed on an "AS IS" BASIS, |
---|
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
---|
16 | * See the License for the specific language governing permissions and |
---|
17 | * limitations under the License. |
---|
18 | * |
---|
19 | ************************************************************************** |
---|
20 | * |
---|
21 | * env.c: |
---|
22 | * Shell variable functions used to load or retrieve shell variable |
---|
23 | * information from the shell variable table. |
---|
24 | * |
---|
25 | * Original author: Ed Sutter (ed.sutter@alcatel-lucent.com) |
---|
26 | * |
---|
27 | */ |
---|
28 | #include <stdarg.h> |
---|
29 | #include "config.h" |
---|
30 | #include "tfs.h" |
---|
31 | #include "tfsprivate.h" |
---|
32 | #include "ether.h" |
---|
33 | #include "genlib.h" |
---|
34 | #include "stddefs.h" |
---|
35 | #include "cli.h" |
---|
36 | #include "version.h" |
---|
37 | #include "boardinfo.h" |
---|
38 | #include "timer.h" |
---|
39 | |
---|
40 | #if INCLUDE_SHELLVARS |
---|
41 | |
---|
42 | char *whatplatform = "@(#)PLATFORM=" PLATFORM_NAME; |
---|
43 | |
---|
44 | #ifdef TARGET_ENV_SETUP |
---|
45 | extern void TARGET_ENV_SETUP(void); |
---|
46 | #endif |
---|
47 | |
---|
48 | #ifndef PROMPT |
---|
49 | #define PROMPT "uMON>" |
---|
50 | #endif |
---|
51 | |
---|
52 | int shell_print(void); |
---|
53 | int envToExec(char *); |
---|
54 | void clearenv(void); |
---|
55 | |
---|
56 | /* Structure used for the shell variables: */ |
---|
57 | struct s_shell { |
---|
58 | char *val; /* Value stored in shell variable */ |
---|
59 | char *name; /* Name of shell variable */ |
---|
60 | int vsize; /* Size of storage allocated for value */ |
---|
61 | struct s_shell *next; |
---|
62 | }; |
---|
63 | |
---|
64 | struct s_shell *shell_vars; |
---|
65 | |
---|
66 | /* If no malloc, then use locally defined env_alloc() and env_free()... |
---|
67 | */ |
---|
68 | #if INCLUDE_MALLOC |
---|
69 | |
---|
70 | #define env_alloc malloc |
---|
71 | #define env_free free |
---|
72 | |
---|
73 | #else |
---|
74 | |
---|
75 | #define ENV_ALLOC_TOT 48 |
---|
76 | #define ENV_ALLOC_SIZE (sizeof(struct s_shell)+8) |
---|
77 | |
---|
78 | struct env_space { |
---|
79 | int inuse; |
---|
80 | char space[ENV_ALLOC_SIZE]; |
---|
81 | } envSpace[ENV_ALLOC_TOT]; |
---|
82 | |
---|
83 | |
---|
84 | char * |
---|
85 | env_alloc(int size) |
---|
86 | { |
---|
87 | int i; |
---|
88 | |
---|
89 | if (size > ENV_ALLOC_SIZE) |
---|
90 | return(0); |
---|
91 | |
---|
92 | for(i=0;i<ENV_ALLOC_TOT;i++) { |
---|
93 | if (envSpace[i].inuse == 0) { |
---|
94 | envSpace[i].inuse = 1; |
---|
95 | memset(envSpace[i].space,0,ENV_ALLOC_SIZE); |
---|
96 | return(envSpace[i].space); |
---|
97 | } |
---|
98 | } |
---|
99 | return(0); |
---|
100 | } |
---|
101 | |
---|
102 | void |
---|
103 | env_free(char *space) |
---|
104 | { |
---|
105 | int i; |
---|
106 | |
---|
107 | for(i=0;i<ENV_ALLOC_TOT;i++) { |
---|
108 | if (envSpace[i].space == space) { |
---|
109 | envSpace[i].inuse = 0; |
---|
110 | break; |
---|
111 | } |
---|
112 | } |
---|
113 | return; |
---|
114 | } |
---|
115 | #endif |
---|
116 | |
---|
117 | /* |
---|
118 | * Set() |
---|
119 | * |
---|
120 | * Syntax: |
---|
121 | * set var clears the variable 'var' |
---|
122 | * set var value assign "value" to variable 'var' |
---|
123 | * set -a var value AND 'var' with 'value' |
---|
124 | * set -o var value OR 'var' with 'value' |
---|
125 | * set -i var [value] increment 'var' by 'value' (or 1 if no value) |
---|
126 | * set -d var [value] decrement 'var' by 'value' (or 1 if no value) |
---|
127 | * set -x result of -i/-d is in hex |
---|
128 | */ |
---|
129 | char *SetHelp[] = { |
---|
130 | "Shell variable operations", |
---|
131 | #if INCLUDE_EE |
---|
132 | "-[ab:cdef:iox] [varname[=expression]] [value]", |
---|
133 | #else |
---|
134 | "-[ab:cdef:iox] [varname] [value]", |
---|
135 | #endif |
---|
136 | #if INCLUDE_VERBOSEHELP |
---|
137 | " -a AND var with value", |
---|
138 | " -b set console baudrate", |
---|
139 | " -c clear the environment", |
---|
140 | " -d decrease var by value (or 1)", |
---|
141 | " -e build an environ string", |
---|
142 | #if INCLUDE_TFS |
---|
143 | " -f{file} create script from environment", |
---|
144 | #endif |
---|
145 | " -i increase var by value (or 1)", |
---|
146 | " -o OR var with value", |
---|
147 | " -x result in hex (NA with expressions, use hex())", |
---|
148 | #endif |
---|
149 | 0, |
---|
150 | }; |
---|
151 | |
---|
152 | #define SET_NOOP 0 |
---|
153 | #define SET_INCR 1 |
---|
154 | #define SET_DECR 2 |
---|
155 | #define SET_OR 3 |
---|
156 | #define SET_AND 4 |
---|
157 | |
---|
158 | int |
---|
159 | Set(int argc,char *argv[]) |
---|
160 | { |
---|
161 | char *envp, buf[CMDLINESIZE]; |
---|
162 | int opt, decimal, setop, i; |
---|
163 | |
---|
164 | setop = SET_NOOP; |
---|
165 | envp = (char *)0; |
---|
166 | decimal = 1; |
---|
167 | while((opt=getopt(argc,argv,"ab:cdef:iox")) != -1) { |
---|
168 | switch(opt) { |
---|
169 | case 'a': /* logical and */ |
---|
170 | setop = SET_AND; |
---|
171 | decimal = 0; |
---|
172 | break; |
---|
173 | case 'b': |
---|
174 | ChangeConsoleBaudrate(atoi(optarg)); |
---|
175 | return(CMD_SUCCESS); |
---|
176 | case 'c': /* clear environment */ |
---|
177 | clearenv(); |
---|
178 | break; |
---|
179 | case 'd': /* decrement */ |
---|
180 | setop = SET_DECR; |
---|
181 | break; |
---|
182 | case 'e': |
---|
183 | envp = getenvp(); |
---|
184 | break; |
---|
185 | #if INCLUDE_TFS |
---|
186 | case 'f': /* build script from environment */ |
---|
187 | envToExec(optarg); |
---|
188 | return(0); |
---|
189 | #endif |
---|
190 | case 'i': /* increment */ |
---|
191 | setop = SET_INCR; |
---|
192 | break; |
---|
193 | case 'o': /* logical or */ |
---|
194 | setop = SET_OR; |
---|
195 | decimal = 0; |
---|
196 | break; |
---|
197 | case 'x': |
---|
198 | decimal = 0; |
---|
199 | break; |
---|
200 | default: |
---|
201 | return(CMD_PARAM_ERROR); |
---|
202 | } |
---|
203 | } |
---|
204 | |
---|
205 | if (!shell_vars) { |
---|
206 | printf("No memory allocated for environment.\n"); |
---|
207 | return(CMD_FAILURE); |
---|
208 | } |
---|
209 | |
---|
210 | if (setop != SET_NOOP) { /* Do some operation on a shell variable */ |
---|
211 | char *varval; |
---|
212 | unsigned long value, opval; |
---|
213 | |
---|
214 | /* For -i & -d, if value is not specified, then assume 1. */ |
---|
215 | if (argc == optind+1) { |
---|
216 | if ((setop == SET_INCR) || (setop == SET_DECR)) |
---|
217 | opval = 1; |
---|
218 | else |
---|
219 | return(CMD_PARAM_ERROR); |
---|
220 | } |
---|
221 | else if (argc == optind+2) |
---|
222 | opval = strtoul(argv[optind+1],0,0); |
---|
223 | else |
---|
224 | return(CMD_PARAM_ERROR); |
---|
225 | |
---|
226 | varval = getenv(argv[optind]); |
---|
227 | if (!varval) { |
---|
228 | printf("%s: not found\n", argv[optind]); |
---|
229 | return(CMD_FAILURE); |
---|
230 | } |
---|
231 | |
---|
232 | value = strtoul(varval,(char **)0,0); |
---|
233 | switch(setop) { |
---|
234 | case SET_INCR: |
---|
235 | value += opval; |
---|
236 | break; |
---|
237 | case SET_DECR: |
---|
238 | value -= opval; |
---|
239 | break; |
---|
240 | case SET_AND: |
---|
241 | value &= opval; |
---|
242 | break; |
---|
243 | case SET_OR: |
---|
244 | value |= opval; |
---|
245 | break; |
---|
246 | } |
---|
247 | if (decimal) |
---|
248 | sprintf(buf,"%ld",value); |
---|
249 | else |
---|
250 | sprintf(buf,"0x%lx",value); |
---|
251 | setenv(argv[optind],buf); |
---|
252 | } |
---|
253 | else if (argc == optind) { /* display all variables */ |
---|
254 | shell_print(); |
---|
255 | } |
---|
256 | else if (argc == (optind+1)) { /* run EE or clear one var or set envp */ |
---|
257 | #if INCLUDE_EE |
---|
258 | switch(setEE(argv[optind])) { |
---|
259 | case 1: |
---|
260 | return(CMD_SUCCESS); |
---|
261 | case -1: |
---|
262 | return(CMD_FAILURE); |
---|
263 | } |
---|
264 | #endif |
---|
265 | if (envp) |
---|
266 | shell_sprintf(argv[optind],"0x%lx",(ulong)envp); |
---|
267 | else |
---|
268 | setenv(argv[optind],0); |
---|
269 | } |
---|
270 | else if (argc >= (optind+2)) { /* Set a specific variable */ |
---|
271 | buf[0] = 0; |
---|
272 | for(i=optind+1;i<argc;i++) { |
---|
273 | if ((strlen(buf) + strlen(argv[i]) + 2) >= sizeof(buf)) { |
---|
274 | printf("String too large\n"); |
---|
275 | break; |
---|
276 | } |
---|
277 | strcat(buf,argv[i]); |
---|
278 | if (i != (argc-1)) |
---|
279 | strcat(buf," "); |
---|
280 | } |
---|
281 | if (!decimal) |
---|
282 | shell_sprintf(argv[optind],"0x%lx",atoi(buf)); |
---|
283 | else |
---|
284 | setenv(argv[optind],buf); |
---|
285 | } |
---|
286 | else |
---|
287 | return(CMD_PARAM_ERROR); |
---|
288 | |
---|
289 | return(CMD_SUCCESS); |
---|
290 | } |
---|
291 | |
---|
292 | /* Shell variable support routines... |
---|
293 | * The basic scheme is to malloc in the space needed for the variable |
---|
294 | * name and the value of that variable. For each variable that |
---|
295 | * exists there is one s_shell structure that is in the linked list. |
---|
296 | * As shell variables are removed, their corresonding s_shell structure |
---|
297 | * is NOT removed, but the data pointed to within the structure is |
---|
298 | * freed. This keeps the linked list implementation extremely simple |
---|
299 | * but maintains the versatility gained by using malloc for the |
---|
300 | * variables instead of some limted set of static arrays. |
---|
301 | */ |
---|
302 | |
---|
303 | |
---|
304 | /* shell_alloc(): |
---|
305 | * First scan through the entire list to see if the requested |
---|
306 | * shell variable name already exists in the list; if it does, |
---|
307 | * then just use the same s_shell entry but change the value. |
---|
308 | * Also, if the new value fits in the same space as the older value, |
---|
309 | * then just use the same memory space (don't do the free/malloc). |
---|
310 | * If it doesn't, then scan through the list again. If there |
---|
311 | * is one that has no variable assigned to it (name = 0), then |
---|
312 | * use it for the new allocation. If all s_shell structures do |
---|
313 | * have valid entries, then malloc a new s_shell structure and then |
---|
314 | * place the new shell variable data in that structure. |
---|
315 | */ |
---|
316 | |
---|
317 | static int |
---|
318 | shell_alloc(char *name,char *value) |
---|
319 | { |
---|
320 | int namelen, valuelen; |
---|
321 | struct s_shell *sp; |
---|
322 | |
---|
323 | sp = shell_vars; |
---|
324 | namelen = strlen(name); |
---|
325 | valuelen = strlen(value); |
---|
326 | while(1) { |
---|
327 | if (sp->name == (char *)0) { |
---|
328 | if (sp->next != (struct s_shell *)0) { |
---|
329 | sp = sp->next; |
---|
330 | continue; |
---|
331 | } |
---|
332 | else |
---|
333 | break; |
---|
334 | } |
---|
335 | if (strcmp(sp->name,name) == 0) { |
---|
336 | if (sp->vsize < valuelen+1) { /* If new value is smaller */ |
---|
337 | env_free(sp->val); /* than the old value, then */ |
---|
338 | sp->val = env_alloc(valuelen+1);/* don't re-allocate any */ |
---|
339 | if (!sp->val) /* memory, just copy into */ |
---|
340 | return(-1); /* the space used by the */ |
---|
341 | sp->vsize = valuelen+1; /* previous value. */ |
---|
342 | } |
---|
343 | strcpy(sp->val,value); |
---|
344 | return(0); |
---|
345 | } |
---|
346 | if (sp->next == (struct s_shell *)0) |
---|
347 | break; |
---|
348 | sp = sp->next; |
---|
349 | } |
---|
350 | sp = shell_vars; |
---|
351 | while(1) { |
---|
352 | if (sp->name == (char *)0) { |
---|
353 | sp->name = env_alloc(namelen+1); |
---|
354 | if (!sp->name) |
---|
355 | return(-1); |
---|
356 | strcpy(sp->name,name); |
---|
357 | sp->val = env_alloc(valuelen+1); |
---|
358 | if (!sp->val) |
---|
359 | return(-1); |
---|
360 | sp->vsize = valuelen+1; |
---|
361 | strcpy(sp->val,value); |
---|
362 | return(0); |
---|
363 | } |
---|
364 | if (sp->next != (struct s_shell *)0) |
---|
365 | sp = sp->next; |
---|
366 | else { |
---|
367 | sp->next = (struct s_shell *)env_alloc(sizeof(struct s_shell)); |
---|
368 | if (!sp->next) |
---|
369 | return(-1); |
---|
370 | sp = sp->next; |
---|
371 | sp->name = env_alloc(namelen+1); |
---|
372 | if (!sp->name) |
---|
373 | return(-1); |
---|
374 | strcpy(sp->name,name); |
---|
375 | sp->val = env_alloc(valuelen+1); |
---|
376 | if (!sp->val) |
---|
377 | return(-1); |
---|
378 | sp->vsize = valuelen+1; |
---|
379 | strcpy(sp->val,value); |
---|
380 | sp->next = (struct s_shell *)0; |
---|
381 | return(0); |
---|
382 | } |
---|
383 | } |
---|
384 | } |
---|
385 | |
---|
386 | /* shell_dealloc(): |
---|
387 | * Remove the requested shell variable from the list. Return 0 if |
---|
388 | * the variable was removed successfully, otherwise return -1. |
---|
389 | */ |
---|
390 | static int |
---|
391 | shell_dealloc(char *name) |
---|
392 | { |
---|
393 | struct s_shell *sp; |
---|
394 | |
---|
395 | sp = shell_vars; |
---|
396 | while(1) { |
---|
397 | if (sp->name == (char *)0) { |
---|
398 | if (sp->next == (struct s_shell *)0) |
---|
399 | return(-1); |
---|
400 | else { |
---|
401 | sp = sp->next; |
---|
402 | continue; |
---|
403 | } |
---|
404 | } |
---|
405 | if (strcmp(name,sp->name) == 0) { |
---|
406 | env_free(sp->name); |
---|
407 | env_free(sp->val); |
---|
408 | sp->name = (char *)0; |
---|
409 | sp->val = (char *)0; |
---|
410 | return(0); |
---|
411 | } |
---|
412 | |
---|
413 | if (sp->next == (struct s_shell *)0) |
---|
414 | return(-1); |
---|
415 | else |
---|
416 | sp = sp->next; |
---|
417 | } |
---|
418 | } |
---|
419 | |
---|
420 | /* ConsoleBaudEnvSet(): |
---|
421 | * Called by to load/reload the CONSOLEBAUD shell variable based on |
---|
422 | * the content of the global variable 'ConsoleBaudRate'. |
---|
423 | */ |
---|
424 | void |
---|
425 | ConsoleBaudEnvSet(void) |
---|
426 | { |
---|
427 | char buf[16]; |
---|
428 | |
---|
429 | sprintf(buf,"%d",ConsoleBaudRate); |
---|
430 | setenv("CONSOLEBAUD",buf); |
---|
431 | } |
---|
432 | |
---|
433 | /* ShellVarInit(); |
---|
434 | * Setup the shell_vars pointer appropriately for additional |
---|
435 | * shell variable assignments that will be made through shell_alloc(). |
---|
436 | */ |
---|
437 | int |
---|
438 | ShellVarInit() |
---|
439 | { |
---|
440 | char buf[16]; |
---|
441 | |
---|
442 | #if !INCLUDE_MALLOC |
---|
443 | memset((char *)&envSpace,0,sizeof(envSpace)); |
---|
444 | #endif |
---|
445 | |
---|
446 | shell_vars = (struct s_shell *)env_alloc(sizeof(struct s_shell)); |
---|
447 | if (!shell_vars) { |
---|
448 | printf("No memory for environment initialization\n"); |
---|
449 | return(-1); |
---|
450 | } |
---|
451 | shell_vars->next = (struct s_shell *)0; |
---|
452 | shell_vars->name = (char *)0; |
---|
453 | setenv("PROMPT",PROMPT); |
---|
454 | sprintf(buf,"0x%lx",APPLICATION_RAMSTART); |
---|
455 | setenv("APPRAMBASE",buf); |
---|
456 | sprintf(buf,"0x%lx",BOOTROM_BASE); |
---|
457 | setenv("BOOTROMBASE",buf); |
---|
458 | setenv("PLATFORM",PLATFORM_NAME); |
---|
459 | setenv("MONITORBUILT",monBuilt()); |
---|
460 | shell_sprintf("MONCOMPTR","0x%lx",(ulong)&moncomptr); |
---|
461 | #if INCLUDE_HWTMR |
---|
462 | shell_sprintf("TARGETTIMER","0x%x",target_timer); |
---|
463 | shell_sprintf("TICKSPERMSEC","0x%x",TIMER_TICKS_PER_MSEC); |
---|
464 | #endif |
---|
465 | |
---|
466 | /* Support the ability to have additional target-specific |
---|
467 | * shell variables initialized at startup... |
---|
468 | */ |
---|
469 | #ifdef TARGET_ENV_SETUP |
---|
470 | TARGET_ENV_SETUP(); |
---|
471 | #endif |
---|
472 | |
---|
473 | shell_sprintf("VERSION_MAJ","%d",MAJOR_VERSION); |
---|
474 | shell_sprintf("VERSION_MIN","%d",MINOR_VERSION); |
---|
475 | shell_sprintf("VERSION_TGT","%d",TARGET_VERSION); |
---|
476 | return(0); |
---|
477 | } |
---|
478 | |
---|
479 | /* getenv: |
---|
480 | * Return the pointer to the value entry if the shell variable |
---|
481 | * name is currently set; otherwise, return a null pointer. |
---|
482 | */ |
---|
483 | char * |
---|
484 | getenv(char *name) |
---|
485 | { |
---|
486 | register struct s_shell *sp; |
---|
487 | |
---|
488 | for(sp = shell_vars;sp != (struct s_shell *)0;sp = sp->next) { |
---|
489 | if (sp->name != (char *)0) { |
---|
490 | if (strcmp(sp->name,name) == 0) |
---|
491 | return(sp->val); |
---|
492 | } |
---|
493 | } |
---|
494 | return((char *)0); |
---|
495 | } |
---|
496 | |
---|
497 | /* getenvp: |
---|
498 | * Build an environment string consisting of all shell variables and |
---|
499 | * their values concatenated into one string. The format is |
---|
500 | * |
---|
501 | * NAME=VALUE LF NAME=VALUE LF NAME=VALUE LF NULL |
---|
502 | * |
---|
503 | * with the limit in size being driven only by the space |
---|
504 | * available on the heap. Note that this uses malloc, and it |
---|
505 | * the responsibility of the caller to free the pointer when done. |
---|
506 | */ |
---|
507 | char * |
---|
508 | getenvp(void) |
---|
509 | { |
---|
510 | int size; |
---|
511 | char *envp, *cp; |
---|
512 | register struct s_shell *sp; |
---|
513 | |
---|
514 | size = 0; |
---|
515 | |
---|
516 | /* Get total size of the current environment vars */ |
---|
517 | for(sp = shell_vars;sp != (struct s_shell *)0;sp = sp->next) { |
---|
518 | if (sp->name != (char *)0) { |
---|
519 | size += (strlen(sp->name) + strlen(sp->val) + 2); |
---|
520 | } |
---|
521 | } |
---|
522 | if (size == 0) |
---|
523 | return((char *)0); |
---|
524 | |
---|
525 | envp = env_alloc(size+1); /* leave room for final NULL */ |
---|
526 | if (envp == 0) |
---|
527 | return((char *)0); |
---|
528 | |
---|
529 | cp = envp; |
---|
530 | for(sp = shell_vars;sp != (struct s_shell *)0;sp = sp->next) { |
---|
531 | if (sp->name != (char *)0) |
---|
532 | cp += sprintf(cp,"%s=%s\n",sp->name,sp->val); |
---|
533 | } |
---|
534 | *cp = 0; /* Append NULL after final separator */ |
---|
535 | return(envp); |
---|
536 | } |
---|
537 | |
---|
538 | /* clearenv(): |
---|
539 | * Clear out the entire environment. |
---|
540 | */ |
---|
541 | void |
---|
542 | clearenv(void) |
---|
543 | { |
---|
544 | struct s_shell *sp; |
---|
545 | |
---|
546 | for(sp = shell_vars;sp != (struct s_shell *)0;sp = sp->next) { |
---|
547 | if (sp->name != (char *)0) { |
---|
548 | env_free(sp->name); |
---|
549 | env_free(sp->val); |
---|
550 | sp->name = (char *)0; |
---|
551 | sp->val = (char *)0; |
---|
552 | } |
---|
553 | } |
---|
554 | } |
---|
555 | |
---|
556 | /* setenv: |
---|
557 | * Interface to shell_dealloc() and shell_alloc(). |
---|
558 | */ |
---|
559 | int |
---|
560 | setenv(char *name,char *value) |
---|
561 | { |
---|
562 | if (!shell_vars) |
---|
563 | return(-1); |
---|
564 | if ((value == (char *)0) || (*value == 0)) |
---|
565 | return(shell_dealloc(name)); |
---|
566 | else |
---|
567 | return(shell_alloc(name,value)); |
---|
568 | } |
---|
569 | |
---|
570 | /* shell_print(): |
---|
571 | * Print out all of the current shell variables and their values. |
---|
572 | */ |
---|
573 | int |
---|
574 | shell_print(void) |
---|
575 | { |
---|
576 | int maxlen, len; |
---|
577 | char format[8]; |
---|
578 | register struct s_shell *sp; |
---|
579 | |
---|
580 | /* Before printing the list, pass through the list to determine the |
---|
581 | * largest variable name. This is used to create a format string |
---|
582 | * that is then passed to printf() when printing the list of |
---|
583 | * name/value pairs. It guarantees that regardless of the length |
---|
584 | * of the name, the format of the printed out put will be consistent |
---|
585 | * for all variables. |
---|
586 | */ |
---|
587 | maxlen = 0; |
---|
588 | sp = shell_vars; |
---|
589 | while(1) { |
---|
590 | if (sp->name) { |
---|
591 | len = strlen(sp->name); |
---|
592 | if (len > maxlen) |
---|
593 | maxlen = len; |
---|
594 | } |
---|
595 | if (sp->next != (struct s_shell *)0) |
---|
596 | sp = sp->next; |
---|
597 | else |
---|
598 | break; |
---|
599 | } |
---|
600 | sprintf(format,"%%%ds = ",maxlen+1); |
---|
601 | |
---|
602 | /* Now that we know the size of the largest variable, we can |
---|
603 | * print the list cleanly... |
---|
604 | */ |
---|
605 | sp = shell_vars; |
---|
606 | while(1) { |
---|
607 | if (sp->name != (char *)0) { |
---|
608 | printf(format, sp->name); |
---|
609 | puts(sp->val); /* sp->val may overflow printf, so use puts */ |
---|
610 | } |
---|
611 | if (sp->next != (struct s_shell *)0) |
---|
612 | sp = sp->next; |
---|
613 | else |
---|
614 | break; |
---|
615 | } |
---|
616 | return(0); |
---|
617 | } |
---|
618 | |
---|
619 | /* shell_sprintf(): |
---|
620 | * Simple way to turn a printf-like formatted string into a shell variable. |
---|
621 | */ |
---|
622 | int |
---|
623 | shell_sprintf(char *varname, char *fmt, ...) |
---|
624 | { |
---|
625 | int tot; |
---|
626 | char buf[CMDLINESIZE]; |
---|
627 | va_list argp; |
---|
628 | |
---|
629 | va_start(argp,fmt); |
---|
630 | tot = vsnprintf(buf,CMDLINESIZE-1,fmt,argp); |
---|
631 | va_end(argp); |
---|
632 | setenv(varname,buf); |
---|
633 | return(tot); |
---|
634 | } |
---|
635 | |
---|
636 | |
---|
637 | #if INCLUDE_TFS |
---|
638 | /* validEnvToExecVar(): |
---|
639 | * Return 1 if the variable should be included in the script |
---|
640 | * generated by envToExec(); else return 0. |
---|
641 | * Specifically... if the variable is generated internally |
---|
642 | * then we don't want to include it in the script. |
---|
643 | */ |
---|
644 | int |
---|
645 | validEnvToExecVar(char *varname) |
---|
646 | { |
---|
647 | char **vp; |
---|
648 | static char *invalid_varprefixes[] = { |
---|
649 | "ARG", "TFS_PREFIX_", "TFS_START_", |
---|
650 | "TFS_END_", "TFS_SPARE_", "TFS_SPARESZ_", |
---|
651 | "TFS_SCNT_", "TFS_DEVINFO_", "FLASH_BASE_", |
---|
652 | "FLASH_SCNT_", "FLASH_END_", |
---|
653 | 0 |
---|
654 | }; |
---|
655 | static char *invalid_varnames[] = { |
---|
656 | "APPRAMBASE", "BOOTROMBASE", "CMDSTAT", |
---|
657 | "CONSOLEBAUD", "MALLOC", "MONCOMPTR", |
---|
658 | "MONITORBUILT", "PLATFORM", "PROMPT", |
---|
659 | "TFS_DEVTOT", "FLASH_DEVTOT", "PROMPT", |
---|
660 | "VERSION_MAJ", "VERSION_MIN", "VERSION_TGT", |
---|
661 | "MONCMD_SRCIP", "MONCMD_SRCPORT", |
---|
662 | #if INCLUDE_HWTMR |
---|
663 | "TARGETTIMER", "TICKSPERMSEC", |
---|
664 | #endif |
---|
665 | 0 |
---|
666 | }; |
---|
667 | |
---|
668 | if (varname == 0) |
---|
669 | return(0); |
---|
670 | |
---|
671 | if (strncmp(varname,"ARG",3) == 0) |
---|
672 | return(0); |
---|
673 | |
---|
674 | #if INCLUDE_BOARDINFO |
---|
675 | if (BoardInfoVar(varname)) |
---|
676 | return(0); |
---|
677 | #endif |
---|
678 | |
---|
679 | for(vp=invalid_varnames;*vp;vp++) { |
---|
680 | if (!strcmp(varname,*vp)) |
---|
681 | return(0); |
---|
682 | } |
---|
683 | for(vp=invalid_varprefixes;*vp;vp++) { |
---|
684 | if (!strncmp(varname,*vp,strlen(*vp))) |
---|
685 | return(0); |
---|
686 | } |
---|
687 | return(1); |
---|
688 | } |
---|
689 | |
---|
690 | /* envToExec(): |
---|
691 | Create a file of "set" commands that can be run to recreate the |
---|
692 | current environment. |
---|
693 | Changed Oct 2008 to eliminate use of getAppRamStart(). |
---|
694 | */ |
---|
695 | int |
---|
696 | envToExec(char *filename) |
---|
697 | { |
---|
698 | int err, vartot, size, rc; |
---|
699 | char *buf, *bp, *cp; |
---|
700 | register struct s_shell *sp; |
---|
701 | |
---|
702 | sp = shell_vars; |
---|
703 | vartot = size = rc = 0; |
---|
704 | |
---|
705 | /* First go through the list to see how much space we need |
---|
706 | * to allocate... |
---|
707 | */ |
---|
708 | while(1) { |
---|
709 | if (validEnvToExecVar(sp->name)) { |
---|
710 | size += strlen(sp->name) + 6; |
---|
711 | cp = sp->val; |
---|
712 | while(*cp) { |
---|
713 | if (*cp == '$') |
---|
714 | size++; |
---|
715 | size++; |
---|
716 | cp++; |
---|
717 | } |
---|
718 | size += 3; |
---|
719 | vartot++; |
---|
720 | } |
---|
721 | if (sp->next != (struct s_shell *)0) |
---|
722 | sp = sp->next; |
---|
723 | else |
---|
724 | break; |
---|
725 | } |
---|
726 | if (size == 0) |
---|
727 | return(0); |
---|
728 | |
---|
729 | /* Now that we know the space needed (stored in 'size' variable), |
---|
730 | * allocate it and build the new file in that space, then use tfsadd() |
---|
731 | * to create the file... |
---|
732 | */ |
---|
733 | vartot = 0; |
---|
734 | sp = shell_vars; |
---|
735 | buf = bp = (char *)env_alloc(size); |
---|
736 | while(1) { |
---|
737 | /* Note: if this code changes, then the code above that is used to |
---|
738 | * allocate the buffer size may also need to change... |
---|
739 | */ |
---|
740 | if (validEnvToExecVar(sp->name)) { |
---|
741 | bp += sprintf(bp,"set %s \"",sp->name); |
---|
742 | cp = sp->val; |
---|
743 | while(*cp) { |
---|
744 | if (*cp == '$') |
---|
745 | *bp++ = '\\'; |
---|
746 | *bp++ = *cp++; |
---|
747 | } |
---|
748 | *bp++ = '\"'; |
---|
749 | *bp++ = '\n'; |
---|
750 | *bp = 0; |
---|
751 | vartot++; |
---|
752 | } |
---|
753 | if (sp->next != (struct s_shell *)0) |
---|
754 | sp = sp->next; |
---|
755 | else |
---|
756 | break; |
---|
757 | } |
---|
758 | if (vartot > 0) { |
---|
759 | err = tfsadd(filename,"envsetup","e",(unsigned char *)buf,strlen(buf)); |
---|
760 | if (err != TFS_OKAY) { |
---|
761 | printf("%s: %s\n",filename,(char *)tfsctrl(TFS_ERRMSG,err,0)); |
---|
762 | rc = -1; |
---|
763 | } |
---|
764 | } |
---|
765 | env_free(buf); |
---|
766 | return(rc); |
---|
767 | } |
---|
768 | #endif |
---|
769 | |
---|
770 | #else |
---|
771 | |
---|
772 | /* The 'set' command is part of the build even if INCLUDE_SHELLVARS |
---|
773 | * is false. This allows the user to still access teh "set -b ###" |
---|
774 | * facility for changing the baudrate. |
---|
775 | */ |
---|
776 | char *SetHelp[] = { |
---|
777 | "Set baud", |
---|
778 | "-[b:] (no args)", |
---|
779 | #if INCLUDE_VERBOSEHELP |
---|
780 | " -b set console baudrate", |
---|
781 | #endif |
---|
782 | 0, |
---|
783 | }; |
---|
784 | |
---|
785 | int |
---|
786 | Set(int argc,char *argv[]) |
---|
787 | { |
---|
788 | int opt; |
---|
789 | |
---|
790 | while((opt=getopt(argc,argv,"b:")) != -1) { |
---|
791 | switch(opt) { |
---|
792 | case 'b': |
---|
793 | ChangeConsoleBaudrate(atoi(optarg)); |
---|
794 | return(CMD_SUCCESS); |
---|
795 | break; |
---|
796 | default: |
---|
797 | return(CMD_PARAM_ERROR); |
---|
798 | } |
---|
799 | } |
---|
800 | printf("Shell vars not included in build.\n"); |
---|
801 | return(CMD_FAILURE); |
---|
802 | } |
---|
803 | |
---|
804 | int |
---|
805 | setenv(char *name,char *value) |
---|
806 | { |
---|
807 | return(-1); |
---|
808 | } |
---|
809 | |
---|
810 | char * |
---|
811 | getenv(char *name) |
---|
812 | { |
---|
813 | return(0); |
---|
814 | } |
---|
815 | |
---|
816 | int |
---|
817 | shell_sprintf(char *varname, char *fmt, ...) |
---|
818 | { |
---|
819 | return(0); |
---|
820 | } |
---|
821 | |
---|
822 | void |
---|
823 | ConsoleBaudEnvSet(void) |
---|
824 | { |
---|
825 | } |
---|
826 | |
---|
827 | char * |
---|
828 | getenvp(void) |
---|
829 | { |
---|
830 | return(0); |
---|
831 | } |
---|
832 | |
---|
833 | #endif |
---|
834 | |
---|
835 | /* ChangeConsoleBaudrate(): |
---|
836 | * Called to attempt to adjust the console baudrate. |
---|
837 | * Support 2 special cases: |
---|
838 | * if baud == 0, then just turn off console echo; |
---|
839 | * if baud == 1, turn it back on. |
---|
840 | */ |
---|
841 | int |
---|
842 | ChangeConsoleBaudrate(int baud) |
---|
843 | { |
---|
844 | if (baud == 0) |
---|
845 | console_echo(0); |
---|
846 | else if (baud == 1) |
---|
847 | console_echo(1); |
---|
848 | else { |
---|
849 | if (ConsoleBaudSet(baud) < 0) { |
---|
850 | printf("Baud=%d failed\n",baud); |
---|
851 | return(-1); |
---|
852 | } |
---|
853 | ConsoleBaudRate = baud; |
---|
854 | ConsoleBaudEnvSet(); |
---|
855 | } |
---|
856 | return(0); |
---|
857 | } |
---|
858 | |
---|